diff --git a/3rdparty/include/pcl/APASSDatabaseFile.h b/3rdparty/include/pcl/APASSDatabaseFile.h new file mode 100644 index 0000000..1dcc17c --- /dev/null +++ b/3rdparty/include/pcl/APASSDatabaseFile.h @@ -0,0 +1,509 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/APASSDatabaseFile.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_APASSDatabaseFile_h +#define __PCL_APASSDatabaseFile_h + +/// \file pcl/APASSDatabaseFile.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::APASSStarFlag + * \brief Data availability and quality flags for APASS star data. + * + * + * + * + * + * + * + * + * + * + * + *
APASSStarFlag::NoMag_V No Johnson V magnitude available.
APASSStarFlag::NoMag_B No Johnson B magnitude available.
APASSStarFlag::NoMag_u No Sloan u' magnitude available (APASS DR10 only).
APASSStarFlag::NoMag_g No Sloan g' magnitude available.
APASSStarFlag::NoMag_r No Sloan r' magnitude available.
APASSStarFlag::NoMag_i No Sloan i' magnitude available.
APASSStarFlag::NoMag_z_s No Sloan z_s magnitude available (APASS DR10 only).
APASSStarFlag::NoMag_Y No Sloan Y magnitude available (APASS DR10 only).
APASSStarFlag::PosErrorHigh Uncertainty in right ascension or declination greater than 0.75 arcseconds.
+ * + * \ingroup point_source_databases + */ +namespace APASSStarFlag +{ + enum mask_type + { + NoMag_V = 0x0001, + NoMag_B = 0x0002, + NoMag_u = 0x0004, + NoMag_g = 0x0008, + NoMag_r = 0x0010, + NoMag_i = 0x0020, + NoMag_z_s = 0x0040, + NoMag_Y = 0x0080, + PosErrorHigh = 0x0100 + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \struct APASSStarData + * \brief Star data structure for APASS catalog search operations. + * + * \ingroup point_source_databases + */ +struct PCL_CLASS APASSStarData +{ + double ra = 0; //!< Right ascension in degrees, in the range [0,360). + double dec = 0; //!< Declination in degrees, in the range [-90,+90]. + float mag_V = 0; //!< Magnitude in Johnson V (Vega system). + float mag_B = 0; //!< Magnitude in Johnson B (Vega system). + float mag_u = 0; //!< Magnitude in Sloan u' (AB system) (APASS DR10 only). + float mag_g = 0; //!< Magnitude in Sloan g' (AB system). + float mag_r = 0; //!< Magnitude in Sloan r' (AB system). + float mag_i = 0; //!< Magnitude in Sloan i' (AB system). + float mag_z_s = 0; //!< Magnitude in Sloan z_s (AB system) (APASS DR10 only). + float mag_Y = 0; //!< Magnitude in Sloan Y (AB system) (APASS DR10 only). + float err_V = 0; //!< Uncertainty in mag_V. + float err_B = 0; //!< Uncertainty in mag_B. + float err_u = 0; //!< Uncertainty in mag_u (APASS DR10 only). + float err_g = 0; //!< Uncertainty in mag_g. + float err_r = 0; //!< Uncertainty in mag_r. + float err_i = 0; //!< Uncertainty in mag_i. + float err_z_s = 0; //!< Uncertainty in mag_z_s (APASS DR10 only). + float err_Y = 0; //!< Uncertainty in mag_Y (APASS DR10 only). + uint16 flags = 0u; //!< Data availability and quality flags. See the APASSStarFlag namespace. +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct pcl::APASSSearchData + * \brief Data items and parameters for APASS catalog search operations. + * + * \ingroup point_source_databases + */ +typedef XPSD::SearchData APASSSearchData; + +// ---------------------------------------------------------------------------- + +/*! + * \class APASSDatabaseFile + * \brief APASS catalog star database file (XPSD format). + * + * This class implements an interface to XPSD files serializing encoded APASS + * star data. As of writing this documentation (December 2020), APASS DR9 and + * DR10 are supported and have been implemented. + * + * The most important functionality of this class is performing fast indexed + * search operations to retrieve point source data for APASS stars matching a + * set of user-defined criteria. See the APASSDatabaseFile::Search() member + * function and the APASSSearchData structure for detailed information. + * + * This implementation provides the following data for the complete APASS DR9 + * and DR10 catalogs: + * + * \li Source positions. + * \li Magnitudes on the Johnson V and B bands (Vega system) and Sloan u', g', + * r', i', z_s and Y magnitudes (AB system). + * \li Data availability and quality flags. + * + * \b References + * + * \li APASS: The AAVSO Photometric All-Sky Survey: + * https://www.aavso.org/apass + * + * \b Credits + * + * This work makes use of data from the AAVSO Photometric All Sky Survey, whose + * funding has been provided by the Robert Martin Ayers Sciences Fund and from + * the NSF (AST-1412587). + * + * \sa StarDatabaseFile, GaiaDatabaseFile + * \ingroup point_source_databases + */ +class PCL_CLASS APASSDatabaseFile : public StarDatabaseFile +{ +public: + + /*! + * Default constructor. + * + * Constructs an invalid instance that cannot be used until initialized by + * calling the Open() member function. + */ + APASSDatabaseFile() = default; + + /*! + * Constructs a &APASSDatabaseFile instance initialized from the specified + * point source database file in XPSD format. As of writing this + * documentation (December 2020), The APASS DR9 and DR10 catalogs are + * available. + * + * In the event of errors or invalid data, this constructor will throw the + * appropriate Error exception. + */ + APASSDatabaseFile( const String& filePath ) + : StarDatabaseFile( filePath ) + { + static_assert( sizeof( EncodedDR9StarData ) == 32, "Invalid sizeof( APASSDatabaseFile::EncodedDR9StarData )" ); + static_assert( sizeof( EncodedDR10StarData ) == 36, "Invalid sizeof( APASSDatabaseFile::EncodedDR10StarData )" ); + if ( Metadata().databaseIdentifier == "APASSDR9" ) + { + m_dr = "DR9"; + m_decoder = &APASSDatabaseFile::GetEncodedDR9Data; + } + else if ( Metadata().databaseIdentifier == "APASSDR10" ) + { + m_dr = "DR10"; + m_decoder = &APASSDatabaseFile::GetEncodedDR10Data; + } + else + throw Error( "Invalid or unsupported APASS database file with unknown identifier '" + + Metadata().databaseIdentifier + "': " + filePath ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + APASSDatabaseFile& operator =( APASSDatabaseFile&& ) = default; + + /*! + * Deleted copy constructor. %APASSDatabaseFile instances are unique, + * hence cannot be copied. + */ + APASSDatabaseFile( const APASSDatabaseFile& ) = delete; + + /*! + * Deleted copy assignment operator. %APASSDatabaseFile instances are + * unique, hence cannot be copied. + */ + APASSDatabaseFile& operator =( const APASSDatabaseFile& ) = delete; + + /*! + * Performs a search operation for point sources matching the specified + * criteria. + * + * This member function performs a fast indexed search for point sources in + * this database file matching the criteria defined in the specified \a data + * structure. See the APASSSearchData structure for detailed information on + * search parameters and output data. + * + * Summarily, search criteria include: + * + * \li The region of the sky where point sources will be searched for. This + * region is defined by the equatorial coordinates of a field center and a + * field radius. + * + * \li An optional range of magnitudes. + * + * \li Optional inclusion/exclusion flags. + * + * \li An optional limit for the number of sources included in the search + * result. + * + * The result of the search operation is also returned in the specified + * \a data structure, including, among others, the following items: + * + * \li The list of point sources found. + * + * \li Instrumentation items for performance analysis, including: total + * search time, time used for I/O operations, total I/O operations, time + * used for data decoding, and time used for data decompression. + */ + void Search( APASSSearchData& data ) const + { + ElapsedTime T; + for ( const XPSD::IndexTree& tree : m_index ) + tree.Search( data.centerRA, data.centerDec, data.radius, &data ); + data.timeTotal += T(); + } + + /*! + * Returns the name of the APASS data release corresponding to the data + * available in this database file. As of writing this documentation + * (December 2020), this member function can return either "DR9" or "DR10". + */ + const IsoString& DataRelease() const + { + return m_dr; + } + +private: + + IsoString m_dr; // data release, one of "DR9", "DR10" + + typedef void (APASSDatabaseFile::*star_decoder)( const ByteArray&, const XPSD::IndexTree&, const XPSD::IndexNode&, void* ) const; + star_decoder m_decoder = nullptr; + +#pragma pack(push, 1) + + /* + * Encoded DR9 star record (32 bytes uncompressed). + */ + struct EncodedDR9StarData + { + // Projected coordinates relative to the origin of the parent quadtree + // node, in mas units. + uint32 dx; + uint32 dy; + // Magnitudes in 0.001 mag units, encoded as (mag + 1.5)*1000. + uint16 mag_V; + uint16 mag_B; + uint16 mag_g; + uint16 mag_r; + uint16 mag_i; + // Magnitude uncertainties in 0.001 mag units. + uint16 err_V; + uint16 err_B; + uint16 err_g; + uint16 err_r; + uint16 err_i; + // Right ascension correction for high declinations, in 0.1 mas units. + int16 dra; + // Data availability and quality flags. + uint16 flags; + }; + + /* + * Encoded DR10 star record (36 bytes uncompressed). + */ + struct EncodedDR10StarData + { + // Projected coordinates relative to the origin of the parent quadtree + // node, in mas units. + uint32 dx; + uint32 dy; + // Magnitudes in 0.001 mag units, encoded as (mag + 1.5)*1000. + uint16 mag_V; + uint16 mag_B; + // uint16 mag_u; + uint16 mag_g; + uint16 mag_r; + uint16 mag_i; + uint16 mag_z_s; + // uint16 mag_Y; + // Magnitude uncertainties in 0.001 mag units. + uint16 err_V; + uint16 err_B; + // uint16 err_u; + uint16 err_g; + uint16 err_r; + uint16 err_i; + uint16 err_z_s; + // uint16 err_Y; + // Right ascension correction for high declinations, in 0.1 mas units. + int16 dra; + // Data availability and quality flags. + uint16 flags; + }; + +#pragma pack(pop) + + void LoadData( void* block, uint64 offset, uint32 size, void* searchData ) const override + { + ElapsedTime T; + StarDatabaseFile::LoadData( block, offset, size, searchData ); + reinterpret_cast( searchData )->timeIO += T(); + ++reinterpret_cast( searchData )->countIO; + } + + void Uncompress( ByteArray& block, uint32 uncompressedSize, void* searchData ) const override + { + ElapsedTime T; + StarDatabaseFile::Uncompress( block, uncompressedSize, searchData ); + reinterpret_cast( searchData )->timeUncompress += T(); + } + + void GetEncodedData( const ByteArray& data, const XPSD::IndexTree& tree, const XPSD::IndexNode& node, void* searchData ) const override + { + (this->*m_decoder)( data, tree, node, searchData ); + } + + void GetEncodedDR9Data( const ByteArray& data, const XPSD::IndexTree& tree, const XPSD::IndexNode& node, void* searchData ) const + { + ElapsedTime T; + APASSSearchData* search = reinterpret_cast( searchData ); + double r = Rad( search->radius ); + const EncodedDR9StarData* S = reinterpret_cast( data.Begin() ); + int count = int( data.Size() / sizeof( EncodedDR9StarData ) ); + int matched = 0; + for ( int i = 0; i < count; ++i, ++S ) + if ( search->requiredFlags == 0 || (S->flags & search->requiredFlags) == search->requiredFlags ) + if ( search->inclusionFlags == 0 || (S->flags & search->inclusionFlags) != 0 ) + if ( search->exclusionFlags == 0 || (S->flags & search->exclusionFlags) == 0 ) + { + float mag_V = 0.001*S->mag_V - 1.5; + if ( mag_V >= search->magnitudeLow ) + if ( mag_V <= search->magnitudeHigh ) + { + APASSStarData star; + double x = node.x0 + double( S->dx )/3600/1000; + double y = node.y0 + double( S->dy )/3600/1000; + tree.Unproject( star.ra, star.dec, x, y ); + if ( unlikely( S->dra != 0 ) ) + { + star.ra += double( S->dra )/3600/1000/10; + if ( star.ra < 0 ) + star.ra += 360; + else if ( star.ra >= 360 ) + star.ra -= 360; + } + if ( Distance( search->centerRA, search->centerDec, star.ra, star.dec ) < r ) + { + if ( search->stars.Length() < size_type( search->sourceLimit ) ) + { + star.mag_V = mag_V; + star.mag_B = 0.001*S->mag_B - 1.5; + star.mag_g = 0.001*S->mag_g - 1.5; + star.mag_r = 0.001*S->mag_r - 1.5; + star.mag_i = 0.001*S->mag_i - 1.5; + star.err_V = 0.001*S->err_V; + star.err_B = 0.001*S->err_B; + star.err_g = 0.001*S->err_g; + star.err_r = 0.001*S->err_r; + star.err_i = 0.001*S->err_i; + star.flags = S->flags; + search->stars << star; + } + else + ++search->excessCount; + ++matched; + } + } + } + + search->rejectCount += count - matched; + search->timeDecode += T(); + } + + void GetEncodedDR10Data( const ByteArray& data, const XPSD::IndexTree& tree, const XPSD::IndexNode& node, void* searchData ) const + { + ElapsedTime T; + APASSSearchData* search = reinterpret_cast( searchData ); + double r = Rad( search->radius ); + const EncodedDR10StarData* S = reinterpret_cast( data.Begin() ); + int count = int( data.Size() / sizeof( EncodedDR10StarData ) ); + int matched = 0; + for ( int i = 0; i < count; ++i, ++S ) + if ( search->requiredFlags == 0 || (S->flags & search->requiredFlags) == search->requiredFlags ) + if ( search->inclusionFlags == 0 || (S->flags & search->inclusionFlags) != 0 ) + if ( search->exclusionFlags == 0 || (S->flags & search->exclusionFlags) == 0 ) + { + float mag_V = 0.001*S->mag_V - 1.5; + if ( mag_V >= search->magnitudeLow ) + if ( mag_V <= search->magnitudeHigh ) + { + APASSStarData star; + double x = node.x0 + double( S->dx )/3600/1000; + double y = node.y0 + double( S->dy )/3600/1000; + tree.Unproject( star.ra, star.dec, x, y ); + if ( unlikely( S->dra != 0 ) ) + { + star.ra += double( S->dra )/3600/1000/10; + if ( star.ra < 0 ) + star.ra += 360; + else if ( star.ra >= 360 ) + star.ra -= 360; + } + if ( Distance( search->centerRA, search->centerDec, star.ra, star.dec ) < r ) + { + if ( search->stars.Length() < size_type( search->sourceLimit ) ) + { + star.mag_V = mag_V; + star.mag_B = 0.001*S->mag_B - 1.5; + // star.mag_u = 0.001*S->mag_u - 1.5; + star.mag_g = 0.001*S->mag_g - 1.5; + star.mag_r = 0.001*S->mag_r - 1.5; + star.mag_i = 0.001*S->mag_i - 1.5; + star.mag_z_s = 0.001*S->mag_z_s - 1.5; + // star.mag_Y = 0.001*S->mag_Y - 1.5; + star.err_V = 0.001*S->err_V; + star.err_B = 0.001*S->err_B; + // star.err_u = 0.001*S->err_u; + star.err_g = 0.001*S->err_g; + star.err_r = 0.001*S->err_r; + star.err_i = 0.001*S->err_i; + star.err_z_s = 0.001*S->err_z_s; + // star.err_Y = 0.001*S->err_Y; + star.flags = S->flags; + search->stars << star; + } + else + ++search->excessCount; + ++matched; + } + } + } + + search->rejectCount += count - matched; + search->timeDecode += T(); + } + + friend class APASSDR9DatabaseFileGenerator; + friend class APASSDR10DatabaseFileGenerator; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_APASSDatabaseFile_h + +// ---------------------------------------------------------------------------- +// EOF pcl/APASSDatabaseFile.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ATrousWaveletTransform.h b/3rdparty/include/pcl/ATrousWaveletTransform.h new file mode 100644 index 0000000..d68100f --- /dev/null +++ b/3rdparty/include/pcl/ATrousWaveletTransform.h @@ -0,0 +1,686 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ATrousWaveletTransform.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_ATrousWaveletTransform_h +#define __PCL_ATrousWaveletTransform_h + +/// \file pcl/ATrousWaveletTransform.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class InterlacedTransformation; + +/*! + * \class ATrousWaveletTransform + * \brief Discrete isotropic à trous wavelet transform. + * + * The Isotropic Undecimated Wavelet Transform, also known as starlet transform + * or à trous (with holes) wavelet transform, produces a coefficient + * set {w1,w2,...,wN,cN}, where each wj is a set of zero-mean coefficients at + * scale j, which we call detail layer, and cN is a large-scale + * smoothed residual, which we call residual layer. Each layer has the + * same dimensions as the input image, hence the transform is redundant. + * + * The wavelet function in the à trous algorithm is the difference between the + * values of a scaling function F at two successive scales. Using the dyadic + * scaling sequence, the wavelet function can be represented as + * (F(x) - F(x/2)). The scaling function F can be any positive low-pass filter. + * + * The reconstruction algorithm consists of the sum of all wj detail layers + * for 1 <= j <= N, plus the residual layer cN. + * + * \b References + * + * \li Jean-Luc Starck, Fionn Murtagh, Mario Bertero, Handbook of + * Mathematical Methods in Imaging, ch. 34, Starlet Transform in + * Astronomical Data Processing, Springer, 2011, pp. 1489-1531. + * + * \li Starck, J.-L., Murtagh, F. and J. Fadili, A., Sparse %Image and + * Signal Processing: Wavelets, Curvelets, Morphological Diversity, + * Cambridge University Press, 2010. + * + * \li Starck, J.-L., Murtagh, F., Astronomical %Image and Data + * Analysis, Springer, 2002. + * + * \li Jean-Luc Starck, Fionn Murtagh, Albert Bijaoui, %Image processing + * and Data Analysis: The Multiscale Approach, Cambridge University Press, + * 1998. + * + * \b Implementation + * + * In our implementation, each layer in a wavelet transform is a floating-point + * image with the same dimensions as the transformed image. Layers are indexed + * from 0 to N. Layers at indexes from 0 to N-1 are detail layers, whose + * elements are actually wavelet difference coefficients. Pixels in a detail + * layer can be negative, zero or positive real values. + * + * The last layer, at index N, is the large-scale residual layer. Pixels in the + * residual layer image can only be positive or zero real values. + * + * \ingroup multiscale_transforms + * + * \note The StarletTransform class is an alias for %ATrousWaveletTransform. + */ +class PCL_CLASS ATrousWaveletTransform : public RedundantMultiscaleTransform +{ +public: + + /*! + * Represents a wavelet layer. + */ + typedef RedundantMultiscaleTransform::layer layer; + + /*! + * Represents a set of wavelet layers, or wavelet transform. + */ + typedef RedundantMultiscaleTransform::transform transform; + + /*! + * Represents a set of layer enabled/disabled states. + */ + typedef RedundantMultiscaleTransform::layer_state_set layer_state_set; + + /*! + * \brief The scaling function of a wavelet transform. + * + * A wavelet scaling function can be either a non-separable kernel filter, + * implemented as the KernelFilter class, or a separable filter implemented + * as SeparableFilter. + * + * Separable filters should be better in terms of performance, since + * separable convolution has O(N) complexity, as opposed to O(N^2) for + * non-separable convolution. However, in current PCL versions separable + * convolutions are only faster for relatively large filter sizes as a resut + * of vectorization with SIMD processor instructions. See the + * SeparableConvolution class and the \ref convolution_speed_limits "Helper + * Functions for Selection of Convolution Algorithms" section for more + * information. + * + * \sa KernelFilter, SeparableFilter + */ + struct WaveletScalingFunction + { + AutoPointer kernelFilter; //!< Non-separable kernel filter + AutoPointer separableFilter; //!< Separable filter + + /*! + * Default constructor. Constructs an uninitialized instance. + */ + WaveletScalingFunction() = default; + + /*! + * Non-separable filter constructor. The scaling function will own a + * duplicate of the specified kernel filter. + */ + WaveletScalingFunction( const KernelFilter& f ) + { + kernelFilter = f.Clone(); + PCL_CHECK( !kernelFilter.IsNull() ) + } + + /*! + * Separable filter constructor. The scaling function will own a + * duplicate of the specified separable filter. + */ + WaveletScalingFunction( const SeparableFilter& f ) + { + separableFilter = f.Clone(); + PCL_CHECK( !separableFilter.IsNull() ) + } + + /*! + * Copy constructor. The scaling function will own a duplicate of the + * kernel or separable filter in the source object. + */ + WaveletScalingFunction( const WaveletScalingFunction& s ) + { + if ( !s.kernelFilter.IsNull() ) + { + kernelFilter = s.kernelFilter->Clone(); + PCL_CHECK( !kernelFilter.IsNull() ) + } + if ( !s.separableFilter.IsNull() ) + { + separableFilter = s.separableFilter->Clone(); + PCL_CHECK( !separableFilter.IsNull() ) + } + } + + /*! + * Move constructor. + */ + WaveletScalingFunction( WaveletScalingFunction&& s ) + : kernelFilter( s.kernelFilter ) + , separableFilter( s.separableFilter ) + { + } + + /*! + * Destroys this scaling function object. Destroys and deallocates the + * existing kernel or separable filter in this object. + */ + virtual ~WaveletScalingFunction() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + WaveletScalingFunction& operator =( const WaveletScalingFunction& s ) + { + if ( s.kernelFilter.IsNull() ) + kernelFilter.Destroy(); + else + { + kernelFilter = s.kernelFilter->Clone(); + PCL_CHECK( !kernelFilter.IsNull() ) + } + + if ( s.separableFilter.IsNull() ) + separableFilter.Destroy(); + else + { + separableFilter = s.separableFilter->Clone(); + PCL_CHECK( !separableFilter.IsNull() ) + } + + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + WaveletScalingFunction& operator =( WaveletScalingFunction&& ) = default; + + /*! + * Returns true if this scaling function is a separable filter; false if + * it is an invalid or non-separable kernel filter. + */ + bool IsSeparable() const + { + return !separableFilter.IsNull() && !separableFilter->IsEmpty(); + } + + /*! + * Returns true if this scaling function is a non-separable kernel + * filter; false if it is an invalid or separable filter. + */ + bool IsNonseparable() const + { + return !kernelFilter.IsNull() && !kernelFilter->IsEmpty(); + } + + /*! + * Returns true iff this scaling function is valid, that is, if it owns a + * nonempty filter. + */ + bool IsValid() const + { + return IsSeparable() || IsNonseparable(); + } + + /*! + * Causes this scaling function to own a duplicate of the specified + * non-separable kernel filter. A previously existing filter is destroyed + * and deallocated. + */ + void Set( const KernelFilter& f ) + { + separableFilter.Destroy(); + kernelFilter = f.Clone(); + PCL_CHECK( !kernelFilter.IsNull() ) + } + + /*! + * Causes this scaling function to own a duplicate of the specified + * separable filter. A previously existing filter is destroyed and + * deallocated. + */ + void Set( const SeparableFilter& f ) + { + kernelFilter.Destroy(); + separableFilter = f.Clone(); + PCL_CHECK( !separableFilter.IsNull() ) + } + + /*! + * Destroys the kernel and/or separable filter(s) owned by this object, + * yielding an invalid instance. + */ + void Clear() + { + kernelFilter.Destroy(); + separableFilter.Destroy(); + } + + /*! + * Equality operator. Returns true only if this scaling function is equal + * to another instance. + */ + bool operator ==( const WaveletScalingFunction& other ) const + { + if ( !kernelFilter.IsNull() ) + return !other.kernelFilter.IsNull() && *kernelFilter == *other.kernelFilter; + if ( !separableFilter.IsNull() ) + return !other.separableFilter.IsNull() && *separableFilter == *other.separableFilter; + return other.kernelFilter.IsNull() && other.separableFilter.IsNull(); + } + }; + + /*! + * Default constructor. + * + * \note This constructor yields an uninitialized instance that cannot be + * used prior to initializing it with a reference to a filter object + * (either KernelFilter or SeparableFilter), which will be used as the + * scaling function of the wavelet transform. + */ + ATrousWaveletTransform() = default; + + /*! + * Constructs an %ATrousWaveletTransform instance using the specified + * scaling function. + * + * \param f A wavelet scaling function that can be either a non-separable + * filter (KernelFilter) or a separable filter (SeparableFilter). + * + * \param n Number of wavelet layers. The transform will consist of \a n + * wavelet layers plus a residual layer, i.e. n+1 total layers. + * + * \param d Scaling sequence. If \a d <= 0, the transform will use the + * dyadic sequence: 1, 2, 4, ... 2^i. If \a d > 0, its value is + * the distance in pixels between two successive scales. + * + * The default values for \a n and \a d are 4 and 0, respectively (four + * wavelet layers and the dyadic scaling sequence). + */ + ATrousWaveletTransform( const WaveletScalingFunction& f, int n = 4, int d = 0 ) + : RedundantMultiscaleTransform( n, d ) + , m_scalingFunction( f ) + { + PCL_CHECK( m_scalingFunction.IsValid() ) + } + + /*! + * Constructs an %ATrousWaveletTransform instance that uses a non-separable + * kernel filter as a scaling function. + * + * \param f Non-separable filter that will be used as the scaling + * function of the transform. Must be a positive, low-pass + * filter function. + * + * \param n Number of wavelet layers. The transform will consist of \a n + * wavelet layers plus a residual layer, i.e. n+1 total layers. + * + * \param d Scaling sequence. If \a d <= 0, the transform will use the + * dyadic sequence: 1, 2, 4, ... 2^i. If \a d > 0, its value is + * the distance in pixels between two successive scales. + * + * The default values for \a n and \a d are 4 and 0, respectively (four + * wavelet layers and the dyadic scaling sequence). + */ + ATrousWaveletTransform( const KernelFilter& f, int n = 4, int d = 0 ) + : RedundantMultiscaleTransform( n, d ) + , m_scalingFunction( f ) + { + PCL_CHECK( m_scalingFunction.IsValid() ) + } + + /*! + * Constructs an %ATrousWaveletTransform instance that uses a separable + * kernel filter as a scaling function. + * + * \param f Separable filter that will be used as the scaling function of + * the transform. Must be a positive, low-pass filter function. + * + * \param n Number of wavelet layers. The transform will consist of \a n + * wavelet layers plus a residual layer, i.e. n+1 total layers. + * + * \param d Scaling sequence. If \a d <= 0, the transform will use the + * dyadic sequence: 1, 2, 4, ... 2^i. If \a d > 0, its value is + * the distance in pixels between two successive scales. + * + * The default values for \a n and \a d are 4 and 0, respectively (four + * wavelet layers and the dyadic scaling sequence). + */ + ATrousWaveletTransform( const SeparableFilter& f, int n = 4, int d = 0 ) + : RedundantMultiscaleTransform( n, d ) + , m_scalingFunction( f ) + { + PCL_CHECK( m_scalingFunction.IsValid() ) + } + + /*! + * Copy constructor. + */ + ATrousWaveletTransform( const ATrousWaveletTransform& ) = default; + + /*! + * Move constructor. + */ + ATrousWaveletTransform( ATrousWaveletTransform&& ) = default; + + /*! + * Destroys this %ATrousWaveletTransform object. All existing wavelet layers + * and the internal scaling function filter object are destroyed and + * deallocated. + */ + virtual ~ATrousWaveletTransform() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ATrousWaveletTransform& operator =( const ATrousWaveletTransform& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ATrousWaveletTransform& operator =( ATrousWaveletTransform&& ) = default; + + /*! + * Returns a reference to the (immutable) scaling function used by this + * wavelet transform. + */ + const WaveletScalingFunction& ScalingFunction() const + { + return m_scalingFunction; + } + + /*! + * Sets a new scaling function \a f for this wavelet transform. + * + * \note As a consequence of calling this member function, all existing + * wavelet layers in this transform are destroyed. + */ + void SetScalingFunction( const WaveletScalingFunction& f ) + { + DestroyLayers(); + m_scalingFunction = f; + PCL_CHECK( m_scalingFunction.IsValid() ) + } + + /*! + * Sets a non-separable kernel filter as the scaling function \a f used by + * this wavelet transform. + * + * \note As a consequence of calling this member function, all existing + * wavelet layers in this transform are destroyed. + */ + void SetScalingFunction( const KernelFilter& f ) + { + DestroyLayers(); + m_scalingFunction.Set( f ); + PCL_CHECK( m_scalingFunction.IsValid() ) + } + + /*! + * Sets a separable kernel filter as the scaling function \a f used by this + * wavelet transform. + * + * \note As a consequence of calling this member function, all existing + * wavelet layers in this transform are destroyed. + */ + void SetScalingFunction( const SeparableFilter& f ) + { + DestroyLayers(); + m_scalingFunction.Set( f ); + PCL_CHECK( m_scalingFunction.IsValid() ) + } + + /*! + * Estimation of the standard deviation of the noise, assuming a Gaussian + * noise distribution. This routine implements the k-sigma clipping noise + * estimation algorithm described by Starck et al. (see the references in + * the detailed documentation for this class). The algorithm is described + * for example in Astronomical %Image and Data Analysis, pp. 37-38. + * + * This routine can be used to provide an initial estimate to the more + * accurate multiresolution support noise estimation algorithm, + * implemented as the NoiseMRS() routine. When used with a relative error + * bound (see the \a eps parameter), this routine can easily yield noise + * estimates to within 1% accuracy. + * + * \param j Wavelet layer index (zero-based). The default index is 0. + * + * \param k Clipping multiplier in sigma units. The default value is 3. + * + * \param eps Fractional relative accuracy. If this parameter is greater + * than zero, the algorithm will iterate until the difference + * between two successive iterations is less than \a eps. The + * default value is 0.01, so this routine iterates to achieve an + * estimate to within 1% accuracy. + * + * \param n Maximum number of iterations. When \a eps is zero, this is + * the fixed number of iterations of the noise estimation + * algorithm. Three iterations usually give an estimate to + * within 5% accuracy. 5 or 6 iterations can provide 1% accuracy + * in most cases. When \a eps is greater than zero, this + * parameter works as a security limit to prevent too long + * execution times when convergence is slow (which shouldn't + * happen under normal conditions). The default value is 10. + * + * \param[out] N Pointer to a variable that will receive the total number + * of pixels tagged as noise during the noise evaluation + * process. This pointer can legally be \c nullptr, which is + * also the default value of this parameter. + * + * Returns the estimated standard deviation of the noise in the specified + * scale \a j of the wavelet transform after a relative \a eps accuracy has + * been reached or \a n sigma clipping iterations have been performed, + * whichever happens first. + * + * The returned value must be scaled by the standard deviation of the + * Gaussian noise at the specified wavelet scale. The scaling factor depends + * on the wavelet scaling function used to perform the wavelet decomposition + * and must be coherent with the transform performed by this object. + * + * If this %ATrousWaveletTransform object does not contain a valid wavelet + * transform, or if the specified wavelet layer has been deleted, this + * routine throws an Error exception. + */ + double NoiseKSigma( int j = 0, float k = 3, + float eps = 0.01, int n = 10, size_type* N = nullptr ) const; + + /*! + * Estimation of the standard deviation of the noise, assuming a Gaussian + * noise distribution, for a specified range of pixel values. + * + * This routine implements essentially the same algorithm as its unbounded + * counterpart: + * + * NoiseKSigma( int j, float k, float eps, int n, size_type* N ). + * + * The difference is that this version allows you to specify a valid range + * of pixel values with the \a low, \a high and \a image parameters. The + * standard deviation of the noise will only be computed for those pixels + * whose values in the specified \a image pertain to the range + * (low,high), that is, for every pixel with value \a v in + * \a image such that the condition \a low < \e v < \a high is true. + * + * The specified \a image must be compatible with the wavelet transform. In + * particular, the dimensions of \a image must be identical to those of the + * wavelet layers in this transform; otherwise an Error exception will be + * thrown. For selection of pixels within the specified range, only the + * currently selected channel in \a image will be taken into account. + * Normally, the specified \a image must be the same image that was used to + * compute the current wavelet decomposition in this object. + * + * For detailed information on the rest of parameters, the implemented + * algorithm, and special usage conditions for this routine, refer to the + * documentation for the unbounded version of this member function. + */ + double NoiseKSigma( int j, const ImageVariant& image, + float low = 0.00002F, float high = 0.99998F, + float k = 3, float eps = 0.01, int n = 10, size_type* N = nullptr ) const; + + /*! + * Estimation of the standard deviation of the Gaussian noise from the + * multiresolution support. This routine implements the iterative algorithm + * described by Jean-Luc Starck and Fionn Murtagh in their paper + * Automatic Noise Estimation from the Multiresolution Support + * (Publications of the Royal Astronomical Society of the Pacific, vol. 110, + * February 1998, pp. 193-199). + * + * \param image The original image. Normally this image should be the same + * image from which this wavelet transform has been + * calculated. + * + * \param sj Noise standard deviation at each wavelet scale for a + * Gaussian noise distribution with unit sigma. There must be + * at least NumberOfLayers() elements in the array pointed to + * by this parameter. + * + * \param sigma Initial estimate of the noise standard deviation in the + * image. The default value is zero. The best starting value + * is the result of the NoiseKSigma() routine. However, the + * noise estimate provided by NoiseKSigma() is relative to a + * particular wavelet layer, so it must be scaled as + * appropriate to make it coherent with the whole image. + * + * \param k Clipping multiplier in sigma units. The default value is 3. + * + * \param[out] N Pointer to a variable that will receive the total number + * of pixels tagged as noise during the noise evaluation + * process. This pointer can legally be \c nullptr, which is + * also the default value of this parameter. + * + * \param low Lower bound of the sampling range in the normalized [0,1] + * range. Pixel sample values less than or equal to \a low + * will be excluded from the noise evaluation process. The + * default value is 0.00002. + * + * \param high Upper bound of the sampling range in the normalized [0,1] + * range. Pixel sample values greater than or equal to + * \a high will be excluded from the noise evaluation + * process. The default value is 0.99998. + * + * Returns the estimated standard deviation of the noise from the + * multiresolution support, using all wavelet scales available. As long as + * successive noise estimates converge to a stable solution, this routine + * performs the necessary iterations until a relative fractional accuracy of + * 1e-4 is achieved. Normally this requires between 4 and 8 iterations, + * depending on the relation between the noise and significant structures in + * the image. + * + * If no convergence is achieved after a large number of iterations, this + * function returns zero and, if a nonzero N argument pointer is specified, + * sets *N = 0. This should never happen if this wavelet transform defines a + * reasonable number of wavelet layers (4 or 5 layers are recommended) and + * the passed parameters are valid and coherent with the wavelet transform. + * + * If this %ATrousWaveletTransform object does not contain a valid wavelet + * transform, if any wavelet layer has been deleted, or if the specified + * image doesn't have the same geometry as the wavelet layers in this + * transform, this routine throws an Error exception. + */ + double NoiseMRS( const ImageVariant& image, const float sj[], + double sigma = 0, float k = 3, size_type* N = nullptr, + float low = 0.00002F, float high = 0.99998F ) const; + +private: + + /* + * Wavelet scaling function. + */ + WaveletScalingFunction m_scalingFunction; + + /* + * Transform (decomposition) + */ + void Transform( const pcl::Image& ) override; + void Transform( const pcl::DImage& ) override; + void Transform( const pcl::ComplexImage& ) override; + void Transform( const pcl::DComplexImage& ) override; + void Transform( const pcl::UInt8Image& ) override; + void Transform( const pcl::UInt16Image& ) override; + void Transform( const pcl::UInt32Image& ) override; + + void ValidateScalingFunction() const; + + friend class ATWTDecomposition; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class pcl::StarletTransform + * \brief Starlet wavelet transform, a synonym for ATrousWaveletTransform. + * + * The isotropic stationary wavelet transform known as à trous wavelet + * transform since the early publications of Mallat, Starck and Murtagh in + * the 90's, is now known "officially" as starlet transform, at least + * since 2010's %Sparse %Image and %Signal %Processing book. + * + * \ingroup multiscale_transforms + */ +typedef ATrousWaveletTransform StarletTransform; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ATrousWaveletTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ATrousWaveletTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AbstractImage.h b/3rdparty/include/pcl/AbstractImage.h new file mode 100644 index 0000000..90c9fd2 --- /dev/null +++ b/3rdparty/include/pcl/AbstractImage.h @@ -0,0 +1,1428 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AbstractImage.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_AbstractImage_h +#define __PCL_AbstractImage_h + +/// \file pcl/AbstractImage.h + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ +class SharedImage; +} +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_width m_geometry->width +#define m_height m_geometry->height +#define m_numberOfChannels m_geometry->numberOfChannels + +#define m_colorSpace m_color->colorSpace +#define m_RGBWS m_color->RGBWS + +// ---------------------------------------------------------------------------- + +/*! + * \class AbstractImage + * \brief Base class of all two-dimensional images in PCL. + * + * %AbstractImage encapsulates ImageGeometry and ImageColor into a single class + * employed as the root base class for all two-dimensional images in PCL. + * + * This class provides fundamental properties and functionality that are + * independent on the particular data types used to store and manage pixel + * samples. + * + * %AbstractImage also provides a simple selection mechanism consisting of a + * rectangular selection (also known as region of interest, or ROI), a + * channel range, and an anchor point. Image selections can be stored in a + * local stack for quick retrieval (see PushSelections() and PopSelections()). + * Note that for practical reasons, image selections have been implemented as + * \c mutable data members internally, so modifying selections is possible for + * immutable %AbstractImage instances. + * + * Finally, %AbstractImage provides function and data members to manage status + * monitoring of images. The status monitoring mechanism can be used to provide + * feedback to the user about the progress of a running process. Status + * monitoring is implemented through the StatusMonitor and StatusCallback + * classes. See the Status(), StatusCallback() and SetStatusCallback() member + * functions for more information. + * + * \sa ImageGeometry, ImageColor, GenericImage, ImageVariant + */ +class PCL_CLASS AbstractImage : public ImageGeometry, + public ImageColor, + public ParallelProcess +{ +public: + + /*! + * A type used to implement a stack of stored image selections. + */ + typedef Array selection_stack; + + /*! + * An enumerated type that represents the set of supported color spaces. + * Valid constants for this enumeration are defined in the ColorSpace + * namespace. + */ + typedef ImageColor::color_space color_space; + + /*! + * Virtual destructor. + */ + virtual ~AbstractImage() + { + } + + /*! + * Returns the number of nominal channels corresponding to the current color + * space of this image. + */ + int NumberOfNominalChannels() const noexcept + { + return ColorSpace::NumberOfNominalChannels( m_colorSpace ); + } + + /*! + * Returns the number of nominal samples in this image. This is equal to the + * area in square pixels multiplied by the number of nominal channels. + */ + size_type NumberOfNominalSamples() const noexcept + { + return NumberOfPixels() * NumberOfNominalChannels(); + } + + /*! + * Returns true iff this image has one or more alpha channels. + * + * Alpha channels are those in excess of nominal channels, e.g. a fourth + * channel in a RGB image, or a second channel in a grayscale image. + */ + bool HasAlphaChannels() const noexcept + { + PCL_PRECONDITION( NumberOfChannels() != 0 ) + return NumberOfChannels() > NumberOfNominalChannels(); + } + + /*! + * Returns the number of existing alpha channels in this image. + */ + int NumberOfAlphaChannels() const noexcept + { + PCL_PRECONDITION( NumberOfChannels() != 0 ) + return NumberOfChannels() - NumberOfNominalChannels(); + } + + /*! + * Returns the number of existing alpha samples in this image. The returned + * value is equal to the number of alpha channels multiplied by the area of + * the image in square pixels. + */ + size_type NumberOfAlphaSamples() const noexcept + { + return NumberOfPixels() * NumberOfAlphaChannels(); + } + + // ------------------------------------------------------------------------- + + /*! + * Selects a single channel. + * + * \param c Channel index, 0 ≤ \a c < \a n, where \a n is the total + * number of channels in this image, including alpha channels. + */ + void SelectChannel( int c ) const noexcept + { + PCL_PRECONDITION( 0 <= c && c < m_numberOfChannels ) + m_selected.channel = m_selected.lastChannel = c; + ValidateChannelRange(); + } + + /*! + * Returns the index of the currently selected channel. + * + * If the current channel selection includes more than one channel, this + * function returns the index of the first selected channel. + * + * This function is a convenience synonym for FirstSelectedChannel(). + */ + int SelectedChannel() const noexcept + { + return m_selected.channel; + } + + /*! + * Selects a range of channels by their channel indices. The selected range + * \e includes the two channels specified. + * + * \param c0 Index of the first channel to select. + * \param c1 Index of the last channel to select. + */ + void SelectChannelRange( int c0, int c1 ) const noexcept + { + PCL_PRECONDITION( 0 <= c0 && c0 < m_numberOfChannels ) + PCL_PRECONDITION( 0 <= c1 && c1 < m_numberOfChannels ) + m_selected.channel = c0; + m_selected.lastChannel = c1; + ValidateChannelRange(); + } + + /*! + * Sets the current channel range selection to include all nominal channels + * exclusively, excluding alpha channels. + */ + void SelectNominalChannels() const noexcept + { + m_selected.channel = 0; + m_selected.lastChannel = NumberOfNominalChannels()-1; + ValidateChannelRange(); + } + + /*! + * Sets the current channel range selection to include the existing alpha + * channels only, excluding the nominal channels. + * + * \note If this image has no alpha channels, this function selects the last + * nominal channel. The channel range selection cannot be empty by design. + */ + void SelectAlphaChannels() const noexcept + { + m_selected.channel = NumberOfNominalChannels(); + m_selected.lastChannel = m_numberOfChannels-1; + ValidateChannelRange(); + } + + /*! + * Resets the channel range selection to include all existing channels (all + * nominal and alpha channels) in this image. + */ + void ResetChannelRange() const noexcept + { + m_selected.channel = 0; + m_selected.lastChannel = pcl::Max( 0, m_numberOfChannels-1 ); + } + + /*! + * Returns the number of selected channels. + */ + int NumberOfSelectedChannels() const noexcept + { + return 1 + m_selected.lastChannel - m_selected.channel; + } + + /*! + * Returns the channel index of the first selected channel. + */ + int FirstSelectedChannel() const noexcept + { + return m_selected.channel; + } + + /*! + * Returns the channel index of the last selected channel. + */ + int LastSelectedChannel() const noexcept + { + return m_selected.lastChannel; + } + + /*! + * Copies the first and last channel indices of the current channel + * selection to the specified variables. + * + * \param[out] c0 Index of the first selected channel. + * \param[out] c1 Index of the last selected channel. + */ + void GetSelectedChannelRange( int& c0, int& c1 ) const noexcept + { + c0 = m_selected.channel; + c1 = m_selected.lastChannel; + } + + /*! + * Selects an anchor point by its separate image coordinates. + * + * \param x Horizontal coordinate of the new anchor point. + * \param y Vertical coordinate of the new anchor point. + */ + void SelectPoint( int x, int y ) const noexcept + { + m_selected.point.MoveTo( x, y ); + } + + /*! + * Selects a new anchor point \a p in image coordinates. + */ + void SelectPoint( const Point& p ) const noexcept + { + m_selected.point = p; + } + + /*! + * Resets the anchor point to the origin of image coordinates, i.e to x=y=0. + */ + void ResetPoint() const noexcept + { + m_selected.point = 0; + } + + /*! + * Returns the current anchor point. + */ + const Point& SelectedPoint() const noexcept + { + return m_selected.point; + } + + /*! + * Defines the current rectangular selection by its separate image + * coordinates. + * + * \param x0,y0 Upper left corner coordinates (horizontal, vertical) of + * the new rectangular selection. + * + * \param x1,y1 Lower right corner coordinates (horizontal, vertical) of + * the new rectangular selection. + * + * The resulting selection is constrained to stay within the image + * boundaries. + */ + void SelectRectangle( int x0, int y0, int x1, int y1 ) const noexcept + { + m_selected.rectangle.Set( x0, y0, x1, y1 ); + Clip( m_selected.rectangle ); + } + + /*! + * Defines the current rectangular selection by its separate corner + * points in image coordinates. + * + * \param p0 Position of the upper left corner of the new selection. + * + * \param p1 Position of the lower right corner of the new selection. + */ + void SelectRectangle( const Point& p0, const Point& p1 ) const noexcept + { + SelectRectangle( p0.x, p0.y, p1.x, p1.y ); + } + + /*! + * Defines the current rectangular selection as the specified rectangle \a r + * in image coordinates. + */ + void SelectRectangle( const Rect& r ) const noexcept + { + SelectRectangle( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Resets the rectangular selection to include the entire image boundaries. + */ + void ResetSelection() const noexcept + { + m_selected.rectangle.Set( 0, 0, m_width, m_height ); + } + + /*! + * Returns true iff the current selection is empty, i.e. if its area is zero. + */ + bool IsEmptySelection() const noexcept + { + return m_selected.rectangle.IsPointOrLine(); + } + + /*! + * Returns true iff the current rectangular selection comprises the entire + * image. + */ + bool IsFullSelection() const noexcept + { + return m_selected.rectangle.x0 <= 0 && + m_selected.rectangle.y0 <= 0 && + m_selected.rectangle.x1 >= m_width && + m_selected.rectangle.y1 >= m_height; + } + + /*! + * Returns the current rectangular selection. + */ + const Rect& SelectedRectangle() const noexcept + { + return m_selected.rectangle; + } + + /*! + * Returns true if this image is completely selected; false if it is + * only partially selected. + * + * In a completely selected image, the current rectangular selection + * includes the whole image, and the current channel range selection + * comprises all existing channels, including nominal and alpha channels. + */ + bool IsCompletelySelected() const noexcept + { + return m_selected.channel == 0 && + m_selected.lastChannel >= m_numberOfChannels-1 && + m_selected.rectangle.x0 <= 0 && + m_selected.rectangle.y0 <= 0 && + m_selected.rectangle.x1 >= m_width && + m_selected.rectangle.y1 >= m_height; + } + + /*! + * Returns the number of selected pixels. This is the area in square pixels + * of the current selection rectangle. + */ + size_type NumberOfSelectedPixels() const noexcept + { + return size_type( m_selected.rectangle.Width() ) * size_type( m_selected.rectangle.Height() ); + // ### N.B. Rect::Area() cannot be used here because it performs a + // *signed* multiplication of two 32-bit signed integers. + //return m_selected.rectangle.Area(); + } + + /*! + * Returns the number of selected samples. This is the area in square pixels + * of the current selection rectangle multiplied by the number of selected + * channels. + */ + size_type NumberOfSelectedSamples() const noexcept + { + return NumberOfSelectedPixels()*size_type( NumberOfSelectedChannels() ); + } + + /*! + * Returns true iff range clipping is currently enabled for this image. + * + * When range clipping is enabled, pixel samples outside the current + * clipping range: + * + * ( RangeClipLow(), RangeClipHigh() ) + * + * are ignored by statistics calculation routines. Note that range bounds + * are always excluded, since the range is open on both sides. The clipping + * range is always defined in the normalized [0,1] range for all pixel + * sample data types; the necessary conversions are performed transparently. + * + * When range clipping is disabled, the clipping range is ignored and all + * pixel samples are considered for statistical calculations. + * + * To make it more flexible, range clipping can be enabled/disabled + * separately for the low and high bounds. + * + * The default clipping range is the normalized (0,1) range. Range clipping + * is disabled by default. + */ + bool IsRangeClippingEnabled() const noexcept + { + return m_selected.clippedLow || m_selected.clippedHigh; + } + + /*! + * Returns true iff range clipping is currently enabled for the low clipping + * bound. When this is true, pixel samples with values less than or equal to + * the low clipping bound (as reported by RangeClipLow() ) will be rejected + * for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + bool IsLowRangeClippingEnabled() const noexcept + { + return m_selected.clippedLow; + } + + /*! + * Returns true iff range clipping is currently enabled for the high + * clipping bound. When this is true, pixel samples with values greater than + * or equal to the high clipping bound (as reported by RangeClipHigh() ) + * will be rejected for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + bool IsHighRangeClippingEnabled() const noexcept + { + return m_selected.clippedHigh; + } + + /*! + * Enables range clippings for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void EnableRangeClipping( bool enableLow = true, bool enableHigh = true ) const noexcept + { + m_selected.clippedLow = enableLow; + m_selected.clippedHigh = enableHigh; + } + + /*! + * Disables range clippings for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void DisableRangeClipping( bool disableLow = true, bool disableHigh = true ) const noexcept + { + m_selected.clippedLow = !disableLow; + m_selected.clippedHigh = !disableHigh; + } + + /*! + * Returns the lower bound of the current clipping range. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + double RangeClipLow() const noexcept + { + return m_selected.clipLow; + } + + /*! + * Returns the upper bound of the current clipping range. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + double RangeClipHigh() const noexcept + { + return m_selected.clipHigh; + } + + /*! + * Sets the lower bound of the clipping range. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void SetRangeClipLow( double clipLow ) const noexcept + { + m_selected.clipLow = clipLow; + if ( m_selected.clipHigh < m_selected.clipLow ) + pcl::Swap( m_selected.clipLow, m_selected.clipHigh ); + } + + /*! + * Sets the upper bound of the clipping range. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void SetRangeClipHigh( double clipHigh ) const noexcept + { + m_selected.clipHigh = clipHigh; + if ( m_selected.clipHigh < m_selected.clipLow ) + pcl::Swap( m_selected.clipLow, m_selected.clipHigh ); + } + + /*! + * Sets the lower and upper bounds of the clipping range and enables range + * clipping (both low and high clipping bounds), in a single function call. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void SetRangeClipping( double clipLow, double clipHigh ) const noexcept + { + if ( clipHigh < clipLow ) + pcl::Swap( clipLow, clipHigh ); + m_selected.clipLow = clipLow; + m_selected.clipHigh = clipHigh; + m_selected.clippedLow = m_selected.clippedHigh = true; + } + + /*! + * Resets the range clipping parameters: + * + * Clipping range lower bound = 0.0 + * Clipping range upper bound = 1.0 + * Range clipping disabled + */ + void ResetRangeClipping() const noexcept + { + m_selected.clipLow = 0; + m_selected.clipHigh = 1; + m_selected.clippedLow = m_selected.clippedHigh = false; + } + + /*! + * Resets all image selections to default values: + * + * \li All channels are selected, including nominal and alpha channels. + * \li The anchor point is located at {0,0}, that is the upper left corner. + * \li The rectangular selection is set to comprise the entire image. + * \li The clipping range is set to [0,1]. + * \li Range clipping is disabled. + * + * Calling this member function is equivalent to: + * + * \code + * ResetChannelRange(); + * ResetPoint(); + * ResetSelection(); + * ResetRangeClipping(); + * \endcode + */ + void ResetSelections() const noexcept + { + ResetChannelRange(); + ResetPoint(); + ResetSelection(); + ResetRangeClipping(); + } + + /*! + * Returns a reference to the internal ImageSelections object in this image. + */ + ImageSelections& Selections() const noexcept + { + return m_selected; + } + + /*! + * Saves the current selections (rectangular area, channel range, anchor + * point and range clipping), pushing them to the internal selection stack. + */ + void PushSelections() const + { + m_savedSelections.Append( m_selected ); + } + + /*! + * Restores and pops (removes) the current selections (rectangular area, + * channel range, anchor point and range clipping) from the internal + * selection stack. + * + * If no selections have been previously pushed to the internal selection + * stack, this function is ignored. + */ + void PopSelections() const + { + if ( CanPopSelections() ) + { + selection_stack::iterator i = m_savedSelections.ReverseBegin(); + m_selected = *i; + m_savedSelections.Remove( i ); + } + } + + /*! + * Returns true iff one or more selections have been pushed to the internal + * selection stack, that is, if the PopSelections() function can be called + * to restore them. + */ + bool CanPopSelections() const noexcept + { + return !m_savedSelections.IsEmpty(); + } + + /*! + * Interprets the coordinates of a rectangle as a parameter to define a + * pixel selection. + * + * \param[in,out] rect If this rectangle is empty (defining either a + * point or a line), this function sets it to the + * current rectangular selection in this image. If this + * rectangle is nonempty, this function constrains its + * coordinates to stay within image boundaries. + * + * Returns true iff the output rectangle is nonempty. + */ + bool ParseRect( Rect& rect ) const noexcept + { + if ( !rect.IsRect() ) + { + rect = m_selected.rectangle; + if ( !rect.IsRect() ) + return false; + } + if ( !Clip( rect ) ) + return false; + return true; + } + + /*! + * Interprets a channel index as a parameter to define a pixel sample + * selection. + * + * \param[in,out] channel If a negative channel index is specified, this + * parameter will be replaced with the currently + * selected channel index in this image. + * + * Returns true iff the output channel index is valid. + */ + bool ParseChannel( int& channel ) const noexcept + { + if ( channel < 0 ) + { + channel = m_selected.channel; + if ( channel < 0 ) + return false; + } + if ( channel >= m_numberOfChannels ) + return false; + + return true; + } + + /*! + * Interprets the coordinates of a rectangle and two channel indexes as + * parameters to define a pixel sample selection. + * + * \param[in,out] rect If this rectangle is empty (defining either a + * point or a line), this function sets it to the + * current rectangular selection in this image. If this + * rectangle is nonempty, this function constrains its + * coordinates to stay within image boundaries. + * + * \param[in,out] firstChannel If a negative channel index is specified, + * this parameter will be replaced with the first + * channel index of the current channel range selection + * in this image. + * + * \param[in,out] lastChannel If a negative channel index is specified, + * this parameter will be replaced with the last + * channel index of the current channel range selection + * in this image. + * + * Returns true iff the output rectangle is nonempty and the output channel + * range is valid. When true is returned, this function ensures that + * \a firstChannel ≤ \a lastChannel. + */ + bool ParseSelection( Rect& rect, int& firstChannel, int& lastChannel ) const noexcept + { + if ( !ParseRect( rect ) || !ParseChannel( firstChannel ) ) + return false; + + if ( lastChannel < 0 ) + { + lastChannel = m_selected.lastChannel; + if ( lastChannel < 0 ) + return false; + } + if ( lastChannel >= m_numberOfChannels ) + return false; + + if ( lastChannel < firstChannel ) + pcl::Swap( firstChannel, lastChannel ); + + return true; + } + + /*! + * Interprets the coordinates of a rectangle and one channel index as + * parameters to define a pixel sample selection. + * + * \param[in,out] rect If this rectangle is empty (defining either a + * point or a line), this function sets it to the + * current rectangular selection in this image. If this + * rectangle is nonempty, this function constrains its + * coordinates to stay within image boundaries. + * + * \param[in,out] channel If a negative channel index is specified, this + * parameter will be replaced with the currently + * selected channel index in this image. + * + * Returns true iff the output rectangle is nonempty and the output channel + * index is valid. + */ + bool ParseSelection( Rect& rect, int& channel ) const noexcept + { + return ParseRect( rect ) && ParseChannel( channel ); + } + + // ------------------------------------------------------------------------- + + /*! + * Returns a reference to the status monitoring object associated with this + * image. + */ + StatusMonitor& Status() const noexcept + { + return m_status; + } + + /*! + * Returns the address of the status monitoring callback object currently + * selected for this image. + */ + pcl::StatusCallback* StatusCallback() const noexcept + { + return m_status.Callback(); + } + + /*! + * \deprecated This function has been deprecated. It is included in this + * version of PCL to keep existing code functional. Use StatusCallback() in + * newly produced code. + */ + pcl::StatusCallback* GetStatusCallback() const noexcept + { + return StatusCallback(); + } + + /*! + * Specifies the address of an object that will be used to perform status + * monitoring callbacks for this image. + */ + void SetStatusCallback( pcl::StatusCallback* callback ) const noexcept + { + m_status.SetCallback( callback ); + } + + /*! + * Returns the maximum number of threads that this image can use + * concurrently to process a set of items. + * + * \param count Number of processing units. A processing + * unit can be a single pixel, a row of pixels, or any suitable + * item, according to the task being performed by the caller. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of processors allowed, which takes + * precedence over the current limit set for this image (see the + * MaxProcessors() and SetMaxProcessors() member functions). If + * zero or a negative value is specified, it is ignored and the + * current MaxProcessors() limit is applied. + * + * \param overheadLimit Thread overhead limit in processing units. The + * function returns a maximum number of threads such that no + * thread would have to process less processing units than this + * value. The default overhead limit is 16 processing units. + * + * This function takes into account if parallel processing is currently + * enabled for this image, as well as the maximum number of processors + * allowed for the calling process. + * + * \sa Thread::NumberOfThreads() + */ + int NumberOfThreads( size_type count, int maxProcessors = 0, size_type overheadLimit = 16u ) const noexcept + { + return m_parallel ? pcl::Min( (maxProcessors > 0) ? maxProcessors : m_maxProcessors, + Thread::NumberOfThreads( count, overheadLimit ) ) : 1; + } + + /*! + * Returns the maximum number of threads that this image can use + * concurrently to process a set of pixel rows. + * + * \param rowCount Number of pixel rows to be processed. If zero or + * a negative value is specified, the height of the image in + * pixels will be used. The default value is zero. + * + * \param rowWidth Width in pixels of the ROI being processed. If + * zero or a negative value is specified, the width of the image + * in pixels is used. The default value is zero. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of processors allowed, which takes + * precedence over the current limit set for this image (see the + * MaxProcessors() and SetMaxProcessors() member functions). If + * zero or a negative value is specified, it is ignored and the + * current MaxProcessors() limit is applied. The default value + * is zero. + * + * \param overheadLimitPx Thread overhead limit in pixels. The function + * will calculate the minimum number of pixel rows that a single + * thread can process, based on this value and on the specified + * \a rowWidth (or the image's width if zero is passed for that + * parameter). The default overhead limit is 1024 pixels. + * + * This function takes into account if parallel processing is currently + * enabled for this image, as well as the maximum number of processors + * allowed for the calling process. + * + * \sa NumberOfThreads(), Thread::NumberOfThreads() + */ + int NumberOfThreadsForRows( int rowCount = 0, int rowWidth = 0, int maxProcessors = 0, size_type overheadLimitPx = 1024u ) const noexcept + { + return NumberOfThreads( (rowCount > 0) ? rowCount : Height(), + maxProcessors, + pcl::Max( size_type( 1 ), size_type( overheadLimitPx/((rowWidth > 0) ? rowWidth : Width()) ) ) ); + } + + /*! + * Returns a list of per-thread counts optimized for parallel processing of + * a set of pixel rows. + * + * \param rowCount Number of pixel rows to be processed. If zero or + * a negative value is specified, the height of the image in + * pixels will be used. The default value is zero. + * + * \param rowWidth Width in pixels of the ROI being processed. If + * zero or a negative value is specified, the width of the image + * in pixels is used. The default value is zero. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of processors allowed, which takes + * precedence over the current limit set for this image (see the + * MaxProcessors() and SetMaxProcessors() member functions). If + * zero or a negative value is specified, it is ignored and the + * current MaxProcessors() limit is applied. The default value + * is zero. + * + * \param overheadLimitPx Thread overhead limit in pixels. The function + * will calculate the minimum number of pixel rows that a single + * thread can process, based on this value and on the specified + * \a rowWidth (or the image's width if zero is passed for that + * parameter). The default overhead limit is 1024 pixels. + * + * This function takes into account if parallel processing is currently + * enabled for this image, as well as the maximum number of processors + * allowed for the calling process. + * + * This function returns a dynamic array of unsigned integers, where each + * element is the number of pixel rows that the corresponding thread should + * process in order to make an optimal usage of the processor resources + * currently available. The length of the returned array is the maximum + * number of threads that the calling process should execute concurrently to + * process the specified number of pixel rows, with the specified overhead + * limit and maximum number of processors. + * + * \sa Thread::OptimalThreadLoads() + */ + Array OptimalThreadRows( int rowCount = 0, int rowWidth = 0, int maxProcessors = 0, size_type overheadLimitPx = 1024u ) const noexcept + { + return Thread::OptimalThreadLoads( (rowCount > 0) ? rowCount : Height(), + pcl::Max( size_type( 1 ), size_type( overheadLimitPx/((rowWidth > 0) ? rowWidth : Width()) ) ), + m_parallel ? ((maxProcessors > 0) ? maxProcessors : m_maxProcessors) : 1 ); + } + + // ------------------------------------------------------------------------- + + /*! + * \struct pcl::AbstractImage::ThreadData + * \brief Thread synchronization data for status monitoring of parallel + * image processing tasks. + * + * The %ThreadData structure provides the required objects to synchronize + * the status monitoring task for a set of running threads. An instance of + * %ThreadData (or of a derived class) can be used along with the + * AbstractImage::RunThreads() function to run a set of threads with + * synchronized monitoring and task abortion. + */ + struct ThreadData + { + mutable StatusMonitor status; //!< %Status monitoring object. + mutable Mutex mutex; //!< Mutual exclusion for synchronized thread access. + mutable size_type count = 0; //!< current monitoring count. + size_type total = 0; //!< Total monitoring count. + size_type numThreads = 0; //!< Number of concurrent threads being executed (set by RunThreads()). + + /*! + * Constructs a default %ThreadData object. + */ + ThreadData() = default; + + /*! + * Constructs a %ThreadData object with a copy of the current status + * monitor of the specified \a image, and the specified total monitoring + * count \a N. + * + * If a zero count \a N is specified, the monitor will be initialized as + * an \e unbounded monitor. See the StatusMonitor::Initialize() member + * function for more information. + */ + ThreadData( const AbstractImage& image, size_type N ) + : status( image.Status() ) + , total( N ) + { + } + + /*! + * Constructs a %ThreadData object with a copy of the specified status + * monitor, and the specified total monitoring count \a N. + * + * If a zero count \a N is specified, the monitor will be initialized as + * an \e unbounded monitor. See the StatusMonitor::Initialize() member + * function for more information. + */ + ThreadData( const StatusMonitor& a_status, size_type N ) + : status( a_status ) + , total( N ) + { + } + }; + + /*! + * Runs a set of threads with synchronized status monitoring and task + * abortion. + * + * \param threads Reference to a ReferenceArray container of threads. + * %ReferenceArray contains pointers to objects and allows + * direct iteration and access by reference. It cannot + * contain null pointers. Each %ReferenceArray element + * must be an instance of a derived class of Thread, where + * a reimplemented Thread::Run() member function should + * perform the required parallel processing. + * + * \param data Reference to a ThreadData object for synchronization. + * + * \param useAffinity If (1) this parameter is true, (2) the \a threads + * array contains two or more threads, and (3) this + * function is being called from the root thread (see + * Thread::IsRootThread()), then each thread will be run + * with its affinity set to a single processor (on systems + * that support thread processor affinity). If one or more + * of the three conditions above is false, the thread(s) + * will be run without forcing their processor affinities. + * + * When the \a threads array contains more than one thread, this static + * member function launches the threads in sequence and waits until all + * threads have finished execution. While the threads are running, the + * \c status member of ThreadData is incremented regularly to perform the + * process monitoring task. This also ensures that the graphical interface + * remains responsive during the whole process. + * + * When the \a threads array contains just one thread, this member function + * simply calls the Thread::Run() member function for the unique thread in + * the array, so no additional parallel execution is performed in the + * single-threaded case. If the reimplemented Thread::Run() member function + * uses standard PCL macros to perform the thread monitoring task (see the + * INIT_THREAD_MONITOR() and UPDATE_THREAD_MONITOR() macros), all possible + * situations will be handled correctly and automatically. + * + * For normal execution of multiple concurrent threads with maximum + * performance, the \a useAffinity parameter should be true in order to + * minimize cache invalidations due to processor reassignments of running + * threads. However, there are cases where forcing processor affinities can + * be counterproductive. An example is real-time previewing of intensive + * processes requiring continuous GUI updates. In these cases, disabling + * processor affinity can help to keep the GUI responsive with the required + * granularity. + * + * The threads can be aborted asynchronously with the standard + * Thread::Abort() mechanism, or through StatusMonitor/StatusCallback. If + * one or more threads are aborted, this function destroys all the threads + * by calling ReferenceArray::Destroy(), and then throws a ProcessAborted + * exception. In the single-threaded case, if the reimplemented + * Thread::Run() member function throws an exception, the array is also + * destroyed and the exception is thrown. Otherwise, if all threads complete + * execution normally, the \a threads array is left intact and the function + * returns. The caller is then responsible for destroying the threads when + * appropriate. + * + * \warning For parallel execution of two or more threads, do not call this + * function from a high-priority thread. Doing so can lead to a significant + * performance loss because this function will consume too much processing + * time just for process monitoring. In general, you should call this + * function from normal priority threads. + */ + template + static void RunThreads( ReferenceArray& threads, ThreadData& data, bool useAffinity = true ) + { + if ( threads.IsEmpty() ) + return; + + data.numThreads = threads.Length(); + if ( data.numThreads == 1 ) + { + try + { + threads[0].Run(); + return; + } + catch ( ... ) + { + threads.Destroy(); + throw; + } + } + + if ( useAffinity ) + if ( !Thread::IsRootThread() ) + useAffinity = false; + + { + int n = 0; + for ( thread& t : threads ) + t.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + } + + uint32 waitTime = StatusMonitor::RefreshRate() >> 1; + waitTime += waitTime >> 2; // waitTime = 0.625 * StatusMonitor::RefreshRate() + + for ( size_type lastCount = 0; ; ) + { + for ( typename ReferenceArray::iterator i = threads.Begin(); ; ) + { + if ( !i->Wait( waitTime ) ) + break; + + if ( ++i == threads.End() ) + { + if ( data.total > 0 ) + data.status += data.total - lastCount; + return; + } + } + + if ( data.mutex.TryLock() ) + { + try + { + if ( data.total > 0 ) + { + data.status += data.count - lastCount; + lastCount = data.count; + } + else + ++data.status; + + data.mutex.Unlock(); + } + catch ( ... ) + { + data.mutex.Unlock(); + for ( thread& t : threads ) + t.Abort(); + for ( thread& t : threads ) + t.Wait(); + threads.Destroy(); + throw ProcessAborted(); + } + } + } + } + +protected: + + mutable ImageSelections m_selected; + mutable selection_stack m_savedSelections; + mutable StatusMonitor m_status; + + AbstractImage() = default; + + AbstractImage( const AbstractImage& ) = default; + + AbstractImage& operator =( const AbstractImage& ) = default; + + void Swap( AbstractImage& image ) noexcept + { + ImageGeometry::Swap( image ); + ImageColor::Swap( image ); + ParallelProcess::Swap( image ); + pcl::Swap( m_selected, image.m_selected ); + pcl::Swap( m_savedSelections, image.m_savedSelections ); + pcl::Swap( m_status, image.m_status ); + } + + void ValidateChannelRange() const noexcept + { + if ( m_numberOfChannels > 0 ) + { + if ( m_selected.channel < 0 ) + m_selected.channel = 0; + else if ( m_selected.channel >= m_numberOfChannels ) + m_selected.channel = m_numberOfChannels-1; + + if ( m_selected.lastChannel < 0 ) + m_selected.lastChannel = 0; + else if ( m_selected.lastChannel >= m_numberOfChannels ) + m_selected.lastChannel = m_numberOfChannels-1; + + if ( m_selected.lastChannel < m_selected.channel ) + pcl::Swap( m_selected.channel, m_selected.lastChannel ); + } + else + { + m_selected.channel = m_selected.lastChannel = 0; + } + } + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + friend class pi::SharedImage; +#endif +}; + +// ---------------------------------------------------------------------------- + +#undef m_width +#undef m_height +#undef m_numberOfChannels +#undef m_colorSpace +#undef m_RGBWS + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup thread_monitoring_macros Helper Macros for Synchronized Status \ + * Monitoring of Image Processing Threads + */ + +/*! + * \def INIT_THREAD_MONITOR() + * \brief Declares and initializes local variables used for synchronization of + * thread status monitoring. + * \ingroup thread_monitoring_macros + * + * This macro is intended to be used at the beginning of a reimplemented + * Thread::Run() member function. It declares and initializes some counters + * required to update a status monitoring count with thread synchronization in + * the UPDATE_THREAD_MONITOR macro. + * + * For an example of code using these macros, see UPDATE_THREAD_MONITOR(). + */ +#define INIT_THREAD_MONITOR() \ + size_type ___n___ = 0, ___n1___ = 0; + +/*! + * \def UPDATE_THREAD_MONITOR() + * \brief Synchronized status monitoring of a set of image processing threads. + * \ingroup thread_monitoring_macros + * + * \param N Number of accumulated monitoring counts before performing a + * a synchronized update of the ThreadData monitoring count. A + * larger value will reduce the frequency of monitor updates. A + * value of 64K (65536), equivalent to the number of pixels in a + * square of 256x256 pixels, is quite appropriate for threads that + * process individual pixels. + * + * This macro increments a status monitoring count in a ThreadData member of an + * image processing thread, with thread synchronization. It must be used within + * a reimplemented Thread::Run() member function. + * + * The thread class where this macro is used must have a data member declared + * as follows: + * + * \code AbstractImage::ThreadData& m_data; \endcode + * + * where AbstractImage::ThreadData can be replaced with a suitable derived + * class, e.g. when the thread requires additional data items. + * + * The \c m_data member is a reference to a structure providing the necessary + * objects to perform the synchronized status monitoring task for a set of + * concurrent threads. For more information on synchronized thread monitoring, + * see the AbstractImage::RunThreads() member function. + * + * To use this macro, the INIT_THREAD_MONITOR macro must also be used at the + * begining of the reimplemented Thread::Run() function. + * + * Here is a brief example pseudocode: + * + * \code + * class FooThreadData : public AbstractImage::ThreadData + * { + * ... constructor and additional data members here + * }; + * + * class FooThread : public Thread + * { + * public: + * + * ... constructor and other member functions here + * + * void Run() override + * { + * INIT_THREAD_MONITOR() + * + * for ( int i = m_startRow, i < m_endRow; ++i ) + * { + * for ( int j = 0; j < width; ++j ) + * { + * ... process a single pixel here + * + * // Update monitor every 64K processed pixels. + * UPDATE_THREAD_MONITOR( 65536 ) + * } + * } + * } + * + * private: + * + * FooThreadData& m_data; + * int m_startRow; + * int m_endRow; + * ... other data members here + * }; + * + * ... the code that initializes and runs the threads: + * + * FooThreadData data; + * ... initialize thread data here + * + * ReferenceArray threads; + * ... create and construct the threads here + * + * AbstractImage::RunThreads( threads, data ); + * threads.Destroy(); + * \endcode + * + * For a similar macro that allows incrementing the status monitor by steps + * larger than one unit, see UPDATE_THREAD_MONITOR_CHUNK(). + */ +#define UPDATE_THREAD_MONITOR( N ) \ + if ( ++___n1___ == (N) ) \ + { \ + if ( this->m_data.numThreads > 1 ) \ + { \ + if ( this->TryIsAborted() ) \ + return; \ + ___n___ += (N); \ + if ( this->m_data.total > 0 ) \ + if ( this->m_data.mutex.TryLock() ) \ + { \ + this->m_data.count += ___n___; \ + this->m_data.mutex.Unlock(); \ + ___n___ = 0; \ + } \ + } \ + else \ + { \ + if ( this->m_data.total > 0 ) \ + this->m_data.status += (N); \ + else \ + ++this->m_data.status; \ + } \ + ___n1___ = 0; \ + } + +/*! + * \def UPDATE_THREAD_MONITOR_CHUNK() + * \brief Synchronized status monitoring of a set of image processing threads. + * \ingroup thread_monitoring_macros + * + * This macro is identical to UPDATE_THREAD_MONITOR(), but it updates the + * status monitoring count by successive steps of the specified \a chunkSize. + * + * Typically, this macro is used in situations where the status monitor cannot + * be incremented by single units, due to the complexity of the monitored code + * or to excessive overhead of monitoring count. The difference between this + * macro and %UPDATE_THREAD_MONITOR() can be easily understood with the + * following two examples. In these examples, we show a reimplemented + * Thread::Run() member function in an image processing thread: + * + * Example of code using %UPDATE_THREAD_MONITOR_CHUNK(): + * + * \code + * void Run() override + * { + * INIT_THREAD_MONITOR() + * + * for ( int i = m_startRow, i < m_endRow; ++i ) + * { + * for ( int j = 0; j < width; ++j ) + * { + * ... process a row of pixels here. + * } + * + * // Update every 64K processed pixels, once for each processed row. + * UPDATE_THREAD_MONITOR_CHUNK( 65536, width ) + * } + * } + * \endcode + * + * Example of code using %UPDATE_THREAD_MONITOR(): + * + * \code + * void Run() override + * { + * INIT_THREAD_MONITOR() + * + * for ( int i = m_startRow, i < m_endRow; ++i ) + * { + * for ( int j = 0; j < width; ++j ) + * { + * ... process a single pixel here. + * + * // Update monitor every 64K processed pixels. + * UPDATE_THREAD_MONITOR( 65536 ) + * } + * } + * } + * \endcode + */ +#define UPDATE_THREAD_MONITOR_CHUNK( N, chunkSize ) \ + if ( (___n1___ += (chunkSize)) == (N) ) \ + { \ + if ( this->m_data.numThreads > 1 ) \ + { \ + if ( this->TryIsAborted() ) \ + return; \ + ___n___ += (N); \ + if ( this->m_data.total > 0 ) \ + if ( this->m_data.mutex.TryLock() ) \ + { \ + this->m_data.count += ___n___; \ + this->m_data.mutex.Unlock(); \ + ___n___ = 0; \ + } \ + } \ + else \ + { \ + if ( this->m_data.total > 0 ) \ + this->m_data.status += (N); \ + else \ + ++this->m_data.status; \ + } \ + ___n1___ = 0; \ + } + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AbstractImage_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AbstractImage.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Action.h b/3rdparty/include/pcl/Action.h new file mode 100644 index 0000000..72928f8 --- /dev/null +++ b/3rdparty/include/pcl/Action.h @@ -0,0 +1,586 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Action.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_Action_h +#define __PCL_Action_h + +/// \file pcl/Action.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ActionInfo + * \brief Provides information about the current state of the core + * application's GUI to module-defined actions. + * + * This structure is passed to the Action::IsEnabled() virtual member function. + * See the description of Action::IsEnabled() for more information. + * + * \sa Action + */ +struct ActionInfo +{ + bool isImage : 1; //!< true if there is an active image window and it is not read-locked + bool isCurrentPreview : 1; //!< true if the active view is a preview + bool isColor : 1; //!< true if the active view is a color image; false if it is grayscale + int : 5; // reserved for future use, should be zero + uint8 bitsPerSample : 8; //!< number of bits per sample in the active view's image + bool isFloatSample : 1; //!< true if the active view's image is in floating-point format + bool hasPreviews : 1; //!< true if the active image window has one or more previews defined + bool hasMask : 1; //!< true if the active image window is masked + bool thereAreImages : 1; //!< true if there are one or more image windows currently open + int : 12; // reserved for future use, should be zero +}; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class Action + * \brief Client-side interface to a PixInsight module-defined action object. + * + * Module-defined actions manage integration of external processes and tools + * with the main menu and tool bars of the PixInsight core application. + * + * Integration of actions is governed by two main properties: menu item and + * tool bar. + * + * Menu Item + * + * This is a string indicating a menu item where an action will be integrated + * within the PixInsight's main menu structure. + * + * The menu item string describes a path on PixInsight's main menu structure. + * Multiple menu items can be specified, separated with the ">" character. + * + * If this parameter is an empty string, the newly created action won't be + * integrated with the main menu. This can be useful for actions that only + * respond to keyboard accelerators, or actions that only integrate with tool + * bars (see the Tool Bar section below). + * + * Integrating actions into existing top-level main menu items + * + * "Image >> Geometry > Rotate 180 degrees" + * "View > Memory Status" + * + * The above strings will integrate actions into existing top-level main menu + * items (Image and View, respectively). In the first example, a submenu + * entitled "Geometry" will be created under the Image top-level menu item, if + * it doesn't exist yet. The sequence '>>' can be used to insert a separator + * menu item, as has been done before "Geometry" in the example above. Then a + * new item "Rotate 180 degrees" will be created and associated to the + * corresponding action. Note that in this case the PixInsight core application + * decides where exactly new actions are inserted within existing menu items, + * applying different criteria for each menu. In general, in these cases new + * actions are inserted on a per-module basis, in strict order of creation. + * + * Creating custom top-level main menu items + * + * Custom main menu top-level entries can also be created. For example, the + * following menu item string: + * + * "MyTools > Color Tools > A better color saturation process" + * + * Will create a new custom "MyTools" top-level item in the main menu, if it + * doesn't already exist. Custom top-level main menu items are inserted after + * the standard Process menu item, in strict order of creation. Common sense + * and care must be observed when creating custom top-level menu items. If + * possible, it is always preferable to integrate actions into existing + * top-level items; one must be motivated by a really strong reason to create a + * custom menu. + * + * Tool Bar + * + * This is an optional parameter. This is the name of a tool bar where the + * action will be integrated. + * + * If this string is empty, the action will not be integrated in a tool bar. + * Otherwise, the string must be the name of a tool bar where a new tool button + * will be created and associated to the action. + * + * A standard tool bar name can be used (i.e. View, File, and so on). If the + * specified name does not correspond to an existing tool bar, a new, custom + * tool bar will be created, and a new tool button corresponding to this action + * will be added to it. + * + * The specified tool bar name can start with a ">" character to insert a tool + * bar separator (a vertical or horizontal line, depending on the tool bar's + * orientation) before the newly created tool button. + */ +class PCL_CLASS Action : public UIObject +{ +public: + + /*! + * Constructs a new %Action object. + * + * \param menuItem Specifies the menu item that will be associated with + * this action. + * + * \param iconSVGFile Path to an existing file in the local file system, + * which must store a valid SVG document defining the icon + * image that will be associated with this action. The SVG + * source code must be encoded in UTF-8. The icon will be + * used for menu items and tool bar buttons associated + * with this action. If this parameter is not specified, + * or if the specified SVG document does not exist, is not + * valid, or cannot be rendered, no icon will be used to + * represent this action. + * + * \param toolBar The name of a tool bar where this action will be + * integrated. If this parameter is not specified, the + * action will not be integrated in a tool bar. + * + * Automatic Resource Location + * + * The specified \a iconSVGFile string can be prefixed with the + * "@module_icons_dir/" special token to let the PixInsight core application + * load the corresponding SVG document automatically from the a standard + * distribution directory. See the documentation for + * MetaProcess::IconImageSVGFile() for complete information. + * + * To learn how the menu item and tool bar parameters work for actions, see + * the description of the Action class. + */ + Action( const String& menuItem, + const String& iconSVGFile = String(), const String& toolBar = String() ); + + /*! + * Constructs a new %Action object. + * + * \param menuItem Specifies the menu item that will be associated with + * this action. + * + * \param iconSVGsource The source code of a valid SVG document defining + * the icon image that will be associated with this + * action. The SVG source code must be encoded in UTF-8. + * The icon will be used for all menu items and tool bar + * buttons associated with this action. If this parameter + * is not specified, or if the specified SVG document is + * not valid or cannot be rendered, no icon will be used + * to represent this action. + * + * \param toolBar The name of a tool bar where this action will be + * integrated. If this parameter is not specified, the + * action will not be integrated in a tool bar. + * + * \note The unused third \c int parameter serves to distinguish this + * constructor from the other one that takes a file path argument. This is + * necessary because both String and IsoString can be constructed from + * literal \c const \c char* arguments. + * + * To learn how the menu item and tool bar parameters work for actions, see + * the description of the Action class. + */ + Action( const String& menuItem, + const IsoString& iconSVGSource, int, const String& toolBar = String() ); + +#ifdef __PCL_ACTION_DEPRECATED_CTOR + + /*! + * Constructs a new %Action object. + * + * \param menuItem Specifies the menu item that will be associated with + * this action. + * + * \param icon A Bitmap object representing the icon image that will + * be associated with this action. The icon will be used + * for menu items and tool bar buttons. If this parameter + * is not specified, no menu icon will be used and a + * default icon will be assigned automatically for tool + * bar buttons, if necessary. + * + * \param toolBar The name of a tool bar where this action will be + * integrated. If this parameter is not specified, the + * action will not be integrated in a tool bar. + * + * To learn how the menu item and tool bar parameters work for actions, see + * the description of the Action class. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use the constructors that define icon images + * in SVG format. Existing modules should also be refactored in the same way + * to support scalable icons. + */ + Action( const String& menuItem, + const Bitmap& icon, const String& toolBar = String() ); + +#endif // __PCL_ACTION_DEPRECATED_CTOR + + /*! + * Move constructor. + */ + Action( Action&& x ) : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys this %Action object. + * + * This destructor does not destroy the actual action object, which is part + * of the PixInsight core application. Only the managed alias object living + * in the caller module is destroyed. + */ + virtual ~Action() + { + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Action& operator =( Action&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since actions are unique objects, calling this member function has no + * effect. + */ + void EnsureUnique() override + { + } + + /*! + * Returns a reference to a null %Action instance. A null %Action does not + * correspond to an existing action in the PixInsight core application. + */ + static Action& Null(); + + /*! + * Returns the menu item where this action has been integrated in the main + * menu of the PixInsight core application. + * + * An action's menu item is a read-only property: its value can only be set + * with the constructor. In other words: Once an action has been created, + * its menu text can be freely changed, but it cannot be moved in the main + * menu structure. + * + * \sa MenuText() + */ + String MenuItem() const; + + /*! + * Returns the text of the menu item where this action has been integrated + * in the main menu of the PixInsight core application. + * + * \sa SetMenuText(), MenuItem() + */ + String MenuText() const; + + /*! + * Changes the text of the menu item where this action has been integrated + * in the main menu of the PixInsight core application. + * + * \param text A string representing the new menu text for this action + * object. + * + * \sa MenuText() + */ + void SetMenuText( const String& text ); + + /*! + * Returns the name of a tool bar where this action has been integrated in + * the PixInsight core application. + * + * Integration of actions with tool bars is optional. If this action has not + * been integrated in a tool bar, this function returns an empty string. + * + * An action's tool bar is a read-only property whose value can only be set + * with the constructor. + * + * \sa SetToolBar() + */ + String ToolBar() const; + + /*! + * Obtains the optional keyboard accelerator associated to this action. + * + * \param[out] keyModifiers Specifies an OR'ed combination of the Shift, + * Control and Alt keys. Use the KeyModifier namespace, defined + * in the pcl/ButtonCodes.h header, to decode this value. + * + * \param[out] keyCode Any valid PCL key code, except those codes + * corresponding to modifier keys or system-managed keys. Use + * the KeyCode namespace, defined in the pcl/KeyCodes.h header, + * to decode the returned value. + * + * If no keyboard accelerator has been associated to this action, zero is + * returned for both parameters. + * + * \sa SetAccelerator(), HasAccelerator(), RemoveAccelerator() + */ + void GetAccelerator( int& keyModifiers, int& keyCode ) const; + + /*! + * Changes the keyboard accelerator associated to this action. + * + * \param keyModifiers An OR'ed combination of the Shift, Control and + * Alt keys. Use the KeyModifier namespace, defined in the + * pcl/ButtonCodes.h header, to build this value. + * + * \param keyCode A valid PCL key code, except those codes + * corresponding to modifier keys or system-managed keys. Use + * the KeyCode namespace, defined in the pcl/KeyCodes.h header, + * to build this value. If this parameter is zero, no keyboard + * accelerator will be associated to this action. + * + * \sa GetAccelerator(), HasAccelerator(), RemoveAccelerator() + */ + void SetAccelerator( int keyModifiers, int keyCode ); + + /*! + * Returns true iff this action has an associated keyboard accelerator. + * + * \sa GetAccelerator(), SetAccelerator(), RemoveAccelerator() + */ + bool HasAccelerator() const + { + int dum, key; GetAccelerator( dum, key ); return key != 0; + } + + /*! + * Clears (deactivates) the keyboard accelerator associated to this action, + * if any. This is an overloaded function, provided for convenience. It + * is equivalent to SetAccelerator( 0, 0 ). + * + * \sa GetAccelerator(), SetAccelerator(), HasAccelerator() + */ + void RemoveAccelerator() + { + SetAccelerator( 0, 0 ); + } + + /*! + * Returns the tool tip text that has been assigned to this action. Tool + * tips are used for tool buttons corresponding to the integration of + * actions in tool bars. + * + * If this action has not been integrated in a tool bar, this function has + * no meaning, and an empty string is always returned. + * + * \sa SetToolTip() + */ + String ToolTip() const; + + /*! + * Changes the tool tip text for this action. Tool tips are used for tool + * buttons corresponding to the integration of actions in tool bars. + * + * \param tip A string that represents the new tool tip text for this + * action object. + * + * If this action has not been integrated in a tool bar, this function is + * ignored. + * + * \sa ToolTip() + */ + void SetToolTip( const String& tip ); + + /*! + * Returns a Bitmap corresponding to the icon that has been assigned to + * this action object. %Action icons are used to render the associated menu + * items and tool bar buttons. + * + * If no icon has been associated to this object, a null Bitmap object is + * returned. + * + * \sa SetIcon() + */ + Bitmap Icon() const; + + /*! + * Changes the icon associated with this %Action to an image specified in + * SVG format. + * + * \param svgSource The source code of a valid SVG document defining the + * icon image that will be associated with this action. + * The SVG source code must be encoded in UTF-8. + * + * The new icon will be used for all menu items and tool bar buttons + * associated with this action after calling this function. If an empty + * string is specified, or if the specified SVG document is not valid, no + * icon will be used to represent this action. + * + * \sa SetIconSVGFile() + */ + void SetIconSVG( const IsoString& svgSource ); + + /*! + * Changes the icon associated with this %Action to an image specified in + * SVG format. + * + * \param filePath Path to an existing file in the local file system, + * which must store a valid SVG document representing the + * icon image that will be associated with this action. + * The SVG source code must be encoded in UTF-8. + * + * The new icon will be used for all menu items and tool bar buttons + * associated with this action after calling this function. If an empty + * string is specified, or if the specified SVG document does not exist or + * is not valid, no icon will be used to represent this action. + * + * Automatic Resource Location + * + * The specified \a filePath string can be prefixed with the + * "@module_icons_dir/" special token to let the PixInsight core application + * load the corresponding SVG document automatically from the a standard + * distribution directory. See the documentation for + * MetaProcess::IconImageSVGFile() for complete information. + * + * \sa SetIconSVG() + */ + void SetIconSVGFile( const String& filePath ); + + /*! + * Changes the icon associated with this %Action object. + * + * \param icon The new icon Bitmap that will be assigned to this %Action. + * + * The new icon will be used for all menu items and tool bar buttons + * associated with this action after calling this function. If a null bitmap + * is specified, no icon will be used to represent this action. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use the SetIconSVG() or SetIconSVGFile() + * member functions, which define action icon images in SVG format. Existing + * modules should be refactored in the same way to support scalable icons. + * + * \sa Icon() + */ + void SetIcon( const Bitmap& icon ); + + /*! + * Callback routine for this action. This function will be called each time + * this action is activated, either by selecting the associated menu item or + * by clicking the corresponding tool button. + * + * Despite this function has not been formalized as a pure virtual function, + * it is such conceptually, so it must be always reimplemented in descendant + * classes. + */ + virtual void Execute(); + + /*! + * Returns the current \e enabled \e state of this %Action object. + * + * Disabled actions have their associated menu items and tool bar buttons + * disabled, and cannot be activated by the user. + * + * The PixInsight application will call this function repeatedly to learn + * the current state of this action, with the purpose of keeping the + * associated interface elements up-to-date. + * + * The caller of this function is a specialized idle-priority thread that is + * permanently running in the background. This means that this function will + * not be executed in the core application's main GUI thread, so all code in + * this function must be thread-safe. Reimplementations of this function in + * derived classes should decide the action's current state and return as + * quickly as possible. + * + * An ActionInfo structure is passed to this function, describing the + * current state of the user interface. That description should be used by + * the IsEnabled() function to decide whether this action should be enabled + * or disabled, depending on the current interface context. + * + * \note The default implementation of this function always returns true, + * regardless of the current context. This means that all actions are + * enabled by default. + * + * \sa ActionInfo + */ + virtual bool IsEnabled( ActionInfo info ) const + { + return true; + } + +private: + + Action( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Action_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Action.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AdaptiveLocalFilter.h b/3rdparty/include/pcl/AdaptiveLocalFilter.h new file mode 100644 index 0000000..28b4413 --- /dev/null +++ b/3rdparty/include/pcl/AdaptiveLocalFilter.h @@ -0,0 +1,216 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AdaptiveLocalFilter.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_AdaptiveLocalFilter_h +#define __PCL_AdaptiveLocalFilter_h + +/// \file pcl/AdaptiveLocalFilter.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class AdaptiveLocalFilter + * \brief Adaptive, local noise reduction filter in the spatial domain. + * + * Implementation of the adaptive, local noise reduction filter in the spatial + * domain as described by González and Woods. + * + * References + * + * R.C. González and R.E. Woods, Digital %Image Processing, Third + * Edition, Pearson / Prentice Hall, 2008. pp 330-332. + */ +class PCL_CLASS AdaptiveLocalFilter : public ImageTransformation, + public ParallelProcess +{ +public: + + /*! + * Constructs an %AdaptiveLocalFilter instance. + * + * \param sigma Standard deviation or median absolute deviation from the + * median (MAD) of the noise (see the \a useMAD parameter). + * If the MAD is used, the specified \a sigma value must be + * consistent with the standard deviation of a normal + * distribution (typically, the computed MAD estimate must be + * multiplied by 1.4826). + * + * \param size Filter size in pixels. This is the length of a side of the + * square pixel neighborhood used by the adaptive filter. The + * filter size must be an odd number greater than or equal to + * three. If an even size is specified, the smallest odd size + * greater than the specified value will be used. The default + * size is five pixels. + * + * \param useMAD If true, use the median absolute deviation from the median + * (MAD) instead of variance / standard deviation for noise + * estimates. Note that this changes the meaning of the + * \a sigma parameter. The default value is false (variance + * is used by default). + */ + AdaptiveLocalFilter( double sigma, int size = 5, bool useMAD = false ) + : m_size( Max( 3, size|1 ) ) + , m_sigma( Max( 0.0, sigma ) ) + , m_useMAD( useMAD ) + { + } + + /*! + * Copy constructor. + */ + AdaptiveLocalFilter( const AdaptiveLocalFilter& ) = default; + + /*! + * Destroys this %AdaptiveLocalFilter object. + */ + virtual ~AdaptiveLocalFilter() + { + } + + /*! + * Returns the filter size in pixels. + */ + int Size() const + { + return m_size; + } + + /*! + * Sets the filter \a size in pixels. + */ + void SetSize( int size ) + { + PCL_PRECONDITION( size >= 3 ) + PCL_PRECONDITION( (size & 1) != 0 ) + m_size = Max( 3, size|1 ); + } + + /*! + * Returns the standard deviation or median absolute deviation from the + * median (MAD) of the noise in this adaptive filter. + * + * The meaning of the returned value depends on whether this filter uses + * variance or MAD for noise estimates --see the UsingMAD() member function + * and the class constructor for more information. + */ + double Sigma() const + { + return m_sigma; + } + + /*! + * Sets the standard deviation or median absolute deviation from the median + * (MAD) of the noise in this adaptive filter. The specified \a sigma must + * be a positive, nonzero value (a zero noise value is legal, but the filter + * will obviously have no effect). + * + * The meaning of the specified \a sigma value depends on whether this + * filter uses variance or MAD for noise estimates--see the UsingMAD() + * member function and the class constructor for more information. + */ + void SetSigma( double sigma ) + { + PCL_PRECONDITION( sigma >= 0 ) + m_sigma = Max( 0.0, sigma ); + } + + /*! + * Returns true iff this adaptive filter uses median absolute deviation (MAD) + * instead of variance / standard deviation to interpret noise estimates. + */ + bool UsingMAD() const + { + return m_useMAD; + } + + /*! + * Sets the way this adaptive filter interprets noise estimates: either as + * the median absolute deviation from the median (MAD) or as the standard + * deviation of the noise in the target image. + */ + void UseMAD( bool useMAD = true ) + { + m_useMAD = useMAD; + } + +protected: + + int m_size; // filter size in pixels. + double m_sigma = 5; // standard deviation of the noise in the target image. + bool m_useMAD = false; // use MAD instead of variance / standard deviation. + + /* + * Adaptive local filter in the spatial domain. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AdaptiveLocalFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AdaptiveLocalFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AkimaInterpolation.h b/3rdparty/include/pcl/AkimaInterpolation.h new file mode 100644 index 0000000..dd4cdd9 --- /dev/null +++ b/3rdparty/include/pcl/AkimaInterpolation.h @@ -0,0 +1,322 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AkimaInterpolation.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_AkimaInterpolation_h +#define __PCL_AkimaInterpolation_h + +/// \file pcl/AkimaInterpolation.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_x this->m_x +#define m_y this->m_y + +/*! + * \class AkimaInterpolation + * \brief Akima subspline interpolation algorithm + * + * References + * + * Hiroshi Akima, A new method of interpolation and smooth curve fitting + * based on local procedures, Journal of the ACM, Vol. 17, No. 4, October + * 1970, pages 589-602. + * + * Implementation + * + * Our implementation is based on the book Numerical Algorithms with + * C, by G. Engeln-Mullges and F. Uhlig (Springer, 1996), section 13.1. + * + * We properly represent corners when a data point lies between two adjacent + * straight lines with different slopes. This means that our implementation + * does not impose continuous differentiability, which deviates from the + * original work by Akima. Supporting the accurate representation of corners + * has several practical advantages in our opinion; one of them is the enhanced + * flexibility for the application of Akima interpolation to graphical + * representations of curves given by a set of prescribed x,y data points. + * + * \sa CubicSplineInterpolation, LinearInterpolation + */ +template +class PCL_CLASS AkimaInterpolation : public UnidimensionalInterpolation +{ +public: + + /*! + * Represents a vector of independent and dependent variable values. + */ + typedef typename UnidimensionalInterpolation::vector_type vector_type; + + /*! + * Represents a vector of interpolation coefficients. + */ + typedef vector_type coefficient_vector; + + /*! + * Constructs an %AkimaInterpolation object. + */ + AkimaInterpolation() = default; + + /*! + * Copy constructor. + */ + AkimaInterpolation( const AkimaInterpolation& ) = default; + + /*! + * Move constructor. + */ + AkimaInterpolation( AkimaInterpolation&& ) = default; + + /*! + * Destroys an %AkimaInterpolation object. + */ + virtual ~AkimaInterpolation() + { + } + + /*! + * Initializes a new interpolation. + * + * \param x %Vector of x-values:\n + * \n + * \li If x is not empty: Must be a vector of monotonically increasing, + * distinct values: x[0] < x[1] < ... < x[n-1].\n + * \li If x is empty: The interpolation will use implicit x[i] = i for + * i = {0,1,...,n-1}.\n + * + * \param y %Vector of function values for i = {0,1,...,n-1}. + * + * The length of the \a y vector (and also the length of a nonempty \a x + * vector) must be \e n >= 5. This is because Akima interpolation requires + * at least 4 subintervals. + */ + void Initialize( const vector_type& x, const vector_type& y ) override + { + if ( y.Length() < 5 ) + throw Error( "AkimaInterpolation::Initialize(): Less than five data points specified." ); + + try + { + Clear(); + UnidimensionalInterpolation::Initialize( x, y ); + + int n = m_y.Length(); + int N = n-1; // Number of subintervals + + m_b = coefficient_vector( N ); + m_c = coefficient_vector( N ); + m_d = coefficient_vector( N ); + + // Chordal slopes + coefficient_vector m0( N+4 ); // room for 4 additional prescribed slopes + T* m = m0.At( 2 ); // allow negative subscripts m[-1] and m[-2] + + // Akima left-hand slopes to support corners + coefficient_vector tL( n ); + + // Calculate chordal slopes for each subinterval + if ( m_x ) + for ( int i = 0; i < N; ++i ) + { + T h = m_x[i+1] - m_x[i]; + if ( 1 + h*h == 1 ) + throw Error( "AkimaInterpolation::Initialize(): Empty interpolation subinterval(s)." ); + m[i] = (m_y[i+1] - m_y[i])/h; + } + else + for ( int i = 0; i < N; ++i ) + m[i] = m_y[i+1] - m_y[i]; + + // Prescribed slopes at ending locations + m[-2 ] = 3*m[ 0] - 2*m[ 1]; + m[-1 ] = 2*m[ 0] - m[ 1]; + m[ N ] = 2*m[N-1] - m[N-2]; + m[N+1] = 3*m[N-1] - 2*m[N-2]; + + /* + * Akima left-hand and right-hand slopes. + * Right-hand slopes are just the interpolation coefficients bi. + */ + for ( int i = 0; i < n; ++i ) + { + T f = Abs( m[i-1] - m[i-2] ); + T e = Abs( m[i+1] - m[i] ) + f; + if ( 1 + e != 1 ) + { + tL[i] = m[i-1] + f*(m[i] - m[i-1])/e; + if ( i < N ) + m_b[i] = tL[i]; + } + else + { + tL[i] = m[i-1]; + if ( i < N ) + m_b[i] = m[i]; + } + } + + /* + * Interpolation coefficients m_b[i], m_c[i], m_d[i]. 'ai' + * coefficients are the m_y[i] ordinate values. + */ + for ( int i = 0; i < N; ++i ) + { + m_c[i] = 3*m[i] - 2*m_b[i] - tL[i+1]; + m_d[i] = m_b[i] + tL[i+1] - 2*m[i]; + + if ( m_x ) + { + T h = m_x[i+1] - m_x[i]; + m_c[i] /= h; + m_d[i] /= h*h; + } + } + } + catch ( ... ) + { + Clear(); + throw; + } + } + + /*! + * Returns an interpolated function value at \a x location. + */ + PCL_HOT_FUNCTION + double operator()( double x ) const override + { + PCL_PRECONDITION( IsValid() ) + + /* + * Find the subinterval i0 such that m_x[i0] <= x < m_x[i0+1]. + * Find the distance dx = x - m_x[i], or dx = x - i for implicit x = {0,1,...n-1}. + */ + int i0; + double dx; + if ( m_x ) + { + i0 = 0; + int i1 = m_x.Length() - 1; + while ( i1-i0 > 1 ) + { + int im = (i0 + i1) >> 1; + if ( x < m_x[im] ) + i1 = im; + else + i0 = im; + } + dx = x - double( m_x[i0] ); + } + else + { + if ( x <= 0 ) + return m_y[0]; + if ( x >= m_y.Length()-1 ) + return m_y[m_y.Length()-1]; + i0 = TruncInt( x ); + dx = x - i0; + } + + /* + * Use a Horner scheme to calculate b[i]*dx + c[i]*dx^2 + d[i]*dx^3. + */ + return m_y[i0] + dx*(m_b[i0] + dx*(m_c[i0] + dx*m_d[i0])); + } + + /*! + * Frees internal data structures in this AkimaInterpolation object. + */ + void Clear() override + { + m_b.Clear(); + m_c.Clear(); + m_d.Clear(); + UnidimensionalInterpolation::Clear(); + } + + /*! + * Returns true iff this interpolation is valid, i.e. if it has been + * correctly initialized and is ready to interpolate function values. + */ + bool IsValid() const override + { + return m_b && m_c && m_d; + } + +protected: + + /* + * Interpolating coefficients for each subinterval. + * The coefficients for dx^0 are the input ordinate values in the m_y vector. + */ + coefficient_vector m_b; // coefficients for dx^1 + coefficient_vector m_c; // coefficients for dx^2 + coefficient_vector m_d; // coefficients for dx^3 +}; + +#undef m_x +#undef m_y + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AkimaInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AkimaInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Algebra.h b/3rdparty/include/pcl/Algebra.h new file mode 100644 index 0000000..40493e1 --- /dev/null +++ b/3rdparty/include/pcl/Algebra.h @@ -0,0 +1,659 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Algebra.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_Algebra_h +#define __PCL_Algebra_h + +/// \file pcl/Algebra.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup in_place_gauss_jordan In-Place Gauss-Jordan Solvers + */ + +/*! + * Solution to the linear system A*X = B + * + * On output, A is replaced by its inverse matrix and B is the set of solution + * vectors X. + * + * This is an overloaded function for the Matrix type, which is a template + * instantiation of GenericMatrix for double. + * + * \ingroup in_place_gauss_jordan + */ +void PCL_FUNC InPlaceGaussJordan( Matrix& A, Matrix& B ); + +/*! + * Solution to the linear system A*X = B + * + * On output, A is replaced by its inverse matrix and B is the set of solution + * vectors X. + * + * This is an overloaded function for the FMatrix type, which is a template + * instantiation of GenericMatrix for float. + * + * \ingroup in_place_gauss_jordan + */ +void PCL_FUNC InPlaceGaussJordan( FMatrix& A, FMatrix& B ); + +/*! + * \class GenericGaussJordan + * \brief Generic Gauss-Jordan linear system solver. + */ +template +class PCL_CLASS GenericGaussJordan +{ +public: + + /*! + * Represents a matrix involved in the solution of a linear system. + */ + typedef GenericMatrix matrix; + + /*! + * Represents a matrix element. + */ + typedef typename matrix::element matrix_element; + + /*! + * Inverse matrix + */ + matrix Ai; // Inverse matrix + + /*! + * Solution vectors + */ + matrix X; // Solution vectors + + /*! + * Solution to the linear system A*X = B + * + * This constructor replaces the Ai member of this object with the inverse + * matrix of \a A, and the X member with the set of solution vectors. + */ + GenericGaussJordan( const matrix& A, const matrix& B ) + { + Ai = A; + X = B; + InPlaceGaussJordan( Ai, X ); + } +}; + +/*! + * \class GaussJordan + * \brief Gauss-Jordan linear system solver for Matrix objects. + * + * %GaussJordan is a template instantiation of GenericGaussJordan for the + * double type. %GaussJordan works with Matrix objects. %Matrix is a template + * instantiation of GenericMatrix for double. + */ +class PCL_CLASS GaussJordan : public GenericGaussJordan +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericGaussJordan algorithm_implementation; + + /*! + * Represents a matrix involved in the solution of a linear system. + */ + typedef algorithm_implementation::matrix matrix; + + /*! + * Represents a matrix element. + */ + typedef matrix::element matrix_element; + + /*! + * Solution to the linear system A*X = B + * + * This constructor replaces the Ai member of this object with the inverse + * matrix of \a A, and the X member with the set of solution vectors. + */ + GaussJordan( const Matrix& A, const Matrix& B ) + : algorithm_implementation( A, B ) + { + } +}; + +/*! + * \class FGaussJordan + * \brief Gauss-Jordan linear system solver for FMatrix objects. + * + * %FGaussJordan is a template instantiation of GenericGaussJordan for the + * float type. %FGaussJordan works with FMatrix objects. %FMatrix is a template + * instantiation of GenericMatrix for float. + */ +class PCL_CLASS FGaussJordan : public GenericGaussJordan +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericGaussJordan algorithm_implementation; + + /*! + * Represents a matrix involved in the solution of a linear system. + */ + typedef algorithm_implementation::matrix matrix; + + /*! + * Represents a matrix element. + */ + typedef matrix::element matrix_element; + + /*! + * Solution to the linear system A*X = B + * + * This constructor replaces the Ai member of this object with the inverse + * matrix of \a A, and the X member with the set of solution vectors. + */ + FGaussJordan( const FMatrix& A, const FMatrix& B ) + : algorithm_implementation( A, B ) + { + } +}; + +// ---------------------------------------------------------------------------- + +void PCL_FUNC InPlaceSVDImplementation( Matrix&, Vector&, Matrix& ); +void PCL_FUNC InPlaceSVDImplementation( FMatrix&, FVector&, FMatrix& ); + +/*! + * \class GenericInPlaceSVD + * \brief Generic in-place singular value decomposition algorithm. + */ +template +class PCL_CLASS GenericInPlaceSVD +{ +public: + + /*! + * Represents a vector involved in a singular value decomposition. + */ + typedef GenericVector vector; + + /*! + * Represents a matrix involved in a singular value decomposition. + */ + typedef GenericMatrix matrix; + + /*! + * Represents a vector component. + */ + typedef typename vector::component vector_component; + + /*! + * Represents a matrix element. + */ + typedef typename matrix::element matrix_element; + + /*! + * The components of this vector are the m (positive) diagonal elements of + * the matrix W in a singular value decomposition A=U*W*Vt. m is the number + * of columns in the decomposed matrix A. + */ + vector W; + + /*! + * Each column of this m x m matrix is the eigenvector for the corresponding + * element of W in a singular value decomposition A=U*W*Vt. m is the number + * of columns in the decomposed matrix A. + */ + matrix V; + + /*! + * Singular Value Decomposition: A = U*W*Vt + * + * The dimensions of A are n rows and m columns. U is an n x m matrix. The m + * components of W are the positive diagonal elements of W, and each column + * of V (m x m) is the eigenvector for the corresponding element of W. + * + * On output, this constructor replaces the specified matrix \a A with the + * matrix U that results from the SVD decomposition (indeed that's why this + * is an in-place decomposition). W and V are stored in the corresponding + * members of this object. + */ + GenericInPlaceSVD( matrix& A ) + : W( A.Columns() ) + , V( A.Columns(), A.Columns() ) + { + InPlaceSVDImplementation( A, W, V ); + } + + /*! + * Returns the column index of the largest eigenvector in matrix V. This is + * the index of the largest component of vector W. + */ + int IndexOfLargestSingularValue() const + { + return W.IndexOfLargestComponent(); + } + + /*! + * Returns the column index of the smallest eigenvector in matrix V. This is + * the index of the smallest nonzero component of vector W. + * + * Before calling this function, you should edit the components of vector W + * to set to zero all singular values below a suitable tolerance. For + * example, using the machine epsilon: + * + * \code + * Matrix A; + * ... + * InPlaceSVD svd( A ); + * for ( int i = 0; i < svd.W.Length(); ++i ) + * if ( 1 + svd.W[i] == 1 ) + * svd.W[i] = 0; + * int i = svd.IndexOfSmallestSingularValue(); + * ... + * \endcode + */ + int IndexOfSmallestSingularValue() const + { + return W.IndexOfSmallestNonzeroComponent(); + } +}; + +/*! + * \class InPlaceSVD + * \brief In-place singular value decomposition algorithm for Matrix and Vector objects. + * + * %InPlaceSVD is a template instantiation of GenericInPlaceSVD for the double + * type. %InPlaceSVD works with Matrix and Vector objects. %Matrix and %Vector + * are template instantiations of GenericMatrix and GenericVector, + * respectively, for the double type. + */ +class PCL_CLASS InPlaceSVD : public GenericInPlaceSVD +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericInPlaceSVD algorithm_implementation; + + /*! + * Represents a vector involved in a singular value decomposition. + */ + typedef algorithm_implementation::vector vector; + + /*! + * Represents a matrix involved in a singular value decomposition. + */ + typedef algorithm_implementation::matrix matrix; + + /*! + * Represents a vector component. + */ + typedef vector::component vector_component; + + /*! + * Represents a matrix element. + */ + typedef matrix::element matrix_element; + + /*! + * Singular Value Decomposition: A = U*W*Vt + * + * The dimensions of A are n rows and m columns. U is an n x m matrix. The m + * components of W are the positive diagonal elements of W, and each column + * of V (m x m) is the eigenvector for the corresponding element of W. + * + * On output, this constructor replaces the specified matrix \a A with the + * matrix U that results from the SVD decomposition (indeed that's why this + * is an in-place decomposition). W and V are stored in the corresponding + * members of this object. + */ + InPlaceSVD( matrix& A ) + : algorithm_implementation( A ) + { + } +}; + +/*! + * \class FInPlaceSVD + * \brief In-place singular value decomposition algorithm for FMatrix and FVector objects. + * + * %FInPlaceSVD is a template instantiation of GenericInPlaceSVD for the float + * type. %FInPlaceSVD works with FMatrix and FVector objects. %FMatrix and + * %FVector are template instantiations of GenericMatrix and GenericVector, + * respectively, for the float type. + */ +class PCL_CLASS FInPlaceSVD : public GenericInPlaceSVD +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericInPlaceSVD algorithm_implementation; + + /*! + * Represents a vector involved in a singular value decomposition. + */ + typedef algorithm_implementation::vector vector; + + /*! + * Represents a matrix involved in a singular value decomposition. + */ + typedef algorithm_implementation::matrix matrix; + + /*! + * Represents a vector component. + */ + typedef vector::component vector_component; + + /*! + * Represents a matrix element. + */ + typedef matrix::element matrix_element; + + /*! + * Singular Value Decomposition: A = U*W*Vt + * + * The dimensions of A are n rows and m columns. U is an n x m matrix. The m + * components of W are the positive diagonal elements of W, and each column + * of V (m x m) is the eigenvector for the corresponding element of W. + * + * On output, this constructor replaces the specified matrix \a A with the + * matrix U that results from the SVD decomposition (indeed that's why this + * is an in-place decomposition). W and V are stored in the corresponding + * members of this object. + */ + FInPlaceSVD( matrix& A ) + : algorithm_implementation( A ) + { + } +}; + +/*! + * \class GenericSVD + * \brief Generic singular value decomposition algorithm. + */ +template +class PCL_CLASS GenericSVD +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericInPlaceSVD algorithm_implementation; + + /*! + * Represents a vector involved in a singular value decomposition. + */ + typedef typename algorithm_implementation::vector vector; + + /*! + * Represents a matrix involved in a singular value decomposition. + */ + typedef typename algorithm_implementation::matrix matrix; + + /*! + * Represents a vector component. + */ + typedef typename vector::component vector_component; + + /*! + * Represents a matrix element. + */ + typedef typename matrix::element matrix_element; + + /*! + * This is the n x m matrix resulting from the singular value decomposition + * A = U*W*Vt. n and m are the rows and columns of the decomposed matrix A. + */ + matrix U; + + /*! + * The components of this vector are the m (positive) diagonal elements of + * the matrix W in a singular value decomposition A = U*W*Vt. m is the + * number of columns in the decomposed matrix A. + */ + vector W; + + /*! + * Each column of this m x m matrix is the eigenvector for the corresponding + * element of W in a singular value decomposition A = U*W*Vt. m is the + * number of columns in the decomposed matrix A. + */ + matrix V; + + /*! + * Singular Value Decomposition: A = U*W*Vt + * + * The dimensions of A are n rows and m columns. U is an n x m matrix. The m + * components of W are the positive diagonal elements of W, and each column + * of V (m x m) is the eigenvector for the corresponding element of W. + * + * On output, this constructor stores U, W and V in the corresponding + * members of this object. + */ + GenericSVD( const matrix& A ) + { + U = A; + algorithm_implementation svd( U ); + W = svd.W; + V = svd.V; + } + + /*! + * Returns the column index of the largest eigenvector in matrix V. This is + * the index of the largest component of vector W. + */ + int IndexOfLargestSingularValue() const + { + return W.IndexOfLargestComponent(); + } + + /*! + * Returns the column index of the smallest eigenvector in matrix V. This is + * the index of the smallest nonzero component of vector W. + * + * Before calling this function, you should edit the components of vector W + * to set to zero all singular values below a suitable tolerance. For + * example, using the machine epsilon: + * + * \code + * Matrix A; + * ... + * SVD svd( A ); + * for ( int i = 0; i < svd.W.Length(); ++i ) + * if ( 1 + svd.W[i] == 1 ) + * svd.W[i] = 0; + * int i = svd.IndexOfSmallestSingularValue(); + * ... + * \endcode + */ + int IndexOfSmallestSingularValue() const + { + return W.IndexOfSmallestNonzeroComponent(); + } +}; + +/*! + * \class SVD + * \brief Singular value decomposition algorithm for Matrix and Vector objects. + * + * %SVD is a template instantiation of GenericSVD for the double type. %SVD + * works with Matrix and Vector objects. %Matrix and %Vector are template + * instantiations of GenericMatrix and GenericVector, respectively, for the + * double type. + */ +class PCL_CLASS SVD : public GenericSVD +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericSVD algorithm_implementation; + + /*! + * Represents a vector involved in a singular value decomposition. + */ + typedef algorithm_implementation::vector vector; + + /*! + * Represents a matrix involved in a singular value decomposition. + */ + typedef algorithm_implementation::matrix matrix; + + /*! + * Represents a vector component. + */ + typedef vector::component vector_component; + + /*! + * Represents a matrix element. + */ + typedef matrix::element matrix_element; + + /*! + * Singular Value Decomposition: A = U*W*Vt + * + * The dimensions of A are n rows and m columns. U is an n x m matrix. The m + * components of W are the positive diagonal elements of W, and each column + * of V (m x m) is the eigenvector for the corresponding element of W. + * + * On output, this constructor stores U, W and V in the corresponding + * members of this object. + */ + SVD( const matrix& A ) + : algorithm_implementation( A ) + { + } +}; + +/*! + * \class FSVD + * \brief Singular value decomposition algorithm for FMatrix and FVector objects. + * + * %FSVD is a template instantiation of GenericSVD for the float type. %FSVD + * works with FMatrix and FVector objects. %FMatrix and %FVector are template + * instantiations of GenericMatrix and GenericVector, respectively, for the + * float type. + */ +class PCL_CLASS FSVD : public GenericSVD +{ +public: + + /*! + * Identifies the parent template class, which implements the underlying + * algorithm for this class. + */ + typedef GenericSVD algorithm_implementation; + + /*! + * Represents a vector involved in a singular value decomposition. + */ + typedef algorithm_implementation::vector vector; + + /*! + * Represents a matrix involved in a singular value decomposition. + */ + typedef algorithm_implementation::matrix matrix; + + /*! + * Represents a vector component. + */ + typedef vector::component vector_component; + + /*! + * Represents a matrix element. + */ + typedef matrix::element matrix_element; + + /*! + * Singular Value Decomposition: A = U*W*Vt + * + * The dimensions of A are n rows and m columns. U is an n x m matrix. The m + * components of W are the positive diagonal elements of W, and each column + * of V (m x m) is the eigenvector for the corresponding element of W. + * + * On output, this constructor stores U, W and V in the corresponding + * members of this object. + */ + FSVD( const matrix& A ) + : algorithm_implementation( A ) + { + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Algebra_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Algebra.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AlignedAllocator.h b/3rdparty/include/pcl/AlignedAllocator.h new file mode 100644 index 0000000..d2ab8dc --- /dev/null +++ b/3rdparty/include/pcl/AlignedAllocator.h @@ -0,0 +1,178 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AlignedAllocator.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_AlignedAllocator_h +#define __PCL_AlignedAllocator_h + +/// \file pcl/AlignedAllocator.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class AlignedAllocator + * \brief A block allocator class for aligned memory allocation/deallocation. + * + * %AlignedAllocator is a block allocator class. It can be used for + * all PCL container classes instead of the default StandardAllocator class, + * from which it derives publicly, providing exactly the same memory allocation + * policies. + * + * %AlignedAllocator guarantees that all allocated memory blocks are aligned + * for optimal performance of SIMD processor instructions on all supported + * platforms. Currently all blocks are allocated with 32 byte alignment, which + * is optimal for both SSE and AVX2 load/store instructions. + * + * For a complete description of block allocators and their fundamental role in + * PCL, read the documentation for the Allocator class. + * + * \sa Allocator, StandardAllocator + */ +class PCL_CLASS AlignedAllocator : public StandardAllocator +{ +public: + + /*! + * Constructs an %AlignedAllocator object. + * + * \param fastGrowth Whether to enable the fast block size growing policy + * for this allocator. + * + * \param canShrink Whether to enable the block shrinking policy for + * this allocator. + * + * See the IsFastGrowthEnabled() and IsShrinkingEnabled() member functions + * for more information on block allocation policies. + */ + AlignedAllocator( bool fastGrowth = true, bool canShrink = true ) + : StandardAllocator( fastGrowth, canShrink ) + { + } + + /*! + * Copy constructor. + */ + AlignedAllocator( const AlignedAllocator& ) = default; + + /*! + * Custom allocation routine. Allocates a contiguous memory block of the + * specified \a size in bytes with 32-byte alignment, and returns the + * address of the first byte in the newly allocated block. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + * + * \sa DeallocateBlock() + */ + void* AllocateBlock( size_type size ) + { + PCL_PRECONDITION( size != 0 ) + void* p = PCL_ALIGNED_MALLOC( size, 32 ); + if ( unlikely( p == nullptr ) ) + throw std::bad_alloc(); + return PCL_ASSUME_ALIGNED_32( p ); + } + + /*! + * Custom deallocation routine. Deallocates a previously allocated + * contiguous memory block that begins at the specified location \a p. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + * + * \sa AllocateBlock() + */ + void DeallocateBlock( void* p ) + { + PCL_PRECONDITION( p != nullptr ) + PCL_ALIGNED_FREE( p ); + } +}; + +} // pcl + +// ---------------------------------------------------------------------------- + +/*! + * Placement new operator for class AlignedAllocator. Returns the specified + * address \a p. + */ +inline void* operator new( pcl::size_type, void* p, pcl::AlignedAllocator& ) +{ + PCL_PRECONDITION( p != nullptr ) + return p; +} + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable: 4100 ) // 'unreferenced formal parameter' + +inline void operator delete( void* p, void*, pcl::AlignedAllocator& ) +{ + PCL_PRECONDITION( p != nullptr ) +} + +#pragma warning( pop ) +#endif // _MSC_VER + +// ---------------------------------------------------------------------------- + +#endif // __PCL_AlignedAllocator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AlignedAllocator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Allocator.h b/3rdparty/include/pcl/Allocator.h new file mode 100644 index 0000000..6c0dd82 --- /dev/null +++ b/3rdparty/include/pcl/Allocator.h @@ -0,0 +1,409 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Allocator.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_Allocator_h +#define __PCL_Allocator_h + +/// \file pcl/Allocator.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Allocator + * \brief Provides memory allocation for PCL containers. + * + * %Allocator inherits directly from its template argument A, which + * corresponds to a block allocator class. A block allocator is + * responsible for allocation and deallocation of untyped blocks of contiguous + * memory. %Allocator inherits block allocation capabilities and specializes + * them for allocation of a particular type T. + * + * The type T must have default and copy construction semantics. + * + * Besides the default and copy constructors, the block allocator class A must + * define the following member functions: + * + * \code + * size_type A::MaxSize() const + * \endcode + * + * Returns the maximum size in bytes that the block allocator is able to + * allocate as a contiguous memory block. + * + * \code + * size_type A::BlockSize( size_type n ) const + * \endcode + * + * Returns the size in bytes of an allocation block suitable to store + * at least \a n contiguous bytes. %Allocator uses this block size to reserve + * memory in chunks of optimized length. This greatly improves efficiency of + * containers because it minimizes the frequency of allocation/deallocation + * operations. + * + * \code + * size_type A::ReallocatedBlockSize( size_type currentSize, size_type newSize ) const + * \endcode + * + * Returns the size in bytes of a reallocated block. \a currentSize is the + * current size in bytes of the block being reallocated, and \a newSize is the + * requested block size. This function is similar to A::BlockSize(), but it is + * called for reallocation of already existing data blocks, for example before + * deleting a subset of container elements. + * + * \code + * void* AllocateBlock( size_type sz ) + * \endcode + * + * Custom allocation routine. Allocates a contiguous memory block of length + * \a sz in bytes, and returns the address of the first byte in the newly + * allocated block. + * + * \code + * void DeallocateBlock( void* p ) + * \endcode + * + * Custom deallocation routine. Deallocates a contiguous block of memory that + * has been previously allocated by any allocator of class A. + * + * StandardAllocator is an example of a block allocator that uses the standard + * \c new and \c delete operators. + * + * \sa StandardAllocator + */ +template +class PCL_CLASS Allocator : public A +{ +public: + + /*! + * Default constructor. + */ + Allocator() = default; + + /*! + * Copy constructor. + */ + Allocator( const Allocator& ) = default; + + /*! + * Constructs an %Allocator instance as a copy of other block allocator. + */ + Allocator( const A& a ) + : A( a ) + { + } + + /*! + * Allocates a contiguous block of memory, sufficient to store at least \a n + * instance of class T. Optionally, allocates the necessary space for \a n + * objects plus \a extra additional bytes. + * + * Returns the starting address of the allocated block. + * + * \note This member function does not construct any T instance; + * it only allocates the required memory to store \a n instances of T. + */ + T* Allocate( size_type n, size_type extra = 0 ) + { + PCL_PRECONDITION( n+extra > 0 ) + return (T*)this->AllocateBlock( n*sizeof( T )+extra ); + //return (T*)new ( *this ) uint8[ n*sizeof( T )+extra ]; + } + + /*! + * Deallocates a block of memory. + * + * \note This member function does not destruct any T instance; it + * only deallocates a previously allocated block where an unspecified number + * of T instances might be stored (either constructed or not). + */ + void Deallocate( T* p ) + { + PCL_PRECONDITION( p != nullptr ) + this->DeallocateBlock( (void*)p ); + //this->operator delete( (void*)p ); + } + + /*! + * Returns the maximum number of instances of class T that this allocator + * can allocate. + */ + size_type MaxLength() const + { + return A::MaxSize()/sizeof( T ); + } + + /*! + * Returns the length of a newly allocated data block. + * + * Given a number \a n of T instances, returns the corresponding paged + * length for this allocator. The paged length is the actual number of + * T instances that would be allocated instead of \a n, which depends on the + * block allocation policy implemented by the block allocator class. + * + * The value returned by this member function is always greater than or + * equal to \a n. + * + * \sa ShrunkLength() + */ + size_type PagedLength( size_type n ) const + { + return A::BlockSize( n*sizeof( T ) )/sizeof( T ); + } + + /*! + * Returns the length of a reallocated data block. + * + * \param currentLength The current length of an allocated data block. + * + * \param newLength The new length of the reallocated data block. + * + * The returned length is the actual number of T instances that would be + * allocated instead of \a newLength, which depends on the block allocation + * policy implemented by the block allocator class. + * + * The value returned by this member function is always greater than or + * equal to \a n. + * + * \sa PagedLength() + */ + size_type ReallocatedLength( size_type currentLength, size_type newLength ) const + { + return A::ReallocatedBlockSize( currentLength*sizeof( T ), newLength*sizeof( T ) )/sizeof( T ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup object_construction_destruction Construction and \ + * Destruction of Objects with Explicit Allocation + */ + +/*! + * Constructs an object with storage at address \a p and allocator \a a. This + * function invokes the default constructor of class T for the object stored at + * \a p. + * \sa Allocator + * \ingroup object_construction_destruction + */ +template inline void Construct( T* p, A& a ) +{ + PCL_PRECONDITION( p != nullptr ) + new( (void*)p, a )T(); +} + +/*! + * Constructs an object with storage at address \a p, initial value \a v, and + * allocator \a a. This function invokes the copy constructor of class T, with + * argument \a v, for the object stored at \a p. + * \sa Allocator + * \ingroup object_construction_destruction + */ +template inline void Construct( T* p, const T1& v, A& a ) +{ + PCL_PRECONDITION( p != nullptr ) + new( (void*)p, a )T( v ); +} + +#ifdef _MSC_VER +# pragma warning( push ) +# pragma warning( disable : 4100 ) // unreferenced formal parameter +#endif // (VC++ limitation !?) + +/*! + * Destroys an object stored at address \a p. Invokes the destructor of + * class T for the object stored at \a p. + * \sa Allocator + * \ingroup object_construction_destruction + */ +template inline void Destroy( T* p ) +{ + PCL_PRECONDITION( p != nullptr ) + p->~T(); +} + +/*! + * Destroys a contiguous sequence of objects. Invokes the destructor of class + * T for each object in the range [p,q). + * \sa Allocator + * \ingroup object_construction_destruction + */ +template inline void Destroy( T* p, T* q ) +{ + PCL_PRECONDITION( p != nullptr && q != nullptr ) + for ( ; p < q; ++p ) + p->~T(); +} + +#ifdef _MSC_VER +# pragma warning( pop ) +#endif + +inline void Destroy( void* ) {} +inline void Destroy( void*, void* ) {} + +inline void Destroy( bool* ) {} +inline void Destroy( bool*, bool* ) {} + +inline void Destroy( signed char* ) {} +inline void Destroy( signed char*, signed char* ) {} + +inline void Destroy( unsigned char* ) {} +inline void Destroy( unsigned char*, unsigned char* ) {} + +inline void Destroy( wchar_t* ) {} +inline void Destroy( wchar_t*, wchar_t* ) {} + +inline void Destroy( char16_t* ) {} +inline void Destroy( char16_t*, char16_t* ) {} + +inline void Destroy( char32_t* ) {} +inline void Destroy( char32_t*, char32_t* ) {} + +inline void Destroy( signed int* ) {} +inline void Destroy( signed int*, signed int* ) {} + +inline void Destroy( unsigned int* ) {} +inline void Destroy( unsigned int*, unsigned int* ) {} + +inline void Destroy( signed short* ) {} +inline void Destroy( signed short*, signed short* ) {} + +inline void Destroy( unsigned short* ) {} +inline void Destroy( unsigned short*, unsigned short* ) {} + +inline void Destroy( signed long* ) {} +inline void Destroy( signed long*, signed long* ) {} + +inline void Destroy( unsigned long* ) {} +inline void Destroy( unsigned long*, unsigned long* ) {} + +inline void Destroy( signed long long* ) {} +inline void Destroy( signed long long*, signed long long* ) {} + +inline void Destroy( unsigned long long* ) {} +inline void Destroy( unsigned long long*, unsigned long long* ) {} + +inline void Destroy( float* ) {} +inline void Destroy( float*, float* ) {} + +inline void Destroy( double* ) {} +inline void Destroy( double*, double* ) {} + +inline void Destroy( long double* ) {} +inline void Destroy( long double*, long double* ) {} + +inline void Destroy( void** ) {} +inline void Destroy( void**, void** ) {} + +inline void Destroy( bool** ) {} +inline void Destroy( bool**, bool** ) {} + +inline void Destroy( signed char** ) {} +inline void Destroy( signed char**, signed char** ) {} + +inline void Destroy( unsigned char** ) {} +inline void Destroy( unsigned char**, unsigned char** ) {} + +inline void Destroy( wchar_t** ) {} +inline void Destroy( wchar_t**, wchar_t** ) {} + +inline void Destroy( signed int** ) {} +inline void Destroy( signed int**, signed int** ) {} + +inline void Destroy( unsigned int** ) {} +inline void Destroy( unsigned int**, unsigned int** ) {} + +inline void Destroy( signed short** ) {} +inline void Destroy( signed short**, signed short** ) {} + +inline void Destroy( unsigned short** ) {} +inline void Destroy( unsigned short**, unsigned short** ) {} + +inline void Destroy( signed long** ) {} +inline void Destroy( signed long**, signed long** ) {} + +inline void Destroy( unsigned long** ) {} +inline void Destroy( unsigned long**, unsigned long** ) {} + +inline void Destroy( signed long long** ) {} +inline void Destroy( signed long long**, signed long long** ) {} + +inline void Destroy( unsigned long long** ) {} +inline void Destroy( unsigned long long**, unsigned long long** ) {} + +inline void Destroy( float** ) {} +inline void Destroy( float**, float** ) {} + +inline void Destroy( double** ) {} +inline void Destroy( double**, double** ) {} + +inline void Destroy( long double** ) {} +inline void Destroy( long double**, long double** ) {} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Allocator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Allocator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Arguments.h b/3rdparty/include/pcl/Arguments.h new file mode 100644 index 0000000..0c55f2c --- /dev/null +++ b/3rdparty/include/pcl/Arguments.h @@ -0,0 +1,681 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Arguments.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_Arguments_h +#define __PCL_Arguments_h + +/// \file pcl/Arguments.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup argument_parsing Argument Parsing Routines and Utilities + */ + +// ---------------------------------------------------------------------------- + +/*! + * \class Argument + * \brief A command-line argument + * + * %Argument implements a command-line argument that can be used with the + * ParseArguments() function. + * + * Command-line arguments can be \e parametric and \e non-parametric + * arguments (also known as \e item \e arguments). + * + * 1. Parametric Arguments + * + * Parametric arguments specify \e modifiers or parameter values of different + * types to their receiving processes. Syntactically, parametric arguments are + * formalized as: + * + * -<arg_id>[<arg_value>] + * + * where the starting hypen character '-' is the standard parameter + * prefix. <arg_id> is the argument identifier and + * <arg_value> is an optional argument value specification. For + * example, in the following parametric arguments: + * + * -n=17 --use-all-processors + * + * the argument identifiers are 'n' and '-use-all-processors', respectively, + * and '=17' is an argument value specification. + * + * We consider four types of parametric arguments: \e literal, \e switch, + * \e numeric and \e string arguments. + * + * 1.1 Literal Arguments + * + * Literal arguments are parametric arguments that don't have a particular + * value. They are modifiers that act as functions of their existence. For + * example, in the following arguments: + * + * -c -x=10 -b="none" --verbose + * + * '-c' and '--verbose' are literal arguments. + * + * 1.2 Switch Arguments + * + * Switch arguments are parametric arguments that can only have a boolean + * \e enabled/disabled state. Switch arguments are of the form: + * + * -<arg_id>+|- + * + * where the + suffix means 'enabled' and the - suffix means 'disabled'. + * For example, here are some switch arguments: + * + * -u+ -color- --mySwitchArgument+ + * + * It is customary to allow the use of switch arguments also as literal + * arguments. When switch arguments are used as literal arguments, a default + * 'enabled' or 'disabled' state is assumed, depending on the functionality and + * purpose of each argument. When switch arguments can also be literal, they + * are formalized as: + * + * -<arg_id>[+|-] + * + * indicating that the + and - suffixes are optional. + * + * 1.3 Numeric Arguments + * + * A numeric argument has an integer or floating-point numeric value. Numeric + * arguments are formalized as: + * + * -<arg_id>=<numeric_constant> + * + * where <numeric_constant> is a valid representation of an integer or + * floating-point real constant, following the applicable syntax rules of the C + * language. Integer constants can have the '0x' standard prefix to indicate + * hexadecimal values. + * + * 1.4 %String Arguments + * + * A string argument has a literal value represented as a string of ISO 8859-1 + * characters. String arguments are formalized as: + * + * -<arg_id>=<string_constant> + * + * where <string_constant> is any sequence of ISO 8859-1 characters, + * optionally enclosed by double quotes. For example: + * + * -s=foo -s1="bar" + * + * are two string arguments with 'foo' and 'bar' values, respectively. When the + * <string_constant> string includes white spaces, the enclosing quotes are + * not optional, as in: + * + * -aStringArg="this is a string literal" + * + * or otherwise the above sequence would be interpreted as a single string + * argument (aStringArg=this) and four additional, non-parametric arguments. + * + * 2. Non-Parametric Arguments + * + * Non-parametric arguments specify \e objects that their receiving processes + * can act on or use in any way. Non-parametric arguments are formalized as: + * + * <arg_value> + * + * where <arg_value> is any sequence of ISO 8859-1 characters. Note that the + * absence of a standard parameter prefix (the hypen character, '-') + * characterizes non-parametric arguments. For example, in the following + * arguments: + * + * -mode="auto" *.js -z foo.scp + * + * '*.js' and 'foo.scp' are two non-parametric arguments. + * + * Each non-parametric argument can be expanded into a list of items. + * For example, the '*.js' argument above would be expanded into a list of all + * files with the .js suffix in the current directory, provided that the + * argument is parsed as a wild file path specification. + * + * \sa ParseArguments(), ArgumentItemMode, ArgumentOption + * + * \ingroup argument_parsing + */ +class PCL_CLASS Argument +{ +public: + + /*! + * Constructs an empty %Argument object. + */ + Argument() + { + Initialize(); + } + + /*! + * Constructs an %Argument object and parses the specified \a argv string. + */ + Argument( const String& argv ) + { + Parse( argv.c_str() ); + } + + /*! + * Constructs an %Argument object and parses the specified \a argv string. + */ + Argument( const char16_type* argv ) + { + Parse( argv ); + } + + /*! + * Constructs an %Argument object and interprets that the specified \a argv + * string corresponds to a non-parametric argument corresponding to the + * \a items list of items. + */ + Argument( const String& argv, const StringList& items ) + { + type = item_arg; + token = argv; + asItems = items; + } + + /*! + * Copy constructor. + */ + Argument( const Argument& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Argument& operator =( const Argument& ) = default; + + /*! + * Equality operator. Returns true if this %Argument object is equal to the + * specified \a x instance. + */ + bool operator ==( const Argument& x ) const + { + if ( id == x.id && type == x.type ) + { + if ( IsLiteral() || !IsValid() ) + return true; + if ( IsNumeric() ) + return asNumeric == x.asNumeric; + if ( IsString() ) + return asString == x.asString; + if ( IsSwitch() ) + return asSwitch == x.asSwitch; + if ( IsItemList() ) + return asItems == x.asItems; + } + return false; + } + + /*! + * Returns true iff this argument has successfully parsed a token string. + */ + bool IsValid() const + { + return type != invalid_arg; + } + + /*! + * Returns the token string corresponding to this argument. The token is the + * exact string that has been parsed by this %Argument instance. If no token + * has been parsed by this instance, an empty string is returned. + */ + String Token() const + { + return token; + } + + /*! + * Returns the argument's parameter identifier, if this argument has been + * parsed and it is a parametric argument, or an empty string + * otherwise. + */ + String Id() const + { + return id; + } + + /*! + * Returns true iff this argument has been parsed and it is a + * non-parametric argument, also known as an item + * argument. + */ + bool IsItemList() const + { + return type == item_arg; + } + + /*! + * Returns a reference to the (constant) list of items that have been + * generated after expansion of a non-parametric argument. The returned list + * cannot be modified, and it's empty if this argument is parametric, or if + * it has not been parsed yet. + */ + const StringList& Items() const + { + return asItems; + } + + /*! + * Returns a reference to the list of items that have been generated after + * expansion of a non-parametric argument. The returned list can be freely + * modified, and it's empty if this argument is parametric, or if it has not + * been parsed yet. + */ + StringList& Items() + { + return asItems; + } + + /*! + * Returns true iff this argument has been parsed and it is a literal + * argument. + */ + bool IsLiteral() const + { + return type == literal_arg; + } + + /*! + * Returns true iff this argument has been parsed and it is a switch + * argument. + */ + bool IsSwitch() const + { + return type == switch_arg; + } + + /*! + * Returns the switch state of this argument, if it has been parsed and it + * is a switch argument, or false otherwise. + */ + bool SwitchState() const + { + return asSwitch; + } + + /*! + * Returns true iff this argument has been parsed and it is a numeric + * argument. + */ + bool IsNumeric() const + { + return type == numeric_arg; + } + + /*! + * Returns the numeric value of this argument, if it has been parsed and it + * is a numeric argument, or zero otherwise. + */ + double NumericValue() const + { + return asNumeric; + } + + /*! + * Returns true iff this argument has been parsed and it is a string + * argument. + */ + bool IsString() const + { + return type == string_arg; + } + + /*! + * Returns the string value of this argument, if it has been parsed and it + * is a string argument, or an empty string otherwise. + */ + String StringValue() const + { + return asString; + } + +private: + + enum arg_type { invalid_arg = -1, item_arg, literal_arg, switch_arg, numeric_arg, string_arg }; + + String token; // argument token + String id; // argument id + arg_type type; // argument type, or invalid + + StringList asItems; // list of non-parameters (e.g. file names or view ids) + bool asSwitch; // logical state of a switch argument + double asNumeric; // value of a numerical argument + String asString; // value of a string argument + + void Initialize() + { + token.Clear(); + id.Clear(); + type = invalid_arg; + asItems.Clear(); + asSwitch = false; + asNumeric = 0; + asString.Clear(); + } + + void Parse( const char16_type* ); +}; + +/*! + * \class pcl::ArgumentList + * \brief A dynamic array of command-line arguments + * \ingroup argument_parsing + */ +typedef Array ArgumentList; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ArgumentItemMode + * \brief Non-parametric argument parsing modes. + * + * + * + * + * + * + *
ArgumentItemMode::Ignore Consider non-parametric items as literal items (plain strings)
ArgumentItemMode::AsFiles Non-parametric items are file paths
ArgumentItemMode::AsViews Non-parametric items are view identifiers
ArgumentItemMode::NoItems Non-parametric items are not allowed
+ * + * \ingroup argument_parsing + */ +namespace ArgumentItemMode +{ + enum value_type + { + Ignore, // Consider non-parametric items as literal items (plain strings) + AsFiles, // Non-parametric items are file paths + AsViews, // Non-parametric items are view identifiers + NoItems, // Non-parametric items are not allowed + }; +} + +/*! + * \class pcl::argument_item_mode + * \brief Represents an ArgumentItemMode enumerated value. + * \ingroup argument_parsing + */ +typedef ArgumentItemMode::value_type argument_item_mode; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ArgumentOption + * \brief Working options affecting how non-parametric arguments are + * interpreted. + * + * + * + * + * + * + *
ArgumentOption::AllowWildcards Allow wildcard characters (*?) in non-parametric items
ArgumentOption::NoPreviews Don't allow preview specifications (with the '->' standard separator)
ArgumentOption::RecursiveDirSearch Perform recursive directory searches for wild path specifications
ArgumentOption::RecursiveSearchArgs Use standard arguments to toggle recursive directory searching
+ * + * \ingroup argument_parsing + */ +namespace ArgumentOption +{ + enum mask_type + { + AllowWildcards = 0x00000001, // Allow wildcard characters (*?) in non-parametric items + NoPreviews = 0x00000002, // Don't allow preview specifications (with the '->' standard separator) + RecursiveDirSearch = 0x00000004, // Perform recursive directory searches for wild path specifications + RecursiveSearchArgs = 0x00000008, // Use standard arguments to toggle recursive directory searching + }; +} + +/*! + * \class pcl::ArgumentOptions + * \brief A combination of ArgumentOption flags + * \ingroup argument_parsing + */ +typedef Flags ArgumentOptions; + +// ---------------------------------------------------------------------------- + +// The implementation of ExtractArguments() is slightly different in core. +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +} // pcl +using namespace pcl; +namespace pi +{ +#endif + +/*! + * Extracts a sequence of command-line arguments of the form: + * + * [<arg_list>] [<item_list>] + * + * where: + * + * <item_list> + * Is a sequence <item> [<item_list>] + * + * <item> + * Is a non-parametric (or "item") argument. If file parsing is active + * (see the \a mode parameter below), each item will be parsed as a file path + * specification. If view parsing is active, items will be considered + * as view identifiers. In both cases, each item may include wildcards to + * define a search pattern, which will be automatically expanded into a + * sequence of actual file paths or view identifiers. + * + * <arg_list> + * Is a sequence <arg> [<arg_list>] + * + * <arg> + * Is a parametric argument (see the documentation for the Argument class for a + * complete description). + * + * \param argv The list of input argument tokens that will be parsed.\n\n + * + * \param mode Indicates how non-parametric items will be handled by this + * function. \a mode must have one of the following values:\n + * \n + * + * + * + * + * + * + * + * + * + *
ArgumentItemMode::Ignore. Non-parametric arguments will + * not be parsed and will be passed unchanged.
ArgumentItemMode::AsFiles. Each non-parametric argument + * is interpreted as a file path specification. Note that neither + * validity of file paths nor the existence of actual files are + * verified.
ArgumentItemMode::AsViews. Each non-parametric argument + * is interpreted and parsed as a view identifier specification. Note + * that only validity of view identifiers is verified, not the + * existence of actual views with such identifiers.
ArgumentItemMode::NoItems. This mode disallows + * non-parametric arguments. An exception is thrown if a + * non-parametric item is found in the input sequence of \a argv + * elements.
\n\n + * + * \param options This is an OR'ed combination of flags from the + * ArgumentOption enumeration:\n + * \n + * + * + * + * + * + * + * + * + * + *
ArgumentItemMode::AllowWildcards. If this flag is + * included, each file argument containing wildcards ('*' and '?' + * characters) will originate a search for all files matching the + * specified wildcard pattern. If view arguments are being considered, + * each wildcard item will be expanded into a list of matching view + * identifiers.
ArgumentItemMode::NoPreviews. This flag prevents the + * inclusion of preview identifiers in the output arguments set. If a + * preview specification (imageId->previewId) is found and this flag + * is active, an exception is thrown.
ArgumentItemMode::RecursiveDirSearch. This flag only + * makes sense along with the ArgumentItemMode::AsFiles mode. If used, + * this flag will originate recursive directory searches for all file + * path specifications containing wildcards. Note that the behavior of + * this flag can be altered by the RecursiveSearchArgs flag (see + * below).
ArgumentItemMode::RecursiveSearchArgs. This flag only + * makes sense along with the ArgumentItemMode::AsFiles mode and the + * RecursiveDirSearch flag (see above). If used, recursive directory + * searches will be controlled by a special toggle argument. All + * instances of this argument will be processed automatically by the + * routine and will not be included in the output arguments list. By + * default, this argument is --r[+|-], but it can be changed + * by calling the SetRecursiveDirSearchArgument() static function.\n + * \n + * Example of wild path argument specifications with recursive search + * through the standard --r toggle argument: + * + * *.cpp --r *.h *.png --r- *.exe + * + * In the example above, *.h and *.png will be + * searched recursively through the entire directory tree rooted at + * the current directory, but *.cpp and *.exe files + * will only be searched for in the current directory.
+ * + * This function generates a ParseError exception when it encounters an error + * while parsing the sequence of input arguments. + * + * Returns a list with all the arguments extracted from the input \a argv + * sequence as instances of the Argument class. If non-parametric arguments are + * being interpreted as file paths, each non-parametric item is expanded to its + * corresponding full file path. If non-parametric arguments are being parsed + * as view identifiers, each non-parametric item is replaced (if appropriate) + * by its full view identifier. Otherwise, non-parametric items are returned + * unchanged. + * + * \ingroup argument_parsing + */ +ArgumentList PCL_FUNC ExtractArguments( const StringList& argv, + argument_item_mode mode = ArgumentItemMode::Ignore, + ArgumentOptions options = ArgumentOptions() ); + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +} // pi +namespace pcl +{ +#endif + +/*! + * Returns the identifier of the argument used by ExtractArguments() for + * automatic toggle of recursive directory searches. By default, this is the + * --r[+|-] argument. + * + * \ingroup argument_parsing + */ +String PCL_FUNC RecursiveDirSearchArgument(); + +/*! + * Sets the identifier of the argument used by ExtractArguments() for + * automatic toggle of recursive directory searches. + * + * \param id New identifier for the automatic recursive search argument. + * N.B.: When specifying this argument, don't include the '-' + * standard parameter prefix. + * + * \ingroup argument_parsing + */ +void PCL_FUNC SetRecursiveDirSearchArgument( const String& id ); + +/*! + * Auxiliary directory search routine used by ExtractArguments(). + * + * Returns a list of full file paths corresponding to a template wild file + * specification (\a filePath), optionally recursing the directory tree, + * starting from the directory specified in \a filePath. + * + * \ingroup argument_parsing + */ +StringList PCL_FUNC SearchDirectory( const String& filePath, bool recursive = false ); + +/*! + * Returns a copy of a source string \a s where all references to environment + * variables have been replaced with their corresponding values. + * + * This function finds all occurrences of environment variables of the form: + * + * $<env_name> + * + * where <env_name> is any sequence of alphabetic, decimal, or underscore + * characters. If <env_name> corresponds to an existing environment + * variable of the calling process, the entire $<env_name> sequence is + * replaced with the variable's value. References to nonexistent environment + * variables, as well as empty references (isolated $ characters), are + * replaced with an empty string (removed). + * + * This function works recursively: it can replace environment variables + * inside the values of environment variables. The routine performs + * replacements recursively until no $ character is found in the string. + * + * \ingroup argument_parsing + */ +String PCL_FUNC ReplaceEnvironmentVariables( const String& s ); + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Arguments_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Arguments.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Array.h b/3rdparty/include/pcl/Array.h new file mode 100644 index 0000000..96d99f9 --- /dev/null +++ b/3rdparty/include/pcl/Array.h @@ -0,0 +1,2171 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Array.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_Array_h +#define __PCL_Array_h + +/// \file pcl/Array.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup dynamic_arrays Dynamic Arrays + */ + +// ---------------------------------------------------------------------------- + +/*! + * \class Array + * \brief Generic dynamic array. + * + * %Array is a generic, finite ordered sequence of objects, implemented as a + * reference-counted, dynamic array of T instances. The type A provides dynamic + * allocation for contiguous sequences of elements of type T (StandardAllocator + * is used by default). + * + * \sa SortedArray, ReferenceArray, ReferenceSortedArray, IndirectArray, + * IndirectSortedArray + * \ingroup dynamic_arrays + */ +template +class PCL_CLASS Array : public DirectContainer +{ +public: + + /*! # + */ + typedef A block_allocator; + + /*! # + */ + typedef pcl::Allocator allocator; + + /*! # + */ + typedef T* iterator; + + /*! # + */ + typedef const T* const_iterator; + + /*! # + */ + typedef ReverseRandomAccessIterator + reverse_iterator; + + /*! # + */ + typedef ReverseRandomAccessIterator + const_reverse_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty array. + */ + Array() + { + m_data = new Data; + } + + /*! + * Constructs an array of \a n default-constructed objects. + */ + explicit + Array( size_type n ) + { + m_data = new Data; + m_data->Allocate( n ); + m_data->Initialize( m_data->begin, m_data->end ); + } + + /*! + * Constructs an array with \a n copies of an object \a v. + */ + Array( size_type n, const T& v ) + { + m_data = new Data; + m_data->Allocate( n ); + m_data->Initialize( m_data->begin, m_data->end, v ); + } + + /*! + * Constructs an array that stores a copy of the objects in the range [i,j) + * of forward iterators. + */ + template + Array( FI i, FI j ) + { + m_data = new Data; + m_data->Allocate( size_type( pcl::Distance( i, j ) ) ); + if ( m_data->begin != nullptr ) + m_data->Build( m_data->begin, i, j ); + } + + /*! + * Constructs an array that stores a copy of the objects in the specified + * initializer list \a l. + * + * This constructor is equivalent to: + * + * \code Array( l.begin(), l.end() ) \endcode + */ + template + Array( std::initializer_list l ) + : Array( l.begin(), l.end() ) + { + } + + /*! + * Copy constructor. + */ + Array( const Array& x ) + : m_data( x.m_data ) + { + if ( m_data != nullptr ) + m_data->Attach(); + } + + /*! + * Move constructor. + */ + Array( Array&& x ) + : m_data( x.m_data ) + { + x.m_data = nullptr; + } + + /*! + * Destroys an %Array object. Destroys and deallocates all contained + * objects. + */ + ~Array() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + /*! + * Returns true iff this array uniquely references its contained data. + */ + bool IsUnique() const noexcept + { + return m_data->IsUnique(); + } + + /*! + * Returns true iff this array is an alias of an array \a x. + * + * Two objects are aliases if both share the same data. + */ + bool IsAliasOf( const Array& x ) const noexcept + { + return m_data == x.m_data; + } + + /*! + * Ensures that this array uniquely references its contained data. + * + * If necessary, this member function generates a duplicate of the array + * data, references it, and then decrements the reference counter of the + * original array data. + */ + void EnsureUnique() + { + if ( !IsUnique() ) + { + Data* newData = new Data; + newData->Allocate( Length() ); + newData->Build( newData->begin, m_data->begin, m_data->end ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the total number of bytes required to store the objects contained + * by this dynamic array. + */ + size_type Size() const noexcept + { + return m_data->Size(); + } + + /*! + * Returns the length of this dynamic array. + */ + size_type Length() const noexcept + { + return m_data->Length(); + } + + /*! + * Returns the capacity of this array. The capacity is the maximum number of + * objects that this array can contain without requiring a reallocation. + */ + size_type Capacity() const noexcept + { + return m_data->Capacity(); + } + + /*! + * Returns the length of the space available in this array, or zero if this + * array cannot contain more objects. The available space is the number of + * objects that can be added to this array without requiring a reallocation. + * It is equal to Capacity() - Length() by definition. + */ + size_type Available() const noexcept + { + return m_data->Available(); + } + + /*! + * Returns true only if this array is valid. An array is valid if it + * references an internal array structure, even if it is an empty array. + * + * In general, all %Array objects are valid with only two exceptions: + * + * \li Objects that have been move-copied or move-assigned to other arrays. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid array object cannot be used and should be destroyed + * immediately. Invalid arrays are always destroyed automatically during + * move construction and move assignment operations. + */ + bool IsValid() const noexcept + { + return m_data != nullptr; + } + + /*! + * Returns true iff this array is empty. + */ + bool IsEmpty() const noexcept + { + return m_data->IsEmpty(); + } + + /*! + * Returns the minimum legal index in this array (always zero). For empty + * arrays, this function returns a meaningless value. + */ + size_type LowerBound() const noexcept + { + return 0; + } + + /*! + * Returns the maximum legal index in this array. It is equal to Length()-1. + * For empty arrays, this function returns a meaningless value. + */ + size_type UpperBound() const noexcept + { + return Length()-1; + } + + /*! + * Returns a reference to the allocator object used by this array. + */ + const allocator& Allocator() const noexcept + { + return m_data->alloc; + } + + /*! + * Sets a new allocator object for this array. + */ + void SetAllocator( const allocator& a ) + { + EnsureUnique(); + m_data->alloc = a; + } + + /*! + * Returns an array iterator located at the specified array index \a i. + */ + iterator At( size_type i ) + { + PCL_PRECONDITION( !IsEmpty() && i < Length() ) + EnsureUnique(); + return m_data->begin + i; + } + + /*! + * Returns an immutable array iterator located at the specified index \a i. + */ + const_iterator At( size_type i ) const noexcept + { + PCL_PRECONDITION( !IsEmpty() && i < Length() ) + return m_data->begin + i; + } + + /*! + * Returns a mutable iterator pointing to the same array element as the + * specified immutable iterator \a i. + * + * \warning As a side-effect of calling this function, the specified + * immutable iterator \a i may become invalid. This happens when this + * function is called for a shared array, since in this case getting a + * mutable iterator involves a deep copy of the array through an implicit + * call to EnsureUnique(). + */ + iterator MutableIterator( const_iterator i ) + { + return At( i - m_data->begin ); + } + + /*! + * Returns a reference to the element at the specified index \a i. No bounds + * checking is performed. + */ + T& operator []( size_type i ) + { + return *At( i ); + } + + /*! + * Returns a reference to the unmodifiable element at the specified index + * \a i in this array. No bounds checking is performed. + */ + const T& operator []( size_type i ) const noexcept + { + return *At( i ); + } + + /*! + * Returns a reference to the first element of this array. + */ + T& operator *() + { + PCL_PRECONDITION( m_data->begin != nullptr ) + EnsureUnique(); + return *m_data->begin; + } + + /*! + * Returns a reference to the unmodifiable first element of this array. + */ + const T& operator *() const noexcept + { + PCL_PRECONDITION( m_data->begin != nullptr ) + return *m_data->begin; + } + + /*! + * Returns a mutable iterator located at the beginning of this array. + */ + iterator Begin() + { + EnsureUnique(); + return m_data->begin; + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator Begin() const noexcept + { + return m_data->begin; + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator ConstBegin() const noexcept + { + return m_data->begin; + } + + /*! + * Returns a mutable iterator located at the end of this array. + */ + iterator End() + { + EnsureUnique(); + return m_data->end; + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator End() const noexcept + { + return m_data->end; + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator ConstEnd() const noexcept + { + return m_data->end; + } + + /*! + * Returns a mutable reverse iterator located at the reverse + * beginning of this array. + * + * The reverse beginning corresponds to the last element in the array. + */ + reverse_iterator ReverseBegin() + { + PCL_PRECONDITION( m_data->end != nullptr ) + EnsureUnique(); + return m_data->end - 1; + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this array. + * + * The reverse beginning corresponds to the last element in the array. + */ + const_reverse_iterator ReverseBegin() const noexcept + { + PCL_PRECONDITION( m_data->end != nullptr ) + return m_data->end - 1; + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this array. + * + * The reverse beginning corresponds to the last element in the array. + */ + const_reverse_iterator ConstReverseBegin() const noexcept + { + PCL_PRECONDITION( m_data->end != nullptr ) + return m_data->end - 1; + } + + /*! + * Returns a mutable reverse iterator located at the reverse end of + * this array. + * + * The reverse end corresponds to an (nonexistent) element immediately + * before the first element in the array. + */ + reverse_iterator ReverseEnd() + { + PCL_PRECONDITION( m_data->begin != nullptr ) + EnsureUnique(); + return m_data->begin - 1; + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this array. + * + * The reverse end corresponds to an (nonexistent) element immediately + * before the first element in the array. + */ + const_reverse_iterator ReverseEnd() const noexcept + { + PCL_PRECONDITION( m_data->begin != nullptr ) + return m_data->begin - 1; + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this array. + * + * The reverse end corresponds to an (nonexistent) element immediately + * before the first element in the array. + */ + const_reverse_iterator ConstReverseEnd() const noexcept + { + PCL_PRECONDITION( m_data->begin != nullptr ) + return m_data->begin - 1; + } + + /*! + * Ensures that the specified iterator points to a uniquely referenced + * object. If necessary, this function builds a new, uniquely referenced + * copy of this array by calling EnsureUnique(). + * + * If the iterator \a i is changed, it is guaranteed to point to the object + * at the same array index it was pointing to before calling this function. + */ + void UniquifyIterator( iterator& i ) + { + PCL_PRECONDITION( i >= m_data->begin && i <= m_data->end ) + if ( !IsUnique() ) + { + distance_type d = i - m_data->begin; + EnsureUnique(); + i = m_data->begin + d; + } + } + + /*! + * Ensures that the specified iterators point to uniquely referenced + * objects. If necessary, this function builds a new, uniquely referenced + * copy of this array by calling EnsureUnique(). + * + * If the iterators \a i and \a j are changed, they are guaranteed to point + * to the objects at the same array indices they were pointing to before + * calling this function. + */ + void UniquifyIterators( iterator& i, iterator& j ) + { + PCL_PRECONDITION( i >= m_data->begin && i <= m_data->end ) + PCL_PRECONDITION( j >= m_data->begin && j <= m_data->end ) + if ( !IsUnique() ) + { + distance_type d = i - m_data->begin; + distance_type r = j - i; + EnsureUnique(); + j = (i = m_data->begin + d) + r; + } + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const noexcept + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + iterator end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const noexcept + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Copy assignment operator. + * + * Causes this array to reference the same data as another array \a x. + * Returns a reference to this object. + */ + Array& operator =( const Array& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns an array \a x to this array. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Increments the reference counter of the source array's data and + * references it in this array. + */ + void Assign( const Array& x ) + { + x.m_data->Attach(); + DetachFromData(); + m_data = x.m_data; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Array& operator =( Array&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from another array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( Array& x ) + { + DetachFromData(); + m_data = x.m_data; + x.m_data = nullptr; + } + + /*! + * Transfers data from another array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( Array&& x ) + { + DetachFromData(); + m_data = x.m_data; + x.m_data = nullptr; + } + + /*! + * Replaces the contents of this array with a sequence of \a n copies of an + * object \a v. + */ + void Assign( const T& v, size_type n = 1 ) + { + if ( n > 0 ) + { + if ( !IsUnique() ) + { + Data* newData = new Data; + DetachFromData(); + m_data = newData; + } + + if ( Capacity() < n ) + { + m_data->Deallocate(); + m_data->Allocate( n ); + } + else + { + m_data->Destroy( m_data->begin, m_data->end ); + m_data->end = m_data->begin + n; + } + + m_data->Initialize( m_data->begin, m_data->end, v ); + } + else + Clear(); + } + + /*! + * Replaces the contents of this array with a copy of the sequence defined + * by the range [i,j) of forward iterators. + * + * \note \a i and \a j must not be iterators into this array. + */ + template + void Assign( FI i, FI j ) + { + size_type n = size_type( pcl::Distance( i, j ) ); + if ( n > 0 ) + { + if ( !IsUnique() ) + { + Data* newData = new Data; + DetachFromData(); + m_data = newData; + } + + if ( Capacity() < n ) + { + m_data->Deallocate(); + m_data->Allocate( n ); + } + else + { + m_data->Destroy( m_data->begin, m_data->end ); + m_data->end = m_data->begin + n; + } + + m_data->Build( m_data->begin, i, j ); + } + else + Clear(); + } + + /*! + * Causes this array to contain the sequence of objects defined by the range + * [i,j) of array iterators. The previously referenced data structure is + * dereferenced and destroyed/deallocated if it becomes unreferenced. + * + * After calling this function, this array, or a subsequently created alias, + * will own and eventually destroy and deallocate the specified sequence of + * contiguous objects. + */ + void Import( iterator i, iterator j ) + { + if ( i >= m_data->available || j <= m_data->begin ) + { + Clear(); + size_type n = size_type( pcl::Distance( i, j ) ); + if ( n > 0 ) + { + EnsureUnique(); + m_data->begin = i; + m_data->end = m_data->available = j; + } + } + } + + /*! + * Releases the data contained by this array. + * + * This member function returns a pointer to the internal data block + * referenced by this object, after ensuring that it is uniquely referenced. + * If the array is empty, this function may return the null pointer. + * + * Before returning, this member function empties this array without + * deallocating its contained data. The caller is then responsible for + * destructing and/or deallocating the returned block when it is no longer + * required. + */ + iterator Release() + { + EnsureUnique(); + iterator b = m_data->begin; + m_data->begin = m_data->end = m_data->available = nullptr; + return b; + } + + /*! + * Inserts a contiguous sequence of \a n default-constructed objects at the + * specified location \a i in this array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first newly created array element, or + * \a i if \a n is zero. + */ + iterator Grow( iterator i, size_type n = 1 ) + { + i = pcl::Range( i, m_data->begin, m_data->end ); + if ( n > 0 ) + { + UniquifyIterator( i ); + m_data->Initialize( i = m_data->UninitializedGrow( i, n ), n ); + } + return i; + } + + /*! + * Appends a contiguous sequence of \a n default-constructed objects to this + * array. This operation is equivalent to: + * + * \code Grow( End(), n ) \endcode + * + * Returns an iterator pointing to the first newly created array element, or + * End() if \a n is zero. + */ + iterator Expand( size_type n = 1 ) + { + return Grow( m_data->end, n ); + } + + /*! + * Removes a contiguous trailing sequence of \a n existing objects from this + * array. This operation is equivalent to: + * + * \code Truncate( End() - n ) \endcode + * + * If the specified count \a n is greater than or equal to the length of + * this array, this function calls Clear() to yield an empty array. + */ + void Shrink( size_type n = 1 ) + { + if ( n < m_data->Length() ) + Truncate( m_data->end - n ); + else + Clear(); + } + + /*! + * Resizes this array to the specified length \a n, either by appending new + * default-constructed objects, or by removing existing trailing objects. + * This operation is equivalent to: + * + * \code + * if ( n > Length() ) + * Expand( n - Length() ); + * else + * Shrink( Length() - n ); + * \endcode + */ + void Resize( size_type n ) + { + size_type l = m_data->Length(); + if ( n > l ) + Expand( n - l ); + else + Shrink( l - n ); + } + + /*! + * Inserts a copy of the objects in a direct container \a x at the specified + * location \a i in this array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. The source array \a x can + * safely be a reference to this array. + * + * Returns an iterator pointing to the first newly created array element, or + * \a i if \a x is empty. + */ + iterator Insert( iterator i, const Array& x ) + { + if ( &x != this ) + return Insert( i, x.Begin(), x.End() ); + Array t( *this ); + t.EnsureUnique(); + return Insert( i, t.m_data->begin, t.m_data->end ); + } + + /*! + * Inserts a contiguous sequence of \a n copies of the object \a v at the + * specified location \a i in this array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first inserted array element, or \a i + * if \a n is zero. + */ + iterator Insert( iterator i, const T& v, size_type n = 1 ) + { + i = pcl::Range( i, m_data->begin, m_data->end ); + if ( n > 0 ) + { + UniquifyIterator( i ); + m_data->Initialize( i = m_data->UninitializedGrow( i, n ), n, v ); + } + return i; + } + + /*! + * Inserts a copy of the sequence of objects defined by the range [p,q) of + * forward iterators at the specified location \a i in this array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first inserted array element, or \a i + * if \a q <= \a p. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + iterator Insert( iterator i, FI p, FI q ) + { + i = pcl::Range( i, m_data->begin, m_data->end ); + size_type n = size_type( pcl::Distance( p, q ) ); + if ( n > 0 ) + { + UniquifyIterator( i ); + m_data->Build( i = m_data->UninitializedGrow( i, n ), p, q ); + } + return i; + } + + /*! + * Appends a copy of the objects stored in the array \a x to this array. + */ + void Append( const Array& x ) + { + Insert( m_data->end, x ); + } + + /*! + * Appends a contiguous sequence of \a n copies of the object \a v to this + * array. + */ + void Append( const T& v, size_type n = 1 ) + { + Insert( m_data->end, v, n ); + } + + /*! + * Appends a copy of the sequence of objects defined by the range [p,q) + * of forward iterators to this array. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + void Append( FI p, FI q ) + { + Insert( m_data->end, p, q ); + } + + /*! + * Inserts a copy of the objects stored in the array \a x at the beginning + * of this array. + */ + void Prepend( const Array& x ) + { + Insert( m_data->begin, x ); + } + + /*! + * Inserts a contiguous sequence of \a n copies of the object \a v at + * the beginning of this array. + */ + void Prepend( const T& v, size_type n = 1 ) + { + Insert( m_data->begin, v, n ); + } + + /*! + * Inserts a copy of the sequence of objects defined by the range [p,q) of + * forward iterators at the beginning of this array. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + void Prepend( FI p, FI q ) + { + Insert( m_data->begin, p, q ); + } + + /*! + * A synonym for Append( const Array<>& ). + */ + void Add( const Array& x ) + { + Append( x ); + } + + /*! + * A synonym for Append( const T&, size_type ) + */ + void Add( const T& v, size_type n = 1 ) + { + Append( v, n ); + } + + /*! + * A synonym for Append( FI, FI ) + */ + template + void Add( FI p, FI q ) + { + Append( p, q ); + } + + /*! + * Destroys and removes a sequence of \a n contiguous objects starting at + * the specified location \a i in this array. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a n is zero, this function does nothing. Otherwise \a i is + * constrained to stay in the range [Begin(),End()) of existing array + * elements. + */ + void Remove( iterator i, size_type n = 1 ) + { + Remove( i, i+n ); + } + + /*! + * Destroys and removes a sequence of contiguous objects in the range [i,j) + * of this array. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + */ + void Remove( iterator i, iterator j ) + { + if ( i < m_data->end ) + if ( i < j ) + { + i = pcl::Max( m_data->begin, i ); + j = pcl::Min( j, m_data->end ); + if ( i > m_data->begin || j < m_data->end ) + { + UniquifyIterators( i, j ); + m_data->Destroy( j = pcl::Copy( i, j, m_data->end ), m_data->end ); + m_data->end = j; + } + else + Clear(); + } + } + + /*! + * Destroys and removes a trailing sequence of contiguous objects from the + * specified iterator of this array. This operation is equivalent to: + * + * \code Remove( i, End() ) \endcode + * + * If the specified iterator is located at or after the end of this array, + * this function does nothing. Otherwise the iterator is constrained to stay + * in the range [Begin(),End()) of existing array elements. + */ + void Truncate( iterator i ) + { + Remove( i, m_data->end ); + } + + /*! + * Destroys and removes all existing objects equal to the specified value + * \a v in this array. + */ + void Remove( const T& v ) + { + Array a; + for ( iterator i = m_data->begin, j = i; ; ++j ) + { + if ( j == m_data->end ) + { + if ( i != m_data->begin ) + { + a.Add( i, j ); + Transfer( a ); + } + break; + } + + if ( *j == v ) + { + a.Add( i, j ); + i = j; + ++i; + } + } + } + + /*! + * Destroys and removes every object x in this array such that the binary + * predicate p( x, \a v ) is true. + */ + template + void Remove( const T& v, BP p ) + { + Array a; + for ( iterator i = m_data->begin, j = i; ; ++j ) + { + if ( j == m_data->end ) + { + if ( i != m_data->begin ) + { + a.Add( i, j ); + Transfer( a ); + } + break; + } + + if ( p( *j, v ) ) + { + a.Add( i, j ); + i = j; + ++i; + } + } + } + + /*! + * Removes and possibly destroys all objects contained, yielding an empty + * array. + * + * If this array is empty, then calling this member function has no effect. + * + * If this array uniquely references its internal array data structure, all + * objects contained are destroyed and deallocated; otherwise its reference + * counter is decremented and a new, empty array data structure is created + * and uniquely referenced. + */ + void Clear() + { + if ( !IsEmpty() ) + if ( IsUnique() ) + m_data->Deallocate(); + else + { + Data* newData = new Data; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Replaces a sequence of contiguous objects defined by the range [i,j) of + * iterators in this array by the objects stored in an array \a x. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or \c nullptr if the resulting array is + * empty. + */ + iterator Replace( iterator i, iterator j, const Array& x ) + { + if ( &x != this ) + return Replace( i, j, x.Begin(), x.End() ); + Array t( *this ); + t.EnsureUnique(); + return Replace( i, j, t.ConstBegin(), t.ConstEnd() ); + } + + /*! + * Replaces a sequence of contiguous objects defined by the range [i,j) of + * iterators in this array by \a n copies of the specified object \a v. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or \c nullptr if the resulting array is + * empty. + */ + iterator Replace( iterator i, iterator j, const T& v, size_type n = 1 ) + { + i = pcl::Range( i, m_data->begin, m_data->end ); + j = pcl::Range( j, m_data->begin, m_data->end ); + if ( i < j ) + if ( i < m_data->end ) + { + UniquifyIterators( i, j ); + size_type d = size_type( j - i ); + if ( d < n ) + { + m_data->Destroy( i, j ); + m_data->Initialize( i = m_data->UninitializedGrow( i, n-d ), n, v ); + } + else + { + iterator k = i + n; + pcl::Fill( i, k, v ); + Remove( k, j ); + if ( m_data->begin == nullptr ) + i = nullptr; + } + } + return i; + } + + /*! + * Replaces a sequence of contiguous objects defined by the range [i,j) of + * iterators in this array by the sequence of objects in the range [p,q) of + * forward iterators. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or \c nullptr if the resulting array is + * empty. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + iterator Replace( iterator i, iterator j, FI p, FI q ) + { + i = pcl::Range( i, m_data->begin, m_data->end ); + j = pcl::Range( j, m_data->begin, m_data->end ); + if ( i < j ) + if ( i < m_data->end ) + { + UniquifyIterators( i, j ); + size_type d = size_type( j - i ); + size_type n = size_type( pcl::Distance( p, q ) ); + if ( d < n ) + { + m_data->Destroy( i, j ); + m_data->Build( i = m_data->UninitializedGrow( i, n-d ), p, q ); + } + else + { + Remove( pcl::Move( i, p, q ), j ); + if ( m_data->begin == nullptr ) + i = nullptr; + } + } + return i; + } + + /*! + * Ensures that this array has enough capacity to store \a n objects. + * + * After calling this member function with \a n > 0, this object is + * guaranteed to uniquely reference its array data. + */ + void Reserve( size_type n ) + { + if ( n > 0 ) + if ( IsUnique() ) + { + if ( Capacity() < n ) + { + iterator b = m_data->alloc.Allocate( n ); + iterator e = m_data->Build( b, m_data->begin, m_data->end ); + m_data->Deallocate(); + m_data->begin = b; + m_data->end = e; + m_data->available = m_data->begin + n; + } + } + else + { + Data* newData = new Data; + newData->begin = newData->alloc.Allocate( n = pcl::Max( Length(), n ) ); + newData->end = newData->Build( newData->begin, m_data->begin, m_data->end ); + newData->available = newData->begin + n; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Causes this array to allocate the exact required memory space to store + * its contained objects. + * + * If the array has excess capacity, a new copy of its contained objects + * is generated and stored in a newly allocated memory block that fits them + * exactly, then the previous memory block is deallocated. + * + * If the array is empty, calling this function is equivalent to Clear(). + * Note that in this case a previously allocated memory block (by a call to + * Reserve()) may also be deallocated. + */ + void Squeeze() + { + if ( IsUnique() ) + { + if ( Available() > 0 ) + { + iterator b = m_data->alloc.Allocate( Length() ); + iterator e = m_data->Build( b, m_data->begin, m_data->end ); + m_data->Deallocate(); + m_data->begin = b; + m_data->end = m_data->available = e; + } + } + else + { + Data* newData = new Data; + if ( !IsEmpty() ) + { + newData->begin = newData->alloc.Allocate( Length() ); + newData->available = newData->end = newData->Build( newData->begin, m_data->begin, m_data->end ); + } + DetachFromData(); + m_data = newData; + } + } + + /*! + * Sets all objects contained by this array equal to \a v. + */ + void Fill( const T& v ) + { + EnsureUnique(); + pcl::Fill( m_data->begin, m_data->end, v ); + } + + /*! + * Securely fills this array and all instances sharing its data with the + * specified value \a v. + * + * The normal data sharing mechanism is ignored on purpose by this member + * function, so if there are other objects sharing the same array data, all + * of them will be affected unconditionally. + * + * This function is useful to ensure that sensitive data, such as user + * passwords and user names, are destroyed without the risk of surviving + * duplicates as a result of implicit data sharing. + */ + void SecureFill( const T& v ) + { + pcl::Fill( m_data->begin, m_data->end, v ); + } + + /*! + * Calls f( T& x ) for every object x contained by this array, successively + * from the first contained object to the last one. + */ + template + void Apply( F f ) + { + EnsureUnique(); + pcl::Apply( m_data->begin, m_data->end, f ); + } + + /*! + * Calls f( const T& x ) for every object x contained by this array, + * successively from the first contained object to the last one. + */ + template + void Apply( F f ) const noexcept( noexcept( f ) ) + { + pcl::Apply( m_data->begin, m_data->end, f ); + } + + /*! + * Returns an iterator pointing to the first object x in this array such + * that f( const T& x ) is true. Returns End() if such object does not + * exist. + */ + template + iterator FirstThat( F f ) const noexcept( noexcept( f ) ) + { + return const_cast( pcl::FirstThat( m_data->begin, m_data->end, f ) ); + } + + /*! + * Returns an iterator pointing to the last object x in this array such + * that f( const T& x ) is true. Returns End() if such object does not + * exist. + */ + template + iterator LastThat( F f ) const noexcept( noexcept( f ) ) + { + return const_cast( pcl::LastThat( m_data->begin, m_data->end, f ) ); + } + + /*! # + */ + size_type Count( const T& v ) const noexcept + { + return pcl::Count( m_data->begin, m_data->end, v ); + } + + /*! # + */ + template + size_type Count( const T& v, BP p ) const noexcept( noexcept( p ) ) + { + return pcl::Count( m_data->begin, m_data->end, v, p ); + } + + /*! # + */ + template + size_type CountIf( UP p ) const noexcept( noexcept( p ) ) + { + return pcl::CountIf( m_data->begin, m_data->end, p ); + } + + /*! # + */ + iterator MinItem() const noexcept + { + return const_cast( pcl::MinItem( m_data->begin, m_data->end ) ); + } + + /*! # + */ + template + iterator MinItem( BP p ) const noexcept( noexcept( p ) ) + { + return const_cast( pcl::MinItem( m_data->begin, m_data->end, p ) ); + } + + /*! # + */ + iterator MaxItem() const noexcept + { + return const_cast( pcl::MaxItem( m_data->begin, m_data->end ) ); + } + + /*! # + */ + template + iterator MaxItem( BP p ) const noexcept( noexcept( p ) ) + { + return const_cast( pcl::MaxItem( m_data->begin, m_data->end, p ) ); + } + + /*! # + */ + void Reverse() + { + EnsureUnique(); + pcl::Reverse( m_data->begin, m_data->end ); + } + + /*! # + */ + void Rotate( distance_type n ) + { + if ( Length() > 1 && n != 0 ) + { + EnsureUnique(); + if ( (n %= Length()) < 0 ) + n += Length(); + pcl::Rotate( m_data->begin, m_data->begin+n, m_data->end ); + } + } + + /*! # + */ + void ShiftLeft( const T& v, size_type n = 1 ) + { + if ( !IsEmpty() && n > 0 ) + { + EnsureUnique(); + if ( n >= Length() ) + pcl::Fill( m_data->begin, m_data->end, v ); + else + pcl::ShiftLeft( m_data->begin, m_data->begin+n, m_data->end, v ); + } + } + + /*! # + */ + void ShiftRight( const T& v, size_type n = 1 ) + { + if ( !IsEmpty() && n > 0 ) + { + EnsureUnique(); + if ( n >= Length() ) + pcl::Fill( m_data->begin, m_data->end, v ); + else + pcl::ShiftRight( m_data->begin, m_data->end-n, m_data->end, v ); + } + } + + /*! # + */ + iterator Search( const T& v ) const noexcept + { + return const_cast( pcl::LinearSearch( m_data->begin, m_data->end, v ) ); + } + + /*! # + */ + template + iterator Search( const T& v, BP p ) const noexcept( noexcept( p ) ) + { + return const_cast( pcl::LinearSearch( m_data->begin, m_data->end, v, p ) ); + } + + /*! # + */ + iterator SearchLast( const T& v ) const noexcept + { + return const_cast( pcl::LinearSearchLast( m_data->begin, m_data->end, v ) ); + } + + /*! # + */ + template + iterator SearchLast( const T& v, BP p ) const noexcept( noexcept( p ) ) + { + return const_cast( pcl::LinearSearchLast( m_data->begin, m_data->end, v, p ) ); + } + + /*! # + */ + template + iterator SearchSubset( FI i, FI j ) const noexcept + { + return const_cast( pcl::Search( m_data->begin, m_data->end, i, j ) ); + } + + /*! # + */ + template + iterator SearchSubset( FI i, FI j, BP p ) const noexcept( noexcept( p ) ) + { + return const_cast( pcl::Search( m_data->begin, m_data->end, i, j, p ) ); + } + + /*! # + */ + template + iterator SearchSubset( const C& x ) const noexcept + { + PCL_ASSERT_DIRECT_CONTAINER( C, T ); + return const_cast( pcl::Search( m_data->begin, m_data->end, x.Begin(), x.End() ) ); + } + + /*! # + */ + template + iterator SearchSubset( const C& x, BP p ) const noexcept( noexcept( p ) ) + { + PCL_ASSERT_DIRECT_CONTAINER( C, T ); + return const_cast( pcl::Search( m_data->begin, m_data->end, x.Begin(), x.End(), p ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( BI i, BI j ) const noexcept + { + return const_cast( pcl::SearchLast( m_data->begin, m_data->end, i, j ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( BI i, BI j, BP p ) const noexcept( noexcept( p ) ) + { + return const_cast( pcl::SearchLast( m_data->begin, m_data->end, i, j, p ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( const C& x ) const noexcept + { + PCL_ASSERT_DIRECT_CONTAINER( C, T ); + return const_cast( pcl::SearchLast( m_data->begin, m_data->end, x.Begin(), x.End() ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( const C& x, BP p ) const noexcept( noexcept( p ) ) + { + PCL_ASSERT_DIRECT_CONTAINER( C, T ); + return const_cast( pcl::SearchLast( m_data->begin, m_data->end, x.Begin(), x.End(), p ) ); + } + + /*! # + */ + bool Contains( const T& v ) const noexcept + { + return Search( v ) != m_data->end; + } + + /*! # + */ + template + bool Contains( const T& v, BP p ) const noexcept( noexcept( p ) ) + { + return Search( v, p ) != m_data->end; + } + + /*! # + */ + template + iterator ContainsSubset( FI i, FI j ) const noexcept + { + return SearchSubset( i, j ) != m_data->end; + } + + /*! # + */ + template + iterator ContainsSubset( FI i, FI j, BP p ) const noexcept( noexcept( p ) ) + { + return SearchSubset( i, j, p ) != m_data->end; + } + + /*! # + */ + template + iterator ContainsSubset( const C& c ) const noexcept + { + return SearchSubset( c ) != m_data->end; + } + + /*! # + */ + template + iterator ContainsSubset( const C& c, BP p ) const noexcept( noexcept( p ) ) + { + return SearchSubset( c, p ) != m_data->end; + } + + /*! # + */ + void Sort() + { + EnsureUnique(); + pcl::QuickSort( m_data->begin, m_data->end ); + } + + /*! # + */ + template + void Sort( BP p ) + { + EnsureUnique(); + pcl::QuickSort( m_data->begin, m_data->end, p ); + } + + /*! + * Exchanges two dynamic arrays \a x1 and \a x2. + */ + friend void Swap( Array& x1, Array& x2 ) noexcept + { + pcl::Swap( x1.m_data, x2.m_data ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each element in this array, this function appends a string + * representation (known as a \e token) to the target string \a s. If the + * array contains more than one element, successive tokens are separated + * with the specified \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform an array element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + const_iterator i = m_data->begin; + if ( i < m_data->end ) + { + s.Append( S( *i ) ); + if ( ++i < m_data->end ) + do + { + s.Append( separator ); + s.Append( S( *i ) ); + } + while ( ++i < m_data->end ); + } + return s; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each element x in this array, this function appends a string + * representation (known as a \e token) to the target string \a s by calling + * the \a append function: + * + *\code append( s, S( x ) ); \endcode + * + * If the array contains more than one element, successive tokens are + * separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform an + * array element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably easier to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + const_iterator i = m_data->begin; + if ( i < m_data->end ) + { + append( s, S( *i ) ); + if ( ++i < m_data->end ) + { + S p( separator ); + do + { + append( s, p ); + append( s, S( *i ) ); + } + while ( ++i < m_data->end ); + } + } + return s; + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return ToSeparated( s, ',' ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return ToSeparated( s, ' ' ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return ToSeparated( s, '\t' ); + } + + /*! + * Generates a newline-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\n' ); \endcode + */ + template + S& ToNewLineSeparated( S& s ) const + { + return ToSeparated( s, '\n' ); + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this array. + * + * This function calls pcl::Hash64() for the internal array buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const + { + return pcl::Hash64( m_data->begin, m_data->Size(), seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this array. + * + * This function calls pcl::Hash32() for the internal array buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const noexcept + { + return pcl::Hash32( m_data->begin, m_data->Size(), seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this array. This + * function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const noexcept + { + return Hash64( seed ); + } + + // ------------------------------------------------------------------------- + +private: + + /*! + * \struct Data + * \internal + * Reference-counted array data structure. + */ + struct Data : public ReferenceCounter + { + iterator begin = nullptr; //!< Beginning of the dynamic array + iterator end = nullptr; //!< End of the array + iterator available = nullptr; //!< End of the allocated block + allocator alloc; //!< The allocator object + + /*! + * Constructs an empty array data structure. + */ + Data() = default; + + /*! + * Destroys an array data structure. + */ + ~Data() + { + Deallocate(); + } + + /*! + * Returns the size in bytes of the array. + */ + size_type Size() const noexcept + { + return Length()*sizeof( T ); + } + + /*! + * Returns the number of elements in the array. + */ + size_type Length() const noexcept + { + return end - begin; + } + + /*! + * Returns the total capacity of the allocated block in array elements. + */ + size_type Capacity() const noexcept + { + return available - begin; + } + + /*! + * Returns the number of array elements available in the allocated block. + */ + size_type Available() const noexcept + { + return available - end; + } + + /*! + * Returns true iff the array is empty. + */ + bool IsEmpty() const noexcept + { + return begin == end; + } + + /*! + * Allocates space to store at least \a n array elements, and updates + * internal pointers to define an array of \a n elements. + */ + void Allocate( size_type n ) + { + if ( n > 0 ) + { + size_type m = alloc.PagedLength( n ); + begin = alloc.Allocate( m ); + end = begin + n; + available = begin + m; + } + } + + /*! + * Deallocates array data, yielding an empty structure. + */ + void Deallocate() + { + PCL_CHECK( (begin == nullptr) ? end == nullptr : begin < end ) + if ( begin != nullptr ) + { + Destroy( begin, end ); + alloc.Deallocate( begin ); + begin = end = available = nullptr; + } + } + + /*! + * Constructs array elements with default values in the range [i,j). + */ + void Initialize( iterator __restrict__ i, iterator __restrict__ j ) + { + for ( ; i < j; ++i ) + pcl::Construct( i, alloc ); + } + + /*! + * Constructs \a n consecutive array elements with default values, + * starting from the element pointed to by \a i. + */ + void Initialize( iterator __restrict__ i, size_type n ) + { + for ( ; n > 0; ++i, --n ) + pcl::Construct( i, alloc ); + } + + /*! + * Constructs array elements with the specified value \a v in the range + * [i,j). + */ + void Initialize( iterator __restrict__ i, iterator __restrict__ j, const T& v ) + { + for ( ; i < j; ++i ) + pcl::Construct( i, v, alloc ); + } + + /*! + * Constructs \a n consecutive array elements with the specified value + * \a v, starting from the element pointed to by \a i. + */ + void Initialize( iterator __restrict__ i, size_type n, const T& v ) + { + for ( ; n > 0; ++i, --n ) + pcl::Construct( i, v, alloc ); + } + + /*! + * Copy-constructs array elements starting from the element pointed to by + * \a i, with source elements in the range [p,q) of iterators. Returns an + * iterator after the last constructed element. + */ + template + iterator Build( iterator __restrict__ i, FI p, FI q ) + { + for ( ; p != q; ++i, ++p ) + pcl::Construct( i, *p, alloc ); + return i; + } + + /*! + * Causes this array to grow by \a n uninitialized elements at the + * array location corresponding to the specified iterator \a i. Returns + * an iterator pointing to the first newly created element. + */ + iterator UninitializedGrow( iterator __restrict__ i, size_type n ) + { + if ( n > 0 ) + if ( Available() >= n ) + { + if ( i < end ) + { + iterator __restrict__ j1 = end; + iterator __restrict__ j2 = end + n; + + for ( ;; ) + { + pcl::Construct( --j2, *--j1, alloc ); + + if ( j1 == i ) + { + j2 = end; + break; + } + else if ( j2 == end ) + { + do + *--j2 = *--j1; + while ( j1 > i ); + break; + } + } + + Destroy( i, j2 ); + } + end += n; + } + else + { + size_type m = alloc.PagedLength( Length()+n ); + iterator b = alloc.Allocate( m ); + iterator r = Build( b, begin, i ); + iterator e = Build( r+n, i, end ); + + Deallocate(); + begin = b; + end = e; + available = b + m; + i = r; + } + + return i; + } + + /*! + * Destroys array elements in the range [i,j). + */ + static void Destroy( iterator i, iterator j ) + { + pcl::Destroy( i, j ); + } + }; + + /*! + * \internal + * The reference-counted array data. + */ + Data* m_data = nullptr; + + /*! + * \internal + * Dereferences array data and disposes it if it becomes garbage. + */ + void DetachFromData() + { + if ( !m_data->Detach() ) + delete m_data; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup array_relational_operators Array Relational Operators + */ + +/*! + * Returns true only if two arrays \a x1 and \a x2 are equal. This operator + * compares the objects contained by both arrays. + * \ingroup array_relational_operators + */ +template inline +bool operator ==( const Array& x1, const Array& x2 ) noexcept +{ + return x1.Length() == x2.Length() && pcl::Equal( x1.Begin(), x2.Begin(), x2.End() ); +} + +/*! + * Returns true only if an array \a x1 precedes another array \a x2. This + * operator compares the objects contained by both arrays. + * \ingroup array_relational_operators + */ +template inline +bool operator <( const Array& x1, const Array& x2 ) noexcept +{ + return pcl::Compare( x1.Begin(), x1.End(), x2.Begin(), x2.End() ) < 0; +} + +/*! + * \defgroup array_insertion_operators Array Insertion Operators + */ + +/*! + * Appends an object \a v to an array \a x. Returns a reference to the array. + * + * The template argument type T must have conversion semantics from the type V, + * such as T::T( const V& ) or equivalent. + * \ingroup array_insertion_operators + */ +template inline +Array& operator <<( Array& x, const V& v ) +{ + x.Append( T( v ) ); + return x; +} + +/*! + * Appends an object \a v to an array \a x. Returns a reference to the array. + * + * The template argument type T must have conversion semantics from the type V, + * such as T::T( const V& ) or equivalent. + * \ingroup array_insertion_operators + */ +template inline +Array& operator <<( Array&& x, const V& v ) +{ + x.Append( T( v ) ); + return x; +} + +/*! + * Appends an array \a x2 to an array \a x1. Returns a reference to the + * left-hand array \a x1. + * \ingroup array_insertion_operators + */ +template inline +Array& operator <<( Array& x1, const Array& x2 ) +{ + x1.Append( x2 ); + return x1; +} + +/*! + * Appends an array \a x2 to a temporary array \a x1. Returns a reference to + * the left-hand array \a x1. + * \ingroup array_insertion_operators + */ +template inline +Array& operator <<( Array&& x1, const Array& x2 ) +{ + x1.Append( x2 ); + return x1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Array_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Array.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Association.h b/3rdparty/include/pcl/Association.h new file mode 100644 index 0000000..ad9acf4 --- /dev/null +++ b/3rdparty/include/pcl/Association.h @@ -0,0 +1,164 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Association.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_Association_h +#define __PCL_Association_h + +/// \file pcl/Association.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Association + * \brief Generic association of two objects. + */ +template +class PCL_CLASS Association +{ +public: + + T1 first; //!< First member of this association + T2 second; //!< Second member of this association + + /*! + * Constructs an association with default-constructed member values. + */ + Association() = default; + + /*! + * Copy constructor. + */ + Association( const Association& ) = default; + + /*! + * Move constructor. + */ + Association( Association&& ) = default; + + /*! + * Constructs an association with the specified values \a x1 and \a x2, + * respectively for the \a first and \a second members. + */ + Association( const T1& x1, const T2& x2 ) + : first( x1 ) + , second( x2 ) + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup association_utilities Association Operators and Utility Functions + */ + +/*! + * Returns an Association whose members are copies of the specified objects + * \a x1 and \a x2. + * \ingroup association_utilities + */ +template inline +Association Associate( const T1& x1, const T2& x2 ) +{ + return Association( x1, x2 ); +} + +/*! + * Returns true iff two associations, \a x1 and \a x2, are equal. Two + * associations are equal if their homolog members are equal. + * \ingroup association_utilities + */ +template inline +bool operator ==( const Association& x1, const Association& x2 ) +{ + return x1.first == x2.first && x1.second == x2.second; +} + +/*! + * Returns true iff an association \a x1 is less than other association \a x2. + * The comparison algorithm is as follows: + * + * \code + * if ( x1.first == x2.first ) + * return x1.second < x2.second; + * else + * return x1.first < x2.first; + * \endcode + * + * So in association comparisons the first member of each association has + * precedence over the second member. + * + * The implementation of this operator only requires less than + * semantics for the two types T1 and T2; it doesn't use equality operators. + * \ingroup association_utilities + */ +template inline +bool operator <( const Association& x1, const Association& x2 ) +{ + //return (x1.first == x2.first) ? x1.second < x2.second : x1.first < x2.first; + return (x1.first < x2.first) ? true : ((x2.first < x1.first) ? false : x1.second < x2.second); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Association_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Association.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AstrometricMetadata.h b/3rdparty/include/pcl/AstrometricMetadata.h new file mode 100644 index 0000000..e80d081 --- /dev/null +++ b/3rdparty/include/pcl/AstrometricMetadata.h @@ -0,0 +1,1121 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AstrometricMetadata.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_AstrometricMetadata_h +#define __PCL_AstrometricMetadata_h + +/// \file pcl/AstrometricMetadata.h + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ + class ImageWindow; +} +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup astrometry_support Astrometry Support Classes + * + * This group of classes implement the core astrometry support on the + * PixInsight platform. + * + * The original implementation of these classes has been contributed by Spanish + * software developer and PTeam member Andrés del Pozo, who is also the author + * of all astrometry scripts available in the standard PixInsight distribution, + * including the ImageSolver and AnnotateImage scripts, among others. + */ + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION +class PCL_CLASS ImageWindow; +#endif + +class PCL_CLASS XISFReader; +class PCL_CLASS XISFWriter; + +/*! + * \class AstrometricMetadata + * \brief Astrometric metadata + * + * \ingroup astrometry_support + */ +class PCL_CLASS AstrometricMetadata +{ +public: + + /*! + * \struct pcl::AstrometricMetadata::DescriptionItems + * \brief A collection of strings describing the properties and parameters + * of an astrometric solution. + */ + struct DescriptionItems + { + String referenceMatrix; + String wcsTransformationType; + String controlPoints; + String splineLengths; + String projectionName; + String projectionOrigin; + String resolution; + String rotation; + String referenceSystem; + String observationStartTime; + String observationEndTime; + String observerLocation; + String focalDistance; + String pixelSize; + String fieldOfView; + String centerCoordinates; + String topLeftCoordinates; + String topRightCoordinates; + String bottomLeftCoordinates; + String bottomRightCoordinates; + }; + + /*! + * Default constructor. Constructs an uninitialized %AstrometricMetadata + * object. + */ + AstrometricMetadata() = default; + + /*! + * Copy constructor. + */ + AstrometricMetadata( const AstrometricMetadata& x ) + : m_projection( x.m_projection->Clone() ) + , m_transformWI( x.m_transformWI->Clone() ) + , m_refSys( x.m_refSys ) + , m_width( x.m_width ) + , m_height( x.m_height ) + , m_pixelSize( x.m_pixelSize ) + , m_obsStartTime( x.m_obsStartTime ) + , m_obsEndTime( x.m_obsEndTime ) + , m_geoLongitude( x.m_geoLongitude ) + , m_geoLatitude( x.m_geoLatitude ) + , m_geoHeight( x.m_geoHeight ) + , m_resolution( x.m_resolution ) + , m_focalLength( x.m_focalLength ) + { + } + + /*! + * Move constructor. + */ + AstrometricMetadata( AstrometricMetadata&& ) = default; + + /*! + * Constructor from minimal data. + * + * \param projection Pointer to a dynamically allocated projection + * system. + * + * \param worldTransformation Pointer to a dynamically allocated world + * transformation. + * + * \param width Width in pixels of the image with which this + * astrometric solution is associated. + * + * \param height Height in pixels of the image with which this + * astrometric solution is associated. + * + * Ownership of the specified \a projection and \a worldTransformation + * objects will be transferred to this object, which will destroy and + * deallocate them when appropriate. + */ + AstrometricMetadata( ProjectionBase* projection, WorldTransformation* worldTransformation, int width, int height ); + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + // Implemented in /core/Components/ImageWindow.cpp + AstrometricMetadata( const pi::ImageWindow* ); +#else + /*! + * Constructs an %AstrometricMetadata object from the existing keywords and + * properties of an image \a window. + */ + AstrometricMetadata( const ImageWindow& window ); +#endif + + /*! + * Constructs an %AstrometricMetadata object from the existing keywords and + * properties of the currently selected image in an XISF \a reader. + */ + AstrometricMetadata( XISFReader& reader ); + + /*! + * Virtual destructor. + */ + virtual ~AstrometricMetadata() + { + } + + /*! + * Copy constructor. Returns a reference to this object. + */ + AstrometricMetadata& operator =( const AstrometricMetadata& x ) + { + m_projection = x.m_projection->Clone(); + m_transformWI = x.m_transformWI->Clone(); + m_refSys = x.m_refSys; + m_width = x.m_width; + m_height = x.m_height; + m_pixelSize = x.m_pixelSize; + m_obsStartTime = x.m_obsStartTime; + m_obsEndTime = x.m_obsEndTime; + m_geoLongitude = x.m_geoLongitude; + m_geoLatitude = x.m_geoLatitude; + m_geoHeight = x.m_geoHeight; + m_resolution = x.m_resolution; + m_focalLength = x.m_focalLength; + return *this; + } + + /*! + * Move constructor. Returns a reference to this object. + */ + AstrometricMetadata& operator =( AstrometricMetadata&& ) = default; + + /*! + * Returns true iff this object is valid. A valid %AstrometricMetadata + * instance defines a projection system and a world transformation. + */ + bool IsValid() const + { + return !m_projection.IsNull() && !m_transformWI.IsNull(); + } + + /*! + * Checks that this astrometric solution is valid and can perform coherent + * coordinate transformations, and returns the reprojection errors + * measured at the center and the four corners of the image. + * + * \param[out] centerErrors Reprojection errors at the geometric center + * of the image, or (Width()/2,Height()/2) + * image coordinates. + * + * \param[out] topLeftErrors Reprojection errors at (0,0) image + * coordinates. + * + * \param[out] topRightErrors Reprojection errors at (Width(),0) image + * coordinates. + * + * \param[out] bottomLeftErrors Reprojection errors at (0,Height()) image + * coordinates. + * + * \param[out] bottomRightErrors Reprojection errors at (Width(),Height()) + * image coordinates. + * + * This routine performs five successive coordinate transformations, from + * image to celestial and from celestial to image coordinates, computed for + * the four corners and the geometric center of the image. The reported + * values in the specified point variables are the differences between the + * initial and final image coordinates, on the X and Y axes, in pixels. + * + * This function throws an Error exception if the solution has not been + * initialized, or if it cannot perform valid coordinate transformations. + */ + void Verify( DPoint& centerErrors, + DPoint& topLeftErrors, DPoint& topRightErrors, + DPoint& bottomLeftErrors, DPoint& bottomRightErrors ) const; + + /*! + * Checks that this astrometric solution is valid and can perform coherent + * coordinate transformations. + * + * \param tolerance Maximum difference in pixels allowed for validation. + * The default value is 0.01 pixels. + * + * This routine performs two successive coordinate transformations, from + * image to celestial and from celestial to image coordinates, computed for + * the geometric center of the image. If the absolute value of the + * difference between the initial and final image coordinates is greater + * than the specified tolerance in pixels, for one or both axes, an Error + * exception is thrown. + * + * This function also throws an Error exception if the solution has not been + * initialized, or if it cannot perform valid coordinate transformations. + */ + void Validate( double tolerance = 0.01 ) const; + + /*! + * Returns true if this object uses a world transformation based on 2-D + * surface splines (or thin plates), false if a WCS linear + * transformation is being used. + */ + bool HasSplineWorldTransformation() const + { + return dynamic_cast( m_transformWI.Pointer() ) != nullptr; + } + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + // Implemented in /core/Components/ImageWindow/ImageWindow.cpp + void Write( pi::ImageWindow* window, bool notify = true ) const; +#else + /*! + * Updates the keywords and properties of an image \a window to represent + * this astrometric solution. + * + * The pixel dimensions of the image in the target \a window must be + * coherent with this astrometric solution. If that is not true, this member + * function will throw an Error exception. An Error exception will also be + * thrown if this object does not define a valid astrometric solution. + * + * See the UpdateBasicKeywords(), UpdateWCSKeywords() and UpdateProperties() + * member functions for information on the metadata items modified by this + * function. + */ + void Write( ImageWindow& window, bool notify = true ) const; +#endif + + /*! + * Updates the keywords and properties of the current image in an XISF + * \a writer to store the astrometric solution represented by this object. + * + * The caller must ensure that the pixel dimensions of the current image in + * the target %XISF \a writer, that is, the width and height of the image + * being generated, are coherent with this astrometric solution. Currently + * this condition cannot be verified or enforced by this member function. + * + * This function will throw an Error exception if this object does not + * define a valid astrometric solution. + * + * See the UpdateBasicKeywords(), UpdateWCSKeywords() and UpdateProperties() + * member functions for information on the metadata items modified by this + * function. + */ + void Write( XISFWriter& writer ) const; + + /*! + * Returns the name of the coordinate reference system to which this + * astrometric solution has been referred. + * + * This corresponds to the reference system of the coordinates of the + * reference point sources (usually stars with data acquired from + * astrometric catalogs) used to compute the astrometric solution. The + * current implementation supports the following reference systems: + * + * \b ICRS + * + * Reference point source positions are \e astrometric: they include + * corrections for space motion (proper motions, annual parallax and radial + * velocity, when available) and gravitational deflection of light, but + * \e not annual aberration. This is the default reference system that is + * assumed when none is specified or acquired from existing metadata. + * + * \b GCRS + * + * Reference point source positions are \e proper: they include corrections + * for space motion (proper motions, annual parallax and radial velocity, + * when available), gravitational deflection of light, and annual aberration + * (rigorous relativistic model). + * + * Other nonstandard values can be returned by this function, such as + * different values of the RADESYS FITS keyword. Such values will be + * preserved but won't be supported by standard platform implementations. + */ + IsoString ReferenceSystem() const + { + return m_refSys.IsEmpty() ? IsoString( "ICRS" ) : m_refSys; + } + + /*! + * Sets the coordinate reference system. See ReferenceSystem() for more + * information and supported values. + */ + void SetReferenceSystem( const IsoString& refSys ) + { + m_refSys = refSys.Trimmed(); + } + + /*! + * Returns the name of the reference system of celestial coordinates + * derived from the specified image metadata. + * + * \param properties A list of XISF image properties. + * + * \param keywords A list of FITS header keywords. + * + * The reference system will be inferred from the following metadata items: + * + * \li The standard XISF property 'Observation:CelestialReferenceSystem' + * + * \li The standard FITS keyword 'RADESYS'. + * + * In case of metadata duplicity, XISF properties always take precedence + * over FITS keywords. + * + * Typical returned values are "ICRS" and "GCRS". If no valid reference + * system can be deduced from the specified metadata, this function returns + * an empty string. + */ + static IsoString ReferenceSystemFromMetadata( const PropertyArray& properties, const FITSKeywordArray& keywords ); + + /*! + * Returns the width in pixels of the image associated with the astrometric + * solution represented by this object. + */ + int Width() const + { + return m_width; + } + + /*! + * Returns the height in pixels of the image associated with the astrometric + * solution represented by this object. + */ + int Height() const + { + return m_height; + } + + /*! + * Returns a pointer to the projection system of this astrometric solution. + * Returns \c nullptr if this object is not valid. + */ + const ProjectionBase* Projection() const + { + return m_projection.Pointer(); + } + + /*! + * Returns a pointer to the world coordinate transformation of this + * astrometric solution. Returns \c nullptr if this object is not valid. + */ + const WorldTransformation* WorldTransform() const + { + return m_transformWI.Pointer(); + } + + /*! + * Returns the image resolution in seconds of arc per pixel, calculated from + * the specified \a focal distance in millimeters. + */ + double ResolutionFromFocal( double focal ) const + { + return (focal > 0) ? m_pixelSize.OrElse( 0 )/focal * 0.18/Const::pi() : 0.0; + } + + /*! + * Returns the focal distance in millimeters, calculated from the specified + * image \a resolution expressed in seconds of arc per pixel. + */ + double FocalFromResolution( double resolution ) const + { + return ResolutionFromFocal( resolution ); + } + + /*! + * Returns the angle of rotation of the Y axis of the image with respect to + * the north direction, as represented on a flat projection of the celestial + * sphere. A rotation angle of zero aligns north along the positive Y axis. + * A positive rotation angle rotates the Y axis from north to east. + * + * The returned value is the rotation angle of the projection in degrees. + * The \a flipped variable will be true iff the projection is mirrored on + * the east-west direction. + */ + double Rotation( bool& flipped ) const; + + /*! + * Returns the resolution of the image in degrees per pixel. + * + * This value usually is an approximation since it changes across the image. + * It should only be used for informative purposes. + */ + double Resolution() const + { + return m_resolution; + } + + /*! + * Returns the observation start time, if available. When defined, the + * returned value should be represented in the UTC timescale. + */ + Optional ObservationStartTime() const + { + return m_obsStartTime; + } + + /*! + * Sets the observation start time. The specified \a startTime value should + * be represented in the UTC timescale. + */ + void SetObservationStartTime( TimePoint startTime ) + { + m_obsStartTime = startTime; + } + + /*! + * Returns the observation end time, if available. When defined, the + * returned value should be represented in the UTC timescale. + */ + Optional ObservationEndTime() const + { + return m_obsEndTime; + } + + /*! + * Sets the observation end time. The specified \a endTime value should be + * represented in the UTC timescale. + */ + void SetObservationEndTime( TimePoint endTime ) + { + m_obsEndTime = endTime; + } + + /*! + * Returns an estimate of the observation middle time. If both the start and + * end times are defined, returns the time point between them. If only the + * start time is defined, it is returned. Otherwise an undefined object is + * returned. + */ + Optional ObservationMiddleTime() const + { + if ( !m_obsStartTime.IsDefined() ) + return Optional(); + if ( !m_obsEndTime.IsDefined() ) + return m_obsStartTime; + return m_obsStartTime() + (m_obsEndTime() - m_obsStartTime())/2; + } + + /*! + * Returns the geodetic longitude of the observation location, if available. + * The returned value is expressed in degrees in the range (-180,+180], + * reckoned positive eastward of the reference meridian. + */ + Optional LocationLongitude() const + { + return m_geoLongitude; + } + + /*! + * Sets the geodetic longitude of the observation location. The specified + * \a longitude must be expressed in degrees and can be either in the range + * [0,360] or [-180,+180], reckoned positive eastward. + * + * If a value out of the valid range is specified, this function will throw + * an Error exception. + */ + void SetLocationLongitude( double longitude ) + { + if ( longitude > 180 ) + longitude -= 360; + else if ( longitude <= -180 ) + longitude += 360; + if ( longitude < -180 || longitude > +180 ) + throw Error( "AstrometricMetadata::SetLocationLongitude(): Geographic longitude out of range." ); + m_geoLongitude = longitude; + } + + /*! + * Returns the geodetic latitude of the observation location, if available. + * The returned value is expressed in degrees in the range [-90,+90], + * reckoned positive north of the equator. + */ + Optional LocationLatitude() const + { + return m_geoLatitude; + } + + /*! + * Sets the geodetic latitude of the observation location. The specified + * \a latitude must be expressed in degrees and must be in the range + * [-90,+90], reckoned positive north of the equator. + * + * If a value out of the valid range is specified, this function will throw + * an Error exception. + */ + void SetLocationLatitude( double latitude ) + { + if ( latitude < -90 || latitude > +90 ) + throw Error( "AstrometricMetadata::SetLocationLatitude(): Geographic latitude out of range." ); + m_geoLatitude = latitude; + } + + /*! + * Returns the geodetic height of the observation location in meters, if + * available. + */ + Optional LocationHeight() const + { + return m_geoHeight; + } + + /*! + * Sets the geodetic height of the observation location in meters. + */ + void SetLocationHeight( double height ) + { + m_geoHeight = height; + } + + /*! + * Returns the physical pixel size in micrometers, if available. + */ + Optional PixelSize() const + { + return m_pixelSize; + } + + /*! + * Redefines the physical pixel size in micrometers. Recalculates the focal + * distance as a function of the pixel size. + */ + void SetPixelSize( double pixelSize ) + { + m_pixelSize = pixelSize; + m_focalLength = FocalFromResolution( m_resolution ); + } + + /*! + * Transformation from image coordinates to celestial coordinates. + * + * \param[out] pRD Reference to a point where the output equatorial + * spherical coordinates will be stored, expressed in + * degrees. \a pRD.x will be the right ascension and + * \a pRD.y the declination. Output right ascensions are + * constrained to the [0,360) range. Output declinations + * are in the range [-90,+90]. + * + * \param pI Input image coordinates in pixels. The specified + * location can legally lie outside the image bounds + * defined by [0,0]-[Width(),Height()]. + * + * Returns true iff the specified point \a pI can be projected on the + * celestial sphere using this astrometric solution. + * + * The output coordinates stored in \a pRD will be referred to the reference + * system of this astrometric solution, either ICRS or GCRS, as returned by + * the ReferenceSystem() member function. + * + * \sa RawImageToCelestial(), CelestialToImage() + */ + bool ImageToCelestial( DPoint& pRD, const DPoint& pI ) const + { + if ( !IsValid() ) + throw Error( "Invalid call to AstrometricMetadata::ImageToCelestial(): No astrometric solution." ); + if ( m_projection->Inverse( pRD, m_transformWI->Inverse( pI ) ) ) + { + // Constrain right ascension to the [0,360) range. + if ( pRD.x < 0 ) + pRD.x += 360; + else if ( pRD.x >= 360 ) + pRD.x -= 360; + return true; + } + return false; + } + + /*! + * Transformation from image coordinates to celestial coordinates, without + * enforcing a valid range of right ascensions. + * + * \param[out] pRD Reference to a point where the output equatorial + * spherical coordinates will be stored, expressed in + * degrees. \a pRD.x will be the right ascension and + * \a pRD.y the declination. Output right ascensions are + * \e not constrained to the [0,360) range. Output + * declinations are in the range [-90,+90]. + * + * \param pI Input image coordinates in pixels. The specified + * location can legally lie outside the image bounds + * defined by [0,0]-[Width(),Height()]. + * + * Returns true iff the specified point \a pI can be projected on the + * celestial sphere using this astrometric solution. + * + * The output coordinates stored in \a pRD will be referred to the reference + * system of this astrometric solution, either ICRS or GCRS, as returned by + * the ReferenceSystem() member function. + * + * This function is useful for interpolation schemes where discontinuities + * caused by zero crossings in right ascension, i.e. abrupt changes from 360 + * to 0 degrees, are not admissible numerically. Right ascensions returned + * by this function can be larger than 360 degrees or less than zero, + * ensuring smooth transitions. + * + * \sa ImageToCelestial(), CelestialToImage() + */ + bool RawImageToCelestial( DPoint& pRD, const DPoint& pI ) const + { + if ( !IsValid() ) + throw Error( "Invalid call to AstrometricMetadata::RawImageToCelestial(): No astrometric solution." ); + return m_projection->Inverse( pRD, m_transformWI->Inverse( pI ) ); + } + + /*! + * Transformation from celestial coordinates to image coordinates. + * + * \param[out] pI Reference to a point where the output image coordinates + * will be stored. + * + * \param pRD Input equatorial spherical coordinates expressed in + * degrees. \a pRD.x is the right ascension and \a pRD.y + * is declination. + * + * Returns true iff the specified celestial coordinates can be reprojected + * on the image coordinate system. Note that the output image coordinates + * can lie outside of the image bounds defined by [0,0]-[Width(),Height()]. + * + * The input coordinates specified in \a pRD are expected to be referred to + * the reference system of this astrometric solution, either ICRS or GCRS, + * as returned by the ReferenceSystem() member function. + * + * \sa ImageToCelestial(), RawImageToCelestial() + */ + bool CelestialToImage( DPoint& pI, const DPoint& pRD ) const + { + if ( !IsValid() ) + throw Error( "Invalid call to AstrometricMetadata::CelestialToImage(): No astrometric solution." ); + DPoint pW; + if ( m_projection->Direct( pW, pRD ) ) + { + pI = m_transformWI->Direct( pW ); + return true; + } + return false; + } + + /*! + * Regenerates the astrometric solution from standardized metadata. + * + * \param properties A list of XISF image properties describing + * critical astrometry-related metadata items. + * + * \param keywords A list of FITS header keywords, which should + * contain at least a minimal set of standard WCS + * keywords to define a linear world transformation + * from celestial to image coordinates. + * + * \param controlPoints If not empty, this array must contain a list of + * spline control points and generation parameters + * serialized in raw binary format. See the + * SplineWorldTransformation class for more + * information. + * + * \param width Width in pixels of the image with which this + * astrometric solution is associated. + * + * \param height Height in pixels of the image with which this + * astrometric solution is associated. + * + * The following standard XISF properties will be extracted from the + * specified \a properties array, if available: + * + *
+    * Observation:CelestialReferenceSystem
+    * Observation:Center:RA
+    * Observation:Center:Dec
+    * Observation:Equinox
+    * Observation:Time:Start
+    * Observation:Time:End
+    * Observation:Location:Longitude
+    * Observation:Location:Latitude
+    * Observation:Location:Elevation
+    * Instrument:Telescope:FocalLength
+    * Instrument:Sensor:XPixelSize
+    * 
+ * + * %XISF properties will take precedence over equivalent %FITS keywords. + * + * If the specified \a controlPoints array contains a valid serialization of + * spline control points, the astrometric solution will use a high-precision + * world transformation based on two-dimensional surface splines, also knwon + * as thin plate splines, which is capable of modeling local image + * distortions that are intractable with WCS linear transformations. + * + * If this object contains valid metadata before calling this function, it + * will be disposed as appropriate, and a completely new astrometric + * solution will be constructed. + * + * This member function can throw exceptions (of the Error class) if either + * the specified \a controlPoints array is not empty and does not contain a + * valid raw serialization of a spline-based transformation, or if the + * generated coordinate transformations are not invalid (in the numerical or + * geometric sense). + */ + void Build( const PropertyArray& properties, const FITSKeywordArray& keywords, + const ByteArray& controlPoints, int width, int height ); + + /*! + * Updates the specified \a keywords array with basic astrometric FITS + * header keywords. This includes a number of standard instrumental and + * observational keywords, as well as some customary nonstandard keywords, + * included for compatibility with third-party applications: + * + *
+    * RA
+    * OBJCTRA
+    * DEC
+    * OBJCTDEC
+    * DATE-OBS
+    * DATE-END
+    * OBSGEO-L
+    * LONG-OBS
+    * OBSGEO-B
+    * LAT-OBS
+    * OBSGEO-H
+    * ALT-OBS
+    * FOCALLEN
+    * XPIXSZ
+    * YPIXSZ
+    * PIXSIZE
+    * 
+ * + * Keywords are updated when the corresponding metadata items are available. + */ + void UpdateBasicKeywords( FITSKeywordArray& keywords ) const; + + /*! + * Updates the specified \a keywords array with the set of standard WCS FITS + * header keywords: + * + *
+    * RADESYS
+    * EQUINOX
+    * EPOCH
+    * CTYPE1
+    * CTYPE2
+    * CRVAL1
+    * CRVAL2
+    * CRPIX1
+    * CRPIX2
+    * CD1_1
+    * CD1_2
+    * CD2_1
+    * CD2_2
+    * PC1_1
+    * PC1_2
+    * PC2_1
+    * PC2_2
+    * CDELT1
+    * CDELT2
+    * CROTA1
+    * CROTA2
+    * PV1_1
+    * PV1_2
+    * PV1_3
+    * PV1_4
+    * LONPOLE
+    * LATPOLE
+    * 
+ * + * In addition, a custom nonstandard keyword is also generated to signal the + * availability of a spline-based astrometric solution: + * + *
+    * REFSPLIN
+    * 
+ */ + void UpdateWCSKeywords( FITSKeywordArray& keywords ) const; + + /*! + * Updates the specified \a properties array with a restricted set of view + * properties to reflect the state of this astrometric solution. + * + * The following standard XISF properties will be created or redefined: + * + *
+    * Instrument:Telescope:FocalLength
+    * Instrument:Sensor:XPixelSize
+    * Instrument:Sensor:YPixelSize
+    * Observation:Center:RA
+    * Observation:Center:Dec
+    * Observation:CelestialReferenceSystem
+    * Observation:Equinox
+    * 
+ * + * The following properties can be removed if the transformation is valid, + * since the default coordinate reference point is the geometric center of + * the image, which is used to calculate the values of the standard + * \c Observation:Center:RA and \c Observation:Center:Dec properties: + * + *
+    * Observation:Center:X
+    * Observation:Center:Y
+    * 
+ * + * The following properties will be created or redefined if the + * corresponding metadata items are available, or removed otherwise: + * + *
+    * Observation:Time:Start
+    * Observation:Time:End
+    * Observation:Location:Longitude
+    * Observation:Location:Latitude
+    * Observation:Location:Elevation
+    * 
+ * + * In addition, the following nonstandard property, used by platform image + * plate solving scripts, will be created, redefined, or removed: + * + *
+    * Transformation_ImageToProjection
+    * 
+ */ + void UpdateProperties( PropertyArray& properties ) const; + + /*! + * Removes astrometry-related FITS header keywords from the specified + * \a keywords array. This includes some basic instrumental and + * observational keywords, as well as the following keywords: + * + *
+    * RADESYS
+    * EQUINOX
+    * EPOCH
+    * CTYPE1
+    * CTYPE2
+    * CRVAL1
+    * CRVAL2
+    * CRPIX1
+    * CRPIX2
+    * CD1_1
+    * CD1_2
+    * CD2_1
+    * CD2_2
+    * PC1_1
+    * PC1_2
+    * PC2_1
+    * PC2_2
+    * CDELT1
+    * CDELT2
+    * CROTA1
+    * CROTA2
+    * PV1_1
+    * PV1_2
+    * PV1_3
+    * PV1_4
+    * LONPOLE
+    * LATPOLE
+    * REFSPLIN
+    * 
+ * + * If \a removeCenterKeywords is true, the following keywords will also be + * removed: + * + *
+    * RA
+    * OBJCTRA
+    * DEC
+    * OBJCTDEC
+    * 
+ * + * If \a removeScaleKeywords is true, the following keywords will also be + * removed: + * + *
+    * FOCALLEN
+    * XPIXSZ
+    * YPIXSZ
+    * PIXSIZE
+    * 
+ */ + static void RemoveKeywords( FITSKeywordArray& keywords, bool removeCenterKeywords = true, bool removeScaleKeywords = true ); + + /*! + * Rescales the values of existing FITS header keywords defining physical + * pixel dimensions in the specified \a keywords array. + * + * This function multiplies the values of the following keywords by the + * specified \a scalingFactor: + * + *
+    * XPIXSZ
+    * YPIXSZ
+    * PIXSIZE
+    * 
+ * + * This is useful in cases where a geometric transformation has to be + * applied to an image to modify its scale, such as a resampling operation. + */ + static void RescalePixelSizeKeywords( FITSKeywordArray& keywords, double scalingFactor ); + + /*! + * Removes astrometry-related XISF properties from the specified + * \a properties array. + * + * If \a removeCenterProperties is true, the following properties will also + * be removed: + * + *
+    * Observation:Center:RA
+    * Observation:Center:Dec
+    * Observation:Center:X
+    * Observation:Center:Y
+    * Observation:CelestialReferenceSystem
+    * Observation:Equinox
+    * 
+ * + * If \a removeScaleProperties is true, the following properties will also + * be removed: + * + *
+    * Instrument:Telescope:FocalLength
+    * Instrument:Sensor:XPixelSize
+    * Instrument:Sensor:YPixelSize
+    * 
+ * + * In addition, the following nonstandard property, used by platform image + * plate solving scripts, will be removed: + * + *
+    * Transformation_ImageToProjection
+    * 
+ */ + static void RemoveProperties( PropertyArray& properties, bool removeCenterProperties = true, bool removeScaleProperties = true ); + + /*! + * Removes astrometry-related XISF properties from the specified \a window's + * main view. + * + * See RemoveProperties( PropertyArray&, bool, bool ) for detailed + * information. + */ + static void RemoveProperties( ImageWindow& window, bool removeCenterProperties = true, bool removeScaleProperties = true ); + + /*! + * Rescales the values of existing XISF properties defining physical pixel + * dimensions in the specified \a properties array. + * + * This function multiplies the values of the following properties by the + * specified \a scalingFactor: + * + *
+    * Instrument:Sensor:XPixelSize
+    * Instrument:Sensor:YPixelSize
+    * 
+ * + * This is useful in cases where a geometric transformation has to be + * applied to an image to modify its scale, such as a resampling operation. + */ + static void RescalePixelSizeProperties( PropertyArray& properties, double scalingFactor ); + + /*! + * Rescales the values of existing XISF properties defining physical pixel + * dimensions for the specified \a window's main view. + * + * See RescalePixelSizeProperties( PropertyArray&, double ) for detailed + * information. + */ + static void RescalePixelSizeProperties( ImageWindow& window, double scalingFactor ); + + /*! + * Returns a printable textual representation of the metadata properties and + * parameters of the astrometric solution represented by this object. + */ + String Summary() const; + + /*! + * Returns a collection of strings describing the metadata properties and + * parameters of this astrometric solution. + * + * The returned object is a copy of an internal structure that is generated + * automatically as necessary and cached between successive function calls. + * This allows for efficient real-time representations of astrometric + * metadata and parameters. + */ + DescriptionItems Description() const + { + UpdateDescription(); + return m_description.IsNull() ? DescriptionItems() : *m_description; + } + +private: + + AutoPointer m_projection; + AutoPointer m_transformWI; + IsoString m_refSys; // ICRS(default) or GCRS + Optional m_equinox; // years - deprecated + int m_width = 0; // px + int m_height = 0; // px + Optional m_pixelSize; // um + Optional m_obsStartTime; // UTC + Optional m_obsEndTime; // UTC + Optional m_geoLongitude; // deg + Optional m_geoLatitude; // deg + Optional m_geoHeight; // m + double m_resolution = 0; // deg/px + Optional m_focalLength; // mm + mutable + AutoPointer m_description; + + WCSKeywords ComputeWCSKeywords() const; + void UpdateDescription() const; +}; + +} //pcl + +#endif // __AstrometricMetadata_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AstrometricMetadata.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Atomic.h b/3rdparty/include/pcl/Atomic.h new file mode 100644 index 0000000..6c82b6c --- /dev/null +++ b/3rdparty/include/pcl/Atomic.h @@ -0,0 +1,670 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Atomic.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_Atomic_h +#define __PCL_Atomic_h + +/// \file pcl/Atomic.h + +#include + +#ifdef __PCL_WINDOWS +# include +#ifdef _MSC_VER +# pragma intrinsic (_InterlockedIncrement) +# pragma intrinsic (_InterlockedDecrement) +# pragma intrinsic (_InterlockedCompareExchange) +# pragma intrinsic (_InterlockedExchange) +# pragma intrinsic (_InterlockedExchangeAdd) +#endif +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class AtomicInt + * \brief Atomic operations on integers. + * + * %AtomicInt allows non-blocking synchronization of multithreaded code with + * respect to reference counting and other critical operations in parallel + * algorithm implementations. This class is used extensively by PCL code to + * implement copy-on-write shared containers and container operations in a + * thread-safe way. An example is the ReferenceCounter class, which is at the + * hearth of most PCL container and image classes. + * + * %AtomicInt implements the following synchronization primitives on integers: + * + * reference \n + * dereference \n + * test-and-set \n + * fetch-and-store \n + * fetch-and-add + * + * \sa ReferenceCounter + */ +class PCL_CLASS AtomicInt +{ +public: + + /*! + * Constructs an %AtomicInt instance with the specified \a value. When not + * explicitly specified, the default value is zero. + */ + AtomicInt( int value = 0 ) + : m_value( value ) + { + // ### N.B.: + // The default zero initialization is *critical* - DO NOT change it. + } + + /*! + * Copy constructor. + */ + AtomicInt( const AtomicInt& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + AtomicInt& operator =( const AtomicInt& ) = default; + + /*! + * Returns the current value of this atomic integer. + * + * \note This operation is not guaranteed to be atomic. + */ + operator int() const + { + return m_value; + } + + /*! + * Logical negation operator. Returns true iff this atomic integer is zero. + * + * \note This operation is not guaranteed to be atomic. + */ + bool operator !() const + { + return m_value == 0; + } + + /*! + * Equality operator. Returns true iff this atomic integer is equal to an + * integer \a x. + * + * \note This operation is not guaranteed to be atomic. + */ + bool operator ==( int x ) const + { + return m_value == x; + } + + /*! + * Inequality operator. Returns true iff this atomic integer is not equal to + * an integer \a x. + * + * \note This operation is not guaranteed to be atomic. + */ + bool operator !=( int x ) const + { + return m_value != x; + } + + /*! + * Integer assignment operator. Assigns the specified integer \a x to this + * atomic integer. Returns a reference to this object. + * + * \note This operation is not guaranteed to be atomic. + */ + AtomicInt& operator =( int x ) + { + m_value = x; + return *this; + } + + /*! + * Atomic load operation. + * + * Returns the current value of this atomic integer. + * + * \note The integer load operation is guaranteed to be atomic on all + * supported platforms and architectures. + */ + int Load() + { + return FetchAndAdd( 0 ); + } + + /*! + * Atomic store operation. + * + * Assigns the specified \a newValue to this object. + * + * \note The integer store operation is guaranteed to be atomic on all + * supported platforms and architectures. + */ + void Store( int newValue ) + { + (void)FetchAndStore( newValue ); + } + + /*! + * Atomic increment operation. + * + * Increments the value of this object as an atomic operation. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + void Increment() + { +#ifdef __PCL_WINDOWS + (void)_InterlockedIncrement( &m_value ); +#else + asm volatile( "lock\n\t" + "incl %0\n" + : "=m" (m_value) + : "m" (m_value) + : "memory", "cc" ); +#endif + } + + /*! + * Atomic decrement operation. + * + * Decrements the value of this object as an atomic operation. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + void Decrement() + { +#ifdef __PCL_WINDOWS + (void)_InterlockedDecrement( &m_value ); +#else + asm volatile( "lock\n\t" + "decl %0\n" + : "=m" (m_value) + : "m" (m_value) + : "memory", "cc" ); +#endif + } + + /*! + * Atomic reference operation. + * + * Increments the value of this object as an atomic operation. Returns true + * if the resulting value after incrementing this object is nonzero. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + bool Reference() + { +#ifdef __PCL_WINDOWS + return _InterlockedIncrement( &m_value ) != 0; +#else + uint8 result; + asm volatile( "lock\n\t" + "incl %0\n\t" + "setnz %1\n" + : "=m" (m_value), "=qm" (result) + : "m" (m_value) + : "memory", "cc" ); + return result != 0; +#endif + } + + /*! + * Atomic dereference operation. + * + * Decrements the value of this object as an atomic operation. Returns true + * if the resulting value after decrementing this object is nonzero. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + bool Dereference() + { +#ifdef __PCL_WINDOWS + return _InterlockedDecrement( &m_value ) != 0; +#else + uint8 result; + asm volatile( "lock\n\t" + "decl %0\n\t" + "setnz %1\n" + : "=m" (m_value), "=qm" (result) + : "m" (m_value) + : "memory", "cc" ); + return result != 0; +#endif + } + + /*! + * Atomic test-and-set operation. + * + * If the current value of this object is equal to \a expectedValue, this + * function assigns \a newValue to this object and returns true. If the + * current value is not equal to \a expectedValue, this function performs no + * operation and returns false. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + bool TestAndSet( int expectedValue, int newValue ) + { +#ifdef __PCL_WINDOWS + return _InterlockedCompareExchange( &m_value, newValue, expectedValue ) == expectedValue; +#else + uint8 result; + asm volatile( "lock\n\t" + "cmpxchgl %3,%2\n\t" + "setz %1\n" + : "=a" (newValue), "=qm" (result), "+m" (m_value) + : "r" (newValue), "0" (expectedValue) + : "memory", "cc" ); + return result != 0; +#endif + } + + /*! + * Atomic fetch-and-store operation. + * + * Assigns \a newValue to this object and returns the initial value before + * assignment, as an atomic operation. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + int FetchAndStore( int newValue ) + { +#ifdef __PCL_WINDOWS + return _InterlockedExchange( &m_value, newValue ); +#else + asm volatile( "xchgl %0,%1\n" + : "=r" (newValue), "+m" (m_value) + : "0" (newValue) + : "memory" ); + return newValue; +#endif + } + + /*! + * Atomic fetch-and-add operation. Adds \a valueToAdd to this object and + * returns the initial value before addition, as an atomic operation. + * + * \note This operation is guaranteed to be atomic on all supported + * platforms and architectures. + */ + int FetchAndAdd( int valueToAdd ) + { +#ifdef __PCL_WINDOWS + return _InterlockedExchangeAdd( &m_value, valueToAdd ); +#else + asm volatile( "lock\n\t" + "xaddl %0,%1\n" + : "=r" (valueToAdd), "+m" (m_value) + : "0" (valueToAdd) + : "memory", "cc" ); + return valueToAdd; +#endif + } + +private: + +#ifdef _MSC_VER + __declspec(align(4)) volatile long m_value; +#elif __PCL_WINDOWS + volatile long m_value __attribute__ ((aligned (4))); +#else + volatile int m_value __attribute__ ((aligned (4))); +#endif +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup reentrancy_protection Thread-Safe Protection of Non-Reentrant Code + */ + +// ---------------------------------------------------------------------------- + +/*! + * \class AutoReentrancyGuard + * \brief Automatic reentrancy guard sentinel. + * + * %AutoReentrancyGuard allows you to protect a block of code ensuring that it + * cannot be reentrant. All you need is a static AtomicInt variable that works + * as a 'busy state' flag persistent across function invocations. + * + * Consider the following example: + * + * \code void foo() + * { + * static AtomicInt flag; + * AutoReentrancyGuard guard( flag ); + * if ( guard ) + * { + * // protected code + * } + * } + * \endcode + * + * The function \c foo is not reentrant, so we want to protect it against + * possible reentrant invocations while the function's code is being executed. + * + * The \c flag variable is initially zero (because AtomicInt's default + * constructor initializes its integer member to zero). The first time \c foo + * is called, %AutoReentrancyGuard's constructor can change the value of + * \c flag from zero to one as an atomic operation. When this happens, + * AutoReentrancyGuard::operator bool() returns true, and the code protected + * within the \c if block can be executed. + * + * When the \c guard object gets out of scope (just before the \c foo function + * returns), its class destructor resets \c flag to zero automatically, which + * permits the next non-reentrant execution of \c foo. However, if \c foo is + * called again before \c guard is destroyed, a newly constructed + * %AutoReentrancyGuard object cannot make a transition 0 -> 1 with the static + * \c flag variable, and hence a reentrant execution of the protected code is + * not allowed (in this case, the function simply does nothing and returns + * after the \c if block). Note that the protected code can freely return from + * the function or throw exceptions; the \c flag variable will be reset to zero + * automatically when \c guard gets out of scope. + * + * Since %AutoReentrancyGuard uses AtomicInt to implement atomic transitions, + * code blocks can be protected against reentrant execution in multithreaded + * environments. + * + * The macros PCL_REENTRANCY_GUARDED_BEGIN and PCL_REENTRANCY_GUARDED_END + * greatly simplify reentrancy protection. For example, the above code could be + * implemented as follows: + * + * \code void foo() + * { + * PCL_REENTRANCY_GUARDED_BEGIN + * // protected code + * PCL_REENTRANCY_GUARDED_END + * } \endcode + * + * In addition, the macros PCL_CLASS_REENTRANCY_GUARD and + * PCL_CLASS_REENTRANCY_GUARDED_BEGIN are useful for protection of all + * non-reentrant member functions of a class, and the macros + * PCL_MEMBER_REENTRANCY_GUARD and PCL_MEMBER_REENTRANCY_GUARDED_BEGIN provide + * protection of specific member functions. See these macros for examples. + * + * \ingroup reentrancy_protection + */ +class AutoReentrancyGuard +{ +public: + + /*! + * Constructs an %AutoReentrancyGuard object to monitor the specified + * \a guard variable. If \c guard is zero, its value is set to one as an + * atomic operation. If \c guard is nonzero, its value is not changed. + * + * \warning The monitored guard variable *must* be either a static variable + * local to the function being protected, or a data member of the same class + * to which a protected member function belongs. Otherwise the protection + * mechanism will not work. This can be dangerous, especially because you + * may erroneously think that your code is being protected when it is not. + * In addition, the guard variable must be zero initially, or the protected + * code will never be allowed to work. We strongly recommend you don't use + * this class directly, but the PCL_REENTRANCY_GUARDED_BEGIN and + * PCL_REENTRANCY_GUARDED_END macros to implement function level protection, + * or PCL_CLASS_REENTRANCY_GUARD, PCL_CLASS_REENTRANCY_GUARDED_BEGIN and + * PCL_CLASS_REENTRANCY_GUARDED_END to implement per-instance function + * member protection. + */ + AutoReentrancyGuard( AtomicInt& guard ) + : m_guard( guard ) + { + m_guarded = m_guard.TestAndSet( 0, 1 ); + } + + /*! + * Destroys this object. If the value of the monitored guard variable (see + * the class constructor) was zero when this object was constructed, its + * value is reset to zero as an atomic operation. + */ + ~AutoReentrancyGuard() + { + if ( m_guarded ) + m_guard.Store( 0 ); + } + + /*! + * Returns true iff the value of the monitored guard variable (see the class + * constructor) was zero when this object was constructed. + */ + operator bool() const volatile + { + return m_guarded; + } + +private: + + AtomicInt& m_guard; + bool m_guarded = false; +}; + +/*! + * \def PCL_REENTRANCY_GUARDED_BEGIN + * + * This macro along with PCL_REENTRANCY_GUARDED_END simplifies protection of + * non-reentrant code. See the AutoReentrancyGuard class for detailed + * information and examples. + * + * \ingroup reentrancy_protection + */ +#define PCL_REENTRANCY_GUARDED_BEGIN \ + { \ + static pcl::AtomicInt __r_g__( 0 ); \ + volatile pcl::AutoReentrancyGuard __a_r_g__( __r_g__ ); \ + if ( __a_r_g__ ) \ + { + +/*! + * \def PCL_REENTRANCY_GUARDED_END + * + * This macro, along with PCL_REENTRANCY_GUARDED_BEGIN, simplifies protection + * of non-reentrant code. See the AutoReentrancyGuard class for detailed + * information and examples. + * + * \ingroup reentrancy_protection + */ +#define PCL_REENTRANCY_GUARDED_END \ + } \ + } + +/*! + * \def PCL_CLASS_REENTRANCY_GUARD + * + * Declares a class data member for class-wide protection of non-reentrant + * member functions with the PCL_CLASS_REENTRANCY_GUARDED_BEGIN and + * PCL_REENTRANCY_GUARDED_END macros. + * + * Example: + * + * \code class foo + * { + * public: + * // ... + * private: + * PCL_CLASS_REENTRANCY_GUARD + * + * void bar1() + * { + * PCL_CLASS_REENTRANCY_GUARDED_BEGIN + * // Protected code + * PCL_REENTRANCY_GUARDED_END + * } + * + * void bar2() const + * { + * PCL_CLASS_REENTRANCY_GUARDED_BEGIN + * // Protected code + * PCL_REENTRANCY_GUARDED_END + * } + * }; \endcode + * + * In this example the bar1 and bar2 member functions are protected against + * reentrant execution. Note that reentrancy protection is a per-instance, + * class-wide property in this case: the bar1() and bar2() functions can be + * executed simultaneously for different objects, but they cannot be re-entered + * for the same instance. Furthermore, one of these functions cannot call the + * other for the same object, since both share the same reentrancy guard member + * in the foo class. + * + * See the AutoReentrancyGuard class for more information on the PCL + * implementation of reentrancy protection. + * + * \ingroup reentrancy_protection + */ +#define PCL_CLASS_REENTRANCY_GUARD \ + mutable pcl::AtomicInt __pcl_guard__; + +/*! + * \def PCL_CLASS_REENTRANCY_GUARDED_BEGIN + * + * This macro, along with PCL_CLASS_REENTRANCY_GUARD and + * PCL_REENTRANCY_GUARDED_END, simplifies per-instance protection of + * non-reentrant class member functions. See PCL_CLASS_REENTRANCY_GUARD for an + * example. + * + * See the AutoReentrancyGuard class for more information on the PCL + * implementation of reentrancy protection. + * + * \ingroup reentrancy_protection + */ +#define PCL_CLASS_REENTRANCY_GUARDED_BEGIN \ + { \ + volatile pcl::AutoReentrancyGuard __a_r_g__( __pcl_guard__ ); \ + if ( __a_r_g__ ) \ + { + +/*! + * \def PCL_MEMBER_REENTRANCY_GUARD + * + * Declares a class data member for protection of a specific non-reentrant + * member function with the PCL_MEMBER_REENTRANCY_GUARDED_BEGIN and + * PCL_REENTRANCY_GUARDED_END macros. + * + * Example: + * + * \code class foo + * { + * public: + * // ... + * private: + * PCL_MEMBER_REENTRANCY_GUARD( bar1 ) + * PCL_MEMBER_REENTRANCY_GUARD( bar2 ) + * + * void bar1() + * { + * PCL_MEMBER_REENTRANCY_GUARDED_BEGIN( bar1 ) + * // Protected code + * PCL_REENTRANCY_GUARDED_END + * } + * + * void bar2() const + * { + * PCL_MEMBER_REENTRANCY_GUARDED_BEGIN( bar2 ) + * // Protected code + * PCL_REENTRANCY_GUARDED_END + * } + * }; \endcode + * + * In this example the bar1 and bar2 member functions are protected against + * reentrant execution. Note that reentrancy protection is a per-instance, + * function-specific property in this case: the bar1() and bar2() functions can + * be executed simultaneously for different objects, but they cannot be + * re-entered for the same instance. Since each member function uses its own + * reentrancy guard member in the foo class, each of them can safely call the + * other for the same object. + * + * See the AutoReentrancyGuard class for more information on the PCL + * implementation of reentrancy protection. + * + * \ingroup reentrancy_protection + */ +#define PCL_MEMBER_REENTRANCY_GUARD( member ) \ + mutable pcl::AtomicInt __pcl_guard_##member##__; + +/*! + * \def PCL_MEMBER_REENTRANCY_GUARDED_BEGIN + * + * This macro, along with PCL_MEMBER_REENTRANCY_GUARD and + * PCL_REENTRANCY_GUARDED_END, simplifies per-instance protection of specific + * non-reentrant member functions. See PCL_MEMBER_REENTRANCY_GUARD for an + * example. + * + * See the AutoReentrancyGuard class for more information on the PCL + * implementation of reentrancy protection. + * + * \ingroup reentrancy_protection + */ +#define PCL_MEMBER_REENTRANCY_GUARDED_BEGIN( member ) \ + { \ + volatile pcl::AutoReentrancyGuard __a_r_g__( __pcl_guard_##member##__ );\ + if ( __a_r_g__ ) \ + { + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Atomic_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Atomic.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AutoLock.h b/3rdparty/include/pcl/AutoLock.h new file mode 100644 index 0000000..7ce6044 --- /dev/null +++ b/3rdparty/include/pcl/AutoLock.h @@ -0,0 +1,380 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AutoLock.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_AutoLock_h +#define __PCL_AutoLock_h + +/// \file pcl/AutoLock.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class AutoLock + * \brief Automatic mutex lock/unlock. + * + * %AutoLock is a convenience class that simplifies using Mutex objects to + * protect code or data that can be accessed by multiple threads. + * + * An %AutoLock object locks a %Mutex object upon construction and unlocks it + * upon destruction. This ensures that the state of the %Mutex object will + * always be well defined, and that it will never be left locked, even in + * critical situations involving multiple function return points and + * exceptions. + * + * \sa AutoLockCounter, Mutex + */ +class PCL_CLASS AutoLock +{ +public: + + /*! + * Constructs an %AutoLock object to monitor a specified Mutex object. + * + * \param mutex A %Mutex object that will be monitored by this %AutoLock + * instance. + * + * The specified mutex object will be locked by this constructor. It will be + * unlocked automatically when this %AutoLock object gets out of scope, or + * if it is destroyed explicitly. + */ + explicit AutoLock( pcl::Mutex& mutex ) + : m_mutex( &mutex ) + { + Lock(); + } + + /*! + * Move constructor. + */ + AutoLock( AutoLock&& x ) + : m_mutex( x.m_mutex ) + , m_lock( x.m_lock ) + { + x.m_mutex = nullptr; + } + + /*! + * Destroys this %AutoLock object. + * + * If the monitored mutex object (that was specified in the constructor) is + * locked, it is unlocked by this destructor. + */ + ~AutoLock() + { + Unlock(); + m_mutex = nullptr; + } + + /*! + * Copy constructor. This constructor is disabled because %AutoLock objects + * cannot be copied. + */ + AutoLock( const AutoLock& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %AutoLock objects + * cannot be copied. + */ + AutoLock& operator =( const AutoLock& ) = delete; + + /*! + * Move assignment. This operator is disabled because %AutoLock objects + * cannot be move-assigned. + */ + AutoLock& operator =( AutoLock&& ) = delete; + + /*! + * Locks the monitored mutex object, if it has not been previously locked by + * this object. + */ + void Lock() + { + if ( m_mutex != nullptr ) + if ( m_lock.TestAndSet( 0, 1 ) ) + m_mutex->Lock(); + } + + /*! + * Unlocks the monitored mutex object, if it has been previously locked by + * this object. + */ + void Unlock() + { + if ( m_mutex != nullptr ) + if ( m_lock.TestAndSet( 1, 0 ) ) + m_mutex->Unlock(); + } + +private: + + pcl::Mutex* m_mutex = nullptr; + AtomicInt m_lock; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class AutoLockCounter + * \brief Automatic mutex lock/unlock with limited concurrent access allowance. + * + * %AutoLockCounter is similar to AutoLock: it allows protecting a section of + * code against concurrent thread access through a Mutex, with automatic + * lock/unlock operations upon object construction/destruction. However, + * %AutoLockCounter is slightly more complex because it can allow a specified + * amount of concurrent accesses, while %AutoLock forbids them completely. + * + * %AutoLockCounter is useful for scenarios where the protected code can + * exploit a resource concurrently, but only to a given extent that can be + * predicted or configured. Typical examples are routines performing file + * read/write operations. + * + * Example: + * + * \code + * void ParallelWriteFile( const String& filePath, const ByteArray& data, int limit ) + * { + * static Mutex mutex; + * static AtomicInt count; + * volatile AutoLockCounter lock( mutex, count, limit ); + * File::WriteFile( filePath, data ); + * } + * \endcode + * + * In this example, the ParallelWriteFile routine allows creating and writing + * up to \e limit different disk files simultaneously. If \e limit files are + * already being written concurrently, a new call to ParallelWriteFile() will + * block the caller thread until at least one of the running tasks terminates. + * + * \sa AutoLock, Mutex, AtomicInt + */ +class PCL_CLASS AutoLockCounter +{ +public: + + /*! + * Constructs an %AutoLockCounter object to monitor a Mutex with automatic + * counting of lock operations and a given maximum number of concurrent + * accesses. + * + * \param mutex Reference to a Mutex object that will be monitored by this + * %AutoLockCounter instance. + * + * \param count Reference to an AtomicInt object that will be updated by + * this instance to control the current amount of concurrent + * accesses. + * + * \param limit Maximum number of concurrent accesses allowed. The + * specified \a count variable will be atomically incremented + * by this constructor. If \a count is greater than \a limit + * after the increment, this constructor will lock the + * specified \a mutex. Otherwise the mutex will not be locked + * automatically upon construction. Note that the mutex can + * be locked explicitly by calling the Lock() member function + * for any AutoLock or AutoLockCounter object sharing the + * same \a mutex variable. + * + * By specifying a \a limit of zero, no concurrent access will be allowed + * and this object will be functionally equivalent to an AutoLock instance + * monitoring the same \a mutex. By setting \a limit to a value greater than + * or equal to one, the protected code section will be allowed to run once, + * twice, etc. without a (potentially expensive) lock operation. + * + * If the specified \a mutex has been locked by this object, be it + * automatically or explicitly, it will be unlocked automatically when this + * %AutoLockCounter object is destroyed or gets out of scope. + */ + explicit AutoLockCounter( pcl::Mutex& mutex, AtomicInt& count, int limit ) + : m_mutex( &mutex ) + , m_count( &count ) + , m_lock( 0 ) + { + if ( m_count->FetchAndAdd( 1 ) >= limit-1 ) + { + Lock(); + if ( m_count->Load() < limit ) + Unlock(); + } + } + + /*! + * Move constructor. + */ + AutoLockCounter( AutoLockCounter&& x ) + : m_mutex( x.m_mutex ) + , m_count( x.m_count ) + , m_lock( x.m_lock ) + { + x.m_mutex = nullptr; + x.m_count = nullptr; + } + + /*! + * Destroys this %AutoLockCounter object. + * + * This destructor performs two separate actions: + * + * - If the monitored mutex (which was specified in the constructor) has + * been locked by this object, it will be unlocked. This applies both if the + * mutex has been locked automatically upon construction (because the + * monitored counter was larger than the specified limit), or explicitly by + * calling the Lock() member function for this object. + * + * - The monitored counter, which was atomically incremented upon + * construction, will be atomically decremented. + */ + ~AutoLockCounter() + { + Unlock(); + m_mutex = nullptr; + if ( m_count != nullptr ) + { + m_count->Decrement(); + m_count = nullptr; + } + } + + /*! + * Copy constructor. This constructor is disabled because %AutoLockCounter + * objects cannot be copied. + */ + AutoLockCounter( const AutoLockCounter& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %AutoLockCounter + * objects cannot be copied. + */ + AutoLockCounter& operator =( const AutoLockCounter& ) = delete; + + /*! + * Move assignment. This operator is disabled because %AutoLockCounter + * objects cannot be move-assigned. + */ + AutoLockCounter& operator =( AutoLockCounter&& ) = delete; + + /*! + * Locks the monitored mutex object, if it has not been previously locked by + * this object. + */ + void Lock() + { + if ( m_mutex != nullptr ) + if ( m_lock.TestAndSet( 0, 1 ) ) + m_mutex->Lock(); + } + + /*! + * Unlocks the monitored mutex object, if it has been previously locked by + * this object. + */ + void Unlock() + { + if ( m_mutex != nullptr ) + if ( m_lock.TestAndSet( 1, 0 ) ) + m_mutex->Unlock(); + } + +private: + + pcl::Mutex* m_mutex = nullptr; + AtomicInt* m_count = nullptr; + AtomicInt m_lock; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \def Synchronized + * \brief A macro to protect a simple fragment of code with a Mutex object. + * + * Example of use: + * + * \code + * Mutex mutex; + * ... + * Synchronized( mutex, count += img.Width(); ) + * \endcode + * + * The protected code should not contain tokens that could invalidate macro + * argument semantics. To synchronize more complex pieces of code, use an + * AutoLock object explicitly. For example: + * + * \code + * Mutex mutex; + * ... + * { + * AutoLock locker( mutex ); + * ... some code to protect here ... + * } + * \endcode + */ +#define Synchronized( mutex, code ) \ +{ \ + pcl::AutoLock _________( mutex ); \ + code \ +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AutoLock_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AutoLock.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AutoPointer.h b/3rdparty/include/pcl/AutoPointer.h new file mode 100644 index 0000000..3ab3147 --- /dev/null +++ b/3rdparty/include/pcl/AutoPointer.h @@ -0,0 +1,912 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AutoPointer.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_AutoPointer_h +#define __PCL_AutoPointer_h + +/// \file pcl/AutoPointer.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class StandardDeleter + * \brief An object deleter that uses the standard delete operator. + * + * Deleter objects are used by smart pointer classes (e.g., AutoPointer) to + * destroy and deallocate dynamically allocated objects. A valid deleter class + * must implement the following member functions: + * + * \li Default constructor. + * + * \li Copy constructor. + * + * \li Move constructor. + * + * \li Function call operator with a single argument of type T* (pointer to T). + * This member function will destroy and deallocate the T object pointed to by + * its argument. + * + * \li Function call operator with a single argument of type T[] (array of T). + * This member function will destroy and deallocate a contiguous sequence of + * objects stored at the location pointed to by its argument. + * + * %StandardDeleter implements object and array destruction/deallocation by + * calling the standard \c delete operator. + * + * \sa AutoPointer, AutoPointerCloner + */ +template +class PCL_CLASS StandardDeleter +{ +public: + + /*! + * Represents the type of objects to destroy and deallocate. + */ + typedef T value_type; + + /*! + * Represents a pointer to an object to destroy and deallocate. + */ + + typedef T* pointer; + + /*! + * Function call operator. Destroys and deallocates the object pointed to by + * the specified pointer \a p. + */ + void operator()( pointer p ) const + { + PCL_PRECONDITION( p != nullptr ) + delete p; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class AutoPointer + * \brief A smart pointer with exclusive object ownership and optional + * automatic object destruction. + * + * %AutoPointer stores a pointer to an object of which it is the sole owner. + * The owned object can optionally be destroyed when the owner %AutoPointer + * instance is destroyed. + * + * The template argument T represents the type of the objects owned by this + * template instantiation. The template argument D represents a functor class + * responsible for deletion of objects of type T. By default, %AutoPointer uses + * the StandardDeleter template class, which is a simple wrapper for the + * standard \c delete operator. + * + * Smart pointers are useful entities to guarantee proper destruction and + * deallocation of data in a variety of scenarios, such as exception driven + * code where the same objects have to be destroyed at different points in the + * execution workflow. For example, consider the following pseudocode: + * + * \code + * struct Foo { ... }; + * void Bar() + * { + * Foo* one = nullptr, * two = nullptr; + * try + * { + * // ... some code that may create new Foo objects ... + * if ( condition1 ) one = new Foo; + * if ( condition2 ) two = new Foo; + * // ... some code that can throw exceptions ... + * if ( one != nullptr ) delete one; + * if ( two != nullptr ) delete two; + * } + * catch ( ... ) + * { + * if ( one != nullptr ) delete one; + * if ( two != nullptr ) delete two; + * throw; + * } + * } + * \endcode + * + * Note that the objects pointed to by the \c one and \c two variables have to + * be destroyed at two locations: at the bottom of the \c try block (normal + * execution), and when an exception is caught, within the \c catch block. If + * the %Bar() routine were more complex, even more deallocations might be + * necessary at different locations, making the code intricate and prone to + * memory leaks. + * + * All of these complexities and potential problems can be avoided easily with + * smart pointers. For example, the following snippet would be equivalent to + * the pseudocode above: + * + * \code + * struct Foo { ... }; + * void Bar() + * { + * AutoPointer one, two; + * // ... some code that may create new Foo objects ... + * if ( condition1 ) one = new Foo; + * if ( condition2 ) two = new Foo; + * // ... some code that can throw exceptions ... + * } + * \endcode + * + * With smart pointers, there's no need to explicitly destroy the dynamically + * allocated objects \c one and \c two: The %AutoPointer objects will destroy + * and deallocate them automatically when they get out of scope. On the other + * hand, the %AutoPointer instances behave just like normal pointers allowing + * indirections, pointer assignments, and structure member selections for their + * owned objects transparently. The resulting code is simpler and more robust. + * + * By default, when an %AutoPointer instance is destroyed it also destroys the + * object pointed to by its contained pointer (if the %AutoPointer stores a + * non-null pointer). This automatic deletion feature can be disabled + * in some situations where a single %AutoPointer can store either a pointer to + * a dynamically allocated object, or a pointer to an already existing object + * that must be preserved (e.g., an object living in the stack). For example: + * + * \code + * void Foo( Image& image ) + * { + * // + * // Extract the CIE L* component of a color image ... + * // ... or use the same image as the working lightness if it is grayscale. + * // + * AutoPointer lightness; + * if ( image.IsColor() ) + * { + * lightness = new Image; + * image.ExtractLightness( *lightness ); + * } + * else + * { + * lightness = ℑ + * lightness.DisableAutoDelete(); + * } + * + * DoSomeStuffWithTheLightnessComponent( *lightness ); + * + * // + * // Insert the modified CIE L* component back in the color image. + * // + * if ( image.IsColor() ) + * image.SetLightness( *lightness ); + * } + * \endcode + * + * In the above code, the \c lightness variable can either store a newed image, + * if the passed \a image is a color image, or a pointer to \a image if it is a + * grayscale image. In the latter case we have disabled the automatic deletion + * feature for the \c lightness %AutoPointer, so it won't delete its stored + * pointer when it gets out of scope. + * + * \sa StandardDeleter, AutoPointerCloner + */ +template > +class PCL_CLASS AutoPointer +{ +public: + + /*! + * Represents the type of the object pointed to by this smart pointer. + */ + typedef T value_type; + + /*! + * Represents a pointer stored in this smart pointer. + */ + typedef T* pointer; + + /*! + * Represents a pointer to an immutable object stored in this smart pointer. + */ + typedef const T* const_pointer; + + /*! + * Represents the type of the object responsible for object deletion. + */ + typedef D deleter; + + /*! + * Constructs a null smart pointer. + * + * \param autoDelete Initial state of the automatic deletion feature. The + * default value is true, so auto deletion is always + * enabled by default for newly created %AutoPointer + * objects. + * + * \param d Deleter object, responsible for object destruction + * when the automatic deletion feature is enabled. + * + * A null smart pointer stores a null pointer, so it does not point to a + * valid object. + * + * A copy of the specified deleter \a d will be used. If no deleter is + * specified, this object will use a default-constructed instance of the + * \a D template argument class. + */ + AutoPointer( bool autoDelete = true, const deleter& d = deleter() ) + : m_deleter( d ) + , m_autoDelete( autoDelete ) + { + } + + /*! + * Constructs a smart pointer to store a given pointer. + * + * \param p The pointer to store in this %AutoPointer instance. + * + * \param autoDelete Initial state of the automatic deletion feature. The + * default value is true, so auto deletion is always + * enabled by default for newly created %AutoPointer + * objects. + * + * \param d Deleter object, responsible for object destruction + * when the automatic deletion feature is enabled. + * + * A copy of the specified deleter \a d will be used. If no deleter is + * specified, this object will use a default-constructed instance of the + * \a D template argument class. + */ + AutoPointer( pointer p, bool autoDelete = true, const deleter& d = deleter() ) + : m_deleter( d ) + , m_autoDelete( autoDelete ) + { + m_pointer = p; + } + + /*! + * Non-trivial copy constructor. Constructs a smart pointer by transferring + * the pointer stored in another smart pointer \a x. + * + * The automatic deletion feature for this object will be in the same state + * as it is currently set for the source object \a x. + * + * The smart pointer \a x will transport a null pointer after this instance + * is constructed. This happens irrespective of the state of the automatic + * deletion feature. This guarantees that, as long as no two %AutoPointer + * instances have been \e explicitly constructed to store the same pointer, + * no two %AutoPointer instances can share the same pointer accidentally, + * and hence multiple deletions are not possible. + */ + AutoPointer( AutoPointer& x ) + : m_deleter( x.m_deleter ) + , m_autoDelete( x.m_autoDelete ) + { + m_pointer = x.Release(); + } + + /*! + * Move constructor. + */ + AutoPointer( AutoPointer&& x ) + : m_deleter( std::move( x.m_deleter ) ) + , m_autoDelete( x.m_autoDelete ) + { + m_pointer = x.Release(); + } + + /*! + * Destroys an %AutoPointer object. + * + * If this instance stores a non-null pointer, and the automatic deletion + * feature is enabled, the pointed object will be destroyed by calling the + * deleter object. + */ + virtual ~AutoPointer() + { + Reset(); + } + + /*! + * Causes this smart pointer to store the specified pointer \a p. + * + * If this instance stores a non-null pointer when this function is called, + * and the automatic deletion feature is enabled, the pointed object is + * destroyed by calling the deleter object. + */ + void SetPointer( pointer p ) + { + if ( m_pointer != p ) + { + if ( m_autoDelete ) + if ( m_pointer != nullptr ) + m_deleter( Release() ); // in case m_deleter throws + m_pointer = p; + } + } + + /*! + * Causes this smart pointer to store a null pointer. + * + * If this instance stores a non-null pointer when this function is called, + * and the automatic deletion feature is enabled, the pointed object is + * destroyed by calling the deleter object. + * + * This member function is functionally equivalent to SetPointer( nullptr ). + */ + void Reset() + { + if ( m_pointer != nullptr ) + { + pointer p = Release(); // in case m_deleter throws + if ( m_autoDelete ) + m_deleter( p ); + } + } + + /*! + * A synonym for Reset(). Useful to enforce semantics when the smart pointer + * owns the pointed object. + */ + void Destroy() + { + Reset(); + } + + /*! + * Returns the pointer stored in this %AutoPointer, and causes this object + * to \e forget it by storing a null pointer. + * + * The object pointed is never destroyed by this function, irrespective of + * the state of automatic deletion. In this way, ownership of the pointed + * object (or more specifically, the responsibility for destroying it) is + * transferred to the caller. + */ + pointer Release() + { + pointer p = m_pointer; + m_pointer = nullptr; + return p; + } + + /*! + * Returns a pointer to the immutable object pointed to by this %AutoPointer + * instance. + */ + const_pointer Pointer() const + { + return m_pointer; + } + + /*! + * Returns a copy of the pointer stored in this %AutoPointer instance. + */ + pointer Pointer() + { + return m_pointer; + } + + /*! + * A synonym for Pointer() const. + */ + const_pointer Ptr() const + { + return m_pointer; + } + + /*! + * A synonym for Pointer(). + */ + pointer Ptr() + { + return m_pointer; + } + + /*! + * Returns true iff this smart pointer object stores a null pointer. + */ + bool IsNull() const + { + return m_pointer == nullptr; + } + + /*! + * Returns true iff this smart pointer object stores a non-null pointer. + * Equivalent to !IsNull(). + */ + bool IsValid() const + { + return !IsNull(); + } + + /*! + * Returns true iff the automatic deletion feature of %AutoPointer is + * currently enabled for this object. + * + * When automatic deletion is enabled, the object pointed to by this + * instance will be destroyed (by calling the deleter object) when this + * instance is destroyed, or when it is assigned with a different pointer. + * + * When automatic deletion is disabled, the pointed object will not be + * destroyed automatically. + * + * See the detailed description for the %AutoPointer class for more + * information, including code examples. + * + * \sa EnableAutoDelete(), DisableAutoDelete() + */ + bool IsAutoDelete() const + { + return m_autoDelete; + } + + /*! + * Enables (or disables) the automatic deletion feature of %AutoPointer for + * this object. + * + * \sa IsAutoDelete(), DisableAutoDelete() + */ + void EnableAutoDelete( bool enable = true ) + { + m_autoDelete = enable; + } + + /*! + * Disables (or enables) the automatic deletion feature of %AutoPointer for + * this object. + * + * \sa IsAutoDelete(), EnableAutoDelete() + */ + void DisableAutoDelete( bool disable = true ) + { + EnableAutoDelete( !disable ); + } + + /*! + * Returns a reference to the immutable deleter object in this instance. + */ + const deleter& Deleter() const + { + return m_deleter; + } + + /*! + * Returns a reference to the deleter object in this instance. + */ + deleter& Deleter() + { + return m_deleter; + } + + /*! + * Copy assignment operator. Transfers the pointer stored in another smart + * pointer to this object. + * + * This assignment operator performs the following actions: + * + * (1) If this smart pointer stores a valid (non-null) pointer, and the + * automatic deletion feature is enabled, the pointed object is destroyed by + * the deleter object. + * + * (2) The pointer stored in the other smart pointer \a x is copied to this + * instance. + * + * (3) The other smart pointer \a x is forced to store a null pointer. + * + * (4) Returns a reference to this object. + * + * This operator function does nothing if the specified %AutoPointer \a x + * stores the same pointer as this object. This prevents multiple deletions. + */ + AutoPointer& operator =( AutoPointer& x ) + { + SetPointer( x.Release() ); + m_deleter = x.m_deleter; + m_autoDelete = x.m_autoDelete; + return *this; + } + + /*! + * Move assignment operator. For the %AutoPointer class, this member + * function performs the same actions as the copy assignment operator. + */ + AutoPointer& operator =( AutoPointer&& x ) + { + SetPointer( x.Release() ); + m_deleter = std::move( x.m_deleter ); + m_autoDelete = x.m_autoDelete; + return *this; + } + + /*! + * Causes this smart pointer to store the specified pointer \a p. Returns a + * reference to this object. + * + * If this instance stores a non-null pointer when this function is called, + * and the automatic deletion feature is enabled, the pointed object is + * destroyed by the deleter object. + * + * If this object already stores the specified pointer \a p, this function + * does nothing. + * + * This member function is equivalent to: + * + * \code + * SetPointer( p ); + * \endcode + */ + AutoPointer& operator =( pointer p ) + { + SetPointer( p ); + return *this; + } + + /*! + * Returns a pointer to the immutable object pointed to by this instance. + * + * This operator is a synonym for the Pointer() const member function. + */ + operator const_pointer() const + { + return m_pointer; + } + + /*! + * Returns a copy of the pointer stored in this %AutoPointer instance. + * + * This operator is a synonym for the Pointer() member function. + */ + operator pointer() + { + return m_pointer; + } + + /*! + * Structure member selection operator. Returns a pointer to the immutable + * object pointed to by this %AutoPointer instance. + */ + const_pointer operator ->() const + { + PCL_PRECONDITION( m_pointer != nullptr ) + return m_pointer; + } + + /*! + * Structure member selection operator. Returns a copy of the pointer stored + * in this %AutoPointer instance. + */ + pointer operator ->() + { + PCL_PRECONDITION( m_pointer != nullptr ) + return m_pointer; + } + + /*! + * Dereference operator. Returns a reference to the immutable object pointed + * to by this smart pointer. + */ + const value_type& operator *() const + { + PCL_PRECONDITION( m_pointer != nullptr ) + return *m_pointer; + } + + /*! + * Dereference operator. Returns a reference to the object pointed to by + * this smart pointer. + */ + value_type& operator *() + { + PCL_PRECONDITION( m_pointer != nullptr ) + return *m_pointer; + } + + /*! + * Returns true iff this smart pointer stores a non-null pointer. This + * operator is equivalent to !IsNull(). + */ + operator bool() const + { + return !IsNull(); + } + + /*! + * Exchanges two smart pointers \a x1 and \a x2. + */ + friend void Swap( AutoPointer& x1, AutoPointer& x2 ) + { + pcl::Swap( x1.m_pointer, x2.m_pointer ); + pcl::Swap( x1.m_deleter, x2.m_deleter ); + bool b = x1.m_autoDelete; x1.m_autoDelete = x2.m_autoDelete; x2.m_autoDelete = b; + } + +protected: + + pointer m_pointer = nullptr; + deleter m_deleter; + bool m_autoDelete = true; +}; + +// ---------------------------------------------------------------------------- + +#define ASSERT_COPIABLE_T() \ + static_assert( std::is_copy_constructible::value, "AutoPointerCloner<> requires a copy-constructible type." ) + +/*! + * \class AutoPointerCloner + * \brief A smart pointer able to generate dynamically allocated copies of the + * objects pointed to by other smart pointers. + * + * %AutoPointerCloner is like AutoPointer, from which it derives publicly, with + * the only and substantial difference that it makes a dynamically allocated + * copy (or \e clone) of the object pointed to by another smart pointer upon + * copy construction or copy assignment. This is useful in cases where a + * dynamically allocated data member object must be duplicated automatically by + * the copy constructors and copy assignment operator of its base class. + * + * \sa AutoPointer + */ +template > +class PCL_CLASS AutoPointerCloner : public AutoPointer +{ +public: + + typedef AutoPointer base_type; + + /*! + * Represents the type of the object pointed to by this smart pointer. + */ + typedef typename base_type::value_type value_type; + + /*! + * Represents a pointer stored in this smart pointer. + */ + typedef typename base_type::pointer pointer; + + /*! + * Represents a pointer to an immutable object stored in this smart pointer. + */ + typedef typename base_type::const_pointer const_pointer; + + /*! + * Represents the type of the object responsible for object deletion. + */ + typedef typename base_type::deleter deleter; + + /*! + * Constructs a null smart pointer cloner. + * + * \param autoDelete Initial state of the automatic deletion feature. The + * default value is true, so auto deletion is always + * enabled by default for newly created %AutoPointer + * objects. + * + * \param d Deleter object, responsible for object destruction + * when the automatic deletion feature is enabled. + * + * A null smart pointer stores a null pointer, so it does not point to a + * valid object. + * + * A copy of the specified deleter \a d will be used. If no deleter is + * specified, this object will use a default-constructed instance of the + * deleter template argument class. + */ + AutoPointerCloner( bool autoDelete = true, const deleter& d = deleter() ) + : base_type( autoDelete, d ) + { + ASSERT_COPIABLE_T(); + } + + /*! + * Constructs a smart pointer cloner to store a given pointer. + * + * \param p The pointer to store in this %AutoPointer instance. + * + * \param autoDelete Initial state of the automatic deletion feature. The + * default value is true, so auto deletion is always + * enabled by default for newly created %AutoPointer + * objects. + * + * \param d Deleter object, responsible for object destruction + * when the automatic deletion feature is enabled. + * + * A copy of the specified deleter \a d will be used. If no deleter is + * specified, this object will use a default-constructed instance of the + * deleter template argument class. + */ + AutoPointerCloner( pointer p, bool autoDelete = true, const deleter& d = deleter() ) + : base_type( p, autoDelete, d ) + { + ASSERT_COPIABLE_T(); + } + + /*! + * Non-trivial copy constructor. Constructs a smart pointer cloner by making + * a dynamically allocated copy (or \e clone) of the object pointed to by + * the pointer stored in another smart pointer \a x. + * + * The automatic deletion feature will be enabled for this object if a clone + * object is generated; otherwise it will be in the same state as it is + * currently set for the source object \a x. + * + * Contrarily to the copy constructor of AutoPointer, the source smart + * pointer \a x will not be modified in any way by this constructor. + */ + AutoPointerCloner( const base_type& x ) + : base_type( nullptr ) + { + ASSERT_COPIABLE_T(); + this->m_pointer = x ? new value_type( *x ) : nullptr; + this->m_deleter = x.m_deleter; + this->m_autoDelete = x || x.m_autoDelete; + } + + /*! + * Copy constructor. Constructs a smart pointer cloner by making a + * dynamically allocated copy (or \e clone) of the object pointed to by + * the pointer stored in another smart pointer cloner \a x. + * + * The automatic deletion feature will be enabled for this object if a clone + * object is generated; otherwise it will be in the same state as it is + * currently set for the source object \a x. + * + * Contrarily to the copy constructor of AutoPointer, the source smart + * pointer \a x will not be modified in any way by this constructor. + */ + AutoPointerCloner( const AutoPointerCloner& x ) + : base_type( nullptr ) + { + ASSERT_COPIABLE_T(); + this->m_pointer = x ? new value_type( *x ) : nullptr; + this->m_deleter = x.m_deleter; + this->m_autoDelete = x || x.m_autoDelete; + } + + /*! + * Move constructor. + */ + AutoPointerCloner( base_type&& x ) + : base_type( std::move( x ) ) + { + } + + /*! + * Copy assignment from base class operator. + * + * This assignment operator performs the following actions: + * + * (1) If this smart pointer stores a valid (non-null) pointer, and the + * automatic deletion feature is enabled, the pointed object is destroyed by + * the deleter object. This behavior is the same as for AutoPointer. + * + * (2) If the other smart pointer \a x stores a valid (non-null) pointer, + * a dynamically allocated copy (or \e clone) of the pointed object will be + * generated, and a pointer to the newly constructed object will be stored + * in this instance. In such case, the automatic deletion feature will be + * enabled for this object; otherwise, it will have the same state as in the + * source object \a x, and this object will store a null pointer. + * + * (3) Returns a reference to this object. + * + * In contrast to AutoPointer's copy assignment operator, this operator does + * not modify the specified source object \a x in any way. + */ + AutoPointerCloner& operator =( const base_type& x ) + { + this->SetPointer( x ? new value_type( *x ) : nullptr ); + this->m_deleter = x.m_deleter; + this->m_autoDelete = x || x.m_autoDelete; + return *this; + } + + /*! + * Copy assignment operator. + * + * This assignment operator performs the following actions: + * + * (1) If this smart pointer stores a valid (non-null) pointer, and the + * automatic deletion feature is enabled, the pointed object is destroyed by + * the deleter object. This behavior is the same as for AutoPointer. + * + * (2) If the other smart pointer \a x stores a valid (non-null) pointer, + * a dynamically allocated copy (or \e clone) of the pointed object will be + * generated, and a pointer to the newly constructed object will be stored + * in this instance. In such case, the automatic deletion feature will be + * enabled for this object; otherwise, it will have the same state as in the + * source object \a x, and this object will store a null pointer. + * + * (3) Returns a reference to this object. + * + * In contrast to AutoPointer's copy assignment operator, this operator does + * not modify the specified source object \a x in any way. + */ + AutoPointerCloner& operator =( const AutoPointerCloner& x ) + { + this->SetPointer( x ? new value_type( *x ) : nullptr ); + this->m_deleter = x.m_deleter; + this->m_autoDelete = x || x.m_autoDelete; + return *this; + } + + /*! + * Move assignment operator. This function simply calls the base class + * version of the same operator and returns a reference to this object. + */ + AutoPointerCloner& operator =( base_type&& x ) + { + (void)base_type::operator =( std::move( x ) ); + return *this; + } + + /*! + * Causes this smart pointer cloner to store the specified pointer \a p. + * Returns a reference to this object. + * + * This member function is identical to its base class counterpart + * AutoPointer::operator =( pointer ). It is equivalent to: + * + * \code SetPointer( p ); \endcode + */ + AutoPointerCloner& operator =( pointer p ) + { + this->SetPointer( p ); + return *this; + } +}; + +#undef ASSERT_COPIABLE_T + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AutoPointer_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AutoPointer.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AutoStatusCallbackRestorer.h b/3rdparty/include/pcl/AutoStatusCallbackRestorer.h new file mode 100644 index 0000000..bd31003 --- /dev/null +++ b/3rdparty/include/pcl/AutoStatusCallbackRestorer.h @@ -0,0 +1,233 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AutoStatusCallbackRestorer.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_AutoStatusCallbackRestorer_h +#define __PCL_AutoStatusCallbackRestorer_h + +/// \file pcl/AutoStatusCallbackRestorer.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class AutoStatusCallbackRestorer + * \brief Automatic recovery of status monitoring callbacks. + * + * %AutoStatusCallbackRestorer simplifies working with different status + * monitoring callback objects, including objects allocated as automatic + * variables (i.e., inside functions without the static qualifier), ensuring + * that the initial monitoring callback will be recovered when the instance + * gets out of scope. + * + * An instance of %AutoStatusCallbackRestorer stores a pointer to the + * StatusCallback object being used by a StatusMonitor instance upon + * construction, and restores it upon destruction. This ensures that the + * %StatusMonitor object will always be left in a valid state, even in critical + * situations involving multiple function return points and exceptions. + * + * Consider the following example: + * + * \code + * void Foo( Image& image ) + * { + * StatusCallback* oldStatus = image.StatusCallback(); + * StandardStatus status; + * image.SetStatusCallback( &status ); + * image.Status().Initialize( "Performing Foo()", image.NumberOfPixels() ); + * image.Status().DisableInitialization(); + * + * try + * { + * DoFoo( image ); + * image.SetStatusCallback( oldStatus ); + * } + * catch ( ... ) + * { + * image.SetStatusCallback( oldStatus ); + * throw; + * } + * } + * \endcode + * + * Since \c status is an automatic variable, we cannot return from the Foo() + * function without removing it from image.Status(), because otherwise the + * StatusMonitor object would be referencing a dangling pointer. For this + * reason we have to be careful to restore the \c oldStatus pointer before + * returning from Foo(), including any possible returning points and all + * exceptions thrown. + * + * With %AutoStatusCallbackRestorer the above code can be simplified to: + * + * \code + * void Foo( Image& image ) + * { + * AutoStatusCallbackRestorer saveStatus( image.Status() ); + * StandardStatus status; + * image.SetStatusCallback( &status ); + * image.Status().Initialize( "Performing Foo()", image.NumberOfPixels() ); + * image.Status().DisableInitialization(); + * DoFoo( image ); + * } + * \endcode + * + * Note that the try-catch blocks are now unnecessary. As soon as the + * \c saveStatus variable gets out of scope, the \c image.Status() object will + * use its previous status callback again, that is, the same status callback + * that it was using before calling Foo(). This will happen automatically, + * including both normal function returns and uncaught exceptions within the + * Foo() function. + * + * \sa StatusMonitor, StatusCallback + */ +class PCL_CLASS AutoStatusCallbackRestorer +{ +public: + + /*! + * Constructs an %AutoStatusCallbackRestorer object for the specified + * client status \a monitor. + * + * \param monitor Reference to the client StatusMonitor instance. This + * object will store a pointer to the StatusCallback + * object currently being used by the client \a monitor. + * + * \warning The specified \a monitor object must remain valid while this + * object exists. Otherwise undefined behavior will be invoked when this + * object is destroyed. + */ + explicit AutoStatusCallbackRestorer( StatusMonitor& monitor ) + : m_monitor( monitor ) + { + Store(); + } + + /*! + * Destroys this %AutoStatusCallbackRestorer object. + * + * This destructor restores the status callback being used by the client + * status monitor when this object was constructed, or upon the last call to + * Store(). + */ + ~AutoStatusCallbackRestorer() + { + Restore(); + } + + /*! + * Restores the status callback that was being used by the client status + * monitor when this object was constructed, or upon the last call to + * Store(). + */ + void Restore() + { + m_monitor.m_callback = m_callback; + } + + /*! + * Stores the status callback currently used by the client status monitor. + */ + void Store() + { + m_callback = m_monitor.m_callback; + } + + /*! + * Returns a reference to the client status monitor object. The client + * status monitor has been specified upon construction of this instance and + * cannot be changed. + */ + StatusMonitor& Monitor() const + { + return m_monitor; + } + + /*! + * Returns the address of the status callback object currently stored by + * this instance. This is a pointer to a StatusCallback object that was + * acquired when this object was constructed, or in the last call to the + * Store() member function. + */ + StatusCallback* Callback() const + { + return m_callback; + } + + /*! + * Copy constructor. This constructor is disabled. + */ + AutoStatusCallbackRestorer( const AutoStatusCallbackRestorer& ) = delete; + + /*! + * Copy assignment. This constructor is disabled. + */ + AutoStatusCallbackRestorer& operator =( const AutoStatusCallbackRestorer& ) = delete; + +private: + + StatusMonitor& m_monitor; + StatusCallback* m_callback = nullptr; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AutoStatusCallbackRestorer_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AutoStatusCallbackRestorer.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/AutoViewLock.h b/3rdparty/include/pcl/AutoViewLock.h new file mode 100644 index 0000000..db6dba5 --- /dev/null +++ b/3rdparty/include/pcl/AutoViewLock.h @@ -0,0 +1,345 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/AutoViewLock.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_AutoViewLock_h +#define __PCL_AutoViewLock_h + +/// \file pcl/AutoViewLock.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class AutoViewLock + * \brief Automatic view lock/unlock. + * + * %AutoViewLock simplifies locking and unlocking View objects accessed from + * process execution routines. + * + * An %AutoViewLock object locks a %View upon construction and unlocks it upon + * destruction. This ensures that a view will never be left locked, even in + * critical situations involving multiple function return points and + * exceptions. + * + * %AutoViewLock works for %View just as AutoLock does for Mutex. The main + * difference is that a view can be locked and unlocked for read and write + * operations separately, while a mutex cannot. + * + * Typically %AutoViewLock is used within a reimplementation of the + * ProcessImplementation::ExecuteOn() virtual member function for a process + * instance class. Consider the following example: + * + * \code + * bool FooProcessInstance::ExecuteOn( View& view ) + * { + * try + * { + * view.Lock(); + * + * ImageVariant image = view.Image(); + * + * if ( image.IsComplexSample() ) + * { + * view.Unlock(); + * return false; + * } + * + * Console().EnableAbort(); + * + * StandardStatus status; + * image->SetStatusCallback( &status ); + * + * FooEngine::Apply( image, *this ); + * + * view.Unlock(); + * return true; + * } + * catch ( ... ) + * { + * view.Unlock(); + * throw; + * } + * } + * \endcode + * + * With %AutoViewLock the above code can be simplified considerably: + * + * \code + * bool FooProcessInstance::ExecuteOn( View& view ) + * { + * AutoViewLock lock( view ); + * + * ImageVariant image = view.Image(); + * + * if ( image.IsComplexSample() ) + * return false; + * + * Console().EnableAbort(); + * + * StandardStatus status; + * image->SetStatusCallback( &status ); + * + * FooEngine::Apply( image, *this ); + * + * return true; + * } + * \endcode + * + * Note that the try-catch blocks are now unnecessary. As soon as the \c lock + * variable gets out of scope, the \c view object will be unlocked + * automatically, including both normal function returns and uncaught + * exceptions within the ExecuteOn() function. Keep in mind that all exceptions + * will always be caught by internal PCL routines. + * + * \sa View + */ +class PCL_CLASS AutoViewLock +{ +public: + + /*! + * Constructs an %AutoViewLock object to monitor the specified \a view. + * + * \param view A %View object that will be monitored by this + * %AutoViewLock instance. The object must remain valid for + * the whole lifetime of this %AutoViewLock instance. + * + * \param lock Whether the specified \a view should be locked for read + * and write operations by this constructor. The default + * value is true. + * + * If the \a lock argument is true, the specified \a view will be locked for + * read and write operations immediately by this constructor. It will be + * unlocked automatically when this %AutoViewLock object gets out of scope, + * or if it is destroyed explicitly. + * + * By specifying \a lock=false, you can create an %AutoViewLock object to + * monitor a view and lock it for write operations exclusively: + * + * \code + * void foo( View& view ) + * { + * AutoViewLock lock( view, false ); // do not lock for read-write ops. + * lock.LockForWrite(); + * ... + * } + * \endcode + * + * See AutoViewWriteLock for a convenience class to implements this + * functionality in a cleaner way. + */ + explicit AutoViewLock( View& view, bool lock = true ) + : m_view( view ) + , m_readLock( 0 ) + , m_writeLock( 0 ) + { + if ( lock ) + Lock(); + } + + /*! + * Destroys this %AutoViewLock object. + * + * If the monitored view (that was specified in the constructor) is locked, + * it is unlocked by this destructor. + */ + ~AutoViewLock() + { + Unlock(); + m_view = View::Null(); + } + + /*! + * Copy constructor. This constructor is disabled because views and view + * locks are unique objects. + */ + AutoViewLock( const AutoViewLock& ) = delete; + + /*! + * Copy assignment. This operator is disabled because views and view locks + * are unique objects. + */ + AutoViewLock& operator =( const AutoViewLock& ) = delete; + + /*! + * Locks the monitored view for read and write operations, if it has not + * been previously locked. + * + * For more information, see the documentation for View::Lock(). + */ + void Lock() + { + if ( !m_view.IsNull() ) + { + int unlocked = 0; + if ( m_readLock.TestAndSet( 0, 1 ) ) + ++unlocked; + if ( m_writeLock.TestAndSet( 0, 1 ) ) + ++unlocked; + if ( unlocked ) + m_view.Lock(); + } + } + + /*! + * Unlocks the monitored view for read and write operations, if it has been + * previously locked. + * + * For more information, see the documentation for View::Unlock(). + */ + void Unlock() + { + if ( !m_view.IsNull() ) + { + int locked = 0; + if ( m_readLock.TestAndSet( 1, 0 ) ) + ++locked; + if ( m_writeLock.TestAndSet( 1, 0 ) ) + ++locked; + if ( locked ) + m_view.Unlock(); + } + } + + /*! + * Locks the monitored view for write operations, if it has not already been + * write-locked. + * + * For more information, see the documentation for View::LockForWrite(). + */ + void LockForWrite() + { + if ( !m_view.IsNull() ) + if ( m_writeLock.TestAndSet( 0, 1 ) ) + m_view.LockForWrite(); + } + + /*! + * Unlocks the monitored view for read operations, if it has already been + * read-locked. + * + * For more information, see the documentation for View::UnlockForRead(). + */ + void UnlockForRead() + { + if ( !m_view.IsNull() ) + if ( m_readLock.TestAndSet( 1, 0 ) ) + m_view.UnlockForRead(); + } + + /*! + * Unlocks the monitored view for read operations only, if it has not + * already been unlocked. + * + * For more information, see the documentation for View::RelockForRead(). + */ + void RelockForRead() + { + if ( !m_view.IsNull() ) + if ( m_readLock.TestAndSet( 0, 1 ) ) + m_view.RelockForRead(); + } + +private: + + View m_view; + AtomicInt m_readLock; + AtomicInt m_writeLock; +}; + +/*! + * \class AutoViewWriteLock + * \brief Automatic write-only view lock/unlock. + * + * %AutoViewWriteLock performs automatic write-only locking/unlocking of View + * objects. See the documentation for the base class, AutoViewLock, for + * complete information. + * + * \sa View, AutoViewLock + */ +class PCL_CLASS AutoViewWriteLock : public AutoViewLock +{ +public: + + /*! + * Constructs an %AutoViewWriteLock object to monitor the specified \a view + * and lock it for write operations exclusively. + * + * This constructor is equivalent to the following: + * + * \code + * AutoViewLock lock( view, false ); // do not lock for read-write ops. + * lock.LockForWrite(); + * \endcode + */ + explicit AutoViewWriteLock( View& view ) + : AutoViewLock( view, false/*lock*/ ) + { + LockForWrite(); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_AutoViewLock_h + +// ---------------------------------------------------------------------------- +// EOF pcl/AutoViewLock.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/BicubicFilterInterpolation.h b/3rdparty/include/pcl/BicubicFilterInterpolation.h new file mode 100644 index 0000000..faadc88 --- /dev/null +++ b/3rdparty/include/pcl/BicubicFilterInterpolation.h @@ -0,0 +1,670 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/BicubicFilterInterpolation.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_BicubicFilterInterpolation_h +#define __PCL_BicubicFilterInterpolation_h + +/// \file pcl/BicubicFilterInterpolation.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class CubicFilter + * \brief Mitchell-Netravali parameterized cubic filters. + * + * %CubicFilter implements a two-parameter, separable cubic filter as described + * in Don P. Mitchell, Arun N. Netravali (1988), %Reconstruction Filters in + * %Computer %Graphics, %Computer %Graphics, Vol. 22, No. 4, pp. 221-228. + * + * The family of cubic filters designed by Mitchell and Netravali has two + * parameters called B and C. Although these parameters can take any values, + * the authors recommend values pertaining to the line B + 2C = 1. In + * particular, the filter defined by B=C=1/3 has been proven to have excellent + * characteristics for a wide range of image reconstruction tasks. + * + * \sa MitchellNetravaliCubicFilter, CatmullRomSplineFilter, CubicBSplineFilter + */ +class PCL_CLASS CubicFilter +{ +public: + + /*! + * Constructs a new %CubicFilter object with the specified filter + * parameters \a B and \a C. + */ + CubicFilter( double B, double C ) + : m_B( B ) + , m_C( C ) + { + m_k31 = ( 12 - 9*m_B - 6*m_C)/6; + m_k21 = (-18 + 12*m_B + 6*m_C)/6; + m_k01 = ( 6 - 2*m_B )/6; + m_k32 = ( -m_B - 6*m_C)/6; + m_k22 = ( 6*m_B + 30*m_C)/6; + m_k12 = ( -12*m_B - 48*m_C)/6; + m_k02 = ( 8*m_B + 24*m_C)/6; + } + + /*! + * Copy constructor. + */ + CubicFilter( const CubicFilter& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~CubicFilter() + { + } + + /*! + * Assignment operator. + */ + CubicFilter& operator =( const CubicFilter& ) = default; + + /*! + * Evaluates this cubic filter for \a x. + * + * \note For performance reasons, this function returns an invalid value + * outside the range ]-2,+2[, which is the support of Mitchell-Netravali + * cubic filters. Strictly, zero should be returned outside the support + * range, but since this is a performance-critical routine, we have + * sacrified strictness for the sake of optimization. This function should + * never be called for Abs( \a x ) >= 2. + */ + PCL_HOT_FUNCTION + double operator()( double x ) const noexcept + { + if ( x < 0 ) + x = -x; + return (x < 1) ? m_k01 + x*x*(m_k21 + x*m_k31) : + m_k02 + x*(m_k12 + x*(m_k22 + x*m_k32)); + } + + /*! + * Returns the filter's \e width, measured from the origin to its cutoff + * point. We define the \e support of a (symmetric) filter as the range + * ]-width,+width[. + * + * Mitchell-Netravali cubic filters are zero outside the range ]-2,+2[, + * hence this function always returns 2. + */ + double Width() const noexcept + { + return 2.0; + } + + /*! + * Returns a descriptive text string for this cubic filter. + */ + virtual String Description() const + { + return String().Format( "Cubic filter (B=%.6f, C=%.6f)", m_B, m_C ); + } + + /*! + * Returns a pointer to a dynamically allocated duplicate of this filter. + */ + virtual CubicFilter* Clone() const + { + return new CubicFilter( *this ); + } + +protected: + + double m_k31, m_k21, m_k01, m_k32, m_k22, m_k12, m_k02; + +private: + + double m_B, m_C; // for reference only; not used in calculations +}; + +/*! + * \class MitchellNetravaliCubicFilter + * \brief Mitchell-Netravali cubic filter with B=C=1/3 + * + * This is the cubic filter recommended by Mitchell and Netravali (1988). It is + * implemented as a CubicFilter with parameters B=1/3 and C=1/3. + * + * \sa CubicFilter, CatmullRomSplineFilter, CubicBSplineFilter + */ +class PCL_CLASS MitchellNetravaliCubicFilter : public CubicFilter +{ +public: + + /*! + * Constructs a new %MitchellNetravaliCubicFilter object. + */ + MitchellNetravaliCubicFilter() + : CubicFilter( 1.0/3, 1.0/3 ) + { + } + + /*! + * Copy constructor. + */ + MitchellNetravaliCubicFilter( const MitchellNetravaliCubicFilter& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~MitchellNetravaliCubicFilter() + { + } + + /*! + */ + String Description() const override + { + return "Mitchell-Netravali cubic filter"; + } + + /*! + */ + CubicFilter* Clone() const override + { + return new MitchellNetravaliCubicFilter( *this ); + } +}; + +/*! + * \class CatmullRomSplineFilter + * \brief Catmull-Rom spline filter + * + * The Catmull-Rom spline filter is implemented as a CubicFilter with + * parameters B=0 and C=0.5. + * + * \sa CubicFilter, MitchellNetravaliCubicFilter, CubicBSplineFilter + */ +class PCL_CLASS CatmullRomSplineFilter : public CubicFilter +{ +public: + + /*! + * Constructs a new %CatmullRomSplineFilter object. + */ + CatmullRomSplineFilter() + : CubicFilter( 0, 0.5 ) + { + } + + /*! + * Copy constructor. + */ + CatmullRomSplineFilter( const CatmullRomSplineFilter& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~CatmullRomSplineFilter() + { + } + + /*! + */ + String Description() const override + { + return "Catmull-Rom spline filter"; + } + + /*! + */ + CubicFilter* Clone() const override + { + return new CatmullRomSplineFilter( *this ); + } +}; + +/*! + * \class CubicBSplineFilter + * \brief Cubic B-spline filter + * + * The cubic B-spline filter is implemented as a CubicFilter with + * parameters B=1 and C=0. + * + * \sa CubicFilter, MitchellNetravaliCubicFilter, CatmullRomSplineFilter + */ +class PCL_CLASS CubicBSplineFilter : public CubicFilter +{ +public: + + /*! + * Constructs a new %CubicBSplineFilter object. + */ + CubicBSplineFilter() + : CubicFilter( 1, 0 ) + { + } + + /*! + * Copy constructor. + */ + CubicBSplineFilter( const CubicBSplineFilter& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~CubicBSplineFilter() + { + } + + /*! + */ + String Description() const override + { + return "Cubic B-spline filter"; + } + + /*! + */ + CubicFilter* Clone() const override + { + return new CubicBSplineFilter( *this ); + } +}; + +// ---------------------------------------------------------------------------- + +#define m_width this->m_width +#define m_height this->m_height +#define m_fillBorder this->m_fillBorder +#define m_fillValue this->m_fillValue +#define m_data this->m_data + +// ---------------------------------------------------------------------------- + +/*! + * \class BicubicFilterInterpolation + * \brief Bicubic filter interpolation algorithms. + * + * Bicubic filter interpolation uses a \e cubic \e filter (an instance of + * CubicFilter or a derived class) to interpolate pixel values in a rectangular + * pixel matrix of the specified horizontal and vertical \e radii. Thanks to + * the separability of cubic filters, %BicubicFilterInterpolation can be + * applied with a different filter size on each axis. + * + * \sa BidimensionalInterpolation, CubicFilter, MitchellNetravaliCubicFilter, + * CatmullRomSplineFilter, CubicBSplineFilter, NearestNeighborInterpolation, + * BilinearInterpolation, BicubicSplineInterpolation, + * BicubicBSplineInterpolation, LanczosInterpolation + */ +template +class PCL_CLASS BicubicFilterInterpolation : public BidimensionalInterpolation +{ +public: + + /*! + * Constructs a new %BicubicFilterInterpolation instance. + * + * \param rx,ry Horizontal and vertical interpolation radii, respectively, + * in pixels. Both radii must be >= 1. Interpolation will + * take place in a rectangular pixel matrix with 2*rx + 1 + * columns and 2*ry + 1 rows. + * + * \param filter Reference to a CubicFilter instance that will be used as + * the interpolation filter. + */ + BicubicFilterInterpolation( int rx, int ry, const CubicFilter& filter ) + : m_rx( Max( 1, rx ) ) + , m_ry( Max( 1, ry ) ) + , m_filter( filter ) + { + PCL_PRECONDITION( rx >= 1 ) + PCL_PRECONDITION( ry >= 1 ) + Initialize(); + } + + /*! + * Copy constructor. + */ + BicubicFilterInterpolation( const BicubicFilterInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~BicubicFilterInterpolation() + { + } + + /*! + */ + void Initialize( const T* data, int dataWidth, int dataHeight ) override + { + BidimensionalInterpolation::Initialize( data, dataWidth, dataHeight ); + + if ( m_rx > m_width || m_ry > m_height ) + { + m_rx = Min( m_rx, m_width ); + m_ry = Min( m_ry, m_height ); + Initialize(); + } + } + + /*! + * Returns an interpolated value at {\a x,\a y} location. + * + * \param x,y Coordinates of the interpolation point (horizontal,vertical). + * + * %Interpolation takes place on a rectangular matrix whose center is the + * nearest pixel to {\a x, \a y}. The interpolation matrix has 2*rx + 1 + * columns and 2*ry + 1 rows, where rx and ry are the horizontal and + * vertical interpolation radii, respectively. + */ + PCL_HOT_FUNCTION + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + PCL_PRECONDITION( x >= 0 && x < m_width ) + PCL_PRECONDITION( y >= 0 && y < m_height ) + PCL_CHECK( m_rx >= 1 && m_rx <= m_width ) + PCL_CHECK( m_ry >= 1 && m_ry <= m_height ) + PCL_CHECK( !m_k.IsEmpty() ) + + int x0 = Range( RoundInt( x ), 0, m_width-1 ); + int y0 = Range( RoundInt( y ), 0, m_height-1 ); + + double dx = x - x0; + double dy = y - y0; + + int64 d = int64( y0 - m_ry )*m_width + x0 - m_rx; + + if ( m_rx >= m_ry ) + { + double wx = 0; + for ( int xi = -m_rx, c = 0; xi <= m_rx; ++xi, ++c ) + wx += (m_k[c] = m_filter( m_sx*(xi - dx) )); + + double sy = 0, wy = 0; + for ( int yi = -m_ry; yi <= m_ry; ++yi ) + { + double ky = m_filter( m_sy*(yi - dy) ); + wy += ky; + + const T* p; + int y = y0 + yi; + + if ( y < 0 ) + { + d += m_width; + + if ( m_fillBorder ) + { + sy += m_fillValue * ky; + continue; + } + + p = m_data + (d - 2*int64( m_width )*(y + 1)); + } + else if ( y >= m_height ) + { + if ( m_fillBorder ) + { + sy += m_fillValue * ky; + continue; + } + + p = m_data + (d -= m_width); + } + else + { + p = m_data + d; + d += m_width; + } + + int x = x0 - m_rx; + int x2 = x0 + m_rx; + int x1 = Min( x2, m_width-1 ); + double sx = 0; + const double* kx = m_k.Begin(); + + while ( x < 0 ) + { + ++x; + ++p; + sx += (m_fillBorder ? m_fillValue : double( *(p - (x + x)) )) * *kx++; + } + + for ( ;; ) + { + sx += *p++ * *kx++; + if ( ++x > x1 ) + break; + } + + while ( x <= x2 ) + { + sx += (m_fillBorder ? m_fillValue : double( *--p )) * *kx++; + ++x; + } + + sy += sx/wx * ky; + } + + return sy/wy; + } + else + { + double wy = 0; + for ( int yi = -m_ry, r = 0; yi <= m_ry; ++yi, ++r ) + wy += (m_k[r] = m_filter( m_sy*(yi - dy) )); + + double sx = 0, wx = 0; + for ( int xi = -m_rx; xi <= m_rx; ++xi ) + { + double kx = m_filter( m_sx*(xi - dx) ); + wx += kx; + + const T* p; + int x = x0 + xi; + + if ( x < 0 ) + { + ++d; + + if ( m_fillBorder ) + { + sx += m_fillValue * kx; + continue; + } + + p = m_data + (d - 2*(x + 1)); + } + else if ( x >= m_width ) + { + if ( m_fillBorder ) + { + sx += m_fillValue * kx; + continue; + } + + p = m_data + --d; + } + else + p = m_data + d++; + + int y = y0 - m_ry; + int y2 = y0 + m_ry; + int y1 = Min( y2, m_height-1 ); + double sy = 0; + const double* ky = m_k.Begin(); + + while ( y < 0 ) + { + ++y; + p += m_width; + sy += (m_fillBorder ? m_fillValue : double( *(p - (y + y)*m_width) )) * *ky++; + } + + for ( ;; ) + { + sy += *p * *ky++; + p += m_width; + if ( ++y > y1 ) + break; + } + + while ( y <= y2 ) + { + sy += (m_fillBorder ? m_fillValue : double( *(p -= m_width) )) * *ky++; + ++y; + } + + sx += sy/wy * kx; + } + + return sx/wx; + } + } + + /*! + * Returns the horizontal interpolation radius in pixels. + */ + int HorizontalRadius() const noexcept + { + return m_rx; + } + + /*! + * Returns the vertical interpolation radius in pixels. + */ + int VerticalRadius() const noexcept + { + return m_ry; + } + + /*! + * Sets new interpolation radii. + * + * \param rx,ry Horizontal and vertical interpolation radii, respectively, + * in pixels. Both radii must be >= 1. Interpolation will + * take place in a rectangular pixel matrix with 2*rh + 1 + * columns and 2*rv + 1 rows. + */ + void SetRadii( int rx, int ry ) + { + if ( rx != m_rx || ry != m_ry ) + { + m_rx = Max( 1, rx ); + m_ry = Max( 1, ry ); + + if ( this->data != nullptr ) + { + if ( m_rx > m_width ) + m_rx = m_width; + if ( m_ry > m_height ) + m_ry = m_height; + } + + Initialize(); + } + } + + /*! + * Returns a constant reference to the cubic filter being used by this + * interpolation. + */ + const CubicFilter& Filter() const noexcept + { + return m_filter; + } + + /*! + * Sets a new cubic \a filter to be applied by this interpolation. + */ + void SetFilter( const CubicFilter& filter ) + { + m_filter = filter; + Initialize(); + } + +protected: + + int m_rx, m_ry; // horizontal and vertical radii + double m_sx, m_sy; // filter scaling ratios + mutable DVector m_k; // workspace for interpolated values + CubicFilter m_filter; + + void Initialize() + { + m_sx = m_filter.Width()/(m_rx + 0.5); + m_sy = m_filter.Width()/(m_ry + 0.5); + m_k = DVector( 1 + (Max( m_rx, m_ry ) << 1) ); + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_width +#undef m_height +#undef m_fillBorder +#undef m_fillValue +#undef m_data + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BicubicFilterInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/BicubicFilterInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/BicubicInterpolation.h b/3rdparty/include/pcl/BicubicInterpolation.h new file mode 100644 index 0000000..1769ba1 --- /dev/null +++ b/3rdparty/include/pcl/BicubicInterpolation.h @@ -0,0 +1,791 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/BicubicInterpolation.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_BicubicInterpolation_h +#define __PCL_BicubicInterpolation_h + +/// \file pcl/BicubicInterpolation.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +#define m_width this->m_width +#define m_height this->m_height +#define m_fillBorder this->m_fillBorder +#define m_fillValue this->m_fillValue +#define m_data this->m_data + +// ---------------------------------------------------------------------------- + +/*! + * \class BicubicInterpolationBase + * \brief Base class for bicubic interpolation algorithm implementations + * + * %BicubicInterpolationBase is a base class for BicubicSplineInterpolation and + * BicubicBSplineInterpolation. + * + * \sa BicubicSplineInterpolation, BicubicBSplineInterpolation + */ +template +class PCL_CLASS BicubicInterpolationBase : public BidimensionalInterpolation +{ +public: + + /*! + * Constructs a new %BicubicInterpolationBase instance. + */ + BicubicInterpolationBase() = default; + + /*! + * Copy constructor. + */ + BicubicInterpolationBase( const BicubicInterpolationBase& ) = default; + +protected: + + void InitXY( int& i1, int& j1, double* p0, double* p1, double* p2, double* p3, double x, double y ) const noexcept + { + PCL_PRECONDITION( int( x ) >= 0 ) + PCL_PRECONDITION( int( x ) < m_width ) + PCL_PRECONDITION( int( y ) >= 0 ) + PCL_PRECONDITION( int( y ) < m_height ) + + // Central grid coordinates + i1 = pcl::Range( TruncInt( y ), 0, m_height-1 ); + j1 = pcl::Range( TruncInt( x ), 0, m_width-1 ); + + // Set up source matrix + + int j0 = j1 - 1; + int i0 = i1 - 1; + + int j2 = j1 + 1; + int i2 = i1 + 1; + + int j3 = j1 + 2; + int i3 = i1 + 2; + + const T* fp = m_data + (int64( i0 )*m_width + j0); + + // Row 0 + + if ( i0 < 0 ) + { + fp += m_width; + + if ( m_fillBorder ) + { + p0[0] = p0[1] = p0[2] = p0[3] = m_fillValue; + goto __row1; + } + } + + GetRow( p0, fp, j0, j2, j3 ); + + if ( i0 >= 0 ) + fp += m_width; + +__row1: // Row 1 + + GetRow( p1, fp, j0, j2, j3 ); + + // Row 2 + + if ( i2 < m_height ) + fp += m_width; + + GetRow( p2, fp, j0, j2, j3 ); + + // Row 3 + + if ( i3 < m_height ) + fp += m_width; + else if ( m_fillBorder ) + { + p3[0] = p3[1] = p3[2] = p3[3] = m_fillValue; + goto __done; + } + + GetRow( p3, fp, j0, j2, j3 ); + +__done: + ; + } + + void InitYX( int& i1, int& j1, double* p0, double* p1, double* p2, double* p3, double x, double y ) const noexcept + { + PCL_PRECONDITION( int( x ) >= 0 ) + PCL_PRECONDITION( int( x ) < m_width ) + PCL_PRECONDITION( int( y ) >= 0 ) + PCL_PRECONDITION( int( y ) < m_height ) + + // Central grid coordinates + i1 = pcl::Range( TruncInt( y ), 0, m_height-1 ); + j1 = pcl::Range( TruncInt( x ), 0, m_width-1 ); + + // Set up source matrix + + int j0 = j1 - 1; + int i0 = i1 - 1; + + int j2 = j1 + 1; + int i2 = i1 + 1; + + int j3 = j1 + 2; + int i3 = i1 + 2; + + const T* fp = m_data + (int64( i0 )*m_width + j0); + + // Column 0 + + if ( j0 < 0 ) + { + ++fp; + + if ( m_fillBorder ) + { + p0[0] = p0[1] = p0[2] = p0[3] = m_fillValue; + goto __col1; + } + } + + GetColumn( p0, fp, i0, i2, i3 ); + + if ( j0 >= 0 ) + ++fp; + +__col1: // Column 1 + + GetColumn( p1, fp, i0, i2, i3 ); + + // Column 2 + + if ( j2 < m_width ) + ++fp; + + GetColumn( p2, fp, i0, i2, i3 ); + + // Column 3 + + if ( j3 < m_width ) + ++fp; + else if ( m_fillBorder ) + { + p3[0] = p3[1] = p3[2] = p3[3] = m_fillValue; + goto __done; + } + + GetColumn( p3, fp, i0, i2, i3 ); + +__done: + ; + } + +private: + + void GetRow( double* p, const T* fp, int j0, int j2, int j3 ) const noexcept + { + if ( m_fillBorder ) + { + *p = (j0 >= 0) ? *fp : m_fillValue; + *++p = *++fp; + + if ( j2 < m_width ) + { + *++p = *++fp; + *++p = (j3 < m_width) ? *++fp : m_fillValue; + } + else + p[1] = p[2] = m_fillValue; + } + else + { + if ( j0 < 0 ) + ++fp; + *p = *fp; + if ( j0 >= 0 ) + ++fp; + *++p = *fp; + + if ( j2 < m_width ) + { + *++p = *++fp; + if ( j3 < m_width ) + ++fp; + *++p = *fp; + } + else + { + *++p = *fp; + *++p = *(fp - 1); + } + } + } + + void GetColumn( double* p, const T* fp, int i0, int i2, int i3 ) const noexcept + { + if ( m_fillBorder ) + { + *p = (i0 >= 0) ? *fp : m_fillValue; + *++p = *(fp += m_width); + + if ( i2 < m_height ) + { + *++p = *(fp += m_width); + *++p = (i3 < m_height) ? *(fp += m_width) : m_fillValue; + } + else + p[1] = p[2] = m_fillValue; + } + else + { + if ( i0 < 0 ) + fp += m_width; + *p = *fp; + if ( i0 >= 0 ) + fp += m_width; + *++p = *fp; + + if ( i2 < m_height ) + { + *++p = *(fp += m_width); + if ( i3 < m_height ) + fp += m_width; + *++p = *fp; + } + else + { + *++p = *fp; + *++p = *(fp - m_width); + } + } + } +}; + +// ---------------------------------------------------------------------------- + +#define InitXY this->InitXY +#define InitYX this->InitYX + +/* + * Undefine the following to use any free constant value a != -1/2 + */ +#define __PCL_BICUBIC_SPLINE_A_IS_MINUS_ONE_HALF 1 + +/* + * The "a" constant controls the depth of the negative lobes in the bicubic + * spline interpolation function, -1 <= a < 0. Larger values of a (in absolute + * value) lead to more ringing (sharpness). The default is -1/2, as recommended + * in [Keys 1981]. + */ +#define __PCL_BICUBIC_SPLINE_A -0.5 + +/* + * Default clamping threshold for linear images. This value has been optimized + * for a = -1/2. If you use another value for a, this must also be fine tuned. + */ +#ifndef __PCL_BICUBIC_SPLINE_CLAMPING_THRESHOLD +#define __PCL_BICUBIC_SPLINE_CLAMPING_THRESHOLD 0.3F +#endif + +/*! + * \class BicubicSplineInterpolation + * \brief Bicubic spline interpolation algorithm + * + * Bicubic interpolation algorithms interpolate from the nearest sixteen mapped + * source data items. Our implementation uses the following cubic spline + * function as a separable filter to perform a convolution interpolation: + * + *
+ * f(x) = (a+2)*x^3 - (a+3)*x^2 + 1       for 0 <= x <= 1
+ * f(x) = a*x^3 - 5*a*x^2 + 8*a*x - 4*a   for 1 < x <= 2
+ * f(x) = 0                               otherwise
+ * 
+ * + * Reference: Keys, R. G. (1981), %Cubic %Convolution %Interpolation for + * %Digital %Image %Processing, IEEE Trans. %Acoustics, %Speech & %Signal + * Proc., Vol. 29, pp. 1153-1160. + * + * The a constant parameter of the cubic spline (-1 <= a < 0) controls the + * depth of the negative lobes of the interpolation function. In this + * implementation we have set a fixed value a=-1/2. + * + * Our implementation includes an automatic linear clamping mechanism + * to avoid discontinuity problems when interpolating linear images. The cubic + * spline function has negative lobes that can cause undershoot (aka ringing) + * artifacts when they fall over bright pixels. This happens frequently with + * linear CCD images. See the documentation for the + * BicubicSplineInterpolation::SetClampingThreshold( float ) function for a + * more detailed description of the linear clamping mechanism. + */ +template +class PCL_CLASS BicubicSplineInterpolation : public BicubicInterpolationBase +{ +public: + + /*! + * Constructs a %BicubicSplineInterpolation instance. + * + * The optional \e clamp parameter defines a threshold to trigger the + * linear clamping mechanism. See the documentation for the + * SetClampingThreshold( float ) function for a detailed description of the + * automatic linear clamping mechanism. The default value of \e clamp = 0.1 + * is appropriate for most linear images. + */ + BicubicSplineInterpolation( float clamp = __PCL_BICUBIC_SPLINE_CLAMPING_THRESHOLD ) + : m_clamp( Range( clamp, 0.0F, 1.0F ) ) + { + PCL_PRECONDITION( 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + BicubicSplineInterpolation( const BicubicSplineInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~BicubicSplineInterpolation() + { + } + + /*! + * Returns an interpolated value at {\a x,\a y} location. + * + * \param x,y %Coordinates of the interpolation point (horizontal, + * vertical). + * + * This function performs a two-dimensional interpolation via a convolution + * with the separable cubic spline filter. + */ + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + + // Initialize grid coordinates and source matrix + int i1, j1; + double p0[ 4 ], p1[ 4 ], p2[ 4 ], p3[ 4 ]; + InitXY( i1, j1, p0, p1, p2, p3, x, y ); + + // Cubic spline coefficients + double C[ 4 ]; + GetSplineCoefficients( C, x-j1 ); + + // Interpolate neighbor rows + double c[ 4 ]; + c[0] = Interpolate( p0, C ); + c[1] = Interpolate( p1, C ); + c[2] = Interpolate( p2, C ); + c[3] = Interpolate( p3, C ); + + // Interpolate result vertically + GetSplineCoefficients( C, y-i1 ); + return Interpolate( c, C ); + } + + /*! + * Horizontal interpolation. + * + * \param x,y %Coordinates of the interpolation point (horizontal, + * vertical). + * + * \param[out] fx Address of the first element of a vector where the four + * interpolated X-values will be stored. + * + * This function interpolates horizontally the four neighbor rows for the + * specified \a x, \a y coordinates. This is useful when this interpolation + * algorithm is being used to interpolate an image on the horizontal axis + * exclusively. + */ + void InterpolateX( double fx[], double x, double y ) const noexcept + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + + // Initialize grid coordinates and source matrix + int i1, j1; + double p0[ 4 ], p1[ 4 ], p2[ 4 ], p3[ 4 ]; + InitXY( i1, j1, p0, p1, p2, p3, x, y ); + + // Cubic spline coefficients + double C[ 4 ]; + GetSplineCoefficients( C, x-j1 ); + + // Interpolate neighbor rows + fx[0] = Interpolate( p0, C ); + fx[1] = Interpolate( p1, C ); + fx[2] = Interpolate( p2, C ); + fx[3] = Interpolate( p3, C ); + } + + /*! + * Vertical interpolation. + * + * \param x,y %Coordinates of the interpolation point (horizontal, + * vertical). + * + * \param[out] fy Address of the first element of a vector where the four + * interpolated Y-values will be stored. + * + * This function interpolates vertically the four neighbor columns for the + * specified \a x, \a y coordinates. This is useful when this interpolation + * algorithm is being used to interpolate an image on the vertical axis + * exclusively. + */ + void InterpolateY( double fy[], double x, double y ) const noexcept + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + + // Initialize grid coordinates and source matrix + int i1, j1; + double p0[ 4 ], p1[ 4 ], p2[ 4 ], p3[ 4 ]; + InitYX( i1, j1, p0, p1, p2, p3, x, y ); + + // Cubic spline coefficients + double C[ 4 ]; + GetSplineCoefficients( C, y-i1 ); + + // Interpolate neighbor columns + fy[0] = Interpolate( p0, C ); + fy[1] = Interpolate( p1, C ); + fy[2] = Interpolate( p2, C ); + fy[3] = Interpolate( p3, C ); + } + + /*! + * %Vector interpolation. + * + * \param c Address of the first element of a vector of four data points. + * + * \param dx %Interpolation point in the range [0,+1[. A value of zero + * corresponds to the second element in the f vector. + * + * This function interpolates four neighbor rows or columns by direct + * convolution with the cubic spline function. The four elements of the \a c + * vector can be raw data points, to use cubic spline interpolation in one + * dimension, or they can be interpolated rows or columns from an arbitrary + * 2-D matrix. For example, \a c can be generated by a previous call to + * InterpolateX() or InterpolateY(), respectively to provide source + * interpolated rows or columns, or by equivalent functions from a different + * separable cubic interpolation algorithm. This is useful to mix cubic + * spline interpolation with other interpolation algorithms, which allows + * for flexible interpolation schemes. + */ + double InterpolateVector( const double c[], double dx ) const noexcept + { + double C[ 4 ]; + GetSplineCoefficients( C, dx ); + return Interpolate( c, C ); + } + + /*! + * Returns the current linear clamping threshold for this + * interpolation object. + * + * See the documentation for SetClampingThreshold( float ) for a detailed + * description of the automatic linear clamping mechanism. + */ + float ClampingThreshold() const noexcept + { + return m_clamp; + } + + /*! + * Defines a threshold to trigger the linear clamping mechanism. + * The clamping mechanism automatically switches to linear interpolation + * when the differences between neighbor pixels are so large that the cubic + * interpolation function may cause ringing artifacts. Ringing occurs when + * the negative lobes of the cubic spline interpolation function fall over + * isolated bright source pixels or bright edges. For example, ringing + * problems happen frequently around stars in linear CCD images. For + * nonlinear images, linear clamping is almost never necessary, as in + * nonlinear images (e.g., stretched deep-sky images, or diurnal images) + * there are normally no such large variations between neighbor pixels. + * + * Linear clamping works on a per-row or per-column basis within the + * interpolation neighborhood of 16 pixels. This means that when the + * clamping mechanism selects linear interpolation, it restricts its use to + * the affected (by too strong variations) row or column, without changing + * the bicubic interpolation scheme as a whole. This ensures artifact-free + * interpolated images without degrading the overall performance of bicubic + * spline interpolation. + * + * The specified clamping threshold \e clamp must be in the [0,1] range. + * Lower values cause a more aggressive deringing effect. + */ + void SetClampingThreshold( float c ) noexcept + { + PCL_PRECONDITION( 0 <= c && c <= 1 ) + m_clamp = Range( c, 0.0F, 1.0F ); + } + +private: + + double m_clamp; + + PCL_HOT_FUNCTION + double Interpolate( const double* __restrict__ p, const double* __restrict__ C ) const noexcept + { + // Unclamped code: + //return p[0]*C[0] + p[1]*C[1] + p[2]*C[2] + p[3]*C[3]; + double f12 = p[1]*C[1] + p[2]*C[2]; + double f03 = p[0]*C[0] + p[3]*C[3]; + return (-f03 < f12*m_clamp) ? f12 + f03 : f12/(C[1] + C[2]); + } + + PCL_HOT_FUNCTION + void GetSplineCoefficients( double* __restrict__ C, double dx ) const noexcept + { + double dx2 = dx*dx; + double dx3 = dx2*dx; + +#ifdef __PCL_BICUBIC_SPLINE_A_IS_MINUS_ONE_HALF + // Optimized code for a = -1/2 + // We *really* need optimization here since this routine is called twice + // for each interpolated pixel. + double dx1_2 = dx/2; + double dx2_2 = dx2/2; + double dx3_2 = dx3/2; + double dx22 = dx2 + dx2; + double dx315 = dx3 + dx3_2; + C[0] = dx2 - dx3_2 - dx1_2; + C[1] = dx315 - dx22 - dx2_2 + 1; + C[2] = dx22 - dx315 + dx1_2; + C[3] = dx3_2 - dx2_2; +#else +# define a (__PCL_BICUBIC_SPLINE_A) + C[0] = a*dx3 - 2*a*dx2 + a*dx; + C[1] = (a + 2)*dx3 - (a + 3)*dx2 + 1; + C[2] = -(a + 2)*dx3 + (2*a + 3)*dx2 - a*dx; + C[3] = -a*dx3 + a*dx2; +# undef a +#endif + } +}; + +/*! + * \class BicubicInterpolation + * \brief Bicubic interpolation - an alias for BicubicSplineInterpolation + * + * %BicubicInterpolation is a synonym for the BicubicSplineInterpolation class. + * + * \deprecated This class exists to support old PCL-based code; all new code + * should use the BicubicSplineInterpolation class. + * + * \sa BicubicSplineInterpolation + */ +template +class PCL_CLASS BicubicInterpolation : public BicubicSplineInterpolation +{ +public: + + /*! + * Constructs a %BicubicInterpolation instance. + */ + BicubicInterpolation() = default; + + /*! + * Copy constructor. + */ + BicubicInterpolation( const BicubicInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~BicubicInterpolation() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BicubicBSplineInterpolation + * \brief Bicubic B-Spline Interpolation Algorithm + * + * Like bicubic spline interpolation, the bicubic B-spline interpolation + * algorithm also interpolates from the nearest sixteen data items. However, + * this algorithm uses B-spline interpolating functions instead of cubic + * splines, which yields quite (too?) smooth results. + * + * This implementation is based on Bicubic %Interpolation for %Image + * Scaling, by Paul Bourke. It performs a convolution with a nonseparable + * 2-D filter, so its performance is O(n^2). + * + * \sa BicubicSplineInterpolation, BicubicInterpolation, BilinearInterpolation, + * NearestNeighborInterpolation + */ +template +class PCL_CLASS BicubicBSplineInterpolation : public BicubicInterpolationBase +{ +public: + + /*! + * Constructs a %BicubicBSplineInterpolation instance. + */ + BicubicBSplineInterpolation() = default; + + /*! + * Copy constructor. + */ + BicubicBSplineInterpolation( const BicubicBSplineInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~BicubicBSplineInterpolation() + { + } + + /*! + * Interpolated value at \a {x,y} location. + * + * \param x,y %Coordinates of the interpolation point (horizontal, + * vertical). + */ + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( f != 0 ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + + // Initialize grid coordinates and source matrix + int i1, j1; + double p0[ 4 ], p1[ 4 ], p2[ 4 ], p3[ 4 ]; + InitXY( i1, j1, p0, p1, p2, p3, x, y ); + + // Bicubic B-Spline interpolation functions + + double dx = x - j1; + double dx0 = -1 - dx; + double dx1 = -dx; + double dx2 = 1 - dx; + double dx3 = 2 - dx; + + double dy = y - i1; + double dy0 = -1 - dy; + double dy1 = -dy; + double dy2 = 1 - dy; + double dy3 = 2 - dy; + + return + BXY( p0, 0, dx0, dy0 ) + + BXY( p0, 1, dx1, dy0 ) + + BXY( p0, 2, dx2, dy0 ) + + BXY( p0, 3, dx3, dy0 ) + + BXY( p1, 0, dx0, dy1 ) + + BXY( p1, 1, dx1, dy1 ) + + BXY( p1, 2, dx2, dy1 ) + + BXY( p1, 3, dx3, dy1 ) + + BXY( p2, 0, dx0, dy2 ) + + BXY( p2, 1, dx1, dy2 ) + + BXY( p2, 2, dx2, dy2 ) + + BXY( p2, 3, dx3, dy2 ) + + BXY( p3, 0, dx0, dy3 ) + + BXY( p3, 1, dx1, dy3 ) + + BXY( p3, 2, dx2, dy3 ) + + BXY( p3, 3, dx3, dy3 ); + } + +private: + + double BXY( const double* __restrict__ p, int j, double x, double y ) const noexcept + { + return p[j]*B( x )*B( y ); + } + + double B( double x ) const noexcept + { + double fx = (x > 0) ? x*x*x : 0; + + double fxp1 = x + 1; + fxp1 = (fxp1 > 0) ? fxp1*fxp1*fxp1 : 0; + + double fxp2 = x + 2; + fxp2 = (fxp2 > 0) ? fxp2*fxp2*fxp2 : 0; + + double fxm1 = x - 1; + fxm1 = (fxm1 > 0) ? fxm1*fxm1*fxm1 : 0; + + return (fxp2 - 4*fxp1 + 6*fx - 4*fxm1)/6; + } +}; + +// ---------------------------------------------------------------------------- + +#undef InitXY +#undef InitYX + +// ---------------------------------------------------------------------------- + +#undef m_width +#undef m_height +#undef m_fillBorder +#undef m_fillValue +#undef m_data + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BicubicInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/BicubicInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/BidimensionalInterpolation.h b/3rdparty/include/pcl/BidimensionalInterpolation.h new file mode 100644 index 0000000..59966b7 --- /dev/null +++ b/3rdparty/include/pcl/BidimensionalInterpolation.h @@ -0,0 +1,236 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/BidimensionalInterpolation.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_BidimensionalInterpolation_h +#define __PCL_BidimensionalInterpolation_h + +/// \file pcl/BidimensionalInterpolation.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class BidimensionalInterpolation + * \brief A generic interface to two-dimensional interpolation algorithms. + * + * %BidimensionalInterpolation is a base class for all two-dimensional + * interpolation algorithm implementations in PCL. + */ +template +class PCL_CLASS BidimensionalInterpolation +{ +public: + + /*! + * Constructs a %BidimensionalInterpolation object. + */ + BidimensionalInterpolation() = default; + + /*! + * Copy constructor. + */ + BidimensionalInterpolation( const BidimensionalInterpolation& ) = default; + + /*! + * Destroys a %BidimensionalInterpolation object. + */ + virtual ~BidimensionalInterpolation() + { + Clear(); + } + + /*! + * Initializes a new interpolation. + * + * \param data Two-dimensional matrix of function values stored in + * row-order. Must remain valid and accessible while this + * object is used to compute interpolated function values. + * + * \param width Horizontal dimension (most rapidly varying coordinate) of + * the data array. + * + * \param height Vertical dimension (most slowly varying coordinate) of the + * data array. + */ + virtual void Initialize( const T* data, int width, int height ) + { + if ( data == nullptr ) + throw Error( "Null data pointer in BidimensionalInterpolation::Initialize()" ); + if ( width <= 0 || height <= 0 ) + throw Error( "Invalid dimensions in BidimensionalInterpolation::Initialize()" ); + m_data = data; + m_width = width; + m_height = height; + } + + /*! + * Returns an interpolated function value at \a x, \a y coordinates. + */ + virtual double operator()( double x, double y ) const = 0; + + /*! + * Clears auxiliary/intermediate data (and/or whatever requires clean up). + * Derived classes overriding this function should call their base class + * version via explicit downcast. + */ + virtual void Clear() + { + m_data = nullptr; + m_width = m_height = 0; + } + + /*! + * Returns a pointer to the interpolated data array. + */ + const T* BeingInterpolated() const + { + return m_data; + } + + /*! + * Returns the width (number of columns) of the interpolated data matrix. + */ + int Width() const + { + return m_width; + } + + /*! + * Returns the height (number of rows) of the interpolated data matrix. + */ + int Height() const + { + return m_height; + } + + /*! + * Enables (or disables) border filling. + * + * When border filling is enabled, a user-defined constant fill value is + * used to interpolate at locations near the borders of the data matrix. + * + * When border filling is disabled, existing border values are extended to + * interpolate at border locations (Neumann boundary conditions). + */ + void EnableBorderFilling( bool enable = true ) + { + m_fillBorder = enable; + } + + /*! + * Disables (or enables) border filling. + * + * This is a convenience member function, equivalent to: + * + * EnableBorderFilling( !disable ); + */ + void DisableBorderFilling( bool disable = true ) + { + m_fillBorder = !disable; + } + + /*! + * Returns true iff border filling is enabled for this interpolation. See the + * documentation for EnableBorderFilling() for more information. + */ + bool IsBorderFillingEnabled() const + { + return m_fillBorder; + } + + /*! + * Sets the border fill value \a v. See the documentation for + * EnableBorderFilling() for more information about border filling and + * boundary conditions. + * + * \param v Border fill value. It is the responsibility of the caller to + * ensure that the specified value is within the valid range of + * the data type used by this interpolation. + */ + void SetBorderFillValue( double v ) + { + m_fillValue = v; + } + + /*! + * Returns the current border fill value for this interpolation. See the + * documentation for EnableBorderFilling() for more information about border + * filling and boundary conditions. + */ + double BorderFillValue() const + { + return m_fillValue; + } + +protected: + + const T* m_data = nullptr; // functional data being interpolated + int m_width = 0; // width of the data table + int m_height = 0; // height of the data table + double m_fillValue = 0; // fill value, when m_fillBorder = true + bool m_fillBorder = false; // don't apply Neumann boundary conditions +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BidimensionalInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/BidimensionalInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/BilinearInterpolation.h b/3rdparty/include/pcl/BilinearInterpolation.h new file mode 100644 index 0000000..02fd76b --- /dev/null +++ b/3rdparty/include/pcl/BilinearInterpolation.h @@ -0,0 +1,164 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/BilinearInterpolation.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_BilinearInterpolation_h +#define __PCL_BilinearInterpolation_h + +/// \file pcl/BilinearInterpolation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_width this->m_width +#define m_height this->m_height +#define m_fillBorder this->m_fillBorder +#define m_fillValue this->m_fillValue +#define m_data this->m_data + +// ---------------------------------------------------------------------------- + +/*! + * \class BilinearInterpolation + * \brief Bilinear interpolation algorithm. + * + * The bilinear interpolation algorithm interpolates from the nearest four + * mapped source data items. It builds and evaluates two linear interpolation + * polynomials, one for each plane direction. + * + * \sa NearestNeighborInterpolation, BicubicSplineInterpolation, + * BicubicBSplineInterpolation, BicubicFilterInterpolation, + */ +template +class PCL_CLASS BilinearInterpolation : public BidimensionalInterpolation +{ +public: + + /*! + * Constructs a %BilinearInterpolation instance. + */ + BilinearInterpolation() = default; + + /*! + * Copy constructor. + */ + BilinearInterpolation( const BilinearInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~BilinearInterpolation() + { + } + + /*! + * Returns an interpolated value at {\a x,\a y} location. + * + * \param x,y Coordinates of the interpolation point (horizontal,vertical). + */ + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + + int j0 = pcl::Range( TruncInt( x ), 0, m_width-1 ); + int i0 = pcl::Range( TruncInt( y ), 0, m_height-1 ); + + int j1 = j0 + 1; + int i1 = i0 + 1; + + double p00, p10, p01, p11; + const T* fp = m_data + (int64( i0 )*m_width + j0); + + p00 = *fp; + p10 = (j1 < m_width) ? fp[1] : (m_fillBorder ? m_fillValue : *fp); + + if ( i1 < m_height ) + fp += m_width; + else if ( m_fillBorder ) + { + p01 = p11 = m_fillValue; + goto __1; + } + + p01 = *fp; + p11 = (j1 < m_width) ? fp[1] : (m_fillBorder ? m_fillValue : *fp); + +__1: + double dx = x - j0, dx1 = 1 - dx; + double dy = y - i0, dy1 = 1 - dy; + return p00*dx1*dy1 + p10*dx*dy1 + p01*dx1*dy + p11*dx*dy; + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_width +#undef m_height +#undef m_fillBorder +#undef m_fillValue +#undef m_data + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BilinearInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/BilinearInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Bitmap.h b/3rdparty/include/pcl/Bitmap.h new file mode 100644 index 0000000..2d84d1b --- /dev/null +++ b/3rdparty/include/pcl/Bitmap.h @@ -0,0 +1,1531 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Bitmap.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_Bitmap_h +#define __PCL_Bitmap_h + +/// \file pcl/Bitmap.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::BitmapFormat + * \brief Bitmap pixel value interpretation modes. + * + * + * + * + * + * + * + * + *
BitmapFormat::ARGB32AARRGGBB format. The alpha AA component is used to represent the + * transparency of each pìxel: from 0=transparent to 0xFF=opaque. + * This is the default mode.
BitmapFormat::RGB32ffRRGGBB format. The alpha component is set to a constant value of + * 255 = 0xff, hence the bitmap is always opaque. This mode can be used + * to improve the performance of graphics output when painting on + * controls, especially on X11 platforms (Linux and FreeBSD).
BitmapFormat::ARGB32_PremultipliedAARRGGBB format with red, green and blue components premultiplied by + * the alpha channel and divided by 255. This format is faster for + * bitmap renditions drawn with the Graphics and VectorGraphics + * classes.
+ */ +namespace BitmapFormat +{ + enum value_type + { + ARGB32, // AARRGGBB + RGB32, // ffRRGGBB + ARGB32_Premultiplied, // AARRGGBB with premultiplied RGB + + // ### TODO: Core version 1.8.x: Implement 16-bit bitmap formats. +// RGBA64, // RRRRGGGGBBBBAAAA +// RGBA64, // RRRRGGGGBBBBffff +// RGBA64_Premultiplied, // RRRRGGGGBBBBAAAA with premultiplied RGB + + NumberOfBitmapFormats, + + Invalid = -1 + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::SVGRenderOption + * \brief Rendering options for raster image representation of SVG documents. + * + * + * + * + * + * + * + * + *
SVGRenderOption::PreserveAspectRatioRender within the specified rectangular area, preserving the + * original aspect ratio of the SVG drawing. If not selected, render + * freely to fill the specified rectangular area entirely.
SVGRenderOption::HighQualityRender with a high-quality, thread-unsafe implementation supporting + * the entire SVG 1.1 specification. If not selected, use a fast + * thread-safe implementation that supports most of the SVG 1.1 + * specification.
SVGRenderOption::DefaultDefault rendering options: + * SVGRenderOption::PreserveAspectRatio | SVGRenderOption::Fast
+ */ +namespace SVGRenderOption +{ + enum mask_type + { + IgnoreAspectRatio = 0x00000000, // Render freely to fill the specified rectangular area entirely, ignoring aspect ratio. + PreserveAspectRatio = 0x00000001, // Render within the specified rectangular area, preserving the original aspect ratio of the SVG drawing. + Fast = 0x00000000, // Render with a fast, thread-safe implementation that supports most of the SVG 1.1 specification. + HighQuality = 0x00000010, // Render with a high-quality, thread-unsafe implementation supporting the entire SVG 1.1 specification. + Default = PreserveAspectRatio|Fast + }; +}; + +/*! + * \class pcl::SVGRenderOptions + * \brief A collection of rendering options for raster image representation of + * SVG documents. + */ +typedef Flags SVGRenderOptions; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class PCL_CLASS ImageVariant; + +// ---------------------------------------------------------------------------- + +/*! + * \class Bitmap + * \brief Client-side interface to a PixInsight %Bitmap object. + * + * In the PixInsight platform, bitmaps are device-independent images that can + * be used for graphics output and allow direct pixel manipulation. + * + * Pixels in a bitmap are always stored as 32-bit values in the following + * format: + * + * AARRGGBB + * + * where each letter represents a 4-bit hexadecimal digit (from 0 to F). Each + * 8-bit pair represents a pixel component in the range from 0 to 255: + * + * + * + * + * + * + *
AA Alpha value, or pixel opacity: 0 means + * completely transparent, 255 corresponds to an opaque + * pixel.
RR Red pixel color component.
GG Green pixel color component.
BB Blue pixel color component.
+ * + * %Bitmap is a managed, high-level object that encapsulates the properties and + * behavior of an actual bitmap living in the PixInsight core application. + * + * %Bitmap provides a comprehensive set of functions and utility routines to + * manipulate bitmap images, such as direct pixel access functions, specular + * and affine transformations, bitwise logical operations, and high-performance + * rendering of images as bitmaps, among many others. + * + * Along with the Graphics class, %Bitmap can be used for off-screen graphics + * output. Graphics offers a thorough collection of painting routines that can + * be used to generate sophisticated graphics as bitmaps. + * + * As we have said, bitmaps are device-independent images in PixInsight. It + * must be pointed out that there is no equivalent to a \e device-dependent + * bitmap or image in PixInsight: all device dependencies are managed + * internally by the PixInsight core application. + */ +class PCL_CLASS Bitmap : public UIObject +{ +public: + + /*! + * Represents a bitmap pixel format. See the BitmapFormat namespace for + * supported values. + */ + typedef BitmapFormat::value_type pixel_format; + + /*! + * The %display_channel type represents a display channel supported by the + * PixInsight core application. Valid channels are defined in the + * DisplayChannel namespace. + */ + typedef DisplayChannel::value_type display_channel; + + /*! + * The %mask_mode type represents a mask rendering mode supported by + * the PixInsight core application. Valid mask rendering modes are defined + * in the MaskMode namespace. + */ + typedef MaskMode::value_type mask_mode; + + /*! + * Constructs an empty %Bitmap object. + */ + Bitmap(); + + /*! + * Constructs a %Bitmap object of the specified \a width and \a height + * dimensions, and pixel format \a fmt + * + * For the sake of performance, bitmap pixel values are not initialized, so + * they will contain unpredictable \e garbage values. + */ + Bitmap( int width, int height, pixel_format fmt = BitmapFormat::ARGB32 ); + + /*! + * Constructs a %Bitmap object from a source image in the XPM format. + * + * \param xpm Starting address of an XPM image description. + * + * \b References + * + * \li http://en.wikipedia.org/wiki/X_PixMap + * \li http://www.xfree86.org/current/xpm.pdf + */ + Bitmap( const char** xpm ); + + /*! + * Constructs a %Bitmap object by loading an embedded resource or disk file. + * + * \param filePath Path to the source image file or resource. A resource + * path begins with the ":/" prefix. For a list of supported + * image file formats, see the documentation for the + * Load( const String& ) member function. The source file format + * is always determined from the specified file extension. + * + * For more information on embedded resources, see + * Bitmap::Bitmap( const char* ). + * + * In the even of file I/O error, or if the specified file cannot be decoded + * and read correctly, this constructor throws an Error exception. + */ + Bitmap( const String& filePath ); + + /*! + * Constructs a %Bitmap object by loading an embedded resource or disk file. + * + * \param filePath Path to the source image file or resource. A resource + * path begins with the ":/" prefix. For a list of supported + * image file formats, see the documentation for the + * Load( const String& ) member function. The source file format + * is always determined from the specified file extension. + * + * The PixInsight core application uses the Qt resource system for embedded + * images that can be loaded dynamically from .rcc binary files. For + * example, the following code snippet loads one of the standard core + * application icons: + * + * \code Bitmap icon( ":/icons/document.png" ); \endcode + * + * A module can also use the standard ":/@module_root/" prefix to load + * module-defined resources. See MetaModule::LoadResource() for a detailed + * description. + * + * In the even of stream I/O error, or if the specified resource or file + * cannot be decoded and read correctly, this constructor throws an Error + * exception. + * + * \b References + * + * \li The Qt Resource System: http://doc.qt.io/qt-5/resources.html + */ + Bitmap( const char* filePath ); + + /*! + * Constructs a %Bitmap object by loading an embedded resource or disk file. + * This constructor is equivalent to Bitmap::Bitmap( const char* ). + */ + Bitmap( const IsoString& filePath ); + + /*! + * Constructs a %Bitmap object from bitmap data stored in memory. + * + * \param data Starting address of the source bitmap data block. + * + * \param size Length of the source data in bytes. + * + * \param format A nul-terminated character string identifying the format + * of the source data. Currently the following formats are + * supported by the PixInsight core application: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
%BMP Windows %Bitmap
%GIF %Graphics Interchange Format
%ICO Windows %Icon Format
%JPG Joint Photographic Experts Group
%WEBP %WebP image format
%MNG Multiple Network %Graphics
%PBM Portable Bitmap
%PNG Portable Network %Graphics
%PPM Portable Pixel Map
%SVG Scalable Vector Graphics
%TIFF Tagged %Image %File Format
%TGA Truevision TGA Format (TARGA)
%XBM X11 Bitmap
%XPM X11 Pixmap
+ * + * The default value (when no format is specified) is SVG. + * + * \param flags Currently not used. This parameter is reserved for future + * extension and its value must be zero (the default value). + * + * If the \a data address is invalid, or if the data are not valid in the + * specified \a format, this constructor throws an Error exception. + */ + Bitmap( const void* data, size_type size, const char* format = "SVG", uint32 flags = 0 ); + + /*! + * Constructs a %Bitmap object as a subimage of an existing %Bitmap. + * + * \param bmp Source bitmap. + * + * \param r Rectangle that defines the source subimage, in source + * bitmap coordinates. + */ + Bitmap( const Bitmap& bmp, const pcl::Rect& r ); + + /*! + * Constructs a %Bitmap object as a subimage of an existing %Bitmap. + * + * \param bmp Source bitmap. + * + * \param x0, y0 Coordinates of the upper left corner of the rectangle that + * defines the source subimage, in source bitmap coordinates. + * + * \param x1, y1 Coordinates of the lower right corner of the rectangle + * that defines the source subimage, in source bitmap + * coordinates. + */ + Bitmap( const Bitmap& bmp, int x0, int y0, int x1, int y1 ); + + /*! + * Copy constructor. This object will reference the same server-side bitmap + * as the specified instance \a b. + */ + Bitmap( const Bitmap& bmp ) : UIObject( bmp ) + { + } + + /*! + * Move constructor. + */ + Bitmap( Bitmap&& x ) : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys a %Bitmap object. + * + * The actual bitmap object that this %Bitmap instance refers to lives in + * the PixInsight core application, and as such, it will be destroyed and + * deallocated (garbage-collected) only when no more references exist to it + * in other high-level managed objects, such as other instances of %Bitmap + * living in installed modules, or some element of the graphical interface. + */ + virtual ~Bitmap() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side bitmap as the specified + * instance \a bmp. If the previous bitmap becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + Bitmap& operator =( const Bitmap& bmp ) + { + Assign( bmp ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Bitmap& operator =( Bitmap&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null %Bitmap instance. A null %Bitmap does not + * correspond to an existing bitmap in the PixInsight core application. + */ + static Bitmap& Null(); + + /*! + * Returns the current pixel format for this bitmap. + * + * Supported pixel format values are enumerated in the BitmapFormat + * namespace. + */ + pixel_format PixelFormat() const; + + /*! + * Sets the pixel format for this bitmap. If necessary, pixel values will + * be converted internally to match the specified format. + * + * Supported pixel format values are enumerated in the BitmapFormat + * namespace. + */ + void SetPixelFormat( pixel_format fmt ); + + /*! + * Renders an image as a bitmap. + * + * \param image The source image to be rendered. It can be a PCL image of + * any supported sample type. + * + * \param zoom Zoom factor. If zoom == 1, the image will be rendered at + * its actual dimensions in pixels. Positive zoom factors are + * enlarging ratios; for example, if zoom == 2, the image will + * be rendered zoomed 2:1 (twice its actual sizes). Negative + * zoom factors are reduction ratios: zoom = -3 means zoomed + * 1:3, or one third of the actual image dimensions. + * + * \param displayChannel See the DisplayChannel enumeration for possible + * values. The default mode is DisplayChannel::RGBK, which means + * that the image will be rendered in RGB/gray composite mode. + * + * \param transparency If this parameter is true and the image has one + * or more alpha channels, the image will be rendered over a + * transparent background and the first alpha channel will + * define pixel opacity. If this parameter is false, alpha + * channels will not be interpreted as transparency masks. + * + * \param mask If non-null, this is the address of an image that will be + * treated as a mask acting for the source image. Mask pixels + * modify the image rendition according to the specified mask + * rendering mode (see the maskMode paramter). The mask image + * must have the same dimensions as the source image. This + * parameter is nullptr by default. + * + * \param maskMode This parameter defines the mask rendering mode to be + * used if a mask image has been specified. See the MaskMode + * enumeration for supported values. The default mode is + * MaskMode::Default, which corresponds to the red overlay mask + * rendering mode. + * + * \param maskInverted If \a mask is non-null and this parameter is + * true, mask pixels will be inverted before rendering them over + * source image pixels. + * + * \param LUT If non-null, this is the address of a look-up + * table that will be used to remap bitmap pixel values. + * This parameter is nullptr by default. + * + * \param fastDownsample If this parameter is true, a fast sparse + * interpolation algorithm will be used to render the image if a + * \a zoom factor less than -2 is specified. Fast subsampling + * interpolation is considerably faster than normal (slow) + * interpolation, but the generated renditions are less + * accurate. In general though, fast interpolation errors are + * barely noticeable. This parameter is true by default. + * + * \param callback If non-null, this is the address of a callback routine + * that will be invoked during the bitmap rendition procedure. + * If the callback routine returns false, the rendition is + * aborted and a null bitmap (Bitmap::Null()) is returned. By + * default this parameter is nullptr. + * + * This is a high-performance routine, implemented with highly optimized + * parallel code, that can be used for real-time image visualization. If + * allowed through global preferences, it will use all available processors + * and processor cores by means of concurrent threads. + */ + static Bitmap Render( const ImageVariant& image, + int zoom = 1, display_channel displayChannel = DisplayChannel::RGBK, bool transparency = true, + const ImageVariant* mask = nullptr, mask_mode maskMode = MaskMode::Default, bool maskInverted = false, + const uint8** LUT = nullptr, bool fastDownsample = true, bool (*callback)() = nullptr ); + + /*! + * Obtains the dimensions (width, height) of this bitmap in pixels. + */ + void GetDimensions( int& width, int& height ) const; + + /*! + * Returns the width of this bitmap in pixels. + */ + int Width() const + { + int w, dum; GetDimensions( w, dum ); return w; + } + + /*! + * Returns the height of this bitmap in pixels. + */ + int Height() const + { + int dum, h; GetDimensions( dum, h ); return h; + } + + /*! + * Returns the bounding rectangle of this bitmap. + * + * The upper-left corner of the returned rectangle is always at (0,0). The + * width and height of the returned rectangle are the bitmap dimensions. + */ + pcl::Rect Bounds() const + { + int w, h; GetDimensions( w, h ); return pcl::Rect( w, h ); + } + + /*! + * Returns true iff this bitmap is empty. An empty bitmap has zero dimensions + * and does not contain any image. + */ + bool IsEmpty() const; + + /*! + * Returns true iff this bitmap contains an image, that is, if it is not an + * empty bitmap. + * + * This is a convenience operator that simply returns !IsEmpty(). + */ + operator bool() const + { + return !IsEmpty(); + } + + /*! + * \defgroup bitmap_pixel_access Bitmap Pixel Access Functions + */ + + /*! + * Returns the value of a bitmap pixel. + * + * \param x,y Bitmap coordinates of the pixel to read. Pixel coordinates + * can vary in the range from (0,0) to (Width()-1, Height()-1). + * + * \ingroup bitmap_pixel_access + */ + RGBA Pixel( int x, int y ) const; + + /*! + * Returns the value of a bitmap pixel. + * + * \param p A Point object whose coordinates identify the pixel to read. + * Pixel coordinates can vary in the range from (0,0) to + * (Width()-1, Height()-1). + * + * \ingroup bitmap_pixel_access + */ + RGBA Pixel( const pcl::Point& p ) const + { + return Pixel( p.x, p.y ); + } + + /*! + * Sets the value of a bitmap pixel. + * + * \param x,y Bitmap coordinates of the pixel to write. Pixel coordinates + * can vary in the range from (0,0) to (Width()-1, Height()-1). + * + * \param v 32-bit pixel value encoded in the AARRGGBB format: AA is the + * alpha (transparency) value, RR is the red component, GG is + * green and BB is blue. Each element is an 8-bit value. + * + * \ingroup bitmap_pixel_access + */ + void SetPixel( int x, int y, RGBA v ); + + /*! + * Sets the value of a bitmap pixel. + * + * \param p A Point object whose coordinates identify the pixel to write. + * Pixel coordinates can vary in the range from (0,0) to + * (Width()-1, Height()-1). + * + * \param v 32-bit pixel value encoded in the AARRGGBB format: AA is the + * alpha (transparency) value, RR is the red component, GG is + * green and BB is blue. Each element is an 8-bit value. + * + * \ingroup bitmap_pixel_access + */ + void SetPixel( const pcl::Point& p, RGBA v ) + { + SetPixel( p.x, p.y, v ); + } + + /*! + * Returns the (constant) starting address of a row of pixels in this + * bitmap. + * + * \param y Vertical coordinate of the row of pixels. Vertical + * coordinates can vary in the range from 0 to Height()-1. + * + * \ingroup bitmap_pixel_access + */ + const RGBA* ScanLine( int y ) const; + + /*! + * Returns the starting address of a row of pixels in this bitmap. + * + * \param y Vertical coordinate of the row of pixels. Vertical + * coordinates can vary in the range from 0 to Height()-1. + * + * The returned address can be used to modify pixel values. + * + * \ingroup bitmap_pixel_access + */ + RGBA* ScanLine( int y ); + + /*! + * \defgroup bitmap_specular_transformations Bitmap Specular Transformations + */ + + /*! + * Returns a mirrored duplicate of this bitmap. The original (this) bitmap + * is not modified. + * + * \ingroup bitmap_specular_transformations + */ + Bitmap Mirrored() const; + + /*! + * Returns a duplicate of this bitmap, mirrored horizontally. The original + * (this) bitmap is not modified. + * + * \ingroup bitmap_specular_transformations + */ + Bitmap MirroredHorizontally() const; + + /*! + * Returns a duplicate of this bitmap, mirrored vertically. The original + * (this) bitmap is not modified. + * + * \ingroup bitmap_specular_transformations + */ + Bitmap MirroredVertically() const; + + /*! + * \defgroup bitmap_affine_transformations Bitmap Affine Transformations + */ + + /*! + * Returns a scaled duplicate of this bitmap. + * + * \param sx,sy Scaling factors in the X and Y axes. + * + * \param precise If this parameter is true, the scaled bitmap will be + * generated using a precise, smooth interpolation algorithm. + * This parameter is true by default. + * + * \ingroup bitmap_affine_transformations + */ + Bitmap Scaled( double sx, double sy, bool precise = true ) const; + + /*! + * Returns a scaled duplicate of this bitmap. + * + * \param sxy Scaling factor applied to both X and Y axes. + * + * \param precise If this parameter is true, the scaled bitmap will be + * generated using a precise, smooth interpolation algorithm. + * This parameter is true by default. + * + * \ingroup bitmap_affine_transformations + */ + Bitmap Scaled( double sxy, bool precise = true ) const; + + /*! + * Returns a scaled duplicate of this bitmap, with its width equal to a + * prescribed value in pixels. + * + * \param width Width in pixels of the returned bitmap. If this parameter + * is zero, an empty bitmap will be returned. + * + * \param precise If this parameter is true, the scaled bitmap will be + * generated using a precise, smooth interpolation algorithm. + * This parameter is true by default. + * + * \ingroup bitmap_affine_transformations + */ + Bitmap ScaledToWidth( int width, bool precise = true ) const; + + /*! + * Returns a scaled duplicate of this bitmap, with its height equal to a + * prescribed value in pixels. + * + * \param height Height in pixels of the returned bitmap. If this parameter + * is zero, an empty bitmap will be returned. + * + * \param precise If this parameter is true, the scaled bitmap will be + * generated using a precise, smooth interpolation algorithm. + * This parameter is true by default. + * + * \ingroup bitmap_affine_transformations + */ + Bitmap ScaledToHeight( int height, bool precise = true ) const; + + /*! + * Returns a scaled duplicate of this bitmap, with its width and height + * equal to prescribed values in pixels. + * + * \param width, height Width and height in pixels of the returned + * bitmap. If one or both of these parameters are zero, an + * empty bitmap will be returned. + * + * \param precise If this parameter is true, the scaled bitmap will be + * generated using a precise, smooth interpolation algorithm. + * This parameter is true by default. + * + * \ingroup bitmap_affine_transformations + */ + Bitmap ScaledToSize( int width, int height, bool precise = true ) const; + + /*! + * Returns a rotated duplicate of this bitmap. + * + * \param angle %Rotation angle in radians. + * + * \param precise If this parameter is true, the rotated bitmap will be + * generated using a precise, smooth interpolation algorithm. + * This parameter is true by default. + * + * \ingroup bitmap_affine_transformations + */ + Bitmap Rotated( double angle, bool precise = true ) const; + + /*! + * \defgroup bitmap_file_io Bitmap File I/O Routines + */ + + /*! + * Loads a disk image file in this bitmap. + * + * \param filePath %File path to the input image file. + * + * The input file format is always determined by the specified file + * extension (in \a filePath). Supported input formats: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
%BMP Windows %Bitmap (.bmp)
%GIF %Graphics Interchange Format (.gif) (read-only)
%ICO Windows %Icon Format (.ico)
%JPEG Joint Photographic Experts Group (.jpg, .jpeg)
%WEBP %WebP image format (.webp)
%MNG Multiple Network %Graphics (.mng) (read-only)
%PBM Portable BitMap (.pbm) (read-only)
%PNG Portable Network %Graphics (.png)
%PPM Portable Pixel Map (.ppm)
%SVG Scalable Vector Graphics (.svg) (read-only)
%TIFF Tagged %Image %File Format (.tif, .tiff).
%TGA Truevision TGA Format (TARGA) (.tga, .tpic).
%XBM X BitMap (.xbm)
%XPM X PixMap (.xpm)
+ * + * In the even of file I/O error, or if the specified file cannot be decoded + * and loaded correctly, this member function throws an Error exception. + * + * \ingroup bitmap_file_io + */ + void Load( const String& filePath ); + + /*! + * Saves this bitmap to a disk image file. + * + * \param filePath %File path to the output image file. + * + * \param quality Image quality for lossy compression in the range from 0 + * (lowest quality) to 100 (highest quality). Currently, this + * parameter is ignored if the output file is not in one of the + * %JPEG or %WebP formats. If this parameter is < 0, a default, + * format-dependent quality will be used. + * + * The output file format is always determined by the specified file + * extension (in \a filePath). Supported output formats include: + * + * + * + * + * + * + * + * + * + * + * + *
%BMP Windows %Bitmap (.bmp)
%ICO Windows %Icon Format (.ico)
%JPEG Joint Photographic Experts Group (.jpg, .jpeg)
%WEBP %WebP image format (.webp)
%PNG Portable Network %Graphics (.png)
%PPM Portable Pixel Map (.ppm)
%TIFF Tagged %Image %File Format (.tif, .tiff).
%XBM X BitMap (.xbm)
%XPM X PixMap (.xpm)
+ * + * In the even of file I/O error, or if the specified file cannot be encoded + * and written correctly, this member function throws an Error exception. + * + * \ingroup bitmap_file_io + */ + void Save( const String& filePath, int quality = -1 ) const; + + /*! + * Loads this bitmap from data stored in memory. + * + * \param data Starting address of the source bitmap data block. + * + * \param size Length of the source data in bytes. + * + * \param format A nul-terminated character string identifying the format + * of the source data. Currently the only supported format is + * Scalable Vector Graphics (SVG), and this is also the + * default value of this parameter ("SVG"). + * + * \param flags Currently not used. This parameter is reserved for future + * extension and its value must be zero (the default value). + * + * If the \a data address is invalid, or if the data are not valid in the + * specified \a format, this member function throws an Error exception. + */ + void Load( const void* data, size_type size, const char* format = "SVG", uint32 flags = 0 ); + + /*! + * Returns a subimage of this bitmap. + * + * \param x0, y0 Coordinates of the upper left corner of the source + * rectangular region. + * + * \param x1, y1 Coordinates of the lower right corner of the source + * rectangular region. + * + * The rectangular region defines the size and position of the subimage that + * is extracted and returned as a new %Bitmap object. + */ + Bitmap Subimage( int x0, int y0, int x1, int y1 ) const; + + /*! + * Returns a subimage of this bitmap. + * + * \param r A Rect object defining subimage boundaries. + * + * The rectangular area defines the size and position of the subimage that + * is extracted and returned as a new %Bitmap object. + */ + Bitmap Subimage( const pcl::Rect& r ) const + { + return Subimage( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * \defgroup bitmap_bitwise_ops Bitmap Bitwise Logical Operations + */ + + /*! + * Copies a region of a source bitmap to the specified location on this + * bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap, whose pixels will be copied to this bitmap. + * + * \param r Defines the rectangular area that will be copied, in source + * bitmap coordinates. + * + * Target pixels on this bitmap are replaced with pixels read from the + * source bitmap \a src. Source pixels falling outside the boundaries of + * this bitmap are ignored. + * + * \ingroup bitmap_bitwise_ops + */ + void Copy( const pcl::Point& p, const Bitmap& src, const pcl::Rect& r ); + + /*! + * Copies all pixels from a source bitmap to the specified location on this + * bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap, whose pixels will be copied to this bitmap. + * + * Target pixels on this bitmap are replaced with pixels read from the + * source bitmap \a src. Source pixels falling outside the boundaries of + * this bitmap are ignored. + * + * This function is equivalent to: + * + * Copy( p, src, src.Bounds() ); + * + * \ingroup bitmap_bitwise_ops + */ + void Copy( const pcl::Point& p, const Bitmap& src ) + { + Copy( p, src, src.Bounds() ); + } + + /*! + * Copies all pixels from a source bitmap to this bitmap. + * + * \param src Source bitmap, whose pixels will be copied to this bitmap. + * + * Target pixels on this bitmap are replaced with pixels read from the + * source bitmap \a src. Pixels are copied at the upper left corner of this + * image (0,0). Source pixels falling outside the boundaries of this bitmap + * are ignored. + * + * This function is equivalent to: + * + * Copy( pcl::Point( 0, 0 ), src ); + * + * \ingroup bitmap_bitwise_ops + */ + void Copy( const Bitmap& src ) + { + Copy( pcl::Point( 0 ), src ); + } + + /*! + * Fills a rectangular region of this bitmap with a constant value. + * + * \param rect Rectangular region to be filled. + * \param fillWith Pixel value to fill with. + * + * \ingroup bitmap_bitwise_ops + */ + void Fill( const pcl::Rect& rect, RGBA fillWith ); + + /*! + * Fills the entire bitmap with a constant value \a fillWith. This + * function is equivalent to: + * + * Fill( Bounds(), fillWith ); + * + * \ingroup bitmap_bitwise_ops + */ + void Fill( RGBA fillWith ) + { + Fill( Bounds(), fillWith ); + } + + /*! + * Replaces each pixel in a rectangular region of this bitmap with the + * result of the bitwise inclusive OR operation between its current value + * and a specified constant value. + * + * \param rect Rectangular region to be operated. + * \param orWith Value to be ORed with current pixel values. + * + * \ingroup bitmap_bitwise_ops + */ + void Or( const pcl::Rect& rect, RGBA orWith ); + + /*! + * Replaces each pixel in this bitmap with the result of the bitwise + * inclusive OR operation between its current value and a specified constant + * value \a andWith. + * + * This function is equivalent to: + * + * Or( Bounds(), orWith ); + * + * \ingroup bitmap_bitwise_ops + */ + void Or( RGBA orWith ) + { + Or( Bounds(), orWith ); + } + + /*! + * Replaces a rectangular region of this bitmap with the bitwise inclusive + * OR operation between its current pixel values and the pixels of a + * corresponding region of a source bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap whose pixels will be ORed with this bitmap. + * + * \param r Defines the rectangular area that will be operated, in source + * bitmap coordinates. + * + * Target pixels on this bitmap are replaced with the result of the bitwise + * OR operation with the corresponding pixels read from the source bitmap + * \a src. Source pixels falling outside the boundaries of this bitmap are + * ignored. + * + * \ingroup bitmap_bitwise_ops + */ + void Or( const pcl::Point& p, const Bitmap& src, const pcl::Rect& r ); + + /*! + * Replaces a rectangular region of this bitmap with the bitwise inclusive + * OR operation between its current pixel values and the corresponding + * pixels of a source bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap whose pixels will be ORed with this bitmap. + * + * Target pixels on this bitmap are replaced with the result of the bitwise + * OR operation with the corresponding pixels read from the source bitmap + * \a src. Source pixels falling outside the boundaries of this bitmap are + * ignored. + * + * This function is equivalent to: + * + * Or( p, src, src.Bounds() ); + * + * \ingroup bitmap_bitwise_ops + */ + void Or( const pcl::Point& p, const Bitmap& src ) + { + Or( p, src, src.Bounds() ); + } + + /*! + * Replaces all pixels in this bitmap with the bitwise inclusive OR + * operation between their current values and the pixels of a source bitmap + * \a src. This function is equivalent to: + * + * Or( Point( 0, 0 ), src ); + * + * \ingroup bitmap_bitwise_ops + */ + void Or( const Bitmap& src ) + { + Or( pcl::Point( 0 ), src ); + } + + /*! + * Replaces each pixel in a rectangular region of this bitmap with the + * result of the bitwise AND operation between its current value and a + * specified constant value. + * + * \param rect Rectangular region to be operated. + * \param andWith Value to be ANDed with current pixel values. + * + * \ingroup bitmap_bitwise_ops + */ + void And( const pcl::Rect& rect, RGBA andWith ); + + /*! + * Replaces each pixel in this bitmap with the result of the bitwise + * AND operation between its current value and a specified constant value + * \a andWith. + * + * This function is equivalent to: + * + * And( Bounds(), andWith ); + * + * \ingroup bitmap_bitwise_ops + */ + void And( RGBA andWith ) + { + And( Bounds(), andWith ); + } + + /*! + * Replaces a rectangular region of this bitmap with the bitwise AND + * operation between its current pixel values and the pixels of a + * corresponding region of a source bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap whose pixels will be ANDed with this bitmap. + * + * \param r Defines the rectangular area that will be operated, in source + * bitmap coordinates. + * + * Target pixels on this bitmap are replaced with the result of the bitwise + * AND operation with the corresponding pixels read from the source bitmap + * \a src. Source pixels falling outside the boundaries of this bitmap are + * ignored. + * + * \ingroup bitmap_bitwise_ops + */ + void And( const pcl::Point& p, const Bitmap& src, const pcl::Rect& r ); + + /*! + * Replaces a rectangular region of this bitmap with the bitwise AND + * operation between its current pixel values and the corresponding pixels + * of a source bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap whose pixels will be ANDed with this bitmap. + * + * Target pixels on this bitmap are replaced with the result of the bitwise + * AND operation with the corresponding pixels read from the source bitmap + * \a src. Source pixels falling outside the boundaries of this bitmap are + * ignored. + * + * This function is equivalent to: + * + * And( p, src, src.Bounds() ); + * + * \ingroup bitmap_bitwise_ops + */ + void And( const pcl::Point& p, const Bitmap& src ) + { + And( p, src, src.Bounds() ); + } + + /*! + * Replaces all pixels in this bitmap with the bitwise AND operation between + * their current values and the pixels of a source bitmap \a src. This + * function is equivalent to: + * + * And( Point( 0, 0 ), src ); + * + * \ingroup bitmap_bitwise_ops + */ + void And( const Bitmap& src ) + { + And( pcl::Point( 0 ), src ); + } + + /*! + * Replaces each pixel in a rectangular region of this bitmap with the + * result of the bitwise exclusive OR (XOR) operation between its current + * value and a specified constant value. + * + * \param rect Rectangular region to be operated. + * \param xorWith Value to be XORed with current pixel values. + * + * \ingroup bitmap_bitwise_ops + */ + void Xor( const pcl::Rect& rect, RGBA xorWith ); + + /*! + * Replaces each pixel in this bitmap with the result of the bitwise + * exclusive OR (XOR) operation between its current value and a specified + * constant value \a xorWith. + * + * This function is equivalent to: + * + * Xor( Bounds(), xorWith ); + * + * \ingroup bitmap_bitwise_ops + */ + void Xor( RGBA xorWith ) + { + Xor( Bounds(), xorWith ); + } + + /*! + * Replaces a rectangular region of this bitmap with the bitwise exclusive + * OR (XOR) operation between its current pixel values and the pixels of a + * corresponding region of a source bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap whose pixels will be XORed with this bitmap. + * + * \param r Defines the rectangular area that will be operated, in source + * bitmap coordinates. + * + * Target pixels on this bitmap are replaced with the result of the XOR + * operation with the corresponding pixels read from the source bitmap + * \a src. Source pixels falling outside the boundaries of this bitmap are + * ignored. + * + * \ingroup bitmap_bitwise_ops + */ + void Xor( const pcl::Point& p, const Bitmap& src, const pcl::Rect& r ); + + /*! + * Replaces a rectangular region of this bitmap with the bitwise exclusive + * OR (XOR) operation between its current pixel values and the corresponding + * pixels of a source bitmap. + * + * \param p Position of the upper left corner of the target rectangle on + * this bitmap. + * + * \param src Source bitmap whose pixels will be XORed with this bitmap. + * + * Target pixels on this bitmap are replaced with the result of the + * exclusive OR (XOR) operation with the corresponding pixels read from the + * source bitmap \a src. Source pixels falling outside the boundaries of + * this bitmap are ignored. + * + * This function is equivalent to: + * + * Xor( p, src, src.Bounds() ); + * + * \ingroup bitmap_bitwise_ops + */ + void Xor( const pcl::Point& p, const Bitmap& src ) + { + Xor( p, src, src.Bounds() ); + } + + /*! + * Replaces all pixels in this bitmap with the bitwise exclusive OR (XOR) + * operation between their current values and the pixels of a source bitmap + * \a src. This function is equivalent to: + * + * Xor( Point( 0, 0 ), src ); + * + * \ingroup bitmap_bitwise_ops + */ + void Xor( const Bitmap& src ) + { + Xor( pcl::Point( 0 ), src ); + } + + /*! + * Replaces the pixels pertaining to a rectangle defined on this bitmap with + * the bitwise exclusive OR (XOR) operation between their current values and + * a specified constant value. + * + * \param rect Rectangle that will be operated. + * + * \param xorWith Value to be XORed with current pixel values. + * + * This function does not operate on a rectangular region; only the \e sides + * of the specified rectangle are XORed: two one-pixel columns and two + * one-pixel rows. + * + * \ingroup bitmap_bitwise_ops + */ + void XorRect( const pcl::Rect& rect, RGBA xorWith ); + + /*! + * Replaces the pixels pertaining to the bounding rectangle of this bitmap + * with the bitwise exclusive OR (XOR) operation between their current + * values and a specified constant value. + * + * \param xorWith Value to be XORed with current pixel values. + * + * This function is equivalent to: + * + * XorRect( Bounds(), xorWith ); + * + * \ingroup bitmap_bitwise_ops + */ + void XorRect( RGBA xorWith ) + { + XorRect( Bounds(), xorWith ); + } + + /*! + * Inverts a rectangular region of this bitmap. + * + * \param rect Rectangular region to be inverted. + * + * This function does not invert alpha pixel components, but just color + * components. It is equivalent to: + * + * Xor( rect, 0x00ffffff ); + * + * \ingroup bitmap_bitwise_ops + */ + void Invert( const pcl::Rect& rect ) + { + Xor( rect, 0x00ffffff ); + } + + /*! + * Inverts all pixels of this bitmap. + * + * This function does not invert alpha pixel components, but just color + * components. It is equivalent to: + * + * Invert( Bounds() ); + * + * \ingroup bitmap_bitwise_ops + */ + void Invert() + { + Invert( Bounds() ); + } + + /*! + * Inverts the pixels pertaining to a rectangle \a rect defined on this + * bitmap. + * + * This function does not invert alpha pixel components, but just color + * components. It is equivalent to: + * + * XorRect( rect, 0x00ffffff ); + * + * \ingroup bitmap_bitwise_ops + */ + void InvertRect( const pcl::Rect& rect ) + { + XorRect( rect, 0x00ffffff ); + } + + /*! + * Inverts the pixels pertaining to the bounding rectangle of this bitmap. + * + * This function does not invert alpha pixel components, but just color + * components. It is equivalent to: + * + * InvertRect( Bounds() ); + * + * \ingroup bitmap_bitwise_ops + */ + void InvertRect() + { + InvertRect( Bounds() ); + } + + /*! + * \defgroup bitmap_color_replacement Bitmap Color Replacement Functions + */ + + /*! + * Replaces all occurrences of a specified pixel value in a rectangular + * region of this bitmap with a new value. + * + * \param rect Rectangular region. + * \param replaceThis Pixel value to be replaced. + * \param replaceWith New pixel value for replacement. + * + * \ingroup bitmap_color_replacement + */ + void ReplaceColor( const pcl::Rect& rect, RGBA replaceThis, RGBA replaceWith ); + + /*! + * Replaces all occurrences of a specified pixel value in this bitmap with a + * new value. + * + * \param replaceThis Pixel value to be replaced. + * \param replaceWith New pixel value for replacement. + * + * This function is equivalent to: + * + * ReplaceColor( Bounds(), replaceThis, replaceWith ); + * + * \ingroup bitmap_color_replacement + */ + void ReplaceColor( RGBA replaceThis, RGBA replaceWith ) + { + ReplaceColor( Bounds(), replaceThis, replaceWith ); + } + + /*! + * Replaces the alpha (transparency) components of all pixels in a + * rectangular region of this bitmap with a new alpha value. + * + * \param rect Rectangular region. + * \param newAlpha New alpha (transparency) value in the range [0,255]. + * + * \ingroup bitmap_color_replacement + */ + void SetAlpha( const pcl::Rect& rect, uint8 newAlpha ); + + /*! + * Replaces the alpha (transparency) components of all pixels in this bitmap + * with a new alpha value. + * + * \param newAlpha New alpha (transparency) value in the range [0,255]. + * + * This function is equivalent to: + * + * SetAlpha( Bounds(), newAlpha ); + * + * \ingroup bitmap_color_replacement + */ + void SetAlpha( uint8 newAlpha ) + { + SetAlpha( Bounds(), newAlpha ); + } + + /*! + * Returns the ratio between output device pixels and pixels of this + * device-independent bitmap. See the SetPhysicalPixelRatio() member + * function for a detailed description. + * + * \ingroup ui_scaling_functions + * \sa SetPhysicalPixelRatio() + */ + double PhysicalPixelRatio() const; + + /*! + * Sets the ratio between output device pixels and pixels of this + * device-independent bitmap. This ratio is used as a scaling factor by + * core bitmap rendering routines to reproduce bitmaps on high-dpi screens + * and other high-density graphics output devices. + * + * The specified \e ratio must be greater than or equal to one. On macOS + * with Retina monitors working in high-dpi modes, this function can be used + * to ensure that a bitmap will be reproduced as a high-resolution image by + * setting its output pixel ratio to 2.0. In such case the bitmap will be + * drawn on the screen with one half its actual pixel dimensions in logical + * pixels, using the native physical monitor resoluton. On other platforms + * such as X11 (Linux and FreeBSD) and Windows, where no automatic display + * scaling is performed, the physical pixel ratio of a bitmap is ignored. + * + * \ingroup ui_scaling_functions + * \sa PhysicalPixelRatio() + */ + void SetPhysicalPixelRatio( double ratio ); + + /*! + * Renders an SVG document file as a raster image into a new %Bitmap object. + * + * \param filePath Path to an existing file in the local file system, + * which must store a valid SVG document representing the + * image to be rendered. The SVG source code must be + * encoded in UTF-8. + * + * \param width,height The width and height in pixels of the image where + * the SVG rendition will be generated. If a dimension is + * ≤ 0, the rendition will use the corresponding + * dimension specified by the SVG document: either viewBox + * coordinates, if available, or the width and height + * attributes of the root svg element. + * + * \param options Rendering options. See the SVGRenderOption namespace + * for possible values. + * + * Automatic Resource Location + * + * This function can load SVG documents from arbitrary locations on the + * local file system. However, modules typically install their process and + * interface icons on the /rsc/icons/module directory under the local + * PixInsight installation. A module can specify the "@module_icons_dir/" + * prefix in the \a filePath argument to this function to let the PixInsight + * core application load the corresponding SVG document from the appropriate + * standard distribution directory automatically. For example, suppose that + * this function is invoked by a "Foo" module as follows: + * + * \code + * Bitmap RenderSpecialIcon() + * { + * return Bitmap::FromSVGFile( "@module_icons_dir/special/icon.svg" ); + * } + * \endcode + * + * Then the core application will attempt to load the following SVG file: + * + * <install-dir>/rsc/icons/module/Foo/special/icon.svg + * + * where <install-dir> is the local directory where the running + * PixInsight core application is installed. + * + * \sa FromSVG() + */ + static Bitmap FromSVGFile( const String& filePath, int width = 0, int height = 0, + SVGRenderOptions options = SVGRenderOption::Default ); + + /*! + * Renders an SVG document as a raster image into a new %Bitmap object. + * + * \param filePath The source code of a valid SVG document representing + * the image to be rendered, encoded in UTF-8. + * + * \param width,height The width and height in pixels of the image where + * the SVG rendition will be generated. If a dimension is + * ≤ 0, the rendition will use the corresponding + * dimension specified by the SVG document: either viewBox + * coordinates, if available, or the width and height + * attributes of the root svg element. + * + * \param options Rendering options. See the SVGRenderOption namespace + * for possible values. + * + * \sa FromSVGFile() + */ + static Bitmap FromSVG( const IsoString& svgSource, int width = 0, int height = 0, + SVGRenderOptions options = SVGRenderOption::Default ); + +private: + + Bitmap( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class GraphicsContextBase; + friend class Graphics; + friend class VectorGraphics; + friend class Action; + friend class Brush; + friend class Cursor; + friend class Button; + friend class PushButton; + friend class ToolButton; + friend class BitmapBox; + friend class TabBox; + friend class ComboBox; + friend class TreeBox; + friend class ImageView; + friend class ImageWindow; + friend class Process; + friend class FileFormat; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Bitmap_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Bitmap.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/BitmapBox.h b/3rdparty/include/pcl/BitmapBox.h new file mode 100644 index 0000000..c2e83fa --- /dev/null +++ b/3rdparty/include/pcl/BitmapBox.h @@ -0,0 +1,156 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/BitmapBox.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_BitmapBox_h +#define __PCL_BitmapBox_h + +/// \file pcl/BitmapBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class BitmapBox + * \brief Client-side interface to a PixInsight %BitmapBox control. + * + * ### TODO: Write a detailed description for %BitmapBox + */ +class PCL_CLASS BitmapBox : public Frame +{ +public: + + /*! + * Constructs a %BitmapBox control that draws a bitmap \a bmp and is a child + * of \a parent. + */ + BitmapBox( const Bitmap& bmp = Bitmap::Null(), Control& parent = Control::Null() ); + + /*! + * Destroys a %BitmapBox object. + */ + virtual ~BitmapBox() + { + } + + /*! + * Returns the bitmap currently drawn by this %BitmapBox control. + */ + Bitmap CurrentBitmap() const; + + /*! + * Sets the bitmap \a bmp for this %BitmapBox control. + */ + void SetBitmap( const Bitmap& bmp ); + + /*! + * Removes the bitmap in this %BitmapBox control. Does not destroy the + * bitmap (unless it becomes unreferenced); only disassociates it from this + * %BitmapBox control. + */ + void Clear() + { + SetBitmap( Bitmap::Null() ); + } + + /*! + * Returns the margin in pixels that this %BitmapBox control reserves around + * its bitmap. + */ + int Margin() const; + + /*! + * Sets a new margin \a m in pixels for this %BitmapBox control. + */ + void SetMargin( int m ); + + /*! + * Sets the margin of this %BitmapBox control to zero pixels. + */ + void ClearMargin() + { + SetMargin( 0 ); + } + + /*! # + */ + bool IsAutoFitEnabled() const; + + /*! # + */ + void EnableAutoFit( bool = true ); + + /*! # + */ + void DisableAutoFit( bool disable = true ) + { + EnableAutoFit( !disable ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_BitmapBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/BitmapBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Brush.h b/3rdparty/include/pcl/Brush.h new file mode 100644 index 0000000..2591e29 --- /dev/null +++ b/3rdparty/include/pcl/Brush.h @@ -0,0 +1,820 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Brush.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_Brush_h +#define __PCL_Brush_h + +/// \file pcl/Brush.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::BrushStyle + * \brief Supported brush styles. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
BrushStyle::Empty Empty brush (transparent brush)
BrushStyle::Solid Solid brush
BrushStyle::Dense Dense pattern brush
BrushStyle::HalfTone 50% pattern brush
BrushStyle::Sparse Sparse pattern brush
BrushStyle::HorzizontalHatch -----
BrushStyle::VerticalHatch |||||
BrushStyle::CrossHatch +++++
BrushStyle::ForwardDiagonalHatch /////
BrushStyle::BackwardDiagonalHatch\\\\\\\\\\
BrushStyle::CrossDiagonalHatch XXXXX
BrushStyle::Stipple Fill with a tiled Bitmap
BrushStyle::LinearGradient Fill with a linear gradient
BrushStyle::RadialGradient Fill with a radial gradient
BrushStyle::ConicalGradient Fill with a conical gradient
+ */ +namespace BrushStyle +{ + enum value_type + { + Empty, // empty brush (transparent brush) + Solid, // solid brush + Dense, // dense pattern brush + HalfTone, // 50% pattern brush + Sparse, // sparse pattern brush + HorzizontalHatch, // ----- + VerticalHatch, // ||||| + CrossHatch, // +++++ + ForwardDiagonalHatch, // ///// + BackwardDiagonalHatch, // \\\\\. <--- why this dot? :) + CrossDiagonalHatch, // XXXXX + Stipple, // fill with a tiled Bitmap + LinearGradient, // fill with a linear gradient + RadialGradient, // fill with a radial gradient + ConicalGradient, // fill with a conical gradient + + NumberOfBrushStyles + }; +} + +/*! + * \namespace pcl::GradientSpreadMode + * \brief Supported gradient spread modes. + * + * + * + * + * + *
GradientSpreadMode::Pad Areas outside the gradient are filled with the nearest (first or last) stop color.
GradientSpreadMode::Reflect Gradients are reflected outside gradient areas.
GradientSpreadMode::Repeat Gradients are repeated outside gradient areas.
+ */ +namespace GradientSpreadMode +{ + enum value_type + { + Pad, + Reflect, + Repeat, + + NumberOfGradientSpreadModes + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class PCL_CLASS Bitmap; + +// ---------------------------------------------------------------------------- + +/*! + * \class Brush + * \brief Client-side interface to a PixInsight %Brush object. + * + * ### TODO: Write a detailed description for %Brush. + * + * \sa GradientBrush, LinearGradientBrush, RadialGradientBrush, + * ConicalGradientBrush + */ +class PCL_CLASS Brush : public UIObject +{ +public: + + /*! + * Represents the brush style. + * Supported values are defined in the BrushStyle namespace. + */ + typedef BrushStyle::value_type style; + + /*! + * Constructs a brush with the specified \a color and \a style. + */ + Brush( RGBA color = 0xff000000, style = BrushStyle::Solid ); + + /*! + * Constructs a stippled brush with the specified bitmap pattern \a bmp. + */ + Brush( const Bitmap& bmp ); + + /*! + * Copy constructor. This object will reference the same server-side brush + * as the specified instance \a b. + */ + Brush( const Brush& b ) : UIObject( b ) + { + } + + /*! + * Move constructor. + */ + Brush( Brush&& x ) : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys a %Brush object. If this object references an existing brush in + * the PixInsight core application, its reference count is decremented. If + * it becomes unreferenced, it will be garbage-collected. + */ + virtual ~Brush() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side brush as the specified + * instance \a b. If the previous brush becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + Brush& operator =( const Brush& b ) + { + Assign( b ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Brush& operator =( Brush&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null brush. A null %Brush object does + * not correspond to an existing brush object in the PixInsight core + * application. + */ + static Brush& Null(); + + /*! + * Returns the current color of this brush. + */ + RGBA Color() const; + + /*! + * Sets the color of this brush. + */ + void SetColor( RGBA ); + + /*! + * Returns the current style of this brush. + */ + style Style() const; + + /*! + * Returns true iff this brush is solid, i.e. if its current style is + * BrushStyle::Solid. + */ + bool IsSolid() const + { + return Style() == BrushStyle::Solid; + } + + /*! + * Returns true iff this brush is empty (or transparent), i.e. if its current + * style is BrushStyle::Empty. An empty brush produces transparent shapes. + */ + bool IsEmpty() const + { + return Style() == BrushStyle::Empty; + } + + /*! + * Returns true iff this brush is transparent. This function is a synonym + * for IsEmpty(). + */ + bool IsTransparent() const + { + return IsEmpty(); + } + + /*! + * Returns true iff this brush is \e stippled, i.e. if its current style is + * BrushStyle::Stippled. A stippled brush draws a regular pattern + * consisting of multiple, adjacent copies of a Bitmap image. + */ + bool IsStippled() const + { + return Style() == BrushStyle::Stipple; + } + + /*! + * Sets the style of this brush. + * + * Gradient styles (BrushStyle::LinearGradient, BrushStyle::RadialGradient + * and BrushStyle::ConicalGradient) cannot be set with this function, since + * gradient brushes are implemented as separate PCL classes + * (LinearGradientBrush, RadialGradientBrush and ConicalGradientBrush, + * respectively). + */ + void SetStyle( style ); + + /*! + * Returns the current \e stipple of this brush. If the current style of + * this brush is not BrushStyle::Stippled, a null Bitmap object is + * returned. + */ + Bitmap Stipple() const; + + /*! + * Sets the current \e stipple for this brush. This function implicitly + * forces the style of this brush to be BrushStyle::Stippled. + */ + void SetStipple( const Bitmap& ); + + /*! + * Returns true iff this object is a gradient brush. + */ + virtual bool IsGradient() const + { + return false; + } + +private: + + Brush( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class GraphicsContextBase; + friend class Graphics; + friend class VectorGraphics; + friend class GradientBrush; + friend class Pen; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GradientBrush + * \brief Base class of PCL gradient brushes. + * + * ### TODO: Write a detailed description for %GradientBrush. + * + * \sa Brush, LinearGradientBrush, RadialGradientBrush, ConicalGradientBrush + */ +class PCL_CLASS GradientBrush : public Brush +{ +public: + + /*! + * Represents a gradient spread mode. + * Supported values are defined in the GradientSpreadMode namespace. + */ + typedef GradientSpreadMode::value_type spread_mode; + + /*! \struct Stop + * \brief Gradient stop. + * + * A gradient brush interpolates color values from an ordered list of + * gradient stops. A gradient stop is formed by a position in the + * [0,1] range and a RGBA color value. + */ + struct Stop + { + double position = 0; //!< Stop position in the [0,1] range, where 0 and 1 correspond, respectively, to the starting and end locations of the gradient area. + RGBA color = 0xff000000; //!< Stop color encoded as a 32-bit AARRGGBB value. + + /*! + * Constructs a default gradient stop. + */ + Stop() = default; + + /*! + * Constructs a gradient stop at the specified position \a p with the + * color \a c. + */ + Stop( double p, RGBA c ) + : position( Range( p, 0.0, 1.0 ) ) + , color( c ) + { + } + + /*! + * Copy constructor. + */ + Stop( const Stop& ) = default; + + /*! + * Equality operator. Used to enforce ordering of gradient stop lists. + */ + bool operator ==( const Stop& x ) const + { + return position == x.position && color == x.color; + } + + /*! + * Less than relational operator. Used to enforce ordering of gradient + * stop lists. + * + * Gradient stop comparison is exclusively based on stop positions; stop + * colors are irrelevant for ordering. + */ + bool operator <( const Stop& x ) const + { + return position < x.position; // color is irrelevant to ordering of gradient stops + } + }; + + /*! + * Represents a list of gradient stops. + */ + typedef Array stop_list; + + /*! + * Returns the list of stops in this gradient brush. + */ + stop_list Stops() const; + + /*! + * Returns the current gradient spread mode for this gradient brush. + */ + spread_mode SpreadMode() const; + + /*! + */ + bool IsGradient() const override + { + return true; + } + +protected: + + GradientBrush( void* h ) : Brush( h ) + { + } + + GradientBrush( const GradientBrush& x ) : Brush( x ) + { + } + + GradientBrush( GradientBrush&& x ) : Brush( std::move( x ) ) + { + } +}; + +/*! + * \class LinearGradientBrush + * \brief Linear gradient brush. + * + * ### TODO: Write a detailed description for %LinearGradientBrush. + * + * \sa Brush, GradientBrush, RadialGradientBrush, ConicalGradientBrush + */ +class PCL_CLASS LinearGradientBrush : public GradientBrush +{ +public: + + /*! + * Represents a gradient spread mode. + * Supported values are defined in the GradientSpreadMode namespace. + */ + typedef GradientBrush::spread_mode spread_mode; + + /*! + * Represents a list of gradient stops. + */ + typedef GradientBrush::stop_list stop_list; + + /*! + * Constructs a %LinearGradientBrush object. + * + * \param x1,y1 Coordinates of the gradient's starting point. + * + * \param x2,y2 Coordinates of the gradient's end point. + * + * \param stops Reference to a list of gradient stops. If an empty list is + * specified (as by default), two stops will be generated + * automatically: {0.0,0x00000000} and {1.0,0xFF000000}. + * + * \param spread Gradient spread mode. Supported spread modes are defined + * in the GradientSpreadMode namespace. The default is + * GradientSpreadMode::Pad. + */ + LinearGradientBrush( double x1, double y1, double x2, double y2, + const stop_list& stops = stop_list(), + spread_mode spread = GradientSpreadMode::Pad ); + + /*! + * Constructs a %LinearGradientBrush object. + * + * This is an overloaded constructor, provided for convenience. It behaves + * like the preceding constructor, except the linear gradient parameters are + * specified as a rectangle \a r using floating point coordinates. + */ + LinearGradientBrush( const DRect& r, + const stop_list& stops = stop_list(), + spread_mode spread = GradientSpreadMode::Pad ); + + /*! + * Constructs a %LinearGradientBrush object. + * + * This is an overloaded constructor, provided for convenience. It behaves + * like the preceding constructor, except the linear gradient parameters are + * specified as a rectangle \a r using integer coordinates. + */ + LinearGradientBrush( const Rect& r, + const stop_list& stops = stop_list(), + spread_mode spread = GradientSpreadMode::Pad ); + + /*! + * Copy constructor. This object will reference the same server-side brush + * as the specified instance \a b. + */ + LinearGradientBrush( const LinearGradientBrush& b ) + : GradientBrush( b ) + { + } + + /*! + * Move constructor. + */ + LinearGradientBrush( LinearGradientBrush&& x ) + : GradientBrush( std::move( x ) ) + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side brush as the specified + * instance \a b. If the previous brush becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + LinearGradientBrush& operator =( const LinearGradientBrush& b ) + { + SetHandle( b.handle ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + LinearGradientBrush& operator =( LinearGradientBrush&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Retrieves the linear gradient parameters of this object. + * + * \param[out] x1,y1 Coordinates of the gradient's starting point. + * \param[out] x2,y2 Coordinates of the gradient's end point. + * + * \sa Parameters() + */ + void GetParameters( double& x1, double& y1, double& x2, double& y2 ) const; + + /*! + * Returns the linear gradient parameters of this object as a DRect + * object. + * + * \sa GetParameters( double&, double&, double&, double& ) + */ + DRect Parameters() const + { + DRect r; + GetParameters( r.x0, r.y0, r.x1, r.y1 ); + return r; + } +}; + +/*! + * \class RadialGradientBrush + * \brief Radial gradient brush. + * + * ### TODO: Write a detailed description for %RadialGradientBrush. + * + * \sa Brush, GradientBrush, LinearGradientBrush, ConicalGradientBrush + */ +class PCL_CLASS RadialGradientBrush : public GradientBrush +{ +public: + + /*! + * Represents a gradient spread mode. + * Supported values are defined in the GradientSpreadMode namespace. + */ + typedef GradientBrush::spread_mode spread_mode; + + /*! + * Represents a list of gradient stops. + */ + typedef GradientBrush::stop_list stop_list; + + /*! + * Constructs a %RadialGradientBrush object. + * + * \param cx,cy Coordinates of the gradient's center. + * + * \param r Gradient's radius. + * + * \param fx,fy Coordinates of the gradient's focal point. If these + * coordinates are not specified, they will be set at + * the specified gradient's center point. + * + * \param stops Reference to a list of gradient stops. If an empty list is + * specified (as by default), two stops will be generated + * automatically: {0.0,0x00000000} and {1.0,0xFF000000}. + * + * \param spread Gradient spread mode. Supported spread modes are defined + * in the GradientSpreadMode namespace. The default is + * GradientSpreadMode::Pad. + */ + RadialGradientBrush( double cx, double cy, double r, double fx = uint32_max, double fy = uint32_max, + const stop_list& stops = stop_list(), + spread_mode spread = GradientSpreadMode::Pad ); + + /*! + * Constructs a %RadialGradientBrush object. + * + * This is an overloaded constructor, provided for convenience. It behaves + * like the preceding constructor, except the radial gradient parameters are + * specified as a center point \a c, radius \a r and focal point \a f. + */ + RadialGradientBrush( const DPoint& c, double r, const DPoint& f = DPoint( uint32_max ), + const stop_list& stops = stop_list(), + spread_mode spread = GradientSpreadMode::Pad ); + + /*! + * Constructs a %RadialGradientBrush object. + * + * This is an overloaded constructor, provided for convenience. It behaves + * like the preceding constructor, except the radial gradient parameters are + * specified as a center point \a c, radius \a r and focal point \a f. + */ + RadialGradientBrush( const Point& c, double r, const Point& f = Point( uint32_max ), + const stop_list& stops = stop_list(), + spread_mode spread = GradientSpreadMode::Pad ); + + /*! + * Copy constructor. This object will reference the same server-side brush + * as the specified instance \a b. + */ + RadialGradientBrush( const RadialGradientBrush& b ) + : GradientBrush( b ) + { + } + + /*! + * Move constructor. + */ + RadialGradientBrush( RadialGradientBrush&& x ) + : GradientBrush( std::move( x ) ) + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side brush as the specified + * instance \a b. If the previous brush becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + RadialGradientBrush& operator =( const RadialGradientBrush& b ) + { + SetHandle( b.handle ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + RadialGradientBrush& operator =( RadialGradientBrush&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Retrieves the radial gradient parameters of this object. + * + * \param[out] cx,cy Coordinates of the gradient's center. + * \param[out] r Gradient's radius. + * \param[out] fx,fy Coordinates of the gradient's focal point. + * + * \sa GetParameters( DPoint&, double&, DPoint& ) + */ + void GetParameters( double& cx, double& cy, double& r, double& fx, double& fy ) const; + + /*! + * Returns the radial gradient parameters of this object. + * + * This is an overloaded function, provided for convenience. It behaves like + * the preceding function, except the center and focal point parameters are + * retrieved as DPoint objects. + * + * \sa GetParameters( double&, double&, double&, double&, double& ) + */ + void GetParameters( DPoint& c, double& r, DPoint& f ) const + { + GetParameters( c.x, c.y, r, f.x, f.y ); + } +}; + +/*! + * \class ConicalGradientBrush + * \brief Conical gradient brush. + * + * ### TODO: Write a detailed description for %ConicalGradientBrush. + * + * \sa Brush, GradientBrush, LinearGradientBrush, RadialGradientBrush + */ +class PCL_CLASS ConicalGradientBrush : public GradientBrush +{ +public: + + /*! + * Represents a list of gradient stops. + */ + typedef GradientBrush::stop_list stop_list; + + /*! + * Constructs a %ConicalGradientBrush object. + * + * \param cx,cy Coordinates of the gradient's center. + * + * \param a Gradient's angle in radians. + * + * \param stops Reference to a list of gradient stops. If an empty list is + * specified (as by default), two stops will be generated + * automatically: {0.0,0x00000000} and {1.0,0xFF000000}. + */ + ConicalGradientBrush( double cx, double cy, double a, const stop_list& stops = stop_list() ); + + /*! + * Constructs a %ConicalGradientBrush object. + * + * This is an overloaded constructor, provided for convenience. It behaves + * like the preceding constructor, except the conical gradient parameters + * specified as a center point \a c and angle \a a in radians. + */ + ConicalGradientBrush( const DPoint& c, double a, const stop_list& stops = stop_list() ); + + /*! + * Constructs a %ConicalGradientBrush object. + * + * This is an overloaded constructor, provided for convenience. It behaves + * like the preceding constructor, except the conical gradient parameters + * specified as a center point \a c and angle \a a in radians. + */ + ConicalGradientBrush( const Point& c, double a, const stop_list& stops = stop_list() ); + + /*! + * Copy constructor. This object will reference the same server-side brush + * as the specified instance \a b. + */ + ConicalGradientBrush( const ConicalGradientBrush& b ) + : GradientBrush( b ) + { + } + + /*! + * Move constructor. + */ + ConicalGradientBrush( ConicalGradientBrush&& x ) + : GradientBrush( std::move( x ) ) + { + } + + /*! + * Assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side brush as the specified + * instance \a b. If the previous brush becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + ConicalGradientBrush& operator =( const ConicalGradientBrush& b ) + { + SetHandle( b.handle ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ConicalGradientBrush& operator =( ConicalGradientBrush&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Retrieves the conical gradient parameters of this object. + * + * \param[out] cx,cy Coordinates of the gradient's center. + * \param[out] a Gradient's angle in radians. + * + * \sa GetParameters( DPoint&, double& ) + */ + void GetParameters( double& cx, double& cy, double& a ) const; + + /*! + * Returns the conical gradient parameters of this object. + * + * This is an overloaded function, provided for convenience. It behaves like + * the preceding function, except the center coordinates are retrieved as a + * DPoint object. + * + * \sa GetParameters( double&, double&, double& ) + */ + void GetParameters( DPoint& c, double& a ) const + { + GetParameters( c.x, c.y, a ); + } +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Brush_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Brush.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Button.h b/3rdparty/include/pcl/Button.h new file mode 100644 index 0000000..6c98d59 --- /dev/null +++ b/3rdparty/include/pcl/Button.h @@ -0,0 +1,430 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Button.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_Button_h +#define __PCL_Button_h + +/// \file pcl/Button.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::CheckState + * \brief Button check states + * + * + * + * + * + *
CheckState::Unchecked The control is not checked
CheckState::Checked The control is checked
CheckState::ThirdState The check box is in its 'third state'
+ * + */ +namespace CheckState +{ + enum value_type + { + Unchecked, // the item is not checked + Checked, // the item is checked + ThirdState // the check box is in its 'third state' + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Button + * \brief Abstract base class for all client-side interfaces to PixInsight + * button controls. + * + * ### TODO: Write a detailed description for Button + */ +class PCL_CLASS Button : public Control +{ +public: + + /*! + * Represents a button check state. Supported values are defined in the + * CheckState namespace. + */ + typedef CheckState::value_type check_state; + + /*! + * Destroys a %Button control. + */ + virtual ~Button() + { + } + + /*! + * Returns the current button text. + */ + String Text() const; + + /*! + * Sets the current button text. + */ + void SetText( const String& ); + + /*! + * Returns the current icon shown by this button, or a null Bitmap object if + * this button has no associated icon. + */ + Bitmap Icon() const; + + /*! + * Sets the icon shown by this button. If a null Bitmap object is specified, + * no icon will be associated with this button. + */ + void SetIcon( const Bitmap& ); + + /*! + * Obtains the current icon dimensions of this button in pixels. The icon's + * \a width and \a height are returned in the referenced variables. + */ + void GetIconSize( int& width, int& height ) const; + + /*! + * Returns the current icon width in pixels for this button. + */ + int IconWidth() const + { + int width, dum; GetIconSize( width, dum ); return width; + } + + /*! + * Returns the current icon height in pixels for this button. + */ + int IconHeight() const + { + int dum, height; GetIconSize( dum, height ); return height; + } + + /*! + * Sets new icon sizes for this button, \a width and \a height in pixels, + * respectively. + */ + void SetIconSize( int width, int height ); + + /*! # + */ + void SetIconSize( int size ) + { + SetIconSize( size, size ); + } + + /*! # + */ + void GetScaledIconSize( int& width, int& height ) const + { + GetIconSize( width, height ); width = PhysicalPixelsToLogical( width ); height = PhysicalPixelsToLogical( height ); + } + + /*! # + */ + int ScaledIconWidth() const + { + int width, dum; GetIconSize( width, dum ); return PhysicalPixelsToLogical( width ); + } + + /*! # + */ + int ScaledIconHeight() const + { + int dum, height; GetIconSize( dum, height ); return PhysicalPixelsToLogical( height ); + } + + /*! # + */ + void SetScaledIconSize( int width, int height ) + { + SetIconSize( LogicalPixelsToPhysical( width ), LogicalPixelsToPhysical( height ) ); + } + + /*! # + */ + void SetScaledIconSize( int size ) + { + size = LogicalPixelsToPhysical( size ); + SetIconSize( size, size ); + } + + /*! + * Returns true iff this button can be pushed down. + * + * \note This is a pure virtual member function that must be reimplemented + * by derived classes. + */ + virtual bool IsPushable() const = 0; + + /*! + * Returns true iff this button is in pushed down state. + */ + bool IsPushed() const; + + /*! + * Sets the current push state of this button. + */ + void SetPushed( bool = true ); + + /*! + * A convenience synonym for SetPushed( true ). + */ + void Push() + { + SetPushed( true ); + } + + /*! + * A convenience synonym for SetPushed( false ). + */ + void Unpush() + { + SetPushed( false ); + } + + /*! + * Returns true iff this button can be checked. + * + * \note This is a pure virtual member function that must be reimplemented + * by derived classes. + */ + virtual bool IsCheckable() const = 0; + + /*! + * Returns true iff this button is in checked state. + */ + bool IsChecked() const; + + /*! + * Sets the current check state of this button. + */ + void SetChecked( bool = true ); + + /*! + * A convenience synonym for SetChecked( true ). + */ + void Check() + { + SetChecked( true ); + } + + /*! + * A convenience synonym for SetChecked( false ). + */ + void Uncheck() + { + SetChecked( false ); + } + + /*! + * Returns the current check state of this button. This function must be + * used for button controls that can adopt \e tristate check states. + */ + check_state State() const; + + /*! + * Sets the current check state of this button. This function must be used + * for button controls that can adopt \e tristate check states. + */ + void SetState( check_state ); + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnClick( Button& sender, bool checked ); + // void OnPress( Button& sender ); + // void OnRelease( Button& sender ); + // void OnCheck( Button& sender, Button::check_state state ); + + /*! + * \defgroup button_event_handlers Button Event Handlers + */ + + /*! + * Defines the prototype of a button click event handler. + * + * A button click event is generated when a button control is clicked with + * the mouse (pressed down then released while the mouse cursor stays within + * the button) or activated with the keyboard. + * + * \param sender The control that sends a button click event. + * \param checked Whether the sender button is currently checked. + * + * \ingroup button_event_handlers + */ + typedef void (Control::*click_event_handler)( Button& sender, bool checked ); + + /*! + * Defines the prototype of a button press event handler. + * + * A button press event is generated when a button control is either pressed + * down with the mouse, or released after having being pressed. + * + * \param sender The control that sends a button press event. + * + * \ingroup button_event_handlers + */ + typedef void (Control::*press_event_handler)( Button& sender ); + + /*! + * Defines the prototype of a button check event handler. + * + * A button check event is generated when a checkable button control changes + * its check state, either by clicking it with the mouse, or by activating + * it with the keyboard. + * + * \param sender The control that sends a button press event. + * \param state The current check state of the sender button. + * + * \ingroup button_event_handlers + */ + typedef void (Control::*check_event_handler)( Button& sender, Button::check_state state ); + + /*! + * Sets the button click event handler for this button. + * + * \param handler The button click event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive click events from this + * button. + * + * \ingroup button_event_handlers + */ + void OnClick( click_event_handler handler, Control& receiver ); + + /*! + * Sets the button press event handler for this button. + * + * \param handler The button press event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive press events from this + * button. + * + * \ingroup button_event_handlers + */ + void OnPress( press_event_handler handler, Control& receiver ); + + /*! + * Sets the button release event handler for this button. + * + * \param handler The button release event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive release events from this + * button. + * + * \ingroup button_event_handlers + */ + void OnRelease( press_event_handler handler, Control& receiver ); + + /*! + * Sets the button check event handler for this button. + * + * \param handler The button check event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive check events from this + * button. + * + * \ingroup button_event_handlers + */ + void OnCheck( check_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + click_event_handler onClick = nullptr; + press_event_handler onPress = nullptr; + press_event_handler onRelease = nullptr; + check_event_handler onCheck = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + +protected: + + /*! + * \internal + */ + Button( void* h ) : Control( h ) + { + } + + friend class ButtonEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Button_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Button.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ButtonCodes.h b/3rdparty/include/pcl/ButtonCodes.h new file mode 100644 index 0000000..884b680 --- /dev/null +++ b/3rdparty/include/pcl/ButtonCodes.h @@ -0,0 +1,135 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ButtonCodes.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_ButtonCodes_h +#define __PCL_ButtonCodes_h + +/// \file pcl/ButtonCodes.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::MouseButton + * \brief Defines PCL mouse button codes + * + * + * + * + * + * + * + * + *
MouseButton::Left Primary mouse button
MouseButton::Right Secondary mouse button
MouseButton::Middle Middle mouse button
MouseButton::X1 First X button
MouseButton::X2 Second X button
MouseButton::Unknown Unknown/unsupported mouse button
+ */ +namespace MouseButton +{ + enum mask_type + { + Left = 0x01, // Primary mouse button + Right = 0x02, // Secondary mouse button + Middle = 0x04, // Middle mouse button + X1 = 0x10, // First X button + X2 = 0x20, // Second X button + Unknown = 0 // Unknown/unsupported mouse button + }; +} + +/*! + * A combination of mouse button codes. + */ +typedef Flags MouseButtons; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::KeyModifier + * \brief Defines PCL keyboard modifiers + * + * + * + * + * + * + * + *
KeyModifier::Shift Shift key
KeyModifier::Control Control key (Command key on macOS)
KeyModifier::Alt Alt key
KeyModifier::SpaceBar Space bar
KeyModifier::Meta Meta key (Control key on macOS)
+ */ +namespace KeyModifier +{ + enum mask_type + { + Shift = 0x01, // Shift key + Control = 0x02, // Control key (= Command on macOS) + Alt = 0x04, // Alt key + SpaceBar = 0x08, // Space bar + Meta = 0x10 // Meta key (= Control on macOS) + }; +} + +/*! + * A combination of keyboard modifiers. + */ +typedef Flags KeyModifiers; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ButtonCodes_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ButtonCodes.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ByteArray.h b/3rdparty/include/pcl/ByteArray.h new file mode 100644 index 0000000..16cb525 --- /dev/null +++ b/3rdparty/include/pcl/ByteArray.h @@ -0,0 +1,100 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ByteArray.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_ByteArray_h +#define __PCL_ByteArray_h + +/// \file pcl/ByteArray.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup byte_arrays Byte Array Classes + */ + +/*! + * \class pcl::ByteArray + * \brief Dynamic array of 8-bit unsigned integers + * + * %ByteArray is a template instantiation of Array for \c uint8. + * + * \ingroup byte_arrays + * \ingroup dynamic_arrays + */ +typedef Array ByteArray; + +/*! + * \class pcl::SortedByteArray + * \brief Dynamic sorted array of 8-bit unsigned integers + * + * %SortedByteArray is a template instantiation of SortedArray for \c uint8. + * + * \ingroup byte_arrays + * \ingroup dynamic_arrays + */ +typedef SortedArray SortedByteArray; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ByteArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ByteArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/CUDADevice.h b/3rdparty/include/pcl/CUDADevice.h new file mode 100644 index 0000000..a5e70ad --- /dev/null +++ b/3rdparty/include/pcl/CUDADevice.h @@ -0,0 +1,131 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/CUDADevice.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_CUDADevice_h +#define __PCL_CUDADevice_h + +/// \file pcl/CUDADevice.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class CUDADevice + * \brief Access to core CUDA device services + * + * ### TODO: Write description. + */ +class PCL_CLASS CUDADevice +{ +public: + + /*! + * Default constructor - deleted, not an instantiable class. + */ + CUDADevice() = delete; + + /*! + * Copy constructor - deleted, not an instantiable class. + */ + CUDADevice( const CUDADevice& ) = delete; + + /*! + * Copy assignment operator - deleted, not an instantiable class. + */ + CUDADevice& operator =( CUDADevice& ) = delete; + + /*! + * Returns true iff a valid and operational CUDA device is currently + * available on the running PixInsight platform. + */ + static bool IsAvailable() noexcept; + + /*! + * Returns the identifying name of the active CUDA device, or an empty + * string if there is no valid CUDA device available on the running + * PixInsight platform. + */ + static IsoString Name(); + + /*! + * Returns the total global memory available on the active CUDA device in + * bytes, or zero if no valid CUDA device is available. + */ + static size_type TotalGlobalMemory() noexcept; + + /*! + * Returns the total shared memory available per block on the active CUDA + * device in bytes, or zero if no valid CUDA device is available. + */ + static size_type SharedMemoryPerBlock() noexcept; + + /*! + * Returns the maximum number of threads per block available in the active + * CUDA device, or zero if no valid CUDA device is available. + */ + static int MaxThreadsPerBlock() noexcept; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_CUDADevice_h + +// ---------------------------------------------------------------------------- +// EOF pcl/CUDADevice.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/CanvasColor.h b/3rdparty/include/pcl/CanvasColor.h new file mode 100644 index 0000000..ff73e0c --- /dev/null +++ b/3rdparty/include/pcl/CanvasColor.h @@ -0,0 +1,190 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/CanvasColor.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_CanvasColor_h +#define __PCL_CanvasColor_h + +/// \file pcl/CanvasColor.h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class CanvasColor + * \brief A set of color values used to fill free or unused areas of images + * + * Some geometric image transformations, such as rotations and translations for + * example, generate images with uncovered regions. %CanvasColor defines a set + * of color components to initialize pixels on such unused areas. + * + * %CanvasColor stores pixel values in a normalized floating-point format + * suitable to be used for any pixel sample data type. When using %CanvasColor + * with integer-sampled images, color components should be kept normalized in + * the normalized [0,1] range. + */ +class PCL_CLASS CanvasColor +{ +public: + + /*! + * Constructs a %CanvasColor object with zero (black) color components. + */ + CanvasColor() = default; + + /*! + * Copy constructor. + */ + CanvasColor( const CanvasColor& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + CanvasColor& operator =( const CanvasColor& ) = default; + + /*! + * Retrieves the current RGB sample values in this %CanvasColor object. + * + * \param[out] v0,v1,v2 References to variables that will receive current + * sample values for the red/gray, green and blue + * channels, respectively. + */ + void GetCanvasColor( float& v0, float& v1, float& v2 ) const + { + v0 = canvasColor[0]; v1 = canvasColor[1]; v2 = canvasColor[2]; + } + + /*! + * Retrieves the current RGBA sample values in this %CanvasColor object. + * + * \param[out] v0,v1,v2,v3 References to variables that will receive + * current sample values for the red/gray, green, blue and + * alpha channels, respectively. + */ + void GetCanvasColor( float& v0, float& v1, float& v2, float& v3 ) const + { + v0 = canvasColor[0]; v1 = canvasColor[1]; v2 = canvasColor[2]; v3 = canvasColor[3]; + } + + /*! + * Retrieves the current sample values in this %CanvasColor object. + * + * \param[out] v Starting address of an array where current sample values + * will be copied. This array must provide storage for at + * least four elements. + */ + void GetCanvasColor( float* v ) const + { + v[0] = canvasColor[0]; v[1] = canvasColor[1]; v[2] = canvasColor[2]; v[3] = canvasColor[3]; + } + + /*! + * Sets current RGB sample values for this %CanvasColor object. + * + * \param v0,v1,v2 New red/gray, green and blue sample values. + * + * \note The alpha component will be set to one (white, opaque). + */ + void SetCanvasColor( float v0, float v1, float v2 ) + { + canvasColor[0] = v0; canvasColor[1] = v1; canvasColor[2] = v2; canvasColor[3] = 1; + } + + /*! + * Sets current RGB sample values for this %CanvasColor object. + * + * \param v0,v1,v2,v3 New red/gray, green, blue and alpha sample values. + * + * \note The alpha component will be set to one (white, opaque). + */ + void SetCanvasColor( float v0, float v1, float v2, float v3 ) + { + canvasColor[0] = v0; canvasColor[1] = v1; canvasColor[2] = v2; canvasColor[3] = v3; + } + + /*! + * Sets current sample values for this %CanvasColor object. + * + * \param v Starting address of an array from which new sample values + * will be obtained. At least four elements are required. + */ + void SetCanvasColor( const float* v ) + { + canvasColor[0] = v[0]; canvasColor[1] = v[1]; canvasColor[2] = v[2]; canvasColor[3] = v[3]; + } + + /*! + * Sets all sample values of this %CanvasColor object equal to an specified + * value \a v. + */ + void SetCanvasColor( float v ) + { + canvasColor[0] = canvasColor[1] = canvasColor[2] = canvasColor[3] = v; + } + +protected: + + // Normalized floating-point sample values. Note that to the purpose of this + // structure float provides enough accuracy, even for DImage. + float canvasColor[ 4 ] = {}; // red/gray, green, blue, alpha +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_CanvasColor_h + +// ---------------------------------------------------------------------------- +// EOF pcl/CanvasColor.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/CharTraits.h b/3rdparty/include/pcl/CharTraits.h new file mode 100644 index 0000000..312bee6 --- /dev/null +++ b/3rdparty/include/pcl/CharTraits.h @@ -0,0 +1,1453 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/CharTraits.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_CharTraits_h +#define __PCL_CharTraits_h + +/// \file pcl/CharTraits.h + +#include +#include + +#include + +#include +#include +#include + +#ifdef __PCL_WINDOWS +# include +#else // POSIX +# include +# include +#endif // !__PCL_WINDOWS + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +char16_type PCL_FUNC PCL_ToCaseFolded( char16_type ); +char16_type PCL_FUNC PCL_ToLowercase( char16_type ); +char16_type PCL_FUNC PCL_ToUppercase( char16_type ); + +extern const uint8* PCL_DATA PCL_toLowercaseLatin1; +extern const uint8* PCL_DATA PCL_toUppercaseLatin1; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup char_trait_classes Character Traits Classes + * + * A character traits class characterizes a data type to represent a + * single element of a string, or \e character. For example, a char traits + * class must provide primitive routines to copy, compare and classify + * characters and sequences of characters. Those primitives are then used as + * the building blocks of more complex structures such as character strings and + * other text-oriented containers. + */ + +// ---------------------------------------------------------------------------- + +#define PCL_COMPARE_CODE_POINTS() \ + PCL_PRECONDITION( n1 == 0 || n2 == 0 || s1 != nullptr && s2 != nullptr ) \ + if ( caseSensitive ) \ + { \ + for ( size_type n = pcl::Min( n1, n2 ); n > 0; --n, ++s1, ++s2 ) \ + if ( *s1 != *s2 ) \ + return (*s1 < *s2) ? -1 : +1; \ + } \ + else \ + { \ + for ( size_type n = pcl::Min( n1, n2 ); n > 0; --n, ++s1, ++s2 ) \ + { \ + char_type c1 = ToCaseFolded( *s1 ), c2 = ToCaseFolded( *s2 ); \ + if ( c1 != c2 ) \ + return (c1 < c2) ? -1 : +1; \ + } \ + } \ + return (n1 == n2) ? 0 : ((n1 < n2) ? -1 : +1) + +// ---------------------------------------------------------------------------- + +/* + * Wildcard string matching algorithm adapted from: + * + * Kirk J. Krauss (2014): Matching Wildcards: An Empirical Way to Tame an + * Algorithm, Dr. Dobb's Magazine, October 7, 2014. + * + * http://www.drdobbs.com/architecture-and-design/matching-wildcards-an-empirical-way-to-t/240169123 + */ + +template inline +bool WildMatch( const Tt* t, size_type nt, const Tp* p, size_type np ) +{ + PCL_PRECONDITION( nt == 0 || np == 0 || t != nullptr && p != nullptr ) + + if ( nt == 0 || np == 0 ) + return false; + + const Tt* et = t + nt; + const Tp* ep = p + np; + const Tt* bt = nullptr; + const Tp* bp = nullptr; + + for ( ;; ) + { + Tp c = *p; + + if ( c == Tp( '*' ) ) + { + do + if ( ++p == ep ) + return true; + while ( (c = *p) == Tp( '*' ) ); + + if ( c != Tp( '?' ) ) + while ( Tt( c ) != *t ) + if ( ++t == et ) + return false; + + bp = p; + bt = t; + } + else if ( Tt( c ) != *t && c != Tp( '?' ) ) + { + if ( bp != nullptr ) + { + if ( p != bp ) + { + p = bp; + + if ( Tt( *p ) != *t ) + { + t = ++bt; + continue; + } + + ++p; + } + + if ( t < et ) + { + ++t; + continue; + } + } + + return false; + } + + ++t; + ++p; + + if ( t == et ) + { + if ( p == ep ) + return true; + + while ( *p == Tp( '*' ) ) + if ( ++p == ep ) + return true; + + return false; + } + } +} + +template inline +bool WildMatchIC( const Tt* t, size_type nt, const Tp* p, size_type np, Ut ut, Up up ) +{ + PCL_PRECONDITION( nt == 0 || np == 0 || t != nullptr && p != nullptr && ut != nullptr && up != nullptr ) + + if ( nt == 0 || np == 0 ) + return false; + + const Tt* et = t + nt; + const Tp* ep = p + np; + const Tt* bt = nullptr; + const Tp* bp = nullptr; + + for ( ;; ) + { + Tp c = *p; + + if ( c == Tp( '*' ) ) + { + do + if ( ++p == ep ) + return true; + while ( (c = *p) == Tp( '*' ) ); + + if ( c != Tp( '?' ) ) + { + c = up( c ); + while ( Tt( c ) != ut( *t ) ) + if ( ++t == et ) + return false; + } + + bp = p; + bt = t; + } + else if ( c != Tp( '?' ) ) + { + Tt ft = ut( *t ); + + if ( Tt( up( c ) ) != ft ) + { + if ( bp != nullptr ) + { + if ( p != bp ) + { + p = bp; + + if ( Tt( up( *p ) ) != ft ) + { + t = ++bt; + continue; + } + + ++p; + } + + if ( t < et ) + { + ++t; + continue; + } + } + + return false; + } + } + + ++t; + ++p; + + if ( t == et ) + { + if ( p == ep ) + return true; + + while ( *p == Tp( '*' ) ) + if ( ++p == ep ) + return true; + + return false; + } + } +} + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericCharTraits + * \brief Generic base class of character traits classes + * + * %GenericCharTraits defines fundamental properties and functionality common + * to all character types. + * + * The purpose of a character traits class is to characterize a data + * type to represent a single element of a string, or \e character. For + * example, a char traits class must provide primitive routines to copy, + * compare and classify characters and sequences of characters. + * + * %GenericCharTraits is a template class that must be instantiated for + * suitable data types. Two instantiations of %GenericCharTraits, namely for + * \c char and \c char16_type, originate the IsoString and String fundamental + * PCL classes, respectively. The versatile interface provided by + * %GenericCharTraits makes it possible to implement string classes virtually + * for any data type with default and copy constructor semantics. + * + * \ingroup char_trait_classes + * \sa CharTraits, IsoCharTraits, String, IsoString + */ +template +class PCL_CLASS GenericCharTraits +{ +public: + + /*! + * Represents the character data type used by this traits class. + */ + typedef T char_type; + + /*! + * Number of bytes per character. + */ + static constexpr size_type BytesPerChar() noexcept + { + return sizeof( char_type ); + } + + /*! + * Returns the length of a null-terminated string in characters (\e not + * bytes). + * + * The returned value is the length of the initial contiguous sequence of + * characters that are not equal to Null(). + */ + static size_type Length( const char_type* s ) noexcept + { + const char_type* __restrict__ t = s; + if ( s != nullptr ) + for ( ; *t != Null(); ++t ) {} + return size_type( t - s ); + } + + /*! + * Fills a contiguous region of characters with a constant value. + * + * \param s Initial address of a character sequence. + * \param c Constant value to fill with. + * \param n Number of characters to fill. + */ + static void Fill( char_type* __restrict__ s, char_type c, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n ) + *s++ = c; + } + + /*! + * Copies a contiguous sequence of characters to a specified location. The + * source and destination regions do not overlap. + * + * \param dst Destination location where characters will be copied. + * \param src Initial address of the sequence of source characters. + * \param n Number of characters to copy. + * + * If the source and destination regions overlap, this routine will produce + * an unpredictable result. CopyOverlapped() should be used in these cases. + */ + static void Copy( char_type* __restrict__ dst, const char_type* __restrict__ src, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || dst != nullptr && src != nullptr ) + ::memcpy( dst, src, n*sizeof( char_type ) ); + } + + /*! + * Copies a contiguous sequence of characters to a specified location. The + * source and destination regions may safely overlap. + * + * \param dst Destination location where characters will be copied. + * \param src Initial address of the sequence of source characters. + * \param n Number of characters to copy. + */ + static void CopyOverlapped( char_type* dst, const char_type* src, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || dst != nullptr && src != nullptr ) + ::memmove( dst, src, n*sizeof( char_type ) ); + } + + /*! + * Compares numeric character values between two strings. + * + * \param s1 First string. + * \param n1 Length of the first string in characters. + * \param s2 Second string. + * \param n2 Length of the second string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Returns an integer code representing the comparison result: + * + * \li 0 if \a s1 and \a s2 are equal + * \li -1 if \a s1 is less than \a s2 + * \li +1 if \a s1 is greater than \a s2 + * + * This function compares the numerical values of string characters. For + * case-insensitive comparisons, this generic routine is only valid for the + * ISO/IEC 8859-1 character set: characters in the ranges 0x41-0x5A, + * 0xC0-0xD6 and 0xD8-0xDE are considered identical to its counterparts in + * the ranges 0x61-0x7A, 0xE0-0xF6 and 0xF8-0xFE, respectively. + */ + static int CompareCodePoints( const char_type* __restrict__ s1, size_type n1, + const char_type* __restrict__ s2, size_type n2, bool caseSensitive = true ) noexcept + { + PCL_COMPARE_CODE_POINTS(); + } + + /*! + * Lexicographical comparison between two generic strings. + * + * \param s1 First string. + * \param n1 Length of the first string in characters. + * \param s2 Second string. + * \param n2 Length of the second string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * \param localeAware This parameter is ignored by GenericCharTraits. + * For locale-aware string comparisons, see the + * reimplementations of this static function in the + * IsoCharTraits and CharTraits template class + * instantiations. + * + * Returns an integer code representing the comparison result: + * + * \li 0 if \a s1 and \a s2 are equal + * \li -1 if \a s1 is less than \a s2 + * \li +1 if \a s1 is greater than \a s2 + * + * This default implementation simply calls CompareCodePoints() to compare + * the numerical values of string characters, so it cannot be localized and + * can't be aware of user locale settings. For more comprehensive, + * locale-aware Unicode implementations of this static function, see the + * IsoCharTraits and CharTraits classes. + */ + static int Compare( const char_type* __restrict__ s1, size_type n1, + const char_type* __restrict__ s2, size_type n2, bool caseSensitive = true, bool localeAware = true ) noexcept + { + return CompareCodePoints( s1, n1, s2, n2, caseSensitive ); + } + + /*! + * Wildcard string matching algorithm. + * + * \param t The string to be matched. + * + * \param nt Length of the string to be matched in characters. + * + * \param p The pattern string. May contain multiple instances of the + * wildcard characters '*' and '?'. + * + * \param np Length of the pattern string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Returns true iff the string \a t matches the specified pattern \a p. If + * one of the strings is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + static bool WildMatch( const char_type* __restrict__ t, size_type nt, + const char_type* __restrict__ p, size_type np, bool caseSensitive = true ) noexcept + { + if ( caseSensitive ) + return pcl::WildMatch( t, nt, p, np ); + return pcl::WildMatchIC( t, nt, p, np, ToCaseFolded, ToCaseFolded ); + } + + /*! + * Returns the \e case \e folded equivalent character for the specified + * code point \a c. + * + * Case folding elimitates case differences, which is useful for + * case-insensitive string comparisons. + * + * This default implementation is only valid for the ISO/IEC-8859-1 + * character set. For a comprehensive Unicode implementation see the + * CharTraits class. + */ + static char_type ToCaseFolded( char_type c ) noexcept + { + return ToLowercase( c ); + } + + /*! + * Returns the lowercase equivalent character for the specified code point. + * + * This default implementation is only valid for the ISO/IEC-8859-1 + * character set. For a comprehensive Unicode implementation see the + * CharTraits class. + */ + static constexpr char_type ToLowercase( char_type c ) noexcept + { + return (c >= char_type( 65 ) && c <= char_type( 90 ) + || c >= char_type( 192 ) && c <= char_type( 214 ) + || c >= char_type( 216 ) && c <= char_type( 222 )) ? c + 32 : c; + } + + /*! + * Returns the uppercase equivalent character for the specified code point. + * + * This default implementation is only valid for the ISO/IEC-8859-1 + * character set. For a comprehensive Unicode implementation see the + * CharTraits class. + */ + static constexpr char_type ToUppercase( char_type c ) noexcept + { + return (c >= char_type( 97 ) && c <= char_type( 122 ) + || c >= char_type( 224 ) && c <= char_type( 246 ) + || c >= char_type( 248 ) && c <= char_type( 254 )) ? c - 32 : c; + } + + /*! + * Transforms a string to lower case. + * + * This default implementation is only valid for the ISO/IEC-8859-1 + * character set. For a comprehensive Unicode implementation see the + * CharTraits class. + */ + static void ToLowercase( char_type* __restrict__ s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToLowercase( *s ); + } + + /*! + * Transforms a string to upper case. + * + * This default implementation is only valid for the ISO/IEC-8859-1 + * character set. For a comprehensive Unicode implementation see the + * CharTraits class. + */ + static void ToUppercase( char_type* __restrict__ s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToUppercase( *s ); + } + + /*! + * Returns the null string termination character '\\0'. + */ + static constexpr char_type Null() noexcept + { + return char_type( 0 ); + } + + /*! + * Returns the blank space character (white space). + */ + static constexpr char_type Blank() noexcept + { + return char_type( ' ' ); + } + + /*! + * Returns the horizontal tab control character '\\t'. + */ + static constexpr char_type Tab() noexcept + { + return char_type( '\t' ); + } + + /*! + * Returns the carriage return control character '\\r'. + */ + static constexpr char_type CR() noexcept + { + return char_type( '\r' ); + } + + /*! + * Returns the line feed control character '\\n'. + */ + static constexpr char_type LF() noexcept + { + return char_type( '\n' ); + } + + /*! + * Returns the comma punctuator character ','. + */ + static constexpr char_type Comma() noexcept + { + return char_type( ',' ); + } + + /*! + * Returns the colon punctuator character ':'. + */ + static constexpr char_type Colon() noexcept + { + return char_type( ':' ); + } + + /*! + * Returns the semicolon punctuator character ';'. + */ + static constexpr char_type Semicolon() noexcept + { + return char_type( ';' ); + } + + /*! + * Returns the hyphen punctuator character '-'. + */ + static constexpr char_type Hyphen() noexcept + { + return char_type( '-' ); + } + + /*! + * Returns the plus sign character '+'. + */ + static constexpr char_type PlusSign() noexcept + { + return char_type( '+' ); + } + + /*! + * Returns the minus sign character '-'. + */ + static constexpr char_type MinusSign() noexcept + { + return char_type( '-' ); + } + + /*! + * Returns the decimal separator character '.'. + */ + static constexpr char_type DecimalSeparator() noexcept + { + return char_type( '.' ); + } + + /*! + * Returns the exponent delimiter character 'e'. + */ + static constexpr char_type ExponentDelimiter() noexcept + { + return char_type( 'e' ); + } + + /*! + * Returns the underscore character '_'. + */ + static constexpr char_type Underscore() noexcept + { + return char_type( '_' ); + } + + /*! + * Returns the single quote character "'". + */ + static constexpr char_type SingleQuote() noexcept + { + return char_type( '\'' ); + } + + /*! + * Returns the double quote character '"'. + */ + static constexpr char_type DoubleQuote() noexcept + { + return char_type( '\"' ); + } + + /*! + * Returns true iff a character \a c is a null string terminator. + */ + static constexpr bool IsNull( char_type c ) noexcept + { + return c == Null(); + } + + /*! + * Returns true iff a character \a c is a white space character. + */ + static constexpr bool IsSpace( char_type c ) noexcept + { + return c == Blank() || c == Tab() || c == CR() || c == LF(); + } + + /*! + * Returns true iff a character \a c is a trimable character. Generally + * equivalent to IsSpace(). + */ + static constexpr bool IsTrimable( char_type c ) noexcept + { + return IsSpace( c ); + } + + /*! + * Returns true iff a character \a c is a decimal digit. Decimal digits are + * in the range [0-9]. + */ + static constexpr bool IsDigit( char_type c ) noexcept + { + return c >= char_type( '0' ) && c <= char_type( '9' ); + } + + /*! + * Returns true iff a character \a c is an hexadecimal digit. Hexadecimal + * digits are in the range [a-fA-F]. + */ + static constexpr bool IsHexDigit( char_type c ) noexcept + { + return IsDigit( c ) || c >= char_type( 'A' ) && c <= char_type( 'F' ) || + c >= char_type( 'a' ) && c <= char_type( 'f' ); + } + + /*! + * Returns true iff a character \a c is in the range [a-zA-Z]. + */ + static constexpr bool IsAlpha( char_type c ) noexcept + { + return IsLowercaseAlpha( c ) || IsUppercaseAlpha( c ); + } + + /*! + * Returns true iff a character \a c is in the range [a-z]. + */ + static constexpr bool IsLowercaseAlpha( char_type c ) noexcept + { + return c >= char_type( 'a' ) && c <= char_type( 'z' ); + } + + /*! + * Returns true iff a character \a c is in the range [A-Z]. + */ + static constexpr bool IsUppercaseAlpha( char_type c ) noexcept + { + return c >= char_type( 'A' ) && c <= char_type( 'Z' ); + } + + /*! + * Returns true iff a character \a c is the underscore character '_'. + */ + static constexpr bool IsUnderscore( char_type c ) noexcept + { + return c == Underscore(); + } + + /*! + * Returns true iff a character \a c is a valid symbol element. Symbol digits + * are in the range [a-zA-Z0-9_]. + */ + static constexpr bool IsSymbolDigit( char_type c ) noexcept + { + return IsAlpha( c ) || IsDigit( c ) || IsUnderscore( c ); + } + + /*! + * Returns true iff a character \a c is a valid starting symbol digit. A + * starting symbol digit is in the range [a-zA-Z_]. + */ + static constexpr bool IsStartingSymbolDigit( char_type c ) noexcept + { + return IsAlpha( c ) || IsUnderscore( c ); + } + + /*! + * Returns true iff a character \a c is a numerical sign, either '+' or '-'. + */ + static constexpr bool IsSign( char_type c ) noexcept + { + return c == MinusSign() || c == PlusSign(); + } + + /*! + * Returns true iff a character \a c is the decimal separator '.'. + */ + static constexpr bool IsDecimalSeparator( char_type c ) noexcept + { + return c == DecimalSeparator(); + } + + /*! + * Returns true iff a character \a c is an exponent delimiter. Exponent + * delimiters are in the range [eEdD]. The [dD] pair allows for FORTRAN + * compatibility. + */ + static constexpr bool IsExponentDelimiter( char_type c ) noexcept + { + return c == char_type( 'e' ) || c == char_type( 'E' ) || c == char_type( 'd' ) || c == char_type( 'D' ); + } + + /*! + * Returns true iff a character \a c is a wildcard. The wildcards are the + * asterisk '*' and question mark '?' characters. + */ + static constexpr bool IsWildcard( char_type c ) noexcept + { + return c == char_type( '*' ) || c == char_type( '?' ); + } + + /*! + * Returns a pointer to the first non-trimmable character in the sequence of + * contiguous characters defined by the range [i,j) of pointers. + */ + template + static Ptr1 SearchTrimLeft( Ptr1 i, Ptr2 j ) noexcept + { + for ( ; i < j && IsTrimable( *i ); ++i ) {} + return i; + } + + /*! + * Returns a pointer to the character \e after the last non-trimmable + * character in the sequence of contiguous characters defined by the range + * [i,j) of pointers. + * + * If there are no trimmable characters in the specified sequence, this + * function returns the ending pointer \a j. + */ + template + static Ptr2 SearchTrimRight( Ptr1 i, Ptr2 j ) noexcept + { + for ( ; i < j && IsTrimable( *(j-1) ); --j ) {} + return j; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class IsoCharTraits + * \brief A template instantiation of GenericCharTraits for the \c char type. + * + * %IsoCharTraits is the char traits class used by IsoString. + * + * \ingroup char_trait_classes + */ +class PCL_CLASS IsoCharTraits : public GenericCharTraits +{ +public: + + /*! + * Base class of this char traits class. + */ + typedef GenericCharTraits traits_base; + + /*! + * Represents the character data type used by this traits class. + */ + typedef traits_base::char_type char_type; + + /*! + * Returns the length of a null-terminated 8-bit string in characters + * (\e not bytes). + * + * The returned value is the length of the initial contiguous sequence of + * characters that are not equal to Null(). + */ + static constexpr size_type Length( const char_type* __restrict__ s ) noexcept + { + return (s != nullptr) ? ::strlen( s ) : 0; + } + + /*! + * Fills a contiguous region of characters with a constant value. + * + * \param s Initial address of a character sequence. + * \param c Constant value to fill with. + * \param n Number of characters to fill. + */ + static void Fill( char_type* __restrict__ s, char_type c, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + ::memset( s, c, n ); + } + + /*! + * Copies a contiguous sequence of characters to a specified location. The + * source and destination regions do not overlap. + * + * \param dst Destination location where characters will be copied. + * \param src Initial address of the sequence of source characters. + * \param n Number of characters to copy. + * + * If the source and destination regions overlap, this routine will produce + * an unpredictable result. CopyOverlapped() should be used in these cases. + */ + static void Copy( char_type* __restrict__ dst, const char_type* __restrict__ src, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || dst != nullptr && src != nullptr ) + ::memcpy( dst, src, n ); + } + + /*! + * Copies a contiguous sequence of characters to a specified location. The + * source and destination regions may safely overlap. + * + * \param dst Destination location where characters will be copied. + * \param src Initial address of the sequence of source characters. + * \param n Number of characters to copy. + */ + static void CopyOverlapped( char_type* dst, const char_type* src, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || dst != nullptr && src != nullptr ) + ::memmove( dst, src, n ); + } + + /*! + * Compares numeric character values between two 8-bit strings. + * + * \param s1 First string. + * \param n1 Length of the first string in characters. + * \param s2 Second string. + * \param n2 Length of the second string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Returns an integer code representing the comparison result: + * + * \li 0 if \a s1 and \a s2 are equal + * \li -1 if \a s1 is less than \a s2 + * \li +1 if \a s1 is greater than \a s2 + */ + static int CompareCodePoints( const char_type* __restrict__ s1, size_type n1, + const char_type* __restrict__ s2, size_type n2, bool caseSensitive = true ) noexcept + { + PCL_COMPARE_CODE_POINTS(); + } + + /*! + * Lexicographical comparison between two 8-bit strings. + * + * \param s1 First string. + * \param n1 Length of the first string in characters. + * \param s2 Second string. + * \param n2 Length of the second string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters (as defined by the current locale). + * The default value of this parameter is true. + * + * \param localeAware When true, a locale-aware comparison is + * performed which takes into account the currently + * selected user locale (language and variants). + * When false, an invariant comparison is carried + * out by comparing Unicode code points (which may + * be faster). The default value is true. + * + * Returns an integer code representing the comparison result: + * + * \li 0 if \a s1 and \a s2 are equal + * \li -1 if \a s1 is less than \a s2 + * \li +1 if \a s1 is greater than \a s2 + * + * On OS X and Windows platforms this function invokes system API routines + * to perform locale-aware string comparisons. + * + * On X11 (FreeBSD and Linux platforms), when the \a localeAware + * parameter is true, the comparison uses the current locale as reported by + * calling the setlocale POSIX function: + * + * \code + * setlocale( LC_COLLATE, 0 ); + * \endcode + * + * In PixInsight on X11 platforms, the default user collation and case + * comparison locales are used. A module can change them \e temporarily to + * a custom locale by calling: + * + * \code + * setlocale( LC_COLLATE, "" ); + * setlocale( LC_CTYPE, "" ); + * \endcode + * + * and then, after the necessary work has been done with the custom locales, + * restore the default settings: + * + * \code + * setlocale( LC_COLLATE, "" ); + * setlocale( LC_CTYPE, "" ); + * \endcode + */ + static int Compare( const char_type* __restrict__ s1, size_type n1, + const char_type* __restrict__ s2, size_type n2, bool caseSensitive = true, bool localeAware = true ) noexcept; + + /*! + * Wildcard string matching algorithm. + * + * \param t The string to be matched. + * + * \param nt Length of the string to be matched in characters. + * + * \param p The pattern string. May contain multiple instances of the + * wildcard characters '*' and '?'. + * + * \param np Length of the pattern string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Returns true iff the string \a t matches the specified pattern \a p. If + * one of the strings is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + static bool WildMatch( const char_type* __restrict__ t, size_type nt, + const char_type* __restrict__ p, size_type np, bool caseSensitive = true ) noexcept + { + if ( caseSensitive ) + return pcl::WildMatch( t, nt, p, np ); + return pcl::WildMatchIC( t, nt, p, np, + []( char_type c ) { return ToCaseFolded( c ); }, + []( char_type c ) { return ToCaseFolded( c ); } ); + } + + /*! + * Returns the \e case \e folded equivalent character for the specified + * ISO/IEC-8859-1 code point \a c. + * + * Case folding elimitates case differences, which is useful for + * case-insensitive string comparisons. + * + * For more information on case folding, see Section 3.13 Default Case + * Algorithms in The Unicode Standard. + */ + static char_type ToCaseFolded( char_type c ) noexcept + { + return ToLowercase( c ); + } + + /*! + * Returns the lowercase equivalent character for the specified + * ISO/IEC-8859-1 code point \a c. + */ + static char_type ToLowercase( char_type c ) noexcept + { + return char_type( PCL_toLowercaseLatin1[uint8( c )] ); + } + + /*! + * Returns the uppercase equivalent character for the specified + * ISO/IEC-8859-1 code point \a c. + */ + static char_type ToUppercase( char_type c ) noexcept + { + return char_type( PCL_toUppercaseLatin1[uint8( c )] ); + } + + /*! + * Transforms a string to case folded. + */ + static void ToCaseFolded( char_type* s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToCaseFolded( *s ); + } + + /*! + * Transforms a string to lowercase. + */ + static void ToLowercase( char_type* s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToLowercase( *s ); + } + + /*! + * Transforms a string to uppercase. + */ + static void ToUppercase( char_type* s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToUppercase( *s ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class CharTraits + * \brief A template instantiation of GenericCharTraits for \c char16_type. + * + * %CharTraits is the char traits class used by String. + * + * \ingroup char_trait_classes + */ +class PCL_CLASS CharTraits : public GenericCharTraits +{ +public: + + /*! + * Base class of this char traits class. + */ + typedef GenericCharTraits traits_base; + + /*! + * Represents the character data type used by this traits class. + */ + typedef traits_base::char_type char_type; + + /*! + * Returns the length of a null-terminated UTF-16 string in characters + * (\e not bytes). + * + * The returned value is the length of the initial contiguous sequence of + * characters that are not equal to Null(). + */ + static size_type Length( const char_type* __restrict__ s ) noexcept + { +#ifdef __PCL_WINDOWS + return (s != nullptr) ? ::wcslen( reinterpret_cast( s ) ) : 0u; +#else + return traits_base::Length( s ); +#endif + } + + /*! + * Copies a contiguous sequence of characters to a specified location. The + * source and destination regions do not overlap. + * + * \param dst Destination location where characters will be copied. + * \param src Initial address of the sequence of source characters. + * \param n Number of characters to copy. + * + * If the source and destination regions overlap, this routine will produce + * an unpredictable result. CopyOverlapped() should be used in these cases. + */ + static void Copy( char_type* __restrict__ dst, const char_type* __restrict__ src, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || dst != nullptr && src != nullptr ) + ::memcpy( dst, src, n << 1 ); + } + + /*! + * Copies a contiguous sequence of characters to a specified location. The + * source and destination regions may safely overlap. + * + * \param dst Destination location where characters will be copied. + * \param src Initial address of the sequence of source characters. + * \param n Number of characters to copy. + */ + static void CopyOverlapped( char_type* dst, const char_type* src, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || dst != nullptr && src != nullptr ) + ::memmove( dst, src, n << 1 ); + } + + /*! + * Compares numeric character values between two Unicode strings. + * + * \param s1 First string. + * \param n1 Length of the first string in characters. + * \param s2 Second string. + * \param n2 Length of the second string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Returns an integer code representing the comparison result: + * + * \li 0 if \a s1 and \a s2 are equal + * \li -1 if \a s1 is less than \a s2 + * \li +1 if \a s1 is greater than \a s2 + */ + static int CompareCodePoints( const char_type* __restrict__ s1, size_type n1, + const char_type* __restrict__ s2, size_type n2, bool caseSensitive = true ) noexcept + { + PCL_COMPARE_CODE_POINTS(); + } + + /*! + * Lexicographical comparison between two Unicode strings. + * + * \param s1 First string. + * \param n1 Length of the first string in characters. + * \param s2 Second string. + * \param n2 Length of the second string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters (as defined by the selected locale). + * The default value of this parameter is true. + * + * \param localeAware When true, a locale-aware comparison is + * performed which takes into account the currently + * selected user locale (language and variants). + * When false, an invariant comparison is carried + * out by comparing Unicode code points (which may + * be faster). The default value is true. + * + * Returns an integer code representing the comparison result: + * + * \li 0 if \a s1 and \a s2 are equal + * \li -1 if \a s1 is less than \a s2 + * \li +1 if \a s1 is greater than \a s2 + * + * On OS X and Windows platforms this function invokes system API routines + * to perform locale-aware string comparisons. + * + * On X11 (FreeBSD and Linux platforms), when the \a localeAware + * parameter is true, the comparison uses the current locale as reported by + * calling the setlocale POSIX function: + * + * \code + * setlocale( LC_COLLATE, 0 ); + * \endcode + * + * In PixInsight on X11 platforms, the default user collation and case + * comparison locales are used. A module can change them \e temporarily to + * a custom locale by calling: + * + * \code + * setlocale( LC_COLLATE, "" ); + * setlocale( LC_CTYPE, "" ); + * \endcode + * + * and then, after the necessary work has been done with the custom locales, + * restore the default settings: + * + * \code + * setlocale( LC_COLLATE, "" ); + * setlocale( LC_CTYPE, "" ); + * \endcode + */ + static int Compare( const char_type* __restrict__ s1, size_type n1, + const char_type* __restrict__ s2, size_type n2, bool caseSensitive = true, bool localeAware = true ) noexcept; + + /*! + * Wildcard string matching algorithm. + * + * \param t The string to be matched. + * + * \param nt Length of the string to be matched in characters. + * + * \param p The pattern string. May contain multiple instances of the + * wildcard characters '*' and '?'. + * + * \param np Length of the pattern string in characters. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Returns true iff the string \a t matches the specified pattern \a p. If + * one of the strings is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + static bool WildMatch( const char_type* __restrict__ t, size_type nt, + const char_type* __restrict__ p, size_type np, bool caseSensitive = true ) noexcept + { + if ( caseSensitive ) + return pcl::WildMatch( t, nt, p, np ); + return pcl::WildMatchIC( t, nt, p, np, + []( char_type c ) { return ToCaseFolded( c ); }, + []( char_type c ) { return ToCaseFolded( c ); } ); + } + + /*! + * Wildcard string matching algorithm - overloaded version with 8-bit + * pattern string. + */ + static bool WildMatch( const char_type* __restrict__ t, size_type nt, + const char* __restrict__ p, size_type np, bool caseSensitive = true ) noexcept + { + if ( caseSensitive ) + return pcl::WildMatch( t, nt, p, np ); + return pcl::WildMatchIC( t, nt, p, np, + []( char_type c ) { return ToCaseFolded( c ); }, + []( char c ) { return IsoCharTraits::ToCaseFolded( c ); } ); + } + + /*! + * Returns the \e case \e folded equivalent character for the specified + * UTF-16 code point \a c. + * + * Case folding elimitates case differences, which is useful for + * case-insensitive string comparisons. + * + * We implement the \e simple \e case \e folding Unicode algorithm + * exclusively. For more information on case folding, see Section 3.13 + * Default Case Algorithms in The Unicode Standard. + */ + static char_type ToCaseFolded( char_type c ) noexcept + { + if ( c < 256 ) + { + if ( c >= 65 && c <= 90 || c >= 192 && c <= 214 || c >= 216 && c <= 222 ) + return c + 32; + return c; + } + return PCL_ToCaseFolded( c ); + } + + /*! + * Returns the lowercase equivalent character for the specified UTF-16 code + * point \a c. + */ + static char_type ToLowercase( char_type c ) noexcept + { + if ( c < 256 ) + { + if ( c >= 65 && c <= 90 || c >= 192 && c <= 214 || c >= 216 && c <= 222 ) + return c + 32; + return c; + } + return PCL_ToLowercase( c ); + } + + /*! + * Returns the uppercase equivalent character for the specified UTF-16 code + * point \a c. + */ + static char_type ToUppercase( char_type c ) noexcept + { + if ( c < 256 ) + { + if ( c >= 97 && c <= 122 || c >= 224 && c <= 246 || c >= 248 && c <= 254 ) + return c - 32; + return c; + } + return PCL_ToUppercase( c ); + } + + /*! + * Transforms a string to case folded. + */ + static void ToCaseFolded( char_type* s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToCaseFolded( *s ); + } + + /*! + * Transforms a string to lowercase. + */ + static void ToLowercase( char_type* s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToLowercase( *s ); + } + + /*! + * Transforms a string to uppercase. + */ + static void ToUppercase( char_type* s, size_type n ) noexcept + { + PCL_PRECONDITION( n == 0 || s != nullptr ) + for ( ; n > 0; --n, ++s ) + *s = ToUppercase( *s ); + } + + /*! + * Returns true iff the specified UTF-16 character is a high + * surrogate (the most significant word of a surrogate pair + * forming a UTF-32 code point). High surrogates have values between 0xD800 + * and 0xDBFF. + */ + static constexpr bool IsHighSurrogate( char_type c16 ) noexcept + { + return (c16 & 0xFC00) == 0xD800; + } + + /*! + * Returns the high surrogate word of a UTF-32 code point. The + * specified UTF-32 code must be in the range from 0x010000 to 0x10FFFF, + * since surrogates only exist outside the Basic Multilingual Plane of + * Unicode. + */ + static constexpr char_type HighSurrogate( char32_type c32 ) noexcept + { + return char_type( (c32 >> 10) + 0xD7C0 ); + } + + /*! + * Returns true iff the specified UTF-16 character is a low + * surrogate (the least significant word of a surrogate pair + * forming a UTF-32 code point). Low surrogates have values between 0xDC00 + * and 0xDFFF. + */ + static constexpr bool IsLowSurrogate( char_type c16 ) noexcept + { + return (c16 & 0xFC00) == 0xDC00; + } + + /*! + * Returns the low surrogate word of a UTF-32 code point. The + * specified UTF-32 code must be in the range from 0x010000 to 0x10FFFF, + * since surrogates only exist outside the Basic Multilingual Plane of + * Unicode. + */ + static constexpr char_type LowSurrogate( char32_type c32 ) noexcept + { + return char_type( (c32%0x400) + 0xDC00 ); + } + + /*! + * Returns a UTF-32 code point from its surrogate pair. The + * specified surrogate words must pertain to a valid Unicode code point + * outside the Basic Multilingual Plane (from 0x010000 to 0x10FFFF). + */ + static constexpr char32_type SurrogatePairToUTF32( char_type high, char_type low ) noexcept + { + return (char32_type( high ) << 10) + low - 0x035FDC00; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_CharTraits_h + +// ---------------------------------------------------------------------------- +// EOF pcl/CharTraits.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ChebyshevFit.h b/3rdparty/include/pcl/ChebyshevFit.h new file mode 100644 index 0000000..2c4c2db --- /dev/null +++ b/3rdparty/include/pcl/ChebyshevFit.h @@ -0,0 +1,945 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ChebyshevFit.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_ChebyshevFit_h +#define __PCL_ChebyshevFit_h + +/// \file pcl/ChebyshevFit.h + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +template class GenericScalarChebyshevFit; + +/*! + * \class GenericChebyshevFit + * \brief Approximation of vector-valued functions by Chebyshev polynomial + * expansions. + * + * %GenericChebyshevFit approximates a smooth, vector-valued function f(x) in a + * given interval [a,b] by expansion with a set of truncated series of + * Chebyshev polynomials. As is well known, the Chebyshev expansion: + * + * T(x) = Sum_i( ci*Ti(x) ), + * + * where i belongs to [0,∞), Ti(x) is the Chebyshev polynomial of the ith + * degree, and the ci's are polynomial coefficients, is very close to the + * optimal approximating polynomial that minimizes the error |T(x) - f(x)|, + * where x varies over the fitting interval [a,b]. + * + * For functions converging strongly after a given series length n, one can + * truncate the Chebyshev series to a smaller length m < n to obtain an + * approximating polynomial with a maximum error close to |Tm+1(x)|. + * + * In addition to Chebyshev expansion, truncation and approximation, this class + * also implements generation of Chebyshev polynomials to approximate the + * first derivative and indefinite integral of the fitted function. + * + * The template argument Tx represents the type of the independent variable, or + * the type of the argument x of the fitted function y = f(x). The template + * argument Ty represents the type of a component of the value y of the fitted + * function. + */ +template +class GenericChebyshevFit +{ +public: + + /*! + * Represents an ordered list of Chebyshev polynomial coefficients. + */ + typedef GenericVector coefficients; + + /*! + * Represents a set of ordered lists of Chebyshev polynomial coefficients. + */ + typedef GenericMultiVector coefficient_series; + + /*! + * Represents a function value. + */ + typedef GenericVector function_value; + + /*! + * Represents a set of function values. + */ + typedef GenericMultiVector function_values; + + /*! + * Constructs a truncated Chebyshev polynomial expansion with \a n + * coefficients to approximate the specified N-dimensional, vector-valued + * function \a f in the interval [\a x1,\a x2] of the independent variable. + * + * The function \a f will be called \a n times and should have the following + * prototype (or equivalent by means of suitable type conversions and/or + * default arguments): + * + * GenericVector<Ty> f( Tx ) + * + * where the length of a returned vector must be equal to \a N. + * + * The expansion process will compute n^2 + n cosines, which may dominate the + * complexity of the process if the function \a f is comparatively fast. + * + * The interval [\a x1,\a x2] must not be empty or insignificant with + * respect to the machine epsilon. If that happens, this constructor will + * throw an appropriate Error exception. The interval bounds can be + * specified in any order, that is, \a x2 can legally be < \a x1; in such + * case the bounds will be implicitly swapped by this constructor. + * + * The interval [\a x1,\a x2] will be also the valid range of evaluation for + * this object, which can be retrieved with LowerBound() and UpperBound(). + * See also the Evaluate() member function. + * + * The length \a n of the polynomial coefficient series should be ≥ 2. If + * \a n ≤ 1, the specified value will be ignored and \a n = 2 will be + * forced. Typically, a relatively large series length should be used, say + * between 30 and 100 coefficients, depending on the rate and amplitude of + * function variations within the fitting interval. The polynomial expansion + * can be further truncated to approximate the function to the desired error + * bound. See the Truncate() and Evaluate() member functions for details. + */ + template + GenericChebyshevFit( F f, Tx x1, Tx x2, int N, int n ) + : dx( Abs( x2 - x1 ) ) + , x0( (x1 + x2)/2 ) + , m( Max( 2, n ), Max( 1, N ) ) + { + PCL_PRECONDITION( N > 0 ) + PCL_PRECONDITION( n > 1 ) + if ( 1 + dx == 1 ) + throw Error( "GenericChebyshevFit: Empty or insignificant function evaluation interval." ); + N = m.Length(); + n = m[0]; + Tx dx2 = dx/2; + function_values y( n, N ); + for ( int j = 0; j < n; ++j ) + y[j] = f( x0 + Cos( Const::pi()*(j + 0.5)/n )*dx2 ); + c = coefficient_series( N, n ); + Ty k = 2.0/n; + for ( int i = 0; i < N; ++i ) + for ( int j = 0; j < n; ++j ) + { + Ty s = Ty( 0 ); + for ( int k = 0; k < n; ++k ) + s += y[k][i] * Cos( Const::pi()*j*(k + 0.5)/n ); + c[i][j] = k*s; + } + } + + /*! + * Constructs a truncated Chebyshev polynomial expansion from the specified + * coefficient series \a ck to approximate a vector-valued function in the + * interval [\a x1,\a x2] of the independent variable. The dimension of the + * approximated function and the coefficient series lengths are acquired + * from the specified container \a ck. + * + * This constructor performs basic coherence and structural integrity checks + * on the specified parameters, and throws the appropriate Error exception + * if it detects any problem. However, the validity of polynomial expansion + * coefficients cannot be verified; ensuring it is the responsibility of the + * caller. + */ + GenericChebyshevFit( const coefficient_series& ck, Tx x1, Tx x2 ) + : dx( Abs( x2 - x1 ) ) + , x0( (x1 + x2)/2 ) + , c( ck ) + , m( int( ck.Length() ) ) + { + if ( 1 + dx == 1 ) + throw Error( "GenericChebyshevFit: Empty or insignificant function evaluation interval." ); + if ( c.IsEmpty() ) + throw Error( "GenericChebyshevFit: Empty polynomial expansion." ); + for ( int i = 0; i < m.Length(); ++i ) + if ( (m[i] = c[i].Length()) < 1 ) + throw Error( "GenericChebyshevFit: Invalid coefficient series for dimension " + String( i ) + '.' ); + } + + /*! + * Default constructor. + * + * Constructs an invalid, uninitialized object that cannot be used to + * perform function evaluations. A default-constructed %GenericChebyshevFit + * object should be assigned with an already initialized instance in order + * to become operative. + * + * \sa IsValid() + */ + GenericChebyshevFit() = default; + + /*! + * Copy constructor. + */ + GenericChebyshevFit( const GenericChebyshevFit& ) = default; + + /*! + * Move constructor. + */ + GenericChebyshevFit( GenericChebyshevFit&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + GenericChebyshevFit& operator =( const GenericChebyshevFit& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GenericChebyshevFit& operator =( GenericChebyshevFit&& ) = default; + + /*! + * Returns true if this object has been correctly initialized and can be + * used to perform function evaluations. Returns false if this is an + * uninitialized, default-constructed object + */ + bool IsValid() const + { + return !c.IsEmpty(); + } + + /*! + * Returns the lower bound of this Chebyshev fit. This is the smallest value + * of the independent variable for which the function has been fitted, and + * hence the smallest value for which this object can be legally evaluated + * for function approximation. + * + * \sa UpperBound() + */ + Tx LowerBound() const + { + return x0 - dx/2; + } + + /*! + * Returns the upper bound of this Chebyshev fit. This is the largest value + * of the independent variable for which the function has been fitted, and + * hence the largest value for which this object can be legally evaluated + * for function approximation. + * + * \sa LowerBound() + */ + Tx UpperBound() const + { + return x0 + dx/2; + } + + /*! + * Returns the number of components in the (vector-valued) dependent + * variable. This is the number of vector components in a fitted or + * approximated function value. + */ + int NumberOfComponents() const + { + return m.Length(); + } + + /*! + * Returns the number of coefficients in the generated Chebyshev polynomial + * expansion for the specified zero-based vector component index \a i. This + * is the number of coefficients that was specified or acquired in a class + * constructor. + * + * \sa TruncatedLength() + */ + int Length( int i = 0 ) const + { + PCL_PRECONDITION( i >= 0 && i < NumberOfComponents() ) + return c[i].Length(); + } + + /*! + * Returns the number of coefficients in the truncated Chebyshev polynomial + * expansion for the specified zero-based vector component index \a i. + * + * If \a i < 0, returns the largest number of polynomial coefficients among + * all vector components. + * + * \sa Truncate(), Length() + */ + int TruncatedLength( int i = -1 ) const + { + PCL_PRECONDITION( i < 0 || i < NumberOfComponents() ) + if ( i < 0 ) + return m.MaxComponent(); + return m[i]; + } + + /*! + * Returns the total number of coefficients in this Chebyshev polynomial + * expansion, or the sum of computed coefficients for all vector components. + * + * \sa NumberOfTruncatedCoefficients() + */ + int NumberOfCoefficients() const + { + int N = 0; + for ( int i = 0; i < NumberOfComponents(); ++i ) + N += c[i].Length(); + return N; + } + + /*! + * Returns the total number of coefficients in the truncated Chebyshev + * polynomial expansion, or the sum of the lengths of the truncated + * coefficients series for all vector components. + * + * \sa NumberOfCoefficients() + */ + int NumberOfTruncatedCoefficients() const + { + return m.Sum(); + } + + /*! + * Returns true iff the Chebyshev polynomial expansion has been truncated + * for the specified zero-based vector component index \a i. + * + * If \a i < 0, returns true iff the expansions have been truncated for all + * vector components. + * + * \sa Truncate(), TruncatedLength() + */ + bool IsTruncated( int i = -1 ) const + { + PCL_PRECONDITION( i < 0 || i < NumberOfComponents() ) + if ( i < 0 ) + return m.MaxComponent() < Length(); + return m[i] < c[i].Length(); + } + + /*! + * Returns an estimate of the maximum error in the truncated Chebyshev + * polynomial expansion for the specified zero-based vector component index + * \a i. + * + * If \a i < 0, returns the largest expansion error estimate among all + * vector components. + * + * \sa Truncate() + */ + Ty TruncationError( int i = -1 ) const + { + PCL_PRECONDITION( i < 0 || i < NumberOfComponents() ) + if ( i < 0 ) + { + int N = NumberOfComponents(); + function_value e( N ); + for ( int j = 0; j < N; ++j ) + e[j] = TruncationError( j ); + return e.MaxComponent(); + } + if ( m[i] < c[i].Length() ) + { + Ty e = Ty( 0 ); + for ( int j = c[i].Length(); --j >= m[i]; ) + e += Abs( c[i][j] ); + return e; + } + return Abs( c[i][c[i].Length()-1] ); + } + + /*! + * Attempts to truncate the Chebyshev polynomial expansion for the specified + * maximum error \a e. Returns \c true iff the expansion could be truncated + * successfully for all vector components of the fitted function. + * + * If n is the length of a fitted polynomial series, this function finds a + * truncated length 1 < m ≤ n such that: + * + * Sum_i( |ci| ) < e + * + * where ci is a polynomial coefficient and the zero-based subindex i is in + * the interval [m,n-1]. + * + * The truncated Chebyshev expansion will approximate the fitted function + * component with a maximum error close to ±|e| within the fitting + * interval. + * + * The optional parameter \a mmin is the minimum allowed length of a + * coefficient series. The value of this parameter is 2 by default, which is + * the minimum number of Chebyshev coefficients in a series expansion. + * Specifying a value greater than 2 can be useful sometimes to impose + * stricter accuracy constraints on the truncated series. + * + * This member function does not remove any polynomial coefficients, so the + * original polynomial expansion remains intact. This means that the fitted + * polynomials can be truncated successively to achieve different error + * bounds, as required. + * + * If the polynomial series cannot be truncated to achieve the required + * tolerance in all function components (that is, if either all coefficients + * for a given component are larger than \a e in absolute value, or n = 2), + * this function forces m = n for the components where the requested + * truncation is not feasible, yielding the original, untruncated Chebyshev + * polynomials for those components. In such case this function returns + * \c false. + */ + bool Truncate( Ty e, int mmin = 2 ) + { + e = Abs( e ); + mmin = Max( 2, mmin ); + int N = NumberOfComponents(); + int tc = 0; + for ( int i = 0; i < N; ++i ) + { + Ty s = Ty( 0 ); + for ( m[i] = c[i].Length(); m[i] > mmin; --m[i] ) + if ( (s += Abs( c[i][m[i]-1] )) >= e ) + break; + if ( m[i] < c[i].Length() ) + ++tc; + } + return tc == N; + } + + /*! + * Returns a reference to the immutable set of Chebyshev polynomial + * expansion coefficients in this object. + */ + const coefficient_series& Coefficients() const + { + return c; + } + + /*! + * Evaluates the truncated Chebyshev polynomial expansion for the specified + * value \a x of the independent variable, and returns the approximated + * function value. + * + * The specified evaluation point \a x must lie within the fitting interval, + * given by LowerBound() and UpperBound(), which was specified as the \a x1 + * and \a x2 arguments when the function was initially fitted by the class + * constructor. For performance reasons, this precondition is not verified + * by this member function. If an out-of-range evaluation point is + * specified, this function will return an unpredictable result. + * + * If the polynomial series has been truncated by calling Truncate(), this + * function evaluates the current truncated Chebyshev expansions instead of + * the original ones. + * + * \sa operator ()() + */ + function_value Evaluate( Tx x ) const + { + PCL_PRECONDITION( x >= LowerBound() ) + PCL_PRECONDITION( x <= UpperBound() ) + const Ty y0 = Ty( 2*(x - x0)/dx ); + const Ty y2 = 2*y0; + function_value y( NumberOfComponents() ); + for ( int i = 0; i < y.Length(); ++i ) + { + Ty d0 = Ty( 0 ); + Ty d1 = Ty( 0 ); + const Ty* k = c[i].At( m[i] ); + for ( int j = m[i]; --j > 0; ) + { + Ty d = d1; + d1 = y2*d1 - d0 + *--k; + d0 = d; + } + y[i] = y0*d1 - d0 + *--k/2; + } + return y; + } + + /*! + * A synonym for Evaluate(). + */ + function_value operator ()( Tx x ) const + { + return Evaluate( x ); + } + + /*! + * Returns a %GenericChebyshevFit object that approximates the derivative of + * the function fitted by this object. + * + * The returned object can be used to evaluate the derivative within the + * fitting interval of this object, defined by LowerBound() and + * UpperBound(). + * + * The returned object will always own Chebyshev polynomials with the length + * of the originally fitted series, \e not of the current truncated lengths, + * if the polynomial expansions have been truncated. + * + * \sa Integral() + */ + GenericChebyshevFit Derivative() const + { + int N = NumberOfComponents(); + GenericChebyshevFit ch1; + ch1.dx = dx; + ch1.x0 = x0; + ch1.c = coefficient_series( N ); + ch1.m = IVector( N ); + for ( int i = 0; i < N; ++i ) + { + int n = Max( 1, c[i].Length()-1 ); + ch1.c[i] = coefficients( n ); + ch1.m[i] = n; + if ( n > 1 ) + { + ch1.c[i][n-1] = 2*n*c[i][n]; + ch1.c[i][n-2] = 2*(n-1)*c[i][n-1]; + for ( int j = n-3; j >= 0; --j ) + ch1.c[i][j] = ch1.c[i][j+2] + 2*(j+1)*c[i][j+1]; + ch1.c[i] *= Ty( 2 )/dx; + } + else + ch1.c[i] = Ty( 0 ); + } + return ch1; + } + + /*! + * Returns a %GenericChebyshevFit object that approximates the indefinite + * integral of the function fitted by this object. + * + * The returned object can be used to evaluate the integral within the + * fitting interval of this object, as defined by LowerBound() and + * UpperBound(). The constant of integration is set to a value such that the + * integral is zero at the lower fitting bound. + * + * The returned object will always own Chebyshev polynomials with the length + * of the originally fitted series, \e not of the current truncated lengths, + * if the polynomial expansions have been truncated. + * + * \sa Derivative() + */ + GenericChebyshevFit Integral() const + { + int N = NumberOfComponents(); + GenericChebyshevFit ch; + ch.dx = dx; + ch.x0 = x0; + ch.c = coefficient_series( N ); + ch.m = IVector( N ); + for ( int i = 0; i < N; ++i ) + { + int n = c[i].Length(); + ch.c[i] = coefficients( n ); + ch.m[i] = n; + if ( n > 1 ) + { + const Ty k = Ty( dx )/4; + Ty s = Ty( 0 ); + int f = 1; + for ( int j = 1; j < n-1; ++j, f = -f ) + s += f*(ch.c[i][j] = k*(c[i][j-1] - c[i][j+1])/j); + ch.c[i][0] = 2*(s + f*(ch.c[i][n-1] = k*c[i][n-2]/(n-1))); + } + else + ch.c[i] = Ty( 0 ); + } + return ch; + } + +private: + + Tx dx; // x2 - x1 + Tx x0; // (x1 + x2)/2 + coefficient_series c; // Chebyshev polynomial coefficients + IVector m; // length of the truncated coefficient series + + friend class GenericScalarChebyshevFit; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericScalarChebyshevFit + * \brief Approximation of scalar-valued functions by Chebyshev polynomial + * expansion. + * + * %GenericScalarChebyshevFit approximates a smooth, scalar-valued function + * f(x) in a given interval [a,b] by expansion with a single truncated series + * of Chebyshev polynomials. %GenericScalarChebyshevFit is a convenient + * specialization of GenericChebyshevFit for functions returning a single + * value; refer to the parent class for complete information. + */ +template +class GenericScalarChebyshevFit : public GenericChebyshevFit +{ +public: + + /*! + * Constructs a truncated Chebyshev polynomial expansion with \a n + * coefficients to approximate the specified N-dimensional, scalar-valued + * function \a f in the interval [\a x1,\a x2] of the independent variable. + * + * See GenericChebyshevFit::GenericChebyshevFit() for detailed information. + */ + template + GenericScalarChebyshevFit( F f, Tx x1, Tx x2, int n ) + : GenericChebyshevFit( [f]( Tx x ){ return GenericVector( f( x ), 1 ); }, x1, x2, 1, n ) + { + } + + /*! + * Default constructor. + * + * Constructs an invalid, uninitialized object that cannot be used to + * perform function evaluations. A default-constructed + * %GenericScalarChebyshevFit object should be assigned with an already + * initialized instance in order to become operative. + * + * \sa IsValid() + */ + GenericScalarChebyshevFit() = default; + + /*! + * Copy constructor. + */ + GenericScalarChebyshevFit( const GenericScalarChebyshevFit& ) = default; + + /*! + * Move constructor. + */ + GenericScalarChebyshevFit( GenericScalarChebyshevFit&& ) = default; + + /*! + * Copy assignment operator. + */ + GenericScalarChebyshevFit& operator =( const GenericScalarChebyshevFit& ) = default; + + /*! + * Move assignment operator. + */ + GenericScalarChebyshevFit& operator =( GenericScalarChebyshevFit&& ) = default; + + /*! + * Returns the number of coefficients in the truncated Chebyshev polynomial + * expansion. + * + * \sa Truncate(), Length() + */ + int TruncatedLength() const + { + return GenericChebyshevFit::TruncatedLength( 0 ); + } + + /*! + * Returns true iff the Chebyshev polynomial expansion has been truncated. + * + * \sa Truncate(), TruncatedLength() + */ + bool IsTruncated() const + { + return GenericChebyshevFit::IsTruncated( 0 ); + } + + /*! + * Returns an estimate of the maximum error in the truncated Chebyshev + * polynomial expansion. + * + * \sa Truncate() + */ + Ty TruncationError() const + { + return GenericChebyshevFit::TruncationError( 0 ); + } + + /*! + * Evaluates the truncated Chebyshev polynomial expansion for the specified + * value \a x of the independent variable, and returns the approximated + * function value. + * + * \sa operator ()() + */ + Ty Evaluate( Tx x ) const + { + return GenericChebyshevFit::Evaluate( x )[0]; + } + + /*! + * A synonym for Evaluate(). + */ + Ty operator ()( Tx x ) const + { + return Evaluate( x ); + } + + /*! + * Returns a %GenericChebyshevFit object that approximates the derivative of + * the function fitted by this object. + * + * See GenericChebyshevFit::Derivative() for detailed information. + * + * \sa Integral() + */ + GenericScalarChebyshevFit Derivative() const + { + return GenericChebyshevFit::Derivative(); + } + + /*! + * Returns a %GenericChebyshevFit object that approximates the indefinite + * integral of the function fitted by this object. + * + * See GenericChebyshevFit::Integral() for detailed information. + * + * \sa Derivative() + */ + GenericScalarChebyshevFit Integral() const + { + return GenericChebyshevFit::Integral(); + } + +private: + + /*! + * \internal + * Private constructor from the base class. + */ + GenericScalarChebyshevFit( const GenericChebyshevFit& T ) + : GenericChebyshevFit() + { + this->dx = T.dx; + this->x0 = T.x0; + this->c = typename GenericChebyshevFit::coefficient_series( 1 ); + this->c[0] = T.c[0]; + this->m = IVector( 1 ); + this->m[0] = T.m[0]; + } +}; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_CHEBYSHEV_FIT_INSTANTIATE + +/*! + * \defgroup chebyshev_fit_types Chebyshev Fit Types + */ + +/*! + * \class pcl::F32ChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 32-bit floating point Chebyshev function approximation. + * + * %F32ChebyshevFit is a template instantiation of GenericChebyshevFit for the + * \c float type. + */ +typedef GenericChebyshevFit F32ChebyshevFit; + +/*! + * \class pcl::FChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 32-bit floating point Chebyshev function approximation. + * + * %FChebyshevFit is an alias for F32ChebyshevFit. It is a template + * instantiation of GenericChebyshevFit for the \c float type. + */ +typedef F32ChebyshevFit FChebyshevFit; + +/*! + * \class pcl::F64ChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 64-bit floating point Chebyshev function approximation. + * + * %F64ChebyshevFit is a template instantiation of GenericChebyshevFit for the + * \c double type. + */ +typedef GenericChebyshevFit F64ChebyshevFit; + +/*! + * \class pcl::DChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 64-bit floating point Chebyshev function approximation. + * + * %DChebyshevFit is an alias for F64ChebyshevFit. It is a template + * instantiation of GenericChebyshevFit for the \c double type. + */ +typedef F64ChebyshevFit DChebyshevFit; + +/*! + * \class pcl::ChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 64-bit floating point Chebyshev function approximation. + * + * %ChebyshevFit is an alias for DChebyshevFit. It is a template instantiation + * of GenericChebyshevFit for the \c double type. + */ +typedef DChebyshevFit ChebyshevFit; + +#ifndef _MSC_VER + +/*! + * \class pcl::F80ChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 80-bit extended precision floating point Chebyshev function + * approximation. + * + * %F80ChebyshevFit is a template instantiation of GenericChebyshevFit for the + * \c long \c double type. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef GenericChebyshevFit F80ChebyshevFit; + +/*! + * \class pcl::LDChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 80-bit extended precision floating point Chebyshev function + * approximation. + * + * %LDChebyshevFit is an alias for F80ChebyshevFit. It is a template + * instantiation of GenericChebyshevFit for the \c long \c double type. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef F80ChebyshevFit LDChebyshevFit; + +#endif // !_MSC_VER + +/*! + * \class pcl::F32ScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 32-bit floating point scalar Chebyshev function approximation. + * + * %F32ScalarChebyshevFit is a template instantiation of + * GenericScalarChebyshevFit for the \c float type. + */ +typedef GenericScalarChebyshevFit F32ScalarChebyshevFit; + +/*! + * \class pcl::FScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 32-bit floating point scalar Chebyshev function approximation. + * + * %FScalarChebyshevFit is an alias for F32ScalarChebyshevFit. It is a template + * instantiation of GenericScalarChebyshevFit for the \c float type. + */ +typedef F32ScalarChebyshevFit FScalarChebyshevFit; + +/*! + * \class pcl::F64ScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 64-bit floating point scalar Chebyshev function approximation. + * + * %F64ScalarChebyshevFit is a template instantiation of + * GenericScalarChebyshevFit for the \c double type. + */ +typedef GenericScalarChebyshevFit F64ScalarChebyshevFit; + +/*! + * \class pcl::DScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 64-bit floating point scalar Chebyshev function approximation. + * + * %DScalarChebyshevFit is an alias for F64ScalarChebyshevFit. It is a template + * instantiation of GenericScalarChebyshevFit for the \c double type. + */ +typedef F64ScalarChebyshevFit DScalarChebyshevFit; + +/*! + * \class pcl::ScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 64-bit floating point scalar Chebyshev function approximation. + * + * %ScalarChebyshevFit is an alias for DScalarChebyshevFit. It is a template + * instantiation of GenericScalarChebyshevFit for the \c double type. + */ +typedef DScalarChebyshevFit ScalarChebyshevFit; + +#ifndef _MSC_VER + +/*! + * \class pcl::F80ScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 80-bit extended precision floating point scalar Chebyshev function + * approximation. + * + * %F80ScalarChebyshevFit is a template instantiation of + * GenericScalarChebyshevFit for the \c long \c double type. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef GenericScalarChebyshevFit F80ScalarChebyshevFit; + +/*! + * \class pcl::LDScalarChebyshevFit + * \ingroup chebyshev_fit_types + * \brief 80-bit extended precision floating point scalar Chebyshev function + * approximation. + * + * %LDScalarChebyshevFit is an alias for F80ScalarChebyshevFit. It is a + * template instantiation of GenericScalarChebyshevFit for the \c long + * \c double type. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef F80ScalarChebyshevFit LDScalarChebyshevFit; + +#endif // !_MSC_VER + +#endif // !__PCL_NO_CHEBYSHEV_FIT_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ChebyshevFit_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ChebyshevFit.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/CheckBox.h b/3rdparty/include/pcl/CheckBox.h new file mode 100644 index 0000000..1287c3c --- /dev/null +++ b/3rdparty/include/pcl/CheckBox.h @@ -0,0 +1,129 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/CheckBox.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_CheckBox_h +#define __PCL_CheckBox_h + +/// \file pcl/CheckBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class CheckBox + * \brief Client-side interface to a PixInsight %CheckBox control + * + * ### TODO: Write a detailed description for %CheckBox + */ +class PCL_CLASS CheckBox : public Button +{ +public: + + /*! + * Constructs a %CheckBox with the specified \a text, as a child control of + * \a parent. + */ + CheckBox( const String& text = String(), Control& parent = Control::Null() ); + + /*! + * Destroys a %CheckBox control. + */ + virtual ~CheckBox() + { + } + + /*! + * Returns \c false, since check boxes are not pushable buttons. + */ + bool IsPushable() const override + { + return false; + } + + /*! + * Returns \c true, since check boxes are checkable buttons. + */ + bool IsCheckable() const override + { + return true; + } + + /*! + * Returns \c true only if this check box can have three states. + */ + bool IsTristateMode() const; + + /*! + * Enables or disables \e tristate \e mode. In tristate mode, a check box + * can have three states: checked, unchecked, and \e semi-checked (also + * called \e third \e state). + */ + void SetTristateMode( bool = true ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_CheckBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/CheckBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Checksum.h b/3rdparty/include/pcl/Checksum.h new file mode 100644 index 0000000..451ed3f --- /dev/null +++ b/3rdparty/include/pcl/Checksum.h @@ -0,0 +1,161 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Checksum.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_Checksum_h +#define __PCL_Checksum_h + +/// \file pcl/Checksum.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup checksum_functions Checksum Calculation Functions + */ + +/*! + * Returns the standard checksum value calculated for a data sequence. + * The returned value is the total number of bits set in the sequence of input + * data bytes. + * + * \param data Address of the first byte in the data sequence. + * \param length Length in bytes of the data sequence. + * + * \ingroup checksum_functions + * \sa Checksum( const C& ) + */ +size_type PCL_FUNC inline Checksum( const void* data, size_type length ) +{ + PCL_PRECONDITION( data != nullptr ) + size_type S = 0; + for ( const uint8* p = (const uint8*)data, * p1 = p+length; p < p1; ++p ) + { + uint8 b = *p; + if ( b & 0x01 ) ++S; + if ( b & 0x02 ) ++S; + if ( b & 0x04 ) ++S; + if ( b & 0x08 ) ++S; + if ( b & 0x10 ) ++S; + if ( b & 0x20 ) ++S; + if ( b & 0x40 ) ++S; + if ( b & 0x80 ) ++S; + } + return S; +} + +/*! + * Returns the standard checksum value for a container. + * + * \param data Reference to a container whose standard checksum will be + * calculated. The checksum number will be generated for the + * current data bytes in this container instance. + * + * \ingroup checksum_functions + * \sa Checksum( const void*, size_type ) + */ +template inline +uint32 Checksum( const C& data ) +{ + return Checksum( data.Begin(), sizeof( *(data.Begin()) )*data.Length() ); +} + +/*! + * Returns the CRC-32 error-detecting code calculated for a data sequence. + * + * \param data Address of the first byte in the data sequence. + * \param length Length in bytes of the data sequence. + * + * \b References + * + * CRC calculation routine based on original code by Michael Barr. The employed + * code requires the following copyright notice: + * + * Copyright (c) 2000 by Michael Barr. This software is placed into the + * public domain and may be used for any purpose. However, this notice must + * not be changed or removed and no warranty is either expressed or implied by + * its publication or distribution. + * + * \ingroup checksum_functions + * \sa CRC32( const C& ) + */ +uint32 PCL_FUNC CRC32( const void* data, size_type length ); + +/*! + * Returns the CRC-32 error-detecting code for a container. + * + * \param data Reference to a container whose CRC-32 checksum will be + * calculated. The checksum code will be generated for the + * current data bytes in this container instance. + * + * \ingroup checksum_functions + * \sa CRC32( const void*, size_type ) + */ +template inline +uint32 CRC32( const C& data ) +{ + return CRC32( data.Begin(), sizeof( *(data.Begin()) )*data.Length() ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Checksum_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Checksum.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/CodeEditor.h b/3rdparty/include/pcl/CodeEditor.h new file mode 100644 index 0000000..d44dc29 --- /dev/null +++ b/3rdparty/include/pcl/CodeEditor.h @@ -0,0 +1,894 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/CodeEditor.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_CodeEditor_h +#define __PCL_CodeEditor_h + +/// \file pcl/CodeEditor.h + +#include + +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FindMode + * \brief Flags to control text find and replacement operations. + * + * + * + * + * + * + * + * + * + *
FindMode::RegExp Search with a regular expression instead of a literal substring.
FindMode::Backward Search toward the beginning of the document.
FindMode::CaseSensitive Perform a case-sensitive search.
FindMode::WholeWords Search for whole words only.
FindMode::SelectionOnly Search and replace within the current text selection only
FindMode::Incremental Perform an incremental text find operation. The search begins after a previously matched text block.
FindMode::Default The default text find mode, equal to FindMode::CaseSensitive|FindMode::WholeWords.
+ */ +namespace FindMode +{ + enum mask_type + { + RegExp = 0x00000001, // Search with a regular expression + Backward = 0x00000010, // Search toward the beginning of text + CaseSensitive = 0x00000020, // Case-sensitive search + WholeWords = 0x00000040, // Search for whole words + SelectionOnly = 0x00000100, // Replace within the current selection + Incremental = 0x00000200, // Perform an incremental find operation + Default = CaseSensitive|WholeWords + }; +} + +/*! + * A combination of text find and replacement mode flags. + */ +typedef Flags FindModes; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class CodeEditor + * \brief Client-side interface to a PixInsight %CodeEditor control. + * + * ### TODO: Write a detailed description for %CodeEditor. + */ +class PCL_CLASS CodeEditor : public Control +{ +public: + + /*! + * Constructs a %CodeEditor control. + * + * \param parent The parent control of this object. The default value is + * a null control. + */ + CodeEditor( Control& parent = Control::Null() ); + + /*! + * Destroys a %CodeEditor control. + */ + virtual ~CodeEditor() + { + } + + /*! + * Returns a reference to a line numbers control for this code + * editor. + * + * A line numbers control provides a visual index of the text lines + * currently displayed by a code editor. Typically, a code editor and its + * line numbers control are packed side by side in a HorizontalSizer. + */ + Control& LineNumbersControl(); + + /*! + * Returns the absolute file path associated with this code editor, or an + * empty string if this object has not been associated with a file. + */ + String FilePath() const; + + /*! + * Sets the file path associated with this code editor. + * + * If the specified \a path includes a file name suffix (also known as file + * name \e extension), the control will use it to identify a programming + * language to perform automatic syntax highlighting of the text in the + * editor. Currently the following file suffixes and source code languages + * are supported: + * + * + * + * + * + * + * + * + * + *
.js .jsh JavaScript source files
.scp Command-line script files
.cpp .h .cxx .hpp .hxx .c .cc C/C++ source files
.py Python source files
.xml .xhtml .html .xosm .xpsm (among others) XML source files
.pidoc PixInsight documentation source files
.pm .pmath PixelMath source files
+ * + * Unrecognized (or absent) file suffixes effectively disable the automatic + * syntax highlighting feature. The default value of this parameter is an + * empty string. + */ + void SetFilePath( const String& path ); + + /*! + * Returns the current text in this code editor in UTF-16 format. + */ + String Text() const; + + /*! + * Sets the current text in this code editor in UTF-16 format. + */ + void SetText( const String& text ); + + /*! + * Returns an encoded 8-bit representation of the text in this code editor. + * + * \param encoding The desired text encoding. Currently only the "UTF-8" + * and "ISO-8859-1" encodings are supported. The default + * value is "UTF-8". + */ + IsoString EncodedText( const IsoString& encoding = "UTF-8" ) const; + + /*! + * Returns the text in this code editor encoded in UTF-8 format. + * + * This is a convenience function, equivalent to: + * + * \code EncodedText( "UTF-8" ); \endcode + */ + IsoString TextUTF8() const + { + return EncodedText( "UTF-8" ); + } + + /*! + * Returns the text in this code editor encoded in ISO 8859-1 format. + * + * This is a convenience function, equivalent to: + * + * \code EncodedText( "ISO-8859-1" ); \endcode + */ + IsoString TextISO88591() const + { + return EncodedText( "ISO-8859-1" ); + } + + /*! + * Sets the current text in this code editor, encoded in an 8-bit format. + * + * \param text The encoded 8-bit text. + * + * \param encoding The text encoding. Currently only the "UTF-8" and + * "ISO-8859-1" encodings are supported. The default value + * is "UTF-8". + */ + void SetEncodedText( const IsoString& text, const IsoString& encoding = "UTF-8" ); + + /*! + * Sets the current text in this code editor, encoded in UTF-8 format. + * + * This is a convenience function, equivalent to: + * + * \code SetEncodedText( text, "UTF-8" ); \endcode + */ + void SetTextUTF8( const IsoString& text ) + { + SetEncodedText( text, "UTF-8" ); + } + + /*! + * Sets the current text in this code editor, encoded in ISO 8859-1 format. + * + * This is a convenience function, equivalent to: + * + * \code SetEncodedText( text, "ISO-8859-1" ); \endcode + */ + void SetTextISO88591( const IsoString& text ) + { + SetEncodedText( text, "ISO-8859-1" ); + } + + /*! + * Clears all the text in this code editor. Also clears all undo/redo + * buffers, so this action is irreversible. + */ + void ClearText(); + + /*! + * Returns true iff this code editor is in read-only mode. A + * read-only editor does not allow any command that can modify its text + * contents as a result of a direct user interaction. The text can only be + * changed programmatically for a read-only code editor. + */ + bool IsReadOnly() const; + + /*! + * Enables the read-only mode for this code editor. A read-only editor does + * not allow any command that can modify its text contents as a result of a + * direct user interaction. The text can only be changed programmatically + * for a read-only code editor. + * + * \param readOnly Whether to enable or disable the read-only mode for + * this code editor. + */ + void SetReadOnly( bool readOnly = true ); + + /*! + * Writes the text in this code editor to the specified file, encoded in an + * 8-bit format. + * + * \param filePath Path to the destination file. + * + * \param encoding The desired text encoding. Currently only the "UTF-8" + * and "ISO-8859-1" encodings are supported. The default + * value is "UTF-8". + * + * Returns true if the file was successfully written; false in the event of + * error. + * + * \warning Upon successful completion, this function will overwrite an + * existing file at the specified path, whose previous contents will be + * lost. + */ + bool Save( const String& filePath, const IsoString& encoding = "UTF-8" ); + + /*! + * Writes the text in this code editor to the specified file, encoded in + * UTF-8 format. + * + * This is a convenience function, equivalent to: + * + * \code Save( filePath, "UTF-8" ); \endcode + */ + bool SaveUTF8( const String& filePath ) + { + return Save( filePath, "UTF-8" ); + } + + /*! + * Writes the text in this code editor to the specified file, encoded in + * ISO 8859-1 format. + * + * This is a convenience function, equivalent to: + * + * \code Save( filePath, "ISO-8859-1" ); \endcode + */ + bool SaveISO88591( const String& filePath ) + { + return Save( filePath, "ISO-8859-1" ); + } + + /*! + * Reads an encoded 8-bit text file and loads it in this code editor. + * + * \param filePath Path to the source file. + * + * \param encoding The text encoding. Currently only the "UTF-8" and + * "ISO-8859-1" encodings are supported. The default + * value is "UTF-8". + * + * Returns true if the file was successfully read; false in the event of + * error. + */ + bool Load( const String& filePath, const IsoString& encoding = "UTF-8" ); + + /*! + * Reads a text file encoded in UTF-8 format, and loads it in this code + * editor. + * + * This is a convenience function, equivalent to: + * + * \code Load( filePath, "UTF-8" ); \endcode + */ + bool LoadUTF8( const String& filePath ) + { + return Load( filePath, "UTF-8" ); + } + + /*! + * Reads a text file encoded in ISO 8859-1 format, and loads it in this code + * editor. + * + * This is a convenience function, equivalent to: + * + * \code Load( filePath, "ISO-8859-1" ); \endcode + */ + bool LoadISO88591( const String& filePath ) + { + return Load( filePath, "ISO-8859-1" ); + } + + /*! + * Returns the number of text lines (including empty lines) in this code + * editor. + */ + int NumberOfLines() const; + + /*! + * Returns the total number of characters in the current text of this code + * editor. + */ + int NumberOfCharacters() const; + + /*! + * Returns the current cursor position in visual coordinates. The returned + * object stores the current line and column of the cursor in its Point::y + * and Point::x public data members, respectively. + * + * Line and column coordinates are counted from zero. Line numbers range + * from zero to the number of existing text lines minus one. There is no + * specific limit for the number of text characters in a text line. + */ + Point CursorPosition() const; + + /*! + * Returns the line number of the current cursor position. + */ + int CursorLine() const + { + return CursorPosition().y; + } + + /*! + * Returns the column number of the current cursor position. + */ + int CursorColumn() const + { + return CursorPosition().x; + } + + /*! + * Sets the current cursor position in this code editor to the specified + * \a line and \a column. See CursorPosition() for more information on + * visual text coordinates. + */ + void SetCursorPosition( int line, int column ); + + /*! + * Sets the current cursor position in this code editor through the + * coordinates of a Point object. The new cursor line will be set to + * \a pos.y and the new cursor column to \a pos.x, respectively. + */ + void SetCursorPosition( const Point& pos ) + { + SetCursorPosition( pos.y, pos.x ); + } + + /*! + * Returns true iff this code editor is in insert text mode. Returns + * false if the editor is in replace text mode. + * + * In insert mode, newly generated text by direct user interaction is + * inserted at the current cursor location. In replace mode, newly generated + * text replaces existing characters starting at the current cursor + * location. The insert text mode is always enabled by default. + */ + bool IsInsertMode() const; + + /*! + * Enables the insert text mode for this code editor. + * + * \param insert Whether to enable the insert text mode (if true) or the + * replace text mode (if false). The default value is true. + */ + void SetInsertMode( bool insert = true ); + + /*! + * Enables the replace text mode for this code editor. + * + * \param replace Whether to enable the replace text mode (if true) or the + * insert text mode (if false). The default value is true. + */ + void SetReplaceMode( bool replace = true ) + { + SetInsertMode( !replace ); + } + + /*! + * Returns true iff this code editor is in block selection mode; + * false if it is in line selection mode. + * + * In block selection mode, the user can select rectangular areas of text + * across multiple text lines. In line selection mode, text + * selections can only include entire text lines except for the first and + * last lines in a selection. The line selection mode is always enabled by + * default. + */ + bool IsBlockSelectionMode() const; + + /*! + * Enables the block selection mode for this code editor. + * + * \param blockMode Whether to enable the block selection mode (if true) or + * the line selection mode (if false). The default value + * is true. + */ + void SetBlockSelectionMode( bool blockMode = true ); + + /*! + * Enables the line selection mode for this code editor. + * + * \param lineMode Whether to enable the line selection mode (if true) or + * the block selection mode (if false). The default value + * is true. + */ + void SetLineSelectionMode( bool lineMode = true ) + { + SetBlockSelectionMode( !lineMode ); + } + + /*! + * Returns true iff this code editor is in dynamic word wrap mode. + * + * In dynamic word wrap mode, long text lines extending beyond the visible + * width of the editor's viewport are automatically truncated and continued + * on successive editor lines, so that the user can always see the entire + * contents of all text lines, and a horizontal scroll bar is never shown. + * + * When the dynamic word wrap mode is disabled, long text lines are never + * truncated and the editor shows a horizontal scroll bar when necessary. + * The dynamic word wrap mode is always disabled by default. + */ + bool IsDynamicWordWrapMode() const; + + /*! + * Enables the dynamic word wrap mode for this code editor. + * + * \param wrapMode Whether to enable the dynamic word wrap mode. + */ + void SetDynamicWordWrapMode( bool wrapMode = true ); + + /*! + * Returns the number of \e undo steps available for this code editor. + */ + int UndoSteps() const; + + /*! + * Returns the number of \e redo steps available for this code editor. + */ + int RedoSteps() const; + + /*! + * Returns true iff this code editor has a text selection defined. + */ + bool HasSelection() const; + + /*! + * Returns the visual coordinates of the current selection in this code + * editor. The selection coordinates are stored in the returned rectangle as + * follows: + * + * \li Rect::y0 - Starting line of the current text selection. + * \li Rect::x0 - Starting column of the current text selection. + * \li Rect::y1 - Ending line of the current text selection. + * \li Rect::x1 - Ending column of the current text selection. + */ + Rect Selection() const; + + /*! + * Sets a new text selection defined by its visual coordinates. + * + * \param fromLine Starting line of the new text selection. + * \param fromCol Starting column of the new text selection. + * \param toLine Ending line of the new text selection. + * \param toCol Ending column of the new text selection. + */ + void SetSelection( int fromLine, int fromCol, int toLine, int toCol ); + + /*! + * Sets a new text selection defined by its visual coordinates. + * + * This is a convenience function, equivalent to: + * + * \code SetSelection( r.y0, r.x0, r.y1, r.x1 ); \endcode + */ + void SetSelection( const Rect& r ) + { + SetSelection( r.y0, r.x0, r.y1, r.x1 ); + } + + /*! + * Returns the currently selected text in this code editor, or an empty + * string if this editor has no selection currently defined. + */ + String SelectedText() const; + + /*! + * Inserts the specified \a text at the current cursor location. + * + * If there is a selection defined, the selected text is replaced with the + * inserted \a text. + */ + void InsertText( const String& text ); + + /*! + * Undoes the last editor action. If no action can be undone, this function + * has no effect. + */ + void Undo(); + + /*! + * Redoes the last editor action. If no action can be redone, this function + * has no effect. + */ + void Redo(); + + /*! + * Copies the current text selection to the clipboard and removes the + * selected text. If no selection is defined, this function has no effect. + */ + void Cut(); + + /*! + * Copies the current text selection to the clipboard. If no selection is + * defined, this function has no effect. + */ + void Copy(); + + /*! + * Inserts the contents of the clipboard at the current cursor location. If + * the clipboard is empty, or if its contents cannot be converted to plain + * text, this function has no effect. + */ + void Paste(); + + /*! + * Removes the currently selected text. If there is no text selection + * defined, this function has no effect. + */ + void Delete(); + + /*! + * Selects all the text in this code editor. + */ + void SelectAll(); + + /*! + * Clears the current text selection, if any. This function simply unselects + * the text; it does not remove the selected text. + */ + void Unselect(); + + /*! + * If the cursor points to a bracket or parenthesis character, look for a + * matching pair and move the cursor to the corresponding location. + * + * Returns true iff a matching pair could be found. If there is no bracket or + * parenthesis at the current cursor location, or if a matched pair couldn't + * be found, this function returns false and the cursor is not moved. + */ + bool GotoMatchedParenthesis(); + + /*! + * Highlights all occurrences of a literal text string or a regular + * expression. + * + * \param toFind The text or regular expression to search for, depending on + * the specified \a mode flags. + * + * \param mode An OR'ed combination of flags to control the text find + * operation. Valid flags are enumerated in the pcl::FindMode + * namespace. + * + * The operation takes place on the whole text document, ignoring the + * FindMode::Backward and FindMode::SelectionOnly flags. Returns the number + * of matches found. + */ + int HighlightAllMatches( const String& toFind, FindModes mode ); + + /*! + * Clears all text highlightings. This function does not remove the + * highlighted text; it simply clears the visual highlight indications. + */ + void ClearMatches(); + + /*! + * Finds an occurrence of a literal text string or a regular expression. + * + * \param toFind The text or regular expression to search for, depending on + * the specified \a mode flags. + * + * \param mode An OR'ed combination of flags to control the text find + * operation. Valid flags are enumerated in the pcl::FindMode + * namespace. + * + * Returns true iff a match was found. + */ + bool Find( const String& toFind, FindModes mode ); + + /*! + * Replaces the current selection with the specified text. + * + * \param replaceWith The text that will replace the current selection. + * Can be an empty string (to delete the current + * selection). + * + * If there is some text selected in this editor, this function returns + * true after performing the replacement operation. If there is no text + * currently selected, this function is ignored and false is returned. + */ + bool ReplaceSelection( const String& replaceWith ); + + /*! + * Replaces all occurrences of a literal text string or a regular + * expression with the specified text. + * + * \param toFind The text or regular expression to search for, depending on + * the specified \a mode flags. + * + * \param replaceWith The text that will replace all matches found. Can be + * an empty string (to delete all matched occurrences). + * + * \param mode An OR'ed combination of flags to control the text find and + * replace operation. Valid flags are enumerated in the + * pcl::FindMode namespace. + * + * Returns the number of matches found and replaced. + * + */ + int ReplaceAll( const String& toFind, const String& replaceWith, FindModes mode ); + + /*! + * \defgroup code_editor_event_handlers CodeEditor Event Handlers + */ + + /*! + * Defines the prototype of an editor event handler. + * + * An editor event is generated when a %CodeEditor instance changes its + * state or contents due to direct user interaction. + * + * \param sender The control that sends an editor event. + * + * \ingroup code_editor_event_handlers + */ + typedef void (Control::*editor_event_handler)( CodeEditor& sender ); + + /*! + * Defines the prototype of a cursor event handler. + * + * A cursor event is generated when the cursor position changes in a + * %CodeEditor instance due to direct user interaction. + * + * \param sender The control that sends a cursor event. + * + * \param line Line number of the new cursor position (>= 0). + * + * \param col Column number of the new cursor position (>= 0). + * + * \ingroup code_editor_event_handlers + */ + typedef void (Control::*cursor_event_handler)( CodeEditor& sender, int line, int col ); + + /*! + * Defines the prototype of a selection event handler. + * + * A selection event is generated when the text selection changes in a + * %CodeEditor instance due to direct user interaction. + * + * \param sender The control that sends a selection event. + * + * \param fromLine Line number of the starting position of the new text + * selection. + * + * \param fromCol Column number of the starting position of the new text + * selection. + * + * \param toLine Line number of the ending position of the new text + * selection. + * + * \param toCol Column number of the ending position of the new text + * selection. + * + * \ingroup code_editor_event_handlers + */ + typedef void (Control::*selection_event_handler)( CodeEditor& sender, int fromLine, int fromCol, int toLine, int toCol ); + + /*! + * Defines the prototype of a state event handler. + * + * A state event is generated when a Boolean property changes in a + * %CodeEditor instance due to direct user interaction. + * + * \param sender The control that sends a cursor event. + * + * \param state New property state. + * + * \ingroup code_editor_event_handlers + */ + typedef void (Control::*state_event_handler)( CodeEditor& sender, bool state ); + + /*! + * Sets the handler for text updated events generated by this code + * editor. A text updated event is generated each time the text changes in + * this editor as a result of a direct user interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive text updated events from + * this code editor. + * + * \ingroup code_editor_event_handlers + */ + void OnTextUpdated( editor_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for cursor position updated events generated by + * this code editor. A cursor position updated event is generated each time + * the text cursor (also known as \e caret) moves in this editor as a result + * of a direct user interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive cursor position updated + * events from this code editor. + * + * \ingroup code_editor_event_handlers + */ + void OnCursorPositionUpdated( cursor_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for selection updated events generated by this + * code editor. A selection updated event is generated each time the text + * selection is changed in this editor as a result of a direct user + * interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive selection updated events + * from this code editor. + * + * \ingroup code_editor_event_handlers + */ + void OnSelectionUpdated( selection_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for overwrite mode updated events generated by + * this code editor. An overwrite mode updated event is generated each time + * the overwrite mode is enabled or disabled in this editor (i.e., from + * overwrite mode to replace mode or vice-versa) as a result of a direct + * user interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive overwrite mode updated + * events from this code editor. + * + * \ingroup code_editor_event_handlers + */ + void OnOverwriteModeUpdated( state_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for selection mode updated events generated by + * this code editor. A selection mode updated event is generated each time + * the selection mode is changed in this editor (i.e., from line selection + * mode to block selection mode or vice-versa) as a result of a direct user + * interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive selection mode updated + * events from this code editor. + * + * \ingroup code_editor_event_handlers + */ + void OnSelectionModeUpdated( state_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for dynamic word wrap mode updated events + * generated by this code editor. A dynamic word wrap mode updated event is + * generated each time the dynamic word wrap mode is enabled or disabled in + * this editor as a result of a direct user interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive dynamic word wrap mode + * updated events from this code editor. + * + * \ingroup code_editor_event_handlers + */ + void OnDynamicWordWrapModeUpdated( state_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + editor_event_handler onTextUpdated = nullptr; + cursor_event_handler onCursorPositionUpdated = nullptr; + selection_event_handler onSelectionUpdated = nullptr; + state_event_handler onOverwriteModeUpdated = nullptr; + state_event_handler onSelectionModeUpdated = nullptr; + state_event_handler onDynamicWordWrapModeUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + Control m_lineNumbers; + + friend class CodeEditorEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_CodeEditor_h + +// ---------------------------------------------------------------------------- +// EOF pcl/CodeEditor.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Color.h b/3rdparty/include/pcl/Color.h new file mode 100644 index 0000000..bd7f510 --- /dev/null +++ b/3rdparty/include/pcl/Color.h @@ -0,0 +1,412 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Color.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_Color_h +#define __PCL_Color_h + +/// \file pcl/Color.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup rgba_utility_functions RGBA Color Utility Functions + */ + +/*! + * Defines a 32-bit RGBA pixel value. + * + * A %RGBA pixel value is encoded as follows: + * + * AARRGGBB + * + * where each letter represents a 4-bit hexadecimal digit (from 0 to F). Each + * 8-bit pair represents a pixel component in the range from 0 to 255: + * + * + * + * + * + * + *
AA Alpha value, or pixel transparency: + * 0 means completely transparent, 255 corresponds to an + * opaque pixel.
RR Red pixel color component.
GG Green pixel color component.
BB Blue pixel color component.
+ * + * \ingroup rgba_utility_functions + */ +typedef uint32 RGBA; + +/*! + * Returns the alpha (transparency) component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline uint8 Alpha( RGBA rgba ) +{ + return uint8( rgba >> 24 ); +} + +/*! + * Returns the red color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline uint8 Red( RGBA rgba ) +{ + return uint8( rgba >> 16 ); +} + +/*! + * Returns the green color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline uint8 Green( RGBA rgba ) +{ + return uint8( rgba >> 8 ); +} + +/*! + * Returns the blue color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline uint8 Blue( RGBA rgba ) +{ + return uint8( rgba ); +} + +/*! + * Clears (sets to zero) the alpha (transparency) component of an RGBA pixel + * value. + * + * \ingroup rgba_utility_functions + */ +inline void ClearAlpha( RGBA& rgba ) +{ + rgba &= 0x00fffffful; +} + +/*! + * Clears (sets to zero) the red color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void ClearRed( RGBA& rgba ) +{ + rgba &= 0xff00fffful; +} + +/*! + * Clears (sets to zero) the green color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void ClearGreen( RGBA& rgba ) +{ + rgba &= 0xffff00fful; +} + +/*! + * Clears (sets to zero) the blue color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void ClearBlue( RGBA& rgba ) +{ + rgba &= 0xffffff00ul; +} + +/*! + * Sets the alpha (transparency) component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void SetAlpha( RGBA& rgba, uint8 a ) +{ + ClearAlpha( rgba ); rgba |= uint32( a ) << 24; +} + +/*! + * Sets the red color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void SetRed( RGBA& rgba, uint8 r ) +{ + ClearRed( rgba ); rgba |= uint32( r ) << 16; +} + +/*! + * Sets the green color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void SetGreen( RGBA& rgba, uint8 g ) +{ + ClearGreen( rgba ); rgba |= uint32( g ) << 8; +} + +/*! + * Sets the blue color component of an RGBA pixel value. + * + * \ingroup rgba_utility_functions + */ +inline void SetBlue( RGBA& rgba, uint8 b ) +{ + ClearBlue( rgba ); rgba |= uint32( b ); +} + +/*! + * Returns an RGBA pixel value for the specified separate alpha and color + * component integer values. + * + * \param r Red color component + * \param g Green color component + * \param b Blue color component + * \param a Alpha (transparency) + * + * All components must be in the range [0,255]. + * + * \ingroup rgba_utility_functions + */ +inline RGBA RGBAColor( int r, int g, int b, int a ) +{ + return (uint32( a ) << 24) | (uint32( r ) << 16) | (uint32( g ) << 8) | uint32( b ); +} + +/*! + * Returns an opaque RGBA pixel value for the specified separate color + * component integer values. + * + * \param r Red color component + * \param g Green color component + * \param b Blue color component + * + * All components must be in the range [0,255]. The returned RGBA value has its + * alpha component equal to 255 (opaque). + * + * \ingroup rgba_utility_functions + */ +inline RGBA RGBAColor( int r, int g, int b ) +{ + return 0xff000000ul | (uint32( r ) << 16) | (uint32( g ) << 8) | uint32( b ); +} + +/*! + * Returns an RGBA pixel value for the specified separate alpha and color + * component real values. + * + * \param r Red color component + * \param g Green color component + * \param b Blue color component + * \param a Alpha (transparency) + * + * All components must be in the normalized range [0,1]. + * + * \ingroup rgba_utility_functions + */ +inline RGBA RGBAColor( double r, double g, double b, double a ) +{ + return RGBAColor( RoundInt( 255*r ), RoundInt( 255*g ), RoundInt( 255*b ), RoundInt( 255*a ) ); +} + +/*! + * Returns an RGBA pixel value for the specified separate alpha and color + * component real values. + * + * \param r Red color component + * \param g Green color component + * \param b Blue color component + * \param a Alpha (transparency) + * + * All components must be in the normalized range [0,1]. + * + * \ingroup rgba_utility_functions + */ +inline RGBA RGBAColor( float r, float g, float b, float a ) +{ + return RGBAColor( double( r ), double( g ), double( b ), double( a ) ); +} + +/*! + * Returns an opaque RGBA pixel value for the specified separate color + * component real values. + * + * \param r Red color component + * \param g Green color component + * \param b Blue color component + * + * All components must be in the normalized range [0,1]. The returned RGBA + * value has its alpha component equal to 255 (opaque). + * + * \ingroup rgba_utility_functions + */ +inline RGBA RGBAColor( double r, double g, double b ) +{ + return RGBAColor( RoundInt( 255*r ), RoundInt( 255*g ), RoundInt( 255*b ) ); +} + +/*! + * Returns an opaque RGBA pixel value for the specified separate color + * component real values. + * + * \param r Red color component + * \param g Green color component + * \param b Blue color component + * + * All components must be in the normalized range [0,1]. The returned RGBA + * value has its alpha component equal to 255 (opaque). + * + * \ingroup rgba_utility_functions + */ +inline RGBA RGBAColor( float r, float g, float b ) +{ + return RGBAColor( double( r ), double( g ), double( b ) ); +} + +/*! + * Returns an RGBA pixel value corresponding to a CSS color specification + * string. + * + * The string can be an hex-encoded color value in one of two valid formats: + * + * "#RRGGBB" + * "#RRGGBBAA" + * + * or a valid CSS color name like "white", "black", "red", "orange", and so on. + * + * CSS color names are case-insensitive, and are returned with their alpha + * components equal to 0xFF (opaque), except "transparent", which is returned + * as 0x00000000 (also known as "transparent black"). + * + * If the string cannot be converted to a valid color value, this function + * silently ignores the error and returns zero. + * + * \ingroup rgba_utility_functions + */ +RGBA PCL_FUNC RGBAColor( const IsoString& colorNameOrHex ); + +inline RGBA RGBAColor( const IsoString::ustring_base& colorNameOrHex ) +{ + return RGBAColor( IsoString( colorNameOrHex ) ); +} + +/*! + * An alias to RGBAColor( const IsoString& ). + * + * \ingroup rgba_utility_functions + */ +inline RGBA StringToRGBAColor( const IsoString& colorNameOrHex ) +{ + return RGBAColor( colorNameOrHex ); +} + +inline RGBA StringToRGBAColor( const IsoString::ustring_base& colorNameOrHex ) +{ + return StringToRGBAColor( IsoString( colorNameOrHex ) ); +} + +/*! + * Returns an hex-encoded string representation of an RGBA pixel value, + * ignoring the alpha component. + * + * The returned string has the format "#RRGGBB". + * + * \ingroup rgba_utility_functions + */ +inline IsoString RGBColorToHexString( RGBA c ) +{ + IsoString s; + s.Format( "#%02X%02X%02X", Red( c ), Green( c ), Blue( c ) ); + return s; +} + +/*! + * Returns an hex-encoded string representation of an RGBA pixel value. + * + * The returned string has the format "#RRGGBBAA". + * + * \ingroup rgba_utility_functions + */ +inline IsoString RGBAColorToHexString( RGBA c ) +{ + IsoString s; + s.Format( "#%02X%02X%02X%02X", Red( c ), Green( c ), Blue( c ), Alpha( c ) ); + return s; +} + +/*! + * Returns the CSS color name corresponding to an RGBA pixel value. + * + * The alpha component is ignored, except for the special value 0x00000000, + * which is returned as "Transparent". If the value does not have a CSS named + * color counterpart, this function returns an empty string. + * + * \ingroup rgba_utility_functions + */ +IsoString PCL_FUNC CSSColorName( RGBA ); + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Color_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Color.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ColorComboBox.h b/3rdparty/include/pcl/ColorComboBox.h new file mode 100644 index 0000000..f10e15c --- /dev/null +++ b/3rdparty/include/pcl/ColorComboBox.h @@ -0,0 +1,269 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ColorComboBox.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_ColorComboBox_h +#define __PCL_ColorComboBox_h + +/// \file pcl/ColorComboBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ColorComboBox + * \brief A %ComboBox descendant class to select RGB colors. + * + * %ColorComboBox is a utility class that provides a simple list with the full + * set of CSS3 standard colors. This includes 143 %ComboBox items that are + * automatically shared by all existing %ColorComboBox instances. Thanks to + * this implicit sharing mechanism, a module can define a large number of + * %ColorComboBox controls without consuming too much resources on any + * supported platform. + * + * The list of items corresponding to CSS3 colors is sorted by \e hue value (in + * the HSV or HSI color ordering systems). This makes it much easier the task + * of selecting colors since similar hues are grouped visually. + * + * In addition to CSS3 standard colors, a single custom color item can be + * defined for a %ColorComboBox object. The custom color item is automatically + * managed by %ColorComboBox and appended to the end of standard items. + * + * \sa pcl/Color.h, ComboBox + */ +class PCL_CLASS ColorComboBox : public ComboBox +{ +public: + + /*! + * Constructs a %ColorComboBox as a child control of \a parent. + * + * A standard set of %ComboBox items is created for the full set of CSS3 + * colors. This includes 143 color items. + */ + ColorComboBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %ColorComboBox control. + */ + virtual ~ColorComboBox() + { + } + + /*! + * Returns the RGB color value that corresponds to the currently selected + * %ComboBox item, or zero if no item is currently selected. + * + * \sa SetCurrentColor(), CustomColor(), HasCustomColor() + */ + RGBA CurrentColor() const; + + /*! + * Selects a %ComboBox item corresponding to the specified \a color. + * + * If the specified \a color doesn't correspond to a standard CSS color, it + * replaces the existing custom color item in this %ColorComboBox, + * or a new one is created if there is no custom color item yet. + * + * \note The alpha (transparency) component of the specified \a color is + * always ignored. %ColorComboBox only includes opaque colors (alpha=0xff). + * + * \sa CurrentColor(), CustomColor(), HasCustomColor() + */ + void SetCurrentColor( RGBA color ); + + /*! + * Returns the current custom color in this %ColorComboBox, or zero + * if no custom color has been defined. + * + * To set a new custom color, call SetCurrentColor() with the desired custom + * color value. + * + * \sa HasCustomColor(), CurrentColor(), SetCurrentColor() + */ + RGBA CustomColor() const + { + return m_customColor; + } + + /*! + * Returns true iff a custom color item has been defined in this + * %ColorComboBox control. + * + * This is a convenience member function, equivalent to: + * CustomColor() != 0. + * + * \sa CustomColor(), CurrentColor(), SetCurrentColor() + */ + bool HasCustomColor() const + { + return CustomColor() != 0; + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnColorSelected( ColorComboBox& sender, RGBA color ); + // void OnColorHighlighted( ColorComboBox& sender, RGBA color ); + // void OnCustomColorDefined( ColorComboBox& sender, RGBA color ); + + /*! + * \defgroup colorcombobox_event_handlers ColorComboBox Event Handlers + */ + + /*! + * Defines the prototype of a color combo box event handler. + * + * A color combo box event is generated when an item is selected or + * highlighted in a color combo box, or when a new custom color has + * been defined. + * + * \param sender The %ColorComboBox control that sends a color combo box + * event. + * + * \param color The RGBA value of the color that has been selected or + * highlighted in the \a sender color combo box. + * + * \ingroup colorcombobox_event_handlers + */ + typedef void (Control::*color_event_handler)( ColorComboBox& sender, RGBA color ); + + /*! + * Sets the color selected event handler for this color combo box. + * + * \param handler The color combo box event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever a color is selected in this + * color combo box control. + * + * \param receiver The control that will receive color selected + * events from this color combo box. + * + * \ingroup colorcombobox_event_handlers + */ + void OnColorSelected( color_event_handler handler, Control& receiver ); + + /*! + * Sets the color highlighted event handler for this color combo + * box control. + * + * \param handler The color combo box event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever a color is highlighted in this + * color combo box control. + * + * \param receiver The control that will receive color + * highlighted events from this color combo box. + * + * \ingroup colorcombobox_event_handlers + */ + void OnColorHighlighted( color_event_handler handler, Control& receiver ); + + /*! + * Sets the custom color defined event handler for this color combo + * box control. + * + * \param handler The color combo box event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever a new custom color is defined + * in this color combo box control. + * + * \param receiver The control that will receive custom color + * defined events from this color combo box. + * + * \ingroup colorcombobox_event_handlers + */ + void OnCustomColorDefined( color_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + color_event_handler onColorSelected = nullptr; + Control* onColorSelectedReceiver = nullptr; + + color_event_handler onColorHighlighted = nullptr; + Control* onColorHighlightedReceiver = nullptr; + + color_event_handler onCustomColorDefined = nullptr; + Control* onCustomColorDefinedReceiver = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + RGBA m_customColor; + + void ItemSelected( ComboBox&, int ); + void ItemHighlighted( ComboBox&, int ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ColorComboBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ColorComboBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ColorDialog.h b/3rdparty/include/pcl/ColorDialog.h new file mode 100644 index 0000000..6d3ab2b --- /dev/null +++ b/3rdparty/include/pcl/ColorDialog.h @@ -0,0 +1,196 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ColorDialog.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_ColorDialog_h +#define __PCL_ColorDialog_h + +/// \file pcl/ColorDialog.h + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * ### TODO: Implement a fully-functional color dialog box in PCL. + */ + +// ---------------------------------------------------------------------------- + +class PCL_INTERNAL SimpleColorDialogPrivate; + +/*! + * \class SimpleColorDialog + * \brief A simple color selection dialog + * + * %SimpleColorDialog is a simplified color selection dialog box. This class is + * suitable to implement quick definition of 32-bit RGBA color items as part of + * a user preferences definition interface. It implements optional support for + * an alpha (transparency) component. Color components are specified in the + * eight-bit range [0,255]. + * + * \sa Dialog + */ +class PCL_CLASS SimpleColorDialog : public Dialog +{ +public: + + enum + { + AlphaEnabled = 0x0080, //!< Enable definition of the alpha (transparency) component. + Grayscale = 0x0020 //!< Define a grayscale AARRGGBB color, where RR=GG=BB. + }; + + /*! + * Constructs a %SimpleColorDialog object. + * + * \param color Address of a 32-bit unsigned integer variable (a RGBA + * color value). If a non-null pointer is specified, when the + * user accepts the dialog the selected color value will be + * written to the specified variable. + * + * \param flags A combination of flags that define the behavior of the + * color selection dialog. Currently the following flags are + * supported:\n + * \n + * SimpleColorDialog::AlphaEnabled: Enable definition of the + * alpha (transparency) component\n + * \n + * SimpleColorDialog::Grayscale: Define a grayscale AARRGGBB + * color, where RR=GG=BB. + */ + SimpleColorDialog( RGBA* color = nullptr, uint32 flags = 0 ); + + /*! + * Destroys a %SimpleColorDialog object. + */ + virtual ~SimpleColorDialog() + { + } + + /*! + * Sets the current RGBA color value. + * + * This function can be called before executing the dialog to set an initial + * color value, as an alternative to passing a non-null pointer to the + * constructor. + */ + void SetColor( RGBA color ); + + /*! + * Returns the RGBA color value that has been defined by the user. + * + * If a non-null pointer was passed to the constructor, this function + * returns the same color value that will be (or has been) written to the + * corresponding variable. + */ + RGBA Color() const + { + return m_workingColor; + } + + /*! + * Returns true iff this dialog allows definition of an alpha (transparency) + * color component. + */ + bool IsAlphaEnabled() const + { + return (m_flags & AlphaEnabled) != 0; + } + + /*! + * Returns true iff this dialog defines a grayscale color, where the three + * individual RGB components are equal. + */ + bool IsGrayscale() const + { + return (m_flags & Grayscale) != 0; + } + +protected: + + RGBA* m_color; + RGBA m_workingColor; + uint32 m_flags; + + VerticalSizer Global_Sizer; + HorizontalSizer Color_Sizer; + VerticalSizer Sliders_Sizer; + NumericControl V0_NumericControl; + NumericControl V1_NumericControl; + NumericControl V2_NumericControl; + NumericControl V3_NumericControl; + Control ColorSample_Control; + HorizontalSizer Buttons_Sizer; + PushButton OK_PushButton; + PushButton Cancel_PushButton; + + void Color_ValueUpdated( NumericEdit& sender, double value ); + void ColorSample_Paint( Control& sender, const Rect& updateRect ); + void Done_Click( Button& sender, bool checked ); + void Dialog_Return( Dialog& sender, int retVal ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ColorDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ColorDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ColorFilterArray.h b/3rdparty/include/pcl/ColorFilterArray.h new file mode 100644 index 0000000..c3a8957 --- /dev/null +++ b/3rdparty/include/pcl/ColorFilterArray.h @@ -0,0 +1,348 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ColorFilterArray.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_ColorFilterArray_h +#define __PCL_ColorFilterArray_h + +/// \file pcl/ColorFilterArray.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup cfa_classes Color Filter Array (CFA) Descriptive Classes + */ + +/*! + * \class ColorFilterArray + * \brief Color filter array (CFA) structure. + * + * %ColorFilterArray describes a color filter array (CFA), such as one of the + * Bayer filters typically used in raw digital camera images. + * + * \ingroup cfa_classes + * \sa BayerFilterBGGR, BayerFilterGBRG, BayerFilterGRBG, BayerFilterRGGB + */ +class PCL_CLASS ColorFilterArray +{ +public: + + /*! + * Constructs a %ColorFilterArray object. + * + * \param pattern A sequence of ASCII characters defining a CFA matrix. + * Each string character represents an element of the CFA + * matrix, which can be one of:\n + * \n + * + * + * + * + * + * + * + * + * + *
0 A nonexistent or undefined CFA element.
R Red
G Green
B Blue
W White or panchromatic
C Cyan
M Magenta
Y Yellow
\n + * \n + * The length of this string must be equal to the product + * of \a width by \a height. Otherwise an Error exception + * will be thrown. An exception will also be thrown if one + * or more invalid CFA elements are found in \a pattern. + * + * \param width Horizontal dimension of the CFA matrix in pixels. + * + * \param height Vertical dimension of the CFA matrix in pixels. + * + * \param name An optional string identifying the type or model of CFA + * that is being described by this object. + */ + ColorFilterArray( const IsoString& pattern, int width, int height, const String& name = String() ) + : m_pattern( pattern.Uppercase() ) + , m_width( width ) + , m_height( height ) + , m_name( name ) + { + if ( m_width < 1 || m_height < 1 || size_type( NumberOfElements() ) != m_pattern.Length() ) + throw Error( "Malformed CFA pattern" ); + for ( auto element : m_pattern ) + if ( !IsValidCFAElement( element ) ) + throw Error( "Invalid CFA pattern \'" + m_pattern + "\'" ); + } + + /*! + * Constructs an empty %ColorFilterArray object. An empty CFA has no pattern + * and zero dimensions. + */ + ColorFilterArray() = default; + + /*! + * Copy constructor. + */ + ColorFilterArray( const ColorFilterArray& ) = default; + + /*! + * Move constructor. + */ + ColorFilterArray( ColorFilterArray&& ) = default; + + /*! + * Copy assignment operator. + */ + ColorFilterArray& operator =( const ColorFilterArray& ) = default; + + /*! + * Move assignment operator. + */ + ColorFilterArray& operator =( ColorFilterArray&& ) = default; + + /*! + * Returns a reference to the CFA pattern in this object. + */ + const IsoString& Pattern() const + { + return m_pattern; + } + + /*! + * Returns the horizontal dimension of this CFA structure in pixels. + */ + int Width() const + { + return m_width; + } + + /*! + * Returns the vertical dimension of this CFA structure in pixels. + */ + int Height() const + { + return m_height; + } + + /*! + * Returns the total number of elements (or pixels) in this CFA structure. + */ + int NumberOfElements() const + { + return int( m_pattern.Length() ); + } + + /*! + * Returns true only if this is an empty %ColorFilterArray object. An empty + * CFA has no pattern and zero dimensions. + */ + bool IsEmpty() const + { + return m_pattern.IsEmpty(); + } + + /*! + * Returns a reference to the name of this CFA structure. + */ + const String& Name() const + { + return m_name; + } + + /*! + * Returns true only if this object describes an RGB Bayer filter: BGGR, + * GRBG, GBRG, or RGGB. + */ + bool IsBayerFilter() const + { + return m_pattern == "BGGR" || m_pattern == "GRBG" || m_pattern == "GBRG" || m_pattern == "RGGB"; + } + + /*! + * Returns a copy of the CFA element at the specified \a x and \a y + * coordinates (pixel column and row, respectively). The top-left corner of + * the CFA is by convention located at coordinates x=y=0. + * + * For a description of valid CFA elements, see the class constructor. + */ + char Element( int x, int y ) const + { + size_type i = y*m_width + x; + if ( i < m_pattern.Length() ) + return m_pattern[i]; + return '\0'; + } + + /* + * Clears all internal structures to yield an empty CFA. + */ + void Clear() + { + m_pattern.Clear(); + m_width = m_height = 0; + m_name.Clear(); + } + + /*! + * Returns true iff this object represents the same CFA structure as another + * object \a x. This operator ignores the Name() components of both objects. + */ + bool operator ==( const ColorFilterArray& x ) const + { + return m_pattern == x.m_pattern && m_width == x.m_width && m_height == x.m_height; + } + + /*! + * Returns true only if this %ColorFilterArray object precedes another + * object \a x. This is a lexicographic comparison performed exclusively on + * the CFA patterns, ignoring matrix dimensions and filter names. + */ + bool operator <( const ColorFilterArray& x ) const + { + return m_pattern < x.m_pattern; + } + + /*! + * Returns true only if the specified character is a valid element of a CFA + * pattern specification. For a description of valid CFA elements, see the + * class constructor. + */ + static bool IsValidCFAElement( char element ) + { + return strchr( "0RGBWCMY", element ) != nullptr; + } + +private: + + IsoString m_pattern; + int m_width = 0; + int m_height = 0; + String m_name; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BayerFilterRGGB + * \brief RGGB Bayer filter representation. + * \ingroup cfa_classes + * \sa ColorFilterArray, BayerFilterBGGR, BayerFilterGBRG, BayerFilterGRBG + */ +class PCL_CLASS BayerFilterRGGB : public ColorFilterArray +{ +public: + + BayerFilterRGGB() + : ColorFilterArray( "RGGB", 2, 2, "RGGB Bayer Filter" ) + { + } +}; + +/*! + * \class BayerFilterBGGR + * \brief BGGR Bayer filter representation. + * \ingroup cfa_classes + * \sa ColorFilterArray, BayerFilterGBRG, BayerFilterGRBG, BayerFilterRGGB + */ +class PCL_CLASS BayerFilterBGGR : public ColorFilterArray +{ +public: + + BayerFilterBGGR() + : ColorFilterArray( "BGGR", 2, 2, "BGGR Bayer Filter" ) + { + } +}; + +/*! + * \class BayerFilterGBRG + * \brief GBRG Bayer filter representation. + * \ingroup cfa_classes + * \sa ColorFilterArray, BayerFilterBGGR, BayerFilterGRBG, BayerFilterRGGB + */ +class PCL_CLASS BayerFilterGBRG : public ColorFilterArray +{ +public: + + BayerFilterGBRG() + : ColorFilterArray( "GBRG", 2, 2, "GBRG Bayer Filter" ) + { + } +}; + +/*! + * \class BayerFilterGRBG + * \brief GRBG Bayer filter representation. + * \ingroup cfa_classes + * \sa ColorFilterArray, BayerFilterBGGR, BayerFilterGBRG, BayerFilterRGGB + */ +class PCL_CLASS BayerFilterGRBG : public ColorFilterArray +{ +public: + + BayerFilterGRBG() + : ColorFilterArray( "GRBG", 2, 2, "GRBG Bayer Filter" ) + { + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ColorFilterArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ColorFilterArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ColorSpace.h b/3rdparty/include/pcl/ColorSpace.h new file mode 100644 index 0000000..d63f65c --- /dev/null +++ b/3rdparty/include/pcl/ColorSpace.h @@ -0,0 +1,133 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ColorSpace.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_ColorSpace_h +#define __PCL_ColorSpace_h + +/// \file pcl/ColorSpace.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ColorSpace + * \brief Supported color spaces + * + * Current versions of the PixInsight platform support the following color + * spaces for images: + * + * + * + * + * + * + * + * + * + * + *
ColorSpace::Unknown Corresponds to an unknown or unsupported color space
ColorSpace::Gray Grayscale monochrome space
ColorSpace::RGB RGB color space
ColorSpace::CIEXYZ CIE XYZ color space
ColorSpace::CIELab CIE L*a*b* color space
ColorSpace::CIELch CIE L*c*h* color space
ColorSpace::HSV HSV color space: Hue, Saturation, Value
ColorSpace::HSI HSI color space: Hue, Saturation, Intensity
+ */ +namespace ColorSpace +{ + enum value_type + { + Unknown = -1, // Corresponds to an unknown or unsupported color space + Gray = 0, // Grayscale monochrome space + RGB, // RGB color space + CIEXYZ, // CIE XYZ color space + CIELab, // CIE L*a*b* color space + CIELch, // CIE L*c*h* color space + HSV, // HSV color space: Hue, Saturation, Value + HSI, // HSI color space: Hue, Saturation, Intensity + NumberOfColorSpaces + }; + + /*! + * Returns the number of nominal channels in the specified color space. + */ + inline int NumberOfNominalChannels( int colorSpace ) + { + return (colorSpace == Gray) ? 1 : 3; + } + + /*! + * Returns a string representing the name of a color space. + * + * \param colorSpace A supported color space, identified by its + * corresponding symbolic constant. + */ + String Name( int colorSpace ); + + /*! + * Returns the identifier of a nominal channel in a specified color space. + * + * \param colorSpace A supported color space, identified by its + * corresponding symbolic constant. + * + * \param channel The index >= 0 of a nominal channel or component. + */ + String ChannelId( int colorSpace, int channel ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ColorSpace_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ColorSpace.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ComboBox.h b/3rdparty/include/pcl/ComboBox.h new file mode 100644 index 0000000..e1d456f --- /dev/null +++ b/3rdparty/include/pcl/ComboBox.h @@ -0,0 +1,567 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ComboBox.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_ComboBox_h +#define __PCL_ComboBox_h + +/// \file pcl/ComboBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ComboBox + * \brief Client-side interface to a PixInsight %ComboBox control + * + * ### TODO: Write a detailed description for %ComboBox + */ +class PCL_CLASS ComboBox : public Control +{ +public: + + /*! + * Constructs a %ComboBox as a child control of \a parent. + */ + ComboBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %ComboBox control. + */ + virtual ~ComboBox() + { + } + + /*! + * Returns the total number of items in this %ComboBox control. + */ + int NumberOfItems() const; + + /*! + * Returns the index of the current item in this combo box, or -1 if no item + * is currently selected in this combo box. + */ + int CurrentItem() const; + + /*! + * Selects a combo box item with the specified \a index. + */ + void SetCurrentItem( int index ); + + /*! + * Finds an item in this combo box. Returns the index of the item found, or + * -1 if no item was found that matches the specified criteria. + * + * \param text Text to find. + * + * \param fromIdx Starting index from which the search will begin. + * + * \param exactMatch Whether the search will succeed only if an exact + * match is found, or a partial match is sufficient. + * + * \param caseSensitive True for a case-sensitive search. + */ + int FindItem( const String& text, int fromIdx = 0, bool exactMatch = false, bool caseSensitive = false ) const; + + /*! + * Inserts a new item in this combo box. + * + * \param index Insertion point. If an index greater than or equal to the + * current length is specified, the new item is appended to + * the end of the current set of items. If the index is less + * than or equal to zero, the new item will be prepended to + * the current list of items. + * + * \param text Text for the new item. + * + * \param icon Item icon. + */ + void InsertItem( int index, const String& text, const Bitmap& icon = Bitmap::Null() ); + + /*! + * Adds a new item at the end of this combo box. + * + * This is a convenience function, equivalent to: + * InsertItem( NumberOfItems(), text, icon ) + */ + void AddItem( const String& text, const Bitmap& icon = Bitmap::Null() ) + { + InsertItem( NumberOfItems(), text, icon ); + } + + /*! + * Inserts a list of combo box items. + * + * \param index Insertion point. If an index greater than or equal to the + * current length is specified, the new items are appended to + * the end of the current set of items. If the index is less + * than or equal to zero, the new items will be prepended to + * the current list of items. + * + * \param i,j Two forward iterators defining a range of contiguous + * strings that correspond to the texts of the newly created + * items. + */ + template + void InsertItems( int index, FI i, FI j ) + { + if ( i != j ) + { + DisableUpdates(); + do + InsertItem( index++, *i ); + while ( ++i != j ); + EnableUpdates(); + Update(); + } + } + + /*! + * Appends a list of combo box items. + * + * This is a convenience function, equivalent to: + * InsertItems( NumberOfItems(), i, j ) + */ + template + void AddItems( FI i, FI j ) + { + InsertItems( NumberOfItems(), i, j ); + } + + /*! + * Inserts a list of combo box items from a container. + * + * \param index Insertion point. If an index greater than or equal to the + * current length is specified, the new items are appended to + * the end of the current set of items. If the index is less + * than or equal to zero, the new items will be prepended to + * the current list of items. + * + * \param c A reference to a container with the list of strings that + * will be assigned to newly created items. + * + * This is a convenience function, equivalent to: + * InsertItems( index, c.Begin(), c.End() ) + */ + template + void InsertItems( int index, const C& c ) + { + InsertItems( index, c.Begin(), c.End() ); + } + + /*! + * Appends a list of combo box items from a container. + * + * \param c A reference to a container with the list of strings that will + * be used for newly created items. + * + * This is a convenience function, equivalent to: + * InsertItems( NumberOfItems(), c ); + */ + template + void AddItems( const C& c ) + { + InsertItems( NumberOfItems(), c ); + } + + /*! + * Removes the item at the specified \a index. If the specified index is + * greater than or equal to the current length, or less than zero,, no items + * are removed. + */ + void RemoveItem( int index ); + + /*! + * Removes all existing items in this combo box. + */ + void Clear(); + + /*! + * Returns the current text of the combo box item at the specified \a index. + */ + String ItemText( int index ) const; + + /*! + * Sets the current text of the combo box item at the specified \a index. + */ + void SetItemText( int index, const String& ); + + /*! + * Empties the text of the combo box item at the specified \a index. + */ + void ClearItemText( int index ) + { + SetItemText( index, String() ); + } + + /*! + * Returns the current icon of the combo box item at the specified \a index. + */ + Bitmap ItemIcon( int index ) const; + + /*! + * Changes the icon of the combo box item at the specified \a index. If a + * null bitmap is specified, the combo box item will have no associated icon. + */ + void SetItemIcon( int index, const Bitmap& ); + + /*! + * Clears the icon of the combo box item at the specified \a index. + * + * This is a convenience function, equivalent to: + * SetItemIcon( index, Bitmap::Null() ) + */ + void ClearItemIcon( int index ) + { + SetItemIcon( index, Bitmap::Null() ); + } + + /*! + * Returns true iff this combo box is editable. Editable combo boxes allow + * the user to edit the text of the currently selected item. + */ + bool IsEditEnabled() const; + + /*! + * Enables or disables the editable state of this combo box control. + */ + void EnableEdit( bool = true ); + + /*! + * Disables or enables the editable state of this combo box control. + * + * This is a convenience function, equivalent to: + * EnableEdit( !disable ) + */ + void DisableEdit( bool disable = true ) + { + EnableEdit( !disable ); + } + + /*! + * Returns the current text of the editable part of this combo box control. + */ + String EditText() const; + + /*! + * Sets the text contents of the editable part of this combo box control. + */ + void SetEditText( const String& ); + + /*! + * Empties the editable part of this combo box control. + */ + void ClearEditText() + { + SetEditText( String() ); + } + + /*! + * Returns true iff auto completion is currently enabled for this combo box + * control. + */ + bool IsAutoCompletionEnabled() const; + + /*! + * Enables or disables auto completion for this combo box control. + */ + void EnableAutoCompletion( bool = true ); + + /*! + * Disables or enables auto completion for this combo box control. + * + * This is a convenience function, equivalent to: + * EnableAutoCompletion( !disable ) + */ + void DisableAutoCompletion( bool disable = true ) + { + EnableAutoCompletion( !disable ); + } + + /*! + * Provides the current icon dimensions for this combo box control. + * + * \param[out] width,height Icon dimensions in pixels. + */ + void GetIconSize( int& width, int& height ) const; + + /*! + * Returns the current icon width in pixels for this combo box control. + */ + int IconWidth() const + { + int w, dum; GetIconSize( w, dum ); return w; + } + + /*! + * Returns the current icon height in pixels for this combo box control. + */ + int IconHeight() const + { + int dum, h; GetIconSize( dum, h ); return h; + } + + /*! + * Sets the icon dimensions in pixels for this combo box control. + */ + void SetIconSize( int width, int height ); + + /*! + * Sets the icon size in pixels for this combo box control. + * + * This is a convenience function, equivalent to: + * SetIconSize( size, size ) + */ + void SetIconSize( int size ) + { + SetIconSize( size, size ); + } + + /*! # + */ + void GetScaledIconSize( int& width, int& height ) const + { + GetIconSize( width, height ); width = PhysicalPixelsToLogical( width ); height = PhysicalPixelsToLogical( height ); + } + + /*! # + */ + int ScaledIconWidth() const + { + int width, dum; GetIconSize( width, dum ); return PhysicalPixelsToLogical( width ); + } + + /*! # + */ + int ScaledIconHeight() const + { + int dum, height; GetIconSize( dum, height ); return PhysicalPixelsToLogical( height ); + } + + /*! # + */ + void SetScaledIconSize( int width, int height ) + { + SetIconSize( LogicalPixelsToPhysical( width ), LogicalPixelsToPhysical( height ) ); + } + + /*! # + */ + void SetScaledIconSize( int size ) + { + size = LogicalPixelsToPhysical( size ); + SetIconSize( size, size ); + } + + /*! + * Returns the maximum number of items that can be visible when this combo + * box control is dropped down, or 0 is no specific limit has been set. + */ + int MaxVisibleItemCount() const; + + /*! + * Sets the maximum number of items that can be visible when this combo + * box control is dropped down. If zero is specified, the combo box control + * will show a convenient number of items automatically in drop-down state. + */ + void SetMaxVisibleItemCount( int ); + + /*! + * Returns the minimum number of characters that fit in this combo box + * control, or zero if no specific limit has been set. + */ + int MinItemCharWidth() const; + + /*! + * Sets the minimum number of characters that must fit in this combo box + * control. If zero is specified, the combo box control will adapt its + * size automatically to its initial contents. + */ + void SetMinItemCharWidth( int ); + + // + // Drop-down items list + // + + /*! + * Forces this combo box control to enter the drop-down state. The list of + * existing items is shown on a pop-up panel where they can be browsed and + * selected. + */ + void ShowList(); + + /*! + * Forces this combo box control to exit the drop-down state. The list of + * items will be hidden, if it is currently visible. + */ + void HideList(); + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnItemSelected( ComboBox& sender, int itemIndex ); + // void OnItemHighlighted( ComboBox& sender, int itemIndex ); + // void OnEditTextUpdated( ComboBox& sender ); + + /*! + * \defgroup combobox_event_handlers ComboBox Event Handlers + */ + + /*! + * Defines the prototype of a combo box item event handler. + * + * A combo box item event is generated when an item is selected or + * highlighted in a combo box. + * + * \param sender The ComboBox control that sends a combo box item event. + * + * \param itemIndex The index of the combo box item where the event + * originated, in the range from zero to the number of + * existing combo box items minus one. + * + * \ingroup combobox_event_handlers + */ + typedef void (Control::*item_event_handler)( ComboBox& sender, int itemIndex ); + + /*! + * Defines the prototype of a combo box edit event handler. + * + * A combo box edit event is generated when the text in the editable part of + * a combo box is changed by the user. + * + * \param sender The ComboBox control that sends a combo box edit event. + * + * \ingroup combobox_event_handlers + */ + typedef void (Control::*edit_event_handler)( ComboBox& sender ); + + /*! + * Sets the item selected event handler for this combo box. + * + * \param handler The combo box item event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever an item is selected in this + * combo box control. + * + * \param receiver The control that will receive item selected + * events from this combo box. + * + * \ingroup combobox_event_handlers + */ + void OnItemSelected( item_event_handler handler, Control& receiver ); + + /*! + * Sets the item highlighted event handler for this combo box. + * + * \param handler The combo box item event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever an item is highlighted in this + * combo box control. + * + * \param receiver The control that will receive item highlighted + * events from this combo box. + * + * \ingroup combobox_event_handlers + */ + void OnItemHighlighted( item_event_handler handler, Control& receiver ); + + /*! + * Sets the edit updated event handler for this combo box. + * + * \param handler The combo box edit event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever the text changes in the + * editable part of combo box control. + * + * \param receiver The control that will receive edit updated + * events from this combo box. + * + * \ingroup combobox_event_handlers + */ + void OnEditTextUpdated( edit_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + item_event_handler onItemSelected = nullptr; + item_event_handler onItemHighlighted = nullptr; + edit_event_handler onEditTextUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class ComboBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ComboBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ComboBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Complex.h b/3rdparty/include/pcl/Complex.h new file mode 100644 index 0000000..3b06458 --- /dev/null +++ b/3rdparty/include/pcl/Complex.h @@ -0,0 +1,1110 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Complex.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_Complex_h +#define __PCL_Complex_h + +/// \file pcl/Complex.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define real C[0] +#define imag C[1] + +/*! + * \class Complex + * \brief Generic complex number + * + * %Complex is a careful implementation of complex numbers, including efficient + * computations of complex arithmetic and transcendental functions. + * + * When instantiated for the \c double and \c float types, the generated + * classes are binary-compatible with the C99 complex standard structure. + */ +template +class PCL_CLASS Complex +{ +public: + + /*! + * Represents a component of a complex number: real or imaginary part. + */ + typedef T component; + + /*! + * Constructs an uninitialized complex number. The real and imaginary + * components will have unpredictable values. + */ + Complex() = default; + + /*! + * Constructs a complex number with the specified real and imaginary parts. + */ + Complex( T r, T i = 0 ) noexcept + { + real = r; + imag = i; + } + + /*! + * Nontrivial copy constructor. + */ + template + Complex( const Complex& c ) noexcept + { + real = T( c.Real() ); + imag = T( c.Imag() ); + } + + /*! + * Returns a copy of the real component of this complex number. + */ + constexpr T Real() const noexcept + { + return real; + } + + /*! + * Returns a reference to the real component of this complex number. + */ + T& Real() noexcept + { + return real; + } + + /*! + * Returns a copy of the imaginary component of this complex number. + */ + constexpr T Imag() const noexcept + { + return imag; + } + + /*! + * Returns a reference to the imaginary component of this complex number. + */ + T& Imag() noexcept + { + return imag; + } + + /*! + * Returns true iff the imaginary part of this complex number is zero. + */ + constexpr bool IsReal() const noexcept + { + return imag == 0; + } + + /*! + * Assignment operator. Returns a reference to this complex number. + */ + template + Complex& operator =( const Complex& c ) noexcept + { + real = T( c.Real() ), imag = T( c.Imag() ); + return *this; + } + + /*! + * Assignment/sum operator. Adds the specified complex number \a c to this. + * Returns a reference to this complex number. + */ + template + Complex& operator +=( const Complex& c ) noexcept + { + real += c.Real(), imag += c.Imag(); + return *this; + } + + /*! + * Assignment/subtract operator. Subtracts the specified complex number \a c + * from this. Returns a reference to this complex number. + */ + template + Complex& operator -=( const Complex& c ) noexcept + { + real -= c.Real(), imag -= c.Imag(); + return *this; + } + + /*! + * Assignment/multiply operator. Multiplies this complex number by the + * specified complex \a c. Returns a reference to this complex number. + */ + template + Complex& operator *=( const Complex& c ) noexcept + { + T t = T( real*c.Real() - imag*c.Imag() ); + imag = T( imag*c.Real() + real*c.Imag() ); + real = t; + return *this; + } + + /*! + * Assignment/divide operator. Divides this complex number by the specified + * complex \a c. Returns a reference to this complex number. + */ + template + Complex& operator /=( const Complex& c ) noexcept + { + T r, d, t; + if ( pcl::Abs( c.Real() ) >= pcl::Abs( c.Imag() ) ) + { + PCL_PRECONDITION( c.Real() != 0 ) + r = T( c.Imag()/c.Real() ); + d = T( c.Real() + r*c.Imag() ); + t = T( (real + r*imag)/d ); + imag = (imag - r*real)/d; + } + else + { + PCL_PRECONDITION( c.Imag() != 0 ) + r = T( c.Real()/c.Imag() ); + d = T( c.Imag() + r*c.Real() ); + t = T( (real*r + imag)/d ); + imag = (imag*r - real)/d; + } + real = t; + return *this; + } + + /*! + * Assigns a real number to this complex number. The specified scalar \a x + * is assigned to the real component, and the imaginary component is set to + * zero. Returns a reference to this complex number. + */ + template + Complex& operator =( T1 x ) noexcept + { + real = x, imag = 0; + return *this; + } + + /*! + * Adds a real number to this complex number. The specified scalar \a x is + * added to the real component. Returns a reference to this complex number. + */ + template + Complex& operator +=( T1 x ) noexcept + { + real += x; + return *this; + } + + /*! + * Subtracts a real number from this complex number. The specified scalar \a x + * is subtracted from the real component. Returns a reference to this + * complex number. + */ + template + Complex& operator -=( T1 x ) noexcept + { + real -= x; + return *this; + } + + /*! + * Multiplies this complex number by a real number. The real component is + * multiplied by the specified scalar \a x. Returns a reference to this + * complex number. + */ + template + Complex& operator *=( T1 x ) noexcept + { + real *= x, imag *= x; + return *this; + } + + /*! + * Divides this complex number by a real number. The real component is + * divided by the specified scalar \a x. Returns a reference to this complex + * number. + */ + template + Complex& operator /=( T1 x ) noexcept + { + PCL_PRECONDITION( x != 0 ) + real /= x, imag /= x; + return *this; + } + + /*! + * Unary plus operator. Returns a copy of this complex number. + */ + Complex operator +() const noexcept + { + return *this; + } + + /*! + * Unary minus operator. Returns a complex number symmetric to this. + * + * This function is equivalent to: + * Complex( -Real(), -Imag() ) + */ + Complex operator -() const noexcept + { + return Complex( -real, -imag ); + } + + /*! + * Complex conjugate. This function is equivalent to: + * Complex( Real(), -Imag() ) + */ + Complex Conj() const noexcept + { + return Complex( real, -imag ); + } + + /*! + * Complex conjugate. This operator is a synonym for Conj(). + */ + Complex operator ~() const noexcept + { + return Conj(); + } + + /*! + * Assigns to this complex number its complex conjugate. This function + * changes the sign of the imaginary part of this complex number. + */ + void SetConj() noexcept + { + imag = -imag; + } + + /*! + * Complex magnitude (modulus). + * + * Accurate results are guaranteed even for large ratios between the real + * and complex components. + */ + T Mag() const noexcept + { + T r = pcl::Abs( real ); + T i = pcl::Abs( imag ); + T m; + if ( r == 0 ) + m = i; + else if ( i == 0 ) + m = r; + else + { + bool q = r < i; + m = q ? r/i : i/r; + m = (q ? i : r) * pcl::Sqrt( 1 + m*m ); + } + return m; + } + + /*! + * Explicit conversion operator to double. + * + * Returns the complex magnitude or modulus of this complex number, so this + * operator is equivalent to Mag() const. + */ + explicit operator double() const noexcept + { + return double( Mag() ); + } + + /*! + * Complex norm. + * This function is equivalent to: Real()*Real() + Imag()*Imag(). + */ + constexpr T Norm() const noexcept + { + return real*real + imag*imag; + } + + /*! + * Complex argument. + * Returns the arc whose tangent is Imag()/Real(). When both real and + * imaginary components are zero, this function returns zero. + */ + constexpr T Arg() const noexcept + { + // Degenerate cases (real=0) are correctly handled by real ArcTan(). For + // the undefined case real=imag=0, we silently return zero. Should we + // throw an exception instead? + return (real != 0 || imag != 0) ? pcl::ArcTan( imag, real ) : 0; + } + +private: + + /* + * C99 binary-compatible complex components. + */ + T C[ 2 ]; // C[0] = real, C[1] = imaginary +}; + +#undef real +#undef imag + +/* + * ### N.B.: Template class Complex cannot have virtual member functions. + * This is because sizeof( Complex ) _must_ be equal to 2*sizeof( T ). + */ +template +struct PCL_AssertComplexSize +{ + static_assert( sizeof( Complex ) == 2*sizeof( T ), "Invalid sizeof( Complex<> )" ); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup complex_arithmetic_ops Complex Arithmetic Operators + */ + +/*! + * \defgroup complex_basic_functions Complex Basic Functions + */ + +/*! + * Complex absolute value. This function returns the complex magnitude of the + * specified complex number \a c. + * \ingroup complex_basic_functions + */ +template inline +T Abs( const Complex& c ) noexcept +{ + return c.Mag(); +} + +/*! + * Returns a complex number from its polar coordinates: radial distance \a r + * and polar angle theta. The polar angle theta is given by its sine and + * cosine, \a stheta and \a ctheta, respectively. + * \ingroup complex_basic_functions + */ +template inline +Complex Polar( T r, T stheta, T ctheta ) noexcept +{ + return Complex( r*ctheta, r*stheta ); +} + +/*! + * Returns a complex number from its polar coordinates: radial distance \a r + * and polar angle \a theta. The polar angle is specified in radians. + * \ingroup complex_basic_functions + */ +template inline +Complex Polar( T r, T theta ) noexcept +{ + return Polar( r, pcl::Sin( theta ), pcl::Cos( theta ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Complex addition. Returns the sum of two complex numbers \a c1 and \a c2. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator +( const Complex& c1, const Complex& c2 ) noexcept +{ + return Complex( T1( c1.Real() + c2.Real() ), + T1( c1.Imag() + c2.Imag() ) ); +} + +/*! + * Complex addition. Returns the sum of a complex number \a c and a real \a x. + * + * \note The commutativity of complex-real addition is implemented by the + * existence of this function along with operator +( T1, const Complex& ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator +( const Complex& c, T2 x ) noexcept +{ + return Complex( T1( c.Real()+x ), c.Imag() ); +} + +/*! + * Complex addition. Returns the sum of a real number \a x and a complex \a c. + * + * \note The commutativity of complex-real addition is implemented by the + * existence of this function along with operator +( const Complex&, T2 ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator +( T1 x, const Complex& c ) noexcept +{ + return c + x; +} + +/*! + * Complex subtraction. Returns the difference between two complex numbers + * \a c1 and \a c2. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator -( const Complex& c1, const Complex& c2 ) noexcept +{ + return Complex( T1( c1.Real() - c2.Real() ), + T1( c1.Imag() - c2.Imag() ) ); +} + +/*! + * Complex subtraction. Returns the difference between a complex number \a c + * and a real \a x. + * + * \note The noncommutativity of complex-real subtraction is implemented by + * the existence of this function along with + * operator -( T1, const Complex& ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator -( const Complex& c, T2 x ) noexcept +{ + return Complex( T1( c.Real()-x ), c.Imag() ); +} + +/*! + * Complex subtraction. Returns the difference between a real number \a x + * and a complex \a c. + * + * \note The noncommutativity of complex-real subtraction is implemented by + * the existence of this function along with + * operator -( const Complex&, T2 ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator -( T1 x, const Complex& c ) noexcept +{ + return Complex( T2( x-c.Real() ), -c.Imag() ); +} + +/*! + * Complex multiplication. Returns the multiplication of two complex numbers + * \a c1 and \a c2. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator *( const Complex& c1, const Complex& c2 ) noexcept +{ + return Complex( T1( c1.Real()*c2.Real() - c1.Imag()*c2.Imag() ), + T1( c1.Imag()*c2.Real() + c1.Real()*c2.Imag() ) ); +} + +/*! + * Complex multiplication. Returns the multiplication of a complex number \a c + * and a real \a x. + * + * \note The commutativity of complex-real multiplication is implemented by the + * existence of this function along with + * operator *( T1, const Complex& ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator *( const Complex& c, T2 x ) noexcept +{ + return Complex( T1( c.Real()*x ), c.Imag()*x ); +} + +/*! + * Complex multiplication. Returns the multiplication of a real number \a x and + * a complex \a c. + * + * \note The commutativity of complex-real multiplication is implemented by the + * existence of this function along with + * operator *( const Complex&, T2 ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator *( T1 x, const Complex& c ) noexcept +{ + return c * x; +} + +/*! + * Complex division. Returns the division between two complex numbers + * \a c1 and \a c2. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator /( const Complex& c1, const Complex& c2 ) noexcept +{ + Complex c; + T2 r, d; + if ( pcl::Abs( c2.Real() ) >= pcl::Abs( c2.Imag() ) ) + { + PCL_PRECONDITION( c2.Real() != 0 ) + r = c2.Imag() / c2.Real(); + d = c2.Real() + r*c2.Imag(); + c.Real() = T1( (c1.Real() + r*c1.Imag())/d ); + c.Imag() = T1( (c1.Imag() - r*c1.Real())/d ); + } + else + { + PCL_PRECONDITION( c2.Imag() != 0 ) + r = c2.Real() / c2.Imag(); + d = c2.Imag() + r*c2.Real(); + c.Real() = T1( (c1.Real()*r + c1.Imag())/d ); + c.Imag() = T1( (c1.Imag()*r - c1.Real())/d ); + } + return c; +} + +/*! + * Complex division. Returns the division of a complex number \a c + * by a real \a x. + * + * \note The noncommutativity of complex-real division is implemented by the + * existence of this function along with + * operator /( T1, const Complex& ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator /( const Complex& c, T2 x ) noexcept +{ + PCL_PRECONDITION( x != 0 ) + return Complex( T1( c.Real()/x ), T1( c.Imag()/x ) ); +} + +/*! + * Complex division. Returns the division of a real number \a x and a + * complex \a c. + * + * \note The noncommutativity of complex-real division is implemented by the + * existence of this function along with + * operator /( const Complex&, T2 ). + * + * \ingroup complex_arithmetic_ops + */ +template inline +Complex operator /( T1 x, const Complex& c ) noexcept +{ + // return Complex( x, 0 )/c; + Complex c3; + T2 r, d; + if ( pcl::Abs( c.Real() ) >= pcl::Abs( c.Imag() ) ) + { + PCL_PRECONDITION( c.Real() != 0 ) + r = c.Imag()/c.Real(); + d = c.Real() + r*c.Imag(); + c3.Real() = T2( x/d ); + c3.Imag() = T2( -((r*x)/d) ); + } + else + { + PCL_PRECONDITION( c.Imag() != 0 ) + r = c.Real()/c.Imag(); + d = c.Imag() + r*c.Real(); + c3.Real() = T2( (r*x)/d ); + c3.Imag() = T2( -(x/d) ); + } + return c3; +} + +// ---------------------------------------------------------------------------- + +/*! + * Complex square root. + * \ingroup complex_basic_functions + */ +template inline +Complex Sqrt( const Complex& c ) noexcept +{ + if ( c.Real() == 0 && c.Imag() == 0 ) + return Complex( 0 ); + + Complex c1; + T m, r = pcl::Abs( c.Real() ), i = pcl::Abs( c.Imag() ); + + if ( r >= i ) + { + PCL_PRECONDITION( r != 0 ) + T t = i/r; + m = pcl::Sqrt( r ) * pcl::Sqrt( (1 + pcl::Sqrt( 1 + t*t ))/2 ); + } + else + { + PCL_PRECONDITION( i != 0 ) + T t = r/i; + m = pcl::Sqrt( i ) * pcl::Sqrt( (t + pcl::Sqrt( 1 + t*t ))/2 ); + } + + if ( c.Real() >= 0 ) + { + c1.Real() = m; + c1.Imag() = c.Imag()/(m+m); + } + else + { + c1.Imag() = (c.Imag() >= 0) ? m : -m; + c1.Real() = c.Imag()/(c1.Imag()+c1.Imag()); + } + + return c1; +} + +/*! + * Complex exponential function. + * \ingroup complex_basic_functions + */ +template inline +Complex Exp( const Complex& c ) noexcept +{ + T x = pcl::Exp( c.Real() ); + return Complex( x*pcl::Cos( c.Imag() ), x*pcl::Sin( c.Imag() ) ); +} + +/*! + * Complex natural (base e) logarithm. + * \ingroup complex_basic_functions + */ +template inline +Complex Ln( const Complex& c ) noexcept +{ + return Complex( pcl::Ln( c.Mag() ), c.Arg() ); +} + +/*! + * Complex base 10 logarithm. + * \ingroup complex_basic_functions + */ +template inline +Complex Log( const Complex& c ) noexcept +{ + return pcl::Const::log10e() * pcl::Ln( c ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Complex exponentiation. Returns a complex number \a c raised to a real \a x. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex Pow( const Complex& c, T2 x ) noexcept +{ + if ( c.Imag() == 0 ) + return Complex( pcl::Pow( c.Real(), T1( x ) ) ); + else + return pcl::Exp( T1( x )*pcl::Ln( c ) ); +} + +/*! + * Complex exponentiation. Returns a real number \a x raised to a complex \a c. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex Pow( T1 x, const Complex& c ) noexcept +{ + if ( c.Imag() == 0 ) + return Complex( pcl::Pow( T2( x ), c.Real() ) ); + else + return pcl::Exp( c*pcl::Ln( T2( x ) ) ); +} + +/*! + * Complex exponentiation. Returns a complex number \a c1 raised to a + * complex \a c2. + * \ingroup complex_arithmetic_ops + */ +template inline +Complex Pow( const Complex& c1, const Complex& c2 ) noexcept +{ + if ( c2.Imag() == 0 ) + return pcl::Pow( c1, c2.Real() ); + else if ( c1.Imag() == 0 ) + return Complex( pcl::Pow( c1.Real(), c2 ) ); + else + return pcl::Exp( c2*pcl::Ln( c1 ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup complex_transcendental_ops Complex Transcendental Functions + */ + +/*! + * Complex sine. + * \ingroup complex_transcendental_ops + */ +template inline +Complex Sin( const Complex& c ) noexcept +{ + return Complex( pcl::Sin( c.Real() )*pcl::Cosh( c.Imag() ), + pcl::Cos( c.Real() )*pcl::Sinh( c.Imag() ) ); +} + +/*! + * Complex cosine. + * \ingroup complex_transcendental_ops + */ +template inline +Complex Cos( const Complex& c ) noexcept +{ + return Complex( pcl::Cos( c.Real() )*pcl::Cosh( c.Imag() ), + -pcl::Sin( c.Real() )*pcl::Sinh( c.Imag() ) ); +} + +/*! + * Complex tangent. + * \ingroup complex_transcendental_ops + */ +template inline +Complex Tan( const Complex& c ) noexcept +{ + return pcl::Sin( c )/pcl::Cos( c ); +} + +/*! + * Complex hyperbolic sine. + * \ingroup complex_transcendental_ops + */ +template inline +Complex Sinh( const Complex& c ) noexcept +{ + return Complex( pcl::Sinh( c.Real() )*pcl::Cos( c.Imag() ), + pcl::Cosh( c.Real() )*pcl::Sin( c.Imag() ) ); +} + +/*! + * Complex hyperbolic cosine. + * \ingroup complex_transcendental_ops + */ +template inline +Complex Cosh( const Complex& c ) noexcept +{ + return Complex( pcl::Cosh( c.Real() )*pcl::Cos( c.Imag() ), + pcl::Sinh( c.Real() )*pcl::Sin( c.Imag() ) ); +} + +/*! + * Complex hyperbolic tangent. + * \ingroup complex_transcendental_ops + */ +template inline +Complex Tanh( const Complex& c ) noexcept +{ + return pcl::Sinh( c )/pcl::Cosh( c ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup complex_relational_ops Complex Relational Operators + * + * The elements of the complex plane don't follow any particular "natural" + * order. Of course, our definitions of the <, <=, > and >= operators for + * complex numbers are completely arbitrary: we just compare complex + * magnitudes. This effectively sorts complex numbers by concentric circles + * around the origin. + */ + +/*! + * Returns true iff two complex numbers \a c1 and \a c2 are equal. + * \ingroup complex_relational_ops + */ +template inline +bool operator ==( const Complex& c1, const Complex& c2 ) noexcept +{ + return c1.Real() == c2.Real() && c1.Imag() == c2.Imag(); +} + +/*! + * Returns true iff a complex number \a c is equal to a real \a x. + * \ingroup complex_relational_ops + */ +template inline +bool operator ==( const Complex& c, T2 x ) noexcept +{ + return c.Real() == x && c.Imag() == T1( 0 ); +} + +/*! + * Returns true iff a real number \a x is equal to a complex \a c. + * \ingroup complex_relational_ops + */ +template inline +bool operator ==( T1 x, const Complex& c ) noexcept +{ + return c == x; +} + +/*! + * Returns true iff a complex number \a c1 is less than other complex \a c2. + * \ingroup complex_relational_ops + */ +template inline +bool operator <( const Complex& c1, const Complex& c2 ) noexcept +{ + return c1.Mag() < c2.Mag(); +} + +/*! + * Returns true iff a complex number \a c is less than a real number \a x. + * \ingroup complex_relational_ops + */ +template inline +bool operator <( const Complex& c, T2 x ) noexcept +{ + return c.Mag() < pcl::Abs( x ); +} + +/*! + * Returns true iff a real number \a x is less than a complex number \a c. + * \ingroup complex_relational_ops + */ +template inline +bool operator <( T1 x, const Complex& c ) noexcept +{ + return pcl::Abs( x ) < c.Mag(); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup complex_rounding_functions Complex Rounding Functions + */ + +/*! + * Complex rounding. Returns a complex number whose components are the + * components of a specified complex \a c rounded to their nearest integers. + * \ingroup complex_rounding_functions + */ +template inline +Complex Round( const Complex& c ) noexcept +{ + return Complex( pcl::Round( c.Real() ), pcl::Round( c.Imag() ) ); +} + +/*! + * Complex rounding. Returns a complex number whose components are the + * components of a specified complex \a c rounded to the specified number of + * decimal digits \a n. + * \ingroup complex_rounding_functions + */ +template inline +Complex Round( const Complex& c, int n ) noexcept +{ + PCL_PRECONDITION( n >= 0 ) + return Complex( pcl::Round( c.Real(), n ), pcl::Round( c.Imag(), n ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup phase_matrices Phase Matrices Computation Algorithms + */ + +/*! + * Phase correlation matrix. + * + * \param[out] i Address of the first element in the output phase + * correlation matrix. + * + * \param j Address of the ending element in the output phase + * correlation matrix. + * + * \param a Address of the first element in the first operand matrix. + * + * \param b Address of the first element in the second operand matrix. + * + * This routine will compute and store the set of contiguous matrix elements at + * i, i+1, ..., j-1. The total number of computed elements in the output phase + * correlation matrix is equal to j-i. The \a i, \a a and \a b matrices must + * provide storage for at least j-i complex numbers. + * + * \ingroup phase_matrices + */ +template inline +void PhaseCorrelationMatrix( Complex* __restrict__ i, const Complex* __restrict__ j, + const Complex* __restrict__ a, const Complex* __restrict__ b ) noexcept +{ + const T tiny = T( 1.0e-20 ); + for ( ; i < j; ++i, ++a, ++b ) + { + Complex n = *a * ~*b; + *i = n/Max( tiny, Abs( n ) ); + } +} + +/*! + * Cross power spectrum matrix. + * + * \param[out] i Address of the first element in the output cross power + * spectrum matrix. + * + * \param j Address of the ending element in the output cross power + * spectrum matrix. + * + * \param a Address of the first element in the first operand matrix. + * + * \param b Address of the first element in the second operand matrix. + * + * This routine will compute and store the set of contiguous matrix elements at + * i, i+1, ..., j-1. The total number of computed elements in the output cross + * power spectrum matrix is equal to j-i. The \a i, \a a and \a b matrices must + * provide storage for at least j-i complex numbers. + * + * \ingroup phase_matrices + */ +template inline +void CrossPowerSpectrumMatrix( Complex* __restrict__ i, const Complex* __restrict__ j, + const Complex* __restrict__ a, const Complex* __restrict__ b ) noexcept +{ + const T tiny = T( 1.0e-20 ); + for ( ; i < j; ++i, ++a, ++b ) + *i = (*b * ~*a)/Max( tiny, Abs( *a ) * Abs( *b ) ); +} + +// +// Stream extraction/insertion. +// +/* ### PCL 2.x: Add these along with pcl::DataStream, etc... +template inline +S& operator >>( S& s, Complex& c ) +{ + return s >> c.Real() >> c.Imag(); +} + +template inline +S& operator <<( S& s, const Complex& c ) +{ + return s << c.Real() << c.Imag(); +} + */ + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_COMPLEX_INSTANTIATE + +/*! + * \defgroup complex_types Complex Number Types + */ + +/*! + * \class pcl::Complex32 + * \ingroup complex_types + * \brief A complex number whose components are 32-bit floating point real + * numbers. + * + * Complex32 is a template instantiation of Complex for the \c float type. + */ +typedef Complex Complex32; + +/*! + * \class pcl::fcomplex + * \ingroup complex_types + * \brief A complex number whose components are 32-bit floating point real + * numbers. + * + * fcomplex is an alias for Complex32. It is a template instantiation of + * Complex for the \c float type. + */ +typedef Complex32 fcomplex; + +/*! + * \class pcl::Complex64 + * \ingroup complex_types + * \brief A complex number whose components are 64-bit floating point real + * numbers. + * + * Complex64 is a template instantiation of Complex for the \c double type. + */ +typedef Complex Complex64; + +/*! + * \class pcl::dcomplex + * \ingroup complex_types + * \brief A complex number whose components are 64-bit floating point real + * numbers. + * + * dcomplex is an alias for Complex64. It is a template instantiation of + * Complex for the \c double type. + */ +typedef Complex64 dcomplex; + +/*! + * \class pcl::complex + * \ingroup complex_types + * \brief A complex number whose components are 64-bit floating point real + * numbers. + * + * complex is an alias for dcomplex. It is a template instantiation of Complex + * for the \c double type. + */ +typedef dcomplex complex; + +#endif // __PCL_NO_COMPLEX_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Complex_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Complex.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Compression.h b/3rdparty/include/pcl/Compression.h new file mode 100644 index 0000000..45c211f --- /dev/null +++ b/3rdparty/include/pcl/Compression.h @@ -0,0 +1,809 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Compression.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_Compression_h +#define __PCL_Compression_h + +/// \file pcl/Compression.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup compression_classes Data Compression Classes + */ + +/*! + * \class Compression + * \brief Abstract base class of data compression algorithm implementations. + * + * %Compression defines a common interface for compression algorithms such as + * Zlib/deflate, LZ4, LZMA, etc. + * + * \ingroup compression_classes + * \sa ZLibCompression, LZ4Compression, LZ4HCCompression, BloscLZCompression + */ +class PCL_CLASS Compression : public ParallelProcess +{ +public: + + /*! + * \struct pcl::Compression::Subblock + * \brief Compression subblock data. + */ + struct Subblock + { + ByteArray compressedData; //!< Sub-block compressed data. + size_type uncompressedSize = 0; //!< size in bytes of the uncompressed subblock. + uint64 checksum = 0; //!< If non-zero, 64-bit non-cryptographic checksum of the compressed data. + }; + + /*! + * \struct pcl::Compression::Performance + * \brief Compression/decompression performance measurements. + */ + struct Performance + { + float sizeReduction = 0; //!< Relative size reduction, e.g.: 0.25 for a 25% size reduction. + double throughput = 0; //!< Compression/decompression rate in MiB per second. + int numberOfThreads = 0; //!< Number of parallel threads used. + }; + + /*! + * A dynamic, ordered list of compression subblocks. + */ + typedef Array subblock_list; + + /*! + * Default constructor. This object will be initialized with the following + * parameters: + * + * \li Compression level: Use an algorithm-dependent default level to + * achieve a good compromise between running speed and compression ratio. + * + * \li Byte shuffling: Enabled. + * + * \li Item size: One byte (which inhibits shuffling). + * + * \li Sub-block checksums: Enabled. + * + * \li Sub-block size: Use the maximum possible subblock size for each + * compression algorithm. + * + * \li Parallel processing: Enabled to use the maximum possible number of + * processors. + */ + Compression() = default; + + /*! + * Copy constructor. + */ + Compression( const Compression& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Compression& operator =( const Compression& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~Compression() + { + } + + /*! + * Returns the name of this data compression algorithm. + */ + virtual String AlgorithmName() const = 0; + + /*! + * Returns the maximum compression optimization level supported by this + * algorithm. Higher levels tend to provide higher compression ratios at the + * cost of more computational work. + */ + virtual int MaxCompressionLevel() const = 0; + + /*! + * Returns the default compression optimization level for this algorithm. + * The returned value represents a good compromise between execution speed + * and compression ratio. + */ + virtual int DefaultCompressionLevel() const = 0; + + /*! + * Returns the current compression optimization level. + * + * See SetCompressionLevel() for more information. + */ + int CompressionLevel() const + { + return m_compressionLevel; + } + + /*! + * Sets an algorithm-dependent compression optimization level. + * + * Higher levels tend to provide higher compression ratios at the cost of + * more computational work. If zero or a negative value is specified, the + * compression routines will select a default level automatically to achieve + * a good compromise between speed and compression ratio for each + * compression algorithm. + */ + void SetCompressionLevel( int level ) + { + m_compressionLevel = Range( level, 0, MaxCompressionLevel() ); + } + + /*! + * Sets the default compression optimization level for this compression + * algorithm. + * + * This function is a shortcut for SetCompressionLevel( 0 ). The default + * compression level attempts to achieve a good compromise between speed and + * compression ratio for each compression algorithm. + */ + void SetDefaultCompressionLevel() + { + SetCompressionLevel( 0 ); + } + + /*! + * Returns true iff byte shuffling is currently enabled for this + * %Compression object. + * + * See EnableByteShuffling() for more information. + */ + bool ByteShufflingEnabled() const + { + return m_byteShuffle; + } + + /*! + * Enables byte shuffling for this %Compression object. + * + * Enable this option to pre-process the data with a byte shuffling routine + * before compression. The byte shuffle algorithm reorganizes the data in a + * clever way that can greatly improve compression ratios, especially for + * data with high \e locality (or data containing similar values close + * together), such as most scientific and observational data. This option + * can be particularly efficient for compression of data structured as + * contiguous sequences of 16-bit, 32-bit and 64-bit numbers, such as most + * images processed with PixInsight. For 8-bit data, byte shuffling is a + * no-op and is hence ignored. Byte shuffling is enabled by default. + */ + void EnableByteShuffling( bool enable = true ) + { + m_byteShuffle = enable; + } + + /*! + * Disables byte shuffling for this %Compression object. + * + * Equivalent to EnableByteShuffling( !disable ). + */ + void DisableByteShuffling( bool disable = true ) + { + EnableByteShuffling( !disable ); + } + + /*! + * Returns the current item size for shuffling. + * + * This is the length in bytes of an element in the uncompressed data, used + * by the byte shuffling algorithm. See EnableByteShuffling() for more + * information. + */ + size_type ItemSize() const + { + return m_itemSize; + } + + /*! + * Sets the item size for shuffling. + * + * \a itemSize is the length in bytes of a data item for the byte shuffling + * algorithm. See EnableByteShuffling() for more information. + */ + void SetItemSize( size_type itemSize ) + { + m_itemSize = uint8( Range( itemSize, size_type( 1 ), size_type( 128 ) ) ); + } + + /*! + * Returns the current compression subblock size in bytes. + * + * See SetSubblockSize() for more information. + */ + size_type SubblockSize() const + { + return m_subblockSize; + } + + /*! + * Sets the compression subblock size. + * + * The specified \a size is the length in bytes of a compression subblock. + * If a value of zero is specified, the effective block size will be the + * maximum possible for this compression algorithm (for example, slightly + * less than 4 GiB for zlib/deflate and slightly less than 2 GiB for LZ4 and + * BloscLZ). The number of elements in the arrays returned by the Compress() + * family of functions will depend on this value. + */ + void SetSubblockSize( size_type size ) + { + m_subblockSize = Range( size, size_type( 0 ), MaxBlockSize() ); + } + + /*! + * Returns true iff subblock checksums are currently enabled for this + * %Compression object. + * + * See EnableChecksums() for more information. + */ + bool ChecksumsEnabled() const + { + return m_checksums; + } + + /*! + * Enables subblock checksums for this %Compression object. + * + * When this option is enabled, a non-cryptographic checksum is computed for + * each compressed subblock and stored along with the subblock data. These + * checksums are computed again before decompression and compared with the + * stored values. This guarantees that the compressed data have not been + * altered. + * + * In current versions of PixInsight, the xxHash algorithm (64-bit version) + * is used for compressed subblock checksums. xxHash is an extremely fast + * hashing function, so its impact on compression/decompression speed is + * negligible. See the pcl::Hash64() function for details. + */ + void EnableChecksums( bool enable = true ) + { + m_checksums = enable; + } + + /*! + * Disables subblock checksums for this %Compression object. + * + * Equivalent to EnableChecksums( !disable ). + */ + void DisableChecksums( bool disable = true ) + { + EnableChecksums( !disable ); + } + + /*! + * Compresses a data block. + * + * \param data Starting address of the data block to be compressed. + * + * \param size Length in bytes of the data block to be compressed. + * + * \param perf If non-null, pointer to a Performance structure where + * performance data will be provided. + * + * Returns a dynamic array of compressed subblocks. Each array element is a + * Subblock structure with the compressed data, the uncompressed length in + * bytes, and an optional checksum. If compression succeeds, the returned + * array will have at least one element. + * + * If the specified \a size is zero, or if one or more subblocks are not + * compressible with this algorithm, this function returns an empty array. + * + * This function can only throw an exception if the specified \a data + * pointer is null, or in the event of an out-of-memory condition. + */ + subblock_list Compress( const void* data, size_type size, Performance* perf = nullptr ) const; + + /*! + * Compression of a direct container with contiguous storage. + * + * \param data Reference to a direct container with contiguous storage + * and PCL container semantics. Meaningful Begin() and Size() + * member functions are required. Typically, the ByteArray + * class is used, although any array-like direct container + * class is appropriate, including Array, String, Vector and + * Matrix, among others. + * + * \param perf If non-null, pointer to a Performance structure where + * performance data will be provided. + * + * Returns a dynamic array of compressed subblocks. Each array element is a + * Subblock structure with the compressed data, the uncompressed length in + * bytes, and an optional checksum. If compression succeeds, the returned + * array will have at least one element. + * + * If the specified container is empty, or if one or more subblocks are not + * compressible with this algorithm, this function returns an empty array. + * + * This function can only throw an exception in the event of an + * out-of-memory condition. + */ + template + subblock_list Compress( const C& data, Performance* perf = nullptr ) const + { + return Compress( data.Begin(), data.Size(), perf ); + } + + /*! + * Decompression of a set of compressed subblocks. + * + * \param data Starting address of the output uncompressed data block. + * + * \param maxSize Maximum space in bytes available at \a data. Must be + * equal to or larger than the total uncompressed size. + * + * \param subblocks Reference to a dynamic array of compressed subblocks. + * The specified array should be the result of a previous + * call to one of the Compress() functions for this + * algorithm. This object must have coherent ItemSize() + * and ByteShufflingEnabled() properties to match the ones + * used when the data was compressed. + * + * \param perf If non-null, pointer to a Performance structure where + * performance data will be provided. + * + * Upon successful completion, the uncompressed data will be available in + * the specified output \a data block, and the function will return the + * length in bytes of the uncompressed data (necessarily smaller than or + * equal to \a maxSize). + * + * In the event of errors, such as invalid or corrupted data, uncompressed + * block or subblock size mismatch, or an out-of-memory condition, this + * function throws an Error exception. In such case the data possibly stored + * in the output \a data buffer will be invalid. + */ + size_type Uncompress( void* data, size_type maxSize, + const subblock_list& subblocks, Performance* perf = nullptr ) const; + + /*! + * Decompression of a set of compressed subblocks. + * + * \param subblocks Reference to a dynamic array of compressed subblocks. + * The specified array should be the result of a previous + * call to one of the Compress() functions for this + * algorithm. This object must have coherent ItemSize() + * and ByteShufflingEnabled() properties to match the ones + * used when the data was compressed. + * + * \param perf If non-null, pointer to a Performance structure where + * performance data will be provided. + * + * Returns the uncompressed data as a ByteArray object. + * + * In the event of errors, such as invalid or corrupted data, uncompressed + * block or subblock size mismatch, or an out-of-memory condition, this + * function throws an Error exception. + */ + ByteArray Uncompress( const subblock_list& subblocks, Performance* perf = nullptr ) const + { + size_type uncompressedSize = 0; + for ( const Subblock& subblock : subblocks ) + uncompressedSize += subblock.uncompressedSize; + ByteArray data( uncompressedSize ); + (void)Uncompress( data.Begin(), uncompressedSize, subblocks, perf ); + return data; + } + + /*! + * Decompression of a compressed data block stored in a ByteArray object. + * Returns the uncompressed data as a ByteArray. + * + * See the Uncompress( const subblock_list&, Performance* ) const member + * function for more information. + */ + ByteArray Uncompress( const ByteArray& compressedData, + size_type uncompressedSize, Performance* perf = nullptr ) const + { + Subblock subblock; + subblock.compressedData = compressedData; + subblock.uncompressedSize = uncompressedSize; + return Uncompress( subblock_list() << subblock, perf ); + } + +private: + + int m_compressionLevel = 0; // 0 = use codec's default + size_type m_subblockSize = 0; // 0 = use largest possible subblocks + uint8 m_itemSize = 1; + bool m_byteShuffle = true; + bool m_checksums = true; + +protected: + + /*! + * Returns the length in bytes of the smallest contiguous data block that + * can be compressed with this algorithm. + */ + virtual size_type MinBlockSize() const = 0; + + /*! + * Returns the length in bytes of the largest contiguous data block that can + * be compressed with this algorithm. + */ + virtual size_type MaxBlockSize() const = 0; + + /*! + * Returns the maximum length in bytes of the contiguous block necessary to + * compress a contiguous block of the specified \a size in bytes. + */ + virtual size_type MaxCompressedBlockSize( size_type size ) const = 0; + + /*! + * Compression of a contiguous block starting at \a inputData with + * \a inputSize length in bytes, using the specified compression \a level. + * The compressed data will be written as a contiguous block starting at + * \a outputData, with length smaller than or equal to \a outputSize. + * Returns the number of bytes written to \a outputData, or zero if the data + * are not compressible. + */ + virtual size_type CompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize, int level ) const = 0; + + /*! + * Decompression of a contiguous compressed block starting at \a inputData + * with \a inputSize length in bytes. The uncompressed data will be written + * as a contiguous block starting at \a outputData, with length equal to + * \a outputSize. Returns the number of bytes written to \a outputData, + * which should be equal to \a outputSize, or smaller in the event of error. + */ + virtual size_type UncompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize ) const = 0; + + /*! + * Byte shuffling algorithm applied to \a size bytes starting at \a data, + * with element length \a itemSize in bytes. Returns the shuffled data as a + * ByteArray object. + */ + static ByteArray Shuffle( const uint8* data, size_type size, size_type itemSize ) + { + ByteArray shuffled( size ); + if ( size > 0 && data != nullptr ) + { + size_type numberOfItems = size / itemSize; + ByteArray::iterator s = shuffled.Begin(); + for ( size_type j = 0; j < itemSize; ++j ) + { + ByteArray::const_iterator u = data + j; + for ( size_type i = 0; i < numberOfItems; ++i, ++s, u += itemSize ) + *s = *u; + } + ::memcpy( s, data + numberOfItems*itemSize, size % itemSize ); + } + return shuffled; + } + + /*! + * Reverse byte shuffling algorithm (or \e unshuffling) applied to \a size + * bytes starting at \a data, with element length \a itemSize in bytes. + * Returns the unshuffled data as a ByteArray object. + */ + static ByteArray Unshuffle( const uint8* data, size_type size, size_type itemSize ) + { + ByteArray unshuffled( size ); + if ( size > 0 && data != nullptr ) + { + size_type numberOfItems = size / itemSize; + ByteArray::const_iterator s = data; + for ( size_type j = 0; j < itemSize; ++j ) + { + ByteArray::iterator u = unshuffled.At( j ); + for ( size_type i = 0; i < numberOfItems; ++i, ++s, u += itemSize ) + *u = *s; + } + ::memcpy( unshuffled.At( numberOfItems*itemSize ), s, size % itemSize ); + } + return unshuffled; + } + + /*! + * In-place reverse byte shuffling algorithm (or \e unshuffling) applied to + * \a size bytes starting at \a data, with element length \a itemSize in + * bytes. + */ + static void InPlaceUnshuffle( uint8* data, size_type size, size_type itemSize ) + { + if ( size > 0 && data != nullptr ) + { + const ByteArray shuffled( data, data+size ); + size_type numberOfItems = size / itemSize; + ByteArray::const_iterator s = shuffled.Begin(); + for ( size_type j = 0; j < itemSize; ++j ) + { + ByteArray::iterator u = data + j; + for ( size_type i = 0; i < numberOfItems; ++i, ++s, u += itemSize ) + *u = *s; + } + } + } + + /*! + * Helper function to throw an error message with inclusion of the algorithm + * name. + */ + void Throw( const String& errorMessage ) const; + + friend class PCL_CompressionEngine; + friend class PCL_DecompressionEngine; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ZLibCompression + * \brief Implementation of the ZLib/Deflate compression algorithm. + * + * This class implements the deflate lossless compression algorithm in the + * standard zlib format. This is the default PixInsight/XISF compression codec. + * + * The underlying implementation in the PixInsight core application is the + * well-known zlib library written by Jean-Loup Gailly and Mark Adler. + * + * \b References + * + * \li Jean-Loup Gailly, L. Peter Deutsch (1996), RFC 1950: ZLIB Compressed + * Data Format Specification version 3.3 + * + * \li Jean-Loup Gailly, L. Peter Deutsch (1996), RFC 1951: DEFLATE + * Compressed Data Format Specification version 1.3 + * + * \li Greg Roelofs, Mark Adler, Zlib Home Site: http://www.zlib.net/ + * + * \ingroup compression_classes + * \sa Compression, LZ4Compression, LZ4HCCompression, BloscLZCompression + */ +class PCL_CLASS ZLibCompression : public Compression +{ +public: + + /*! + * Returns the name of this data compression algorithm (ZLib). + */ + String AlgorithmName() const override + { + return "ZLib"; + } + + /*! + */ + int MaxCompressionLevel() const override; + + /*! + */ + int DefaultCompressionLevel() const override; + + +private: + + /*! + */ + size_type MinBlockSize() const override; + + /*! + */ + size_type MaxBlockSize() const override; + + /*! + */ + size_type MaxCompressedBlockSize( size_type size ) const override; + + /*! + */ + size_type CompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize, int level ) const override; + + /*! + */ + size_type UncompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class LZ4Compression + * \brief Implementation of the LZ4 compression algorithm. + * + * This class implements the LZ4 compression algorithm by Yann Collet. + * + * LZ4 is a lossless data compression algorithm focused on compression and + * decompression speed. + * + * The underlying implementation in the PixInsight core application is the + * reference implementation by Yann Collet, which has been released under a New + * BSD license. + * + * \b References + * + * \li LZ4 source code repository: https://github.com/Cyan4973/lz4 + * + * \li LZ4 website: http://cyan4973.github.io/lz4/ + * + * \ingroup compression_classes + * \sa Compression, LZ4HCCompression, ZLibCompression, BloscLZCompression + */ +class PCL_CLASS LZ4Compression : public Compression +{ +public: + + /*! + * Returns the name of this data compression algorithm (LZ4-HC). + */ + String AlgorithmName() const override + { + return "LZ4"; + } + + /*! + */ + int MaxCompressionLevel() const override; + + /*! + */ + int DefaultCompressionLevel() const override; + + +private: + + /*! + */ + size_type MinBlockSize() const override; + + /*! + */ + size_type MaxBlockSize() const override; + + /*! + */ + size_type MaxCompressedBlockSize( size_type size ) const override; + + /*! + */ + size_type CompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize, int level ) const override; + + /*! + */ + size_type UncompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class LZ4HCCompression + * \brief Implementation of the LZ4-HC compression algorithm. + * + * This class implements the LZ4 compression algorithm (high compression + * variant) by Yann Collet. + * + * LZ4 is a lossless data compression algorithm focused on compression and + * decompression speed. + * + * The underlying implementation in the PixInsight core application is the + * reference implementation by Yann Collet, which has been released under a New + * BSD license. + * + * \b References + * + * \li LZ4 source code repository: https://github.com/Cyan4973/lz4 + * + * \li LZ4 website: http://cyan4973.github.io/lz4/ + * + * \ingroup compression_classes + * \sa Compression, LZ4Compression, ZLibCompression, BloscLZCompression + */ +class PCL_CLASS LZ4HCCompression : public Compression +{ +public: + + /*! + * Returns the name of this data compression algorithm (LZ4-HC). + */ + String AlgorithmName() const override + { + return "LZ4-HC"; + } + + /*! + */ + int MaxCompressionLevel() const override; + + /*! + */ + int DefaultCompressionLevel() const override; + + +private: + + /*! + */ + size_type MinBlockSize() const override; + + /*! + */ + size_type MaxBlockSize() const override; + + /*! + */ + size_type MaxCompressedBlockSize( size_type size ) const override; + + /*! + */ + size_type CompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize, int level ) const override; + + /*! + */ + size_type UncompressBlock( void* outputData, size_type outputSize, + const void* inputData, size_type inputSize ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Compression_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Compression.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Console.h b/3rdparty/include/pcl/Console.h new file mode 100644 index 0000000..265d402 --- /dev/null +++ b/3rdparty/include/pcl/Console.h @@ -0,0 +1,829 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Console.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_Console_h +#define __PCL_Console_h + +/// \file pcl/Console.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS View; + +/*! + * \class Console + * \brief A high-level interface to a PixInsight processing console. + * + * The PixInsight platform provides three different user interfaces implemented + * in the PixInsight core application: a graphical user interface (GUI), a + * scripting interface (the PixInsight JavaScript runtime), and a command-line + * interface. The %Console class is a high-level abstraction that represents + * the %Process %Console window of the PixInsight core application, which + * implements the entire command-line and console text input/output + * functionality in PixInsight. + * + * A module can instantiate %Console to perform direct text input/output + * operations. %Console objects are often used to display information about + * ongoing processes, to let the user abort a process, or to put a process in a + * wait state to perform a modal user interface operation (e.g., showing a + * message box) in a thread-safe way. + * + * From the module developer perspective, each module has an associated + * console. Such associations between modules and consoles are managed + * automatically by internal core and PCL routines: module developers just need + * to instantiate the %Console class and use its member functions. + * + * For example, writing a message to the console can be as simple as: + * + * \code + * Console().WriteLn( "Hello, PixInsight" ); + * \endcode + * + * Stream-style console insertion and extraction operators are also available. + * For example, this is equivalent to the above code: + * + * \code + * Console() << "Hello, PixInsight" << '\n'; + * \endcode + * + * When you need to output formatted data, you can use the String::Format() + * family of functions. These functions are similar to the standard printf() C + * runtime function: + * + * \code + * Console console; + * console.WriteLn( String().Format( "Radius = %.6f, Angle = %+.2f°", r, Deg( a ) ) ); + * \endcode + * + * PixInsight consoles can understand and reproduce the full set of ISO-8859-1 + * HTML entities. You see an example on the code fragment above: the \c "°" + * entity prints a degree symbol on the console. + * + * PixInsight consoles can also interpret a number of \e tags, similar to HTML, + * to perform special actions and formatting operations. For example: + * + * \code + * Console() << "This is bold and this is italics
"; + * \endcode + * + * In this example, the "" tag moves the cursor after the last character + * in the console, then the "" tag (conditional break) generates + * a new line only if the current line is not empty. This ensures that + * subsequent text output will start on an empty line at the end of the current + * console contents. The "" and "" tags write text in a bold type face, + * and the "" and "" pair write text in italics. This is just a minimal + * fraction of the rich set of tags understood by PixInsight consoles. + * + * As we describe in detail below, PixInsight consoles support standard ANSI + * escape codes, and can also be used to render inline HTML contents. + * + * It must be pointed out that the entire text output functionality of %Console + * is also available for TextBox controls. A module can instantiate a %TextBox + * control to provide rich text-based output as a process log, the output of an + * external process, or an information panel based on HTML tables, just to name + * a few possibilities implemented frequently. + * + *

%Console Tags

+ * + * Here is a comprehensive list of supported console tags at the time of + * publishing this documentation. New functionality implemented through console + * tags will be documented here as new versions are released. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
\\ Enables/disables bold text.
\\ Enables/disables italics text.
\\ Enables/disables underlined text.
\\ Enables/disables overlined text.
\\ Enables/disables subscript text.
\\ Enables/disables superscript text.
\ Line break.
\
Line break, XML compliant (same as \).
\ Conditional line break: sends a line break if the cursor is not at the beginning of an empty line.
\ Conditional line break, XML compliant (same as \).
\ Backspace: deletes the previous character and moves the cursor one step left, only if it is not at the beginning of a line.
\ Moves the cursor to the end of the console.
\ Moves the cursor to the beginning of the console.
\ Moves the cursor to the previous character, only if it is not at the beginning of a line.
\ Moves the cursor to the next character, only if it is not at the end of a line.
\ Moves the cursor to the end of the current line.
\ Moves the cursor to the beginning of the current line.
\ Moves the cursor to the previous line, if it is not already at the first line.
\ Moves the cursor to the next line, if it is not already at the last line.
\ Clears the console. Avoid issuing this tag arbitrarily - please see the documentation for Console::Clear() for more information.
\ Deletes the text from the current cursor position (included) to the end of the current line.
\ Deletes the text from the current cursor position (included) to the beginning of the current line.
\ Deletes the text from the current cursor position (included) to the end of the console.
\ Deletes the text from the current cursor position (included) to the beginning of the console. Avoid issuing this tag arbitrarily - please see the documentation for Console::Clear() for more information.
\\ Disables/enables word wrapping of text lines.
\\ Disables/enables tag interpretation, except the \ tag, which is always interpreted.
\\ Disables/enables interpretation of ISO-8859-1 entities.
\\ Disables/enables interpretation of tags, except the \ tag, and ISO-8859-1 entities. \ is equivalent to (but faster than) \\.
\\ Equivalent to \\. Useful to show source code fragments.
\ Selects a platform-dependent, monospaced font.
\ Selects a platform-dependent, sans-serif font.
\ Selects a platform-dependent, serif font.
\ Selects the Courier font, or the nearest available monspaced font, depending on the platform.
\ Selects the Helvetica font, or the nearest available sans-serif font, depending on the platform.
\ Selects the Times font, or the nearest available serif font, depending on the platform.
\ Selects the default console font (usually a monospaced font; but user-selectable through preferences).
\ Resets all text settings and styles to default values.
\ If this console corresponds to the processing console window, shows it if it's currently hidden and docked in the PixInsight core application window; otherwise this tag is ignored. Equivalent to calling the Console::Show() member function.
\ If this console corresponds to the processing console window, hides it if it's currently visible and docked in the PixInsight core application window; otherwise this tag is ignored. Equivalent to calling the Console::Hide() member function.
\ Causes any pending data to be written immediately to the console. If there is no unwritten data for this console, this tag has no effect. Equivalent to calling the Console::Flush() member function.
\\ Enables/disables HTML mode. In HTML mode, the console interprets and renders a comprehensive set of HTML 4 tags, including full support of tables, as well as a significant part of Level 2 CSS (Cascading Style Sheets) directives. In HTML mode, PixInsight console tags are either ignored or interpreted with their corresponding meaning in HTML 4.
+ * + * In addition, the \\n, \\r and \\b escape characters can be used in place of + * the \, \ and \ tags, respectively. + * + *

Character Entities

+ * + * PixInsight consoles fully recognize and interpret the whole set of + * HTML 4 character entities, including all ISO 8859-1 characters and all + * character entities for symbols, mathematical symbols, Greek letters, + * markup-significant and internationalization characters. + * + * Character entities are of the form: + * + * \; + * + * where \ is one of the references included in the + * following W3C Recommendation document: + * + * http://www.w3.org/TR/REC-html40/sgml/entities.html + * + *

HTML Mode

+ * + * The \ tag allows you to put a PixInsight console in HTML + * mode. In this mode you can embed HTML 4 contents directly. For example, + * this code: + * + * \code + * Console console; + * console.Write( "" + * "" + * "" + * "" + * "
If this is foo and this is bar,
then this can only be foo bar.
" + * "" ); \endcode + * + * generates an HTML table with two rows and two columns. PixInsight consoles + * support most of the HTML 4 specification, including a subset of CSS2. For + * detaled information, this document describes HTML support in Qt, which is + * the underlying implementation in current versions of PixInsight: + * + * http://qt-project.org/doc/qt-4.8/richtext-html-subset.html + * + * In HTML mode, that is, within a pair of \\ tags, no + * PixInsight console tags or ANSI escape codes are recognized or interpreted. + * + *

ANSI Escape Codes

+ * + * Since version 1.8.1 of the PixInsight core application, PixInsight consoles + * support a large set of ANSI CSI (Control Sequence Introducer) codes. For a + * detailed description of ANSI escape codes, refer to the following documents: + * + * http://en.wikipedia.org/wiki/ANSI_escape_code + * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * + * The following table describes the supported CSI codes in the current version + * of PixInsight. ESC represents the escape control character, whose ASCII code + * is 2710 = 1B16. The CSI sequence is ESC followed by + * the left square bracket character, represented as the ESC[ sequence. See the + * examples given at the end of the table. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ESC[ n A %Cursor up n Times (default n=1) (CUU)
ESC[ n B %Cursor down n Times (default n=1) (CUD)
ESC[ n C %Cursor forward n Times (default n=1) (CUF)
ESC[ n D %Cursor backward n Times (default n=1) (CUB)
ESC[ n E %Cursor to next line n Times (default n=1) (CNL)
ESC[ n F %Cursor to preceding line n Times (default n=1) (CPL)
ESC[ n G %Cursor to character absolute column n (default n=1) (CHA)
ESC[ n;m H %Cursor position to row n and column m (default n=m=1) (CUP)
ESC[ n;m f Horizontal & Vertical Position (HVP). Same as H.
ESC[ n J Erase in Display (ED)
+ * + * + * + * + *
n = 0 Erase below up to the end of text. This is the default if no n is specified.
n = 1 Erase above up to the start of text.
n = 2 Erase all (entire console).
ESC[ n K Erase in Line (EL)
+ * + * + * + * + *
n = 0 Erase to right up to the end of line. This is the default if no n is specified.
n = 1 Erase to left up to the start of line.
n = 2 Erase the whole line.
ESC[ n L Insert n line(s) (default n=1) (IL)
ESC[ n M Delete n line(s) (default n=1) (DL)
ESC[ n P Delete n character(s) (default n=1) (DCH)
ESC[ ... m Set graphics rendition (SGR)
+ * The ellipsis represents a list of one or more integer arguments separated by semi-colons. The following arguments are recognized:
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
0 Reset all font and color properties to default values.
1 Bold font
2 Faint (decreased intensity) - ignored (not implemented)
3 Italic font
4 Underline font
5 Blink (slow) - reinterpreted - selects a bold font.
6 Blink (fast) - reinterpreted - selects a bold font.
7 Inverse colors (swap default foreground and background)
8 Invisible - ignored (not implemented)
9 Strike out font
21 Bold font: disable
22 Normal color - ignored (not implemented)
23 Italic font: disable
24 Underline font: disable
25 Blink: disable - reinterpreted - disables bold font (same as 21).
27 Inverse colors: disable
28 Visible - ignored (not implemented)
29 Strike out font: disable
30 ... 37 Set foreground color to n-30: 0=black, 1=red, 2=green, 3=yellow, 4=blue, 5=magenta, 6=cyan, 7=white.
38 KDE's Konsole extended 24-bit color space: Set foreground color (see note below).
39 Default foreground color.
40 ... 47 Set background color to n-40. Colors are the same as for 30 ... 37.
48 KDE's Konsole extended 24-bit color space: Set background color (see note below).
49 Default background color.
53 Overline font
55 Overline font: disable
ESC[s Save %Cursor Position (SCP)
ESC[u Restore %Cursor Position (RCP)
+ * + * KDE Konsole 24-bit colors use the following format: + * + * Select RGB foreground color: ESC[ ... 38;2;r;g;b ... m
+ * Select RGB background color: ESC[ ... 48;2;r;g;b ... m + * + * where r, g and b are the red, green and blue components in the [0,255] + * range. For detailed information on these codes, see the following document: + * + * https://projects.kde.org/projects/kde/applications/konsole/repository/revisions/master/entry/doc/user/README.moreColors + * + * Examples + * + * Write a text line using a bold font: + * + * \code + * Console().WriteLn( "\x1b[1mThis is bold text\x1b[21m" ); \endcode + * + * Write a text line in orange color using an italic font: + * + * \code + * String programName; + * Console().WriteLn( "
\x1b[3;38;2;255;128;0m" + programName + "\x1b[39;23m" ); \endcode + * + * Write some text at the beginning of the current line, removing any previous + * contents: + * + * \code + * Console().Write( "\x1b[2KThis text replaces the whole line" ); \endcode + * + * \sa StatusMonitor, StandardStatus, SpinStatus, MuteStatus, Thread + */ +class PCL_CLASS Console +{ +public: + + /*! + * Constructs a %Console object. + */ + Console(); + + /*! + * Copy constructor, disabled because %Console instances represent unique + * objects that cannot be copied. + */ + Console( const Console& ) = delete; + + /*! + * Move constructor. + */ + Console( Console&& x ) + : m_handle( x.m_handle ) + , m_thread( x.m_thread ) + { + x.m_handle = x.m_thread = nullptr; + } + + /*! + * Copy assignment operator, disabled because %Console instances represent + * unique objects that cannot be copied. + */ + Console& operator =( const Console& ) = delete; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Console& operator =( Console&& x ) + { + if ( &x != this ) + { + m_handle = x.m_handle; + m_thread = x.m_thread; + x.m_handle = x.m_thread = nullptr; + } + return *this; + } + + /*! + * Destroys a %Console object. + */ + virtual ~Console(); + + /*! + * Writes an Unicode string \a s to this console. + */ + void Write( const String& s ); + + /*! + * Writes an Unicode string \a s to this console and appends a newline + * escape character ('\\n'). + * + * Note that this function is faster than appending a newline character to + * the string, such as a call to Write( s + '\\n' ). + */ + void WriteLn( const String& s ); + + /*! + * Sends a single newline escape character ('\\n') to the console. + * + * Note that this function is faster than writing a newline directly with a + * call to Write( '\\n' ). + */ + void WriteLn(); + + /*! + * Writes an informative note message to this console. + * + * This function writes the specified Unicode string \a s using standard + * ANSI terminal color number 2 (green in the default palette). The + * implementation of this member function uses ANSI escape codes. + */ + void Note( const String& s ) + { + Write( "\x1b[32m" + s + "\x1b[39m" ); + } + + /*! + * Writes an informative note message to this console and appends a newline + * escape character ('\\n'). + * + * See the description of Note( const String& ). + */ + void NoteLn( const String& s ) + { + WriteLn( "\x1b[32m" + s + "\x1b[39m" ); + } + + /*! + * Writes a warning message to this console. + * + * This function writes the specified Unicode string \a s using standard + * ANSI terminal color number 5 (magenta in the default palette). The + * implementation of this member function uses ANSI escape codes. + */ + void Warning( const String& s ) + { + Write( "\x1b[35m" + s + "\x1b[39m" ); + } + + /*! + * Writes a warning message to this console and appends a newline escape + * character ('\\n'). + * + * See the description of Warning( const String& ). + */ + void WarningLn( const String& s ) + { + WriteLn( "\x1b[35m" + s + "\x1b[39m" ); + } + + /*! + * Writes a critical error message to this console. + * + * This function writes the specified Unicode string \a s using standard + * ANSI terminal color number 1 (red in the default palette). The + * implementation of this member function uses ANSI escape codes. + */ + void Critical( const String& s ) + { + Write( "\x1b[31m" + s + "\x1b[39m" ); + } + + /*! + * Writes a critical error message to this console and appends a newline + * escape character ('\\n'). + * + * See the description of Critical( const String& ). + */ + void CriticalLn( const String& s ) + { + WriteLn( "\x1b[31m" + s + "\x1b[39m" ); + } + + /*! + * Reads a single character from this console and returns it. + * + * This function puts the current thread in wait state, then waits until a + * character can be obtained in the core application's GUI thread. This + * usually involves waiting for a keyboard event. + * + * \note This member function has not been implemented in the current PCL + * version. Calling it has not effect, and zero is always returned. + */ + int ReadChar(); + + /*! + * Reads a string from this console and returns it. + * + * This function puts the current thread in wait state, then opens a simple + * modal dialog box with a single-line edit control, where the user may + * enter a string. If the user cancels the input dialog, an empty string is + * returned. + * + * \note This member function has not been implemented in the current PCL + * version. Calling it has not effect, and an empty string is always + * returned. + */ + String ReadString(); + + /*! + * Returns true iff the current processing thread has been suspended by the + * PixInsight core application. + */ + bool Suspended() const; + + /*! + * Returns true iff the current processing thread is in wait state. + */ + bool Waiting() const; + + /*! + * Returns true iff the current processing thread can be aborted by the user. + */ + bool AbortEnabled() const; + + /*! + * Returns true iff the user has requested to abort execution of the current + * processing thread. + */ + bool AbortRequested() const; + + /*! + * Resets the current processing thread status. + * + * This function is useful to ignore an abort request for the current + * processing thread. For example, if the user requests to abort execution, + * a module may ask if she or he really wants to cancel, and if the user + * answers 'No', then this member function can be called to clear the + * existing abort request condition. + * + * \note This function must only be called when there is an active process + * running in the current module. It can only be called from the thread + * where either a reimplemented ProcessImplementation::ExecuteOn() or + * ProcessImplementation::ExecuteGlobal() member function has been invoked. + * An Error exception will be thrown otherwise. + */ + void ResetStatus(); + + /*! + * Enables abort requests for the current processing thread. + * + * \note This function must only be called when there is an active process + * running in the current module. It can only be called from the thread + * where either a reimplemented ProcessImplementation::ExecuteOn() or + * ProcessImplementation::ExecuteGlobal() member function has been invoked. + * An Error exception will be thrown otherwise. + */ + void EnableAbort(); + + /*! + * Disables abort requests for the current processing thread. + * + * \note This function must only be called when there is an active process + * running in the current module. It can only be called from the thread + * where either a reimplemented ProcessImplementation::ExecuteOn() or + * ProcessImplementation::ExecuteGlobal() member function has been invoked. + * An Error exception will be thrown otherwise. + */ + void DisableAbort(); + + /*! + * Accepts a pending abort request. + * + * \note This function must only be called when there is an active process + * running in the current module. It can only be called from the thread + * where either a reimplemented ProcessImplementation::ExecuteOn() or + * ProcessImplementation::ExecuteGlobal() member function has been invoked. + * An Error exception will be thrown otherwise. + */ + void Abort(); + + /*! + * Returns true iff this is a valid console object associated to an active + * processing thread. + */ + bool IsValid() const; + + /*! + * Returns true iff this console is valid and has been created by the + * calling thread; either by the root thread or by a running Thread object. + */ + bool IsCurrentThreadConsole() const; + + /*! + * Causes any pending data to be written immediately to this console. If + * there is no unwritten data for this console, this function has no effect. + */ + void Flush(); + + /*! + * Shows the %Process %Console window in the PixInsight core application. + * + * The visibility of a console can only be controlled if it is the process + * console window. Furthermore, a module cannot show or hide the console if + * it is not owned by a docked window; the visibility of a floating window + * cannot be changed programmatically from a module. + * + * This function returns true if the console could be shown (or hidden) + * successfully. Unlike most interface operations, console hide/show + * operations are not cached, so if this function returns true then you know + * that the %Process %Console window is currently visible. + * + * \note Calling this function from a running thread has no effect. Console + * visibility can only be changed from the root thread. + */ + bool Show( bool show = true ); + + /*! + * Hides the %Process %Console window in the PixInsight core application. + * + * This is a convenience function, equivalent to: Show( !hide ) + * + * Returns true iff the console could be hidden (or shown) successfully. + * Refer to the Show() member function for more information. + * + * \note Calling this function from a running thread has no effect. Console + * visibility can only be changed from the root thread. + */ + bool Hide( bool hide = true ) + { + return Show( !hide ); + } + + /*! + * Clears the console. This is a convenience function that simply writes the + * \ tag to the console. + * + * \note Calling this function from a running thread has no effect. The + * console output text of a Thread object cannot be erased by this function. + * + * \note In general, call this function only as a result of an explicit user + * request to clear the console. Clearing the console arbitrarily, without + * having an extremely good reason, is considered bad practice and can be + * a good argument to deny certification of a module. + */ + void Clear(); + + /*! + * + */ + void ExecuteCommand( const String& command ); + + /*! + * Executes a script file. + * + * \param filePath Path to the script file that will be executed. Must be + * a path to an existing script on the local filesystem. + * + * \param arguments A dynamic array, possibly empty, of StringKeyValue + * objects. Each object in this array represents a script + * argument. The key member is the parameter name, and the + * value member is the corresponding parameter value. + * + * The core application will load, parse, authorize and execute the + * specified script file. The scripting language will be detected + * automatically from the file name suffix in \a filePath. Currently the + * .scp and .js suffixes are interpreted for command-line shell scripts and + * JavaScript scripts, respectively. Future versions may accept more + * languages and apply language detection heuristics besides file suffixes. + * + * This member function returns normally if the script was loaded and + * executed. In the event of error, for example if the specified file does + * not exist or can't be accessed, or in the event of security errors or + * failure to authorize script execution from the calling module, this + * member function throws an Error exception. + * + * Note that command-line or JavaScript runtime execution errors cannot be + * reported by this function. That means that this function knows nothing + * about whether the script worked or not correctly, or if it did what was + * expected. + * + * For execution of JavaScript scripts, this function is equivalent to + * ExecuteScriptGlobal(), that is, JavaScript scripts are always executed in + * the global context by default. When executed, the JavaScript script will + * see the following static properties of the %Parameters JS runtime object: + * + * \c Parameters.isGlobalTarget will be set to true. \n + * \c Parameters.isViewTarget will be set to false. \n + * \c Parameters.targetView will be set to \c undefined. + * + * See ExecuteScriptOn() for execution of scripts in view contexts. + * + * \note If this function is called from a running thread, an Error + * exception will be thrown and nothing will be executed. In current + * versions of the PixInsight platform, scripts can only be executed from + * the root thread. The main reason for this limitation is that the + * JavaScript and command-line execution engines are not reentrant. + */ + void ExecuteScript( const String& filePath, const StringKeyValueList& arguments = StringKeyValueList() ); + + /*! + * Executes a script file in the global context. This is the default + * execution execution mode for all scripts. + * + * When a JavaScript script is executed through this member function, the + * following static properties of the %Parameters runtime object will be + * defined as described below: + * + * \c Parameters.isGlobalTarget will be set to true. \n + * \c Parameters.isViewTarget will be set to false. \n + * \c Parameters.targetView will be set to \c undefined. + * + * See ExecuteScript() for a detailed description of script execution from + * PCL/C++ code. + */ + void ExecuteScriptGlobal( const String& filePath, const StringKeyValueList& arguments = StringKeyValueList() ); + + /*! + * Executes a script file in the context of the specified \a view. + * + * When a JavaScript script is executed through this member function, the + * following static properties of the %Parameters runtime object will be + * defined as described below: + * + * \c Parameters.isGlobalTarget will be set to false. \n + * \c Parameters.isViewTarget will be set to true. \n + * \c Parameters.targetView will reference the specified \a view. + * + * See ExecuteScript() for a detailed description of script execution from + * PCL/C++ code. + */ + void ExecuteScriptOn( const View& view, const String& filePath, const StringKeyValueList& arguments = StringKeyValueList() ); + +protected: + + void* m_handle = nullptr; + +private: + + void* m_thread = nullptr; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup console_operators Console Insertion and Extraction Operators + */ + +/*! + * Writes an object \a t to the console \a o. The type T must have + * convert-to-string semantics. Returns a reference to the console \a o. + * \ingroup console_operators + */ +template +inline Console& operator <<( Console& o, T t ) +{ + o.Write( String( t ) ); + return o; +} + +/*! + * Writes a null-terminated string \a s to the console \a o. + * Returns a reference to the console \a o. + * \ingroup console_operators + */ +inline Console& operator <<( Console& o, const char* s ) +{ + o.Write( s ); + return o; +} + +/*! + * Writes a string \a s to the console \a o. + * Returns a reference to the console \a o. + * \ingroup console_operators + */ +inline Console& operator <<( Console& o, const String& s ) +{ + o.Write( s ); + return o; +} + +/*! + * Reads a character \a c from the console \a o. + * Returns a reference to the console \a o. + * \ingroup console_operators + */ +inline Console& operator >>( Console& o, char& c ) +{ + c = o.ReadChar(); + return o; +} + +/*! + * Reads a string \a s from the console \a o. + * Returns a reference to the console \a o. + * \ingroup console_operators + */ +inline Console& operator >>( Console& o, String& s ) +{ + s = o.ReadString(); + return o; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Console_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Console.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Constants.h b/3rdparty/include/pcl/Constants.h new file mode 100644 index 0000000..9c51ad2 --- /dev/null +++ b/3rdparty/include/pcl/Constants.h @@ -0,0 +1,199 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Constants.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_Constants_h +#define __PCL_Constants_h + +/// \file pcl/Constants.h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Const + * \brief Fundamental numeric constants + * + * Specialize this class to obtain constants of the appropriate floating-point + * types. For example: Const::pi() + */ +template +class PCL_CLASS Const +{ +public: + + /*! + * pi/4 (45 degrees) + */ + static constexpr T pi4 () { return T( 0.785398163397448309615660845819875725e+00L ); } + + /*! + * pi/2 (90 degrees) + */ + static constexpr T pi2 () { return T( 0.157079632679489661923132169163975145e+01L ); } + + /*! + * 3*pi/4 (135 degrees) + */ + static constexpr T _3pi4 () { return T( 0.2356194490192344928846982537459627175e+01L ); } + + /*! + * The pi constant (180 degrees) + */ + static constexpr T pi () { return T( 0.31415926535897932384626433832795029e+01L ); } + + /*! + * 5*pi/4 (225 degrees) + */ + static constexpr T _5pi4 () { return T( 0.3926990816987241548078304229099378625e+01L ); } + + /*! + * 3*pi/2 (270 degrees) + */ + static constexpr T _3pi2 () { return T( 0.471238898038468985769396507491925435e+01L ); } + + /*! + * 7*pi/4 (315 degrees) + */ + static constexpr T _7pi4 () { return T( 0.5497787143782138167309625920739130075e+01L ); } + + /*! + * 2*pi (360 degrees) + */ + static constexpr T _2pi () { return T( 0.62831853071795864769252867665590058e+01L ); } + + /*! + * 1/pi + */ + static constexpr T _1_pi () { return T( 0.3183098861837906715377675267450287224677e+00L ); } + + /*! + * 2/pi + */ + static constexpr T _2_pi () { return T( 0.6366197723675813430755350534900574449355e+00L ); } + + /*! + * 2/sqrt( pi ) + */ + static constexpr T _2_sqrtpi () { return T( 0.11283791670955125738961589031215451688501e+01L ); } + + /*! + * 180/pi - the radians-to-degrees conversion factor. + */ + static constexpr T deg () { return T( 0.572957795130823208767981548141051700441964e+02L ); } + + /*! + * Pi/180 - the degrees-to-radians conversion factor. + */ + static constexpr T rad () { return T( 0.174532925199432957692369076848861272222e-01L ); } + + /*! + * The Euler constant e. + */ + static constexpr T e () { return T( 0.27182818284590452353602874713526625e+01L ); } + + /*! + * log2( e ) + */ + static constexpr T log2e () { return T( 0.14426950408889634073599246810018920709799e+01L ); } + + /*! + * log2( 10 ) + */ + static constexpr T log210 () { return T( 0.33219280948873623478703194294893900118996e+01L ); } + + /*! + * log10( e ) + */ + static constexpr T log10e () { return T( 0.4342944819032518276511289189166050837280e+00L ); } + + /*! + * log10( 2 ) + */ + static constexpr T log102 () { return T( 0.3010299956639811952137388947244930416265e+00L ); } + + /*! + * ln( 2 ) + */ + static constexpr T ln2 () { return T( 0.6931471805599453094172321214581766e+00L ); } + + /*! + * ln( 10 ) + */ + static constexpr T ln10 () { return T( 0.23025850929940456840179914546843642e+01L ); } + + /*! + * sqrt( 2 ) + */ + static constexpr T sqrt2 () { return T( 0.14142135623730950488016887242096980785696e+01L ); } + + /*! + * 1/sqrt( 2 ) = sqrt( 2 )/2 + */ + static constexpr T _1_sqrt2 () { return T( 0.7071067811865475244008443621048490392848e+00L ); } + + /*! + * sqrt( 2 )/2 = 1/sqrt( 2 ) + */ + static constexpr T sqrt2_2 () { return T( 0.7071067811865475244008443621048490392848e+00L ); } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Constants_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Constants.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Container.h b/3rdparty/include/pcl/Container.h new file mode 100644 index 0000000..9ec34ab --- /dev/null +++ b/3rdparty/include/pcl/Container.h @@ -0,0 +1,134 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Container.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_Container_h +#define __PCL_Container_h + +/// \file pcl/Container.h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Container + * \brief Root base class of all PCL containers. + */ +class PCL_CLASS Container +{ +}; + +/*! + * \class DirectContainer + * \brief Root base class of all PCL containers of objects. + */ +template +class PCL_CLASS DirectContainer : public Container +{ +public: + + typedef T item_type; +}; + +/*! + * \class IndirectContainer + * \brief Root base class of all PCL containers of pointers to objects. + */ +template +class PCL_CLASS IndirectContainer : public Container +{ +public: + + typedef T* item_type; +}; + +/*! + * \class DirectSortedContainer + * \brief Root base class of all PCL sorted containers of objects. + */ +template +class PCL_CLASS DirectSortedContainer: public DirectContainer +{ +}; + +/*! + * \class IndirectSortedContainer + * \brief Root base class of all PCL sorted containers of pointers to objects. + */ +template +class PCL_CLASS IndirectSortedContainer : public IndirectContainer +{ +}; + +#define PCL_ASSERT_DIRECT_CONTAINER( C, T ) \ + static_assert( std::is_base_of, C>::value, \ + "Argument type must derive from DirectContainer." ) + +#define PCL_ASSERT_INDIRECT_CONTAINER( C, T ) \ + static_assert( std::is_base_of, C>::value, \ + "Argument type must derive from IndirectContainer." ) + +#define PCL_ASSERT_CONTAINER( C, T ) \ + static_assert( std::is_base_of, C>::value \ + || std::is_base_of, C>::value, \ + "Argument type must derive from DirectContainer or IndirectContainer." ) + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Container_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Container.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Control.h b/3rdparty/include/pcl/Control.h new file mode 100644 index 0000000..965dd3c --- /dev/null +++ b/3rdparty/include/pcl/Control.h @@ -0,0 +1,1869 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Control.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_Control_h +#define __PCL_Control_h + +/// \file pcl/Control.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FocusStyle + * \brief Control focus styles + * + * Focus styles refer to the way a control can gain the keyboard focus. + * + * + * + * + * + * + * + *
FocusStyle::NoFocus The control does not accept the keyboard focus
FocusStyle::Tab The control can be focused by pressing the tab key
FocusStyle::Click The control can be focused by clicking on it with the mouse
FocusStyle::Wheel The control can be focused with the mouse wheel
FocusStyle::TextListTab Special mode reserved for macOS
+ */ +namespace FocusStyle +{ + enum mask_type + { + NoFocus = 0x00, // The control doesn't accept focus + Tab = 0x01, // Can focus control by pressing the tab key + Click = 0x02, // Can focus control by mouse clicking + Wheel = 0x04, // Can focus control with the mouse wheel + TextListTab = 0x08 // macOS only + }; +} + +/*! + * A combination of focus styles. + */ +typedef Flags FocusStyles; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +class PCL_CLASS View; + +/*! + * \class Control + * \brief Client-side interface to a PixInsight %Control object + * + * ### TODO: Write a detailed description for %Control. + */ +class PCL_CLASS Control : public UIObject +{ +public: + + /*! + * Constructs a control as a child of \a parent. If no non-null parent is + * specified, the control will be an independent object not associated (in + * the hierarchical sense) to any graphical interface element. + * + * The second \c uint32 argument is not used; it is reserved for future + * extensions, and must be zero in current PCL versions. + */ + Control( Control& parent = Null(), uint32 = 0 ); + + /*! + * Destroys a %Control object. + */ + virtual ~Control() + { + } + + /*! + * Copy constructor. Copy and move semantics are disabled for UI controls + * because of client/server parent-children and event handling relations. + */ + Control( const Control& ) = delete; + + /*! + * Copy assignment. Copy and move semantics are disabled for UI controls + * because of client/server parent-children and event handling relations. + */ + Control& operator =( const Control& ) = delete; + + /*! + * Move constructor. Copy and move semantics are disabled for UI controls + * because of client/server parent-children and event handling relations. + */ + Control( Control&& ) = delete; + + /*! + * Move assignment. Copy and move semantics are disabled for UI controls + * because of client/server parent-children and event handling relations. + */ + Control& operator =( Control&& ) = delete; + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since server-side controls are unique objects, calling this member + * function has no effect. + */ + void EnsureUnique() override + { + } + + /*! + * Returns a reference to a null %Control instance. A null %Control does not + * correspond to an existing control in the PixInsight core application. + */ + static Control& Null(); + + /*! + * Returns the frame rectangle of this control. + */ + pcl::Rect FrameRect() const; + + /*! + * Returns the frame width of this control in pixels. + */ + int FrameWidth() const + { + return FrameRect().Width(); + } + + /*! + * Returns the frame height of this control in pixels. + */ + int FrameHeight() const + { + return FrameRect().Height(); + } + + /*! + * Returns the client rectangle of this control in parent coordinates. + */ + pcl::Rect ClientRect() const; + + /*! + * Returns the width in pixels of the client area of this control. + */ + int ClientWidth() const + { + return ClientRect().Width(); + } + + /*! + * A convenient synonym for ClientWidth(). + */ + int Width() const + { + return ClientWidth(); + } + + /*! + * Returns the height in pixels of the client area of this control. + */ + int ClientHeight() const + { + return ClientRect().Height(); + } + + /*! + * A convenient synonym for ClientHeight(). + */ + int Height() const + { + return ClientHeight(); + } + + /*! + * Returns the client rectangle of this control in client coordinates. + * This function is equivalent to: + * Rect( 0, 0, ClientWidth(), ClientHeight() ) + */ + pcl::Rect BoundsRect() const + { + pcl::Rect r( ClientRect() ); + return pcl::Rect( r.Width(), r.Height() ); + } + + /*! # + */ + void SetClientRect( const pcl::Rect& r ) + { + SetClientRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void SetClientRect( int x0, int y0, int x1, int y1 ); + + /*! # + */ + void Resize( int w, int h ); + + /*! # + */ + void AdjustToContents(); + + /*! + * Returns the minimum width in pixels of the client rectangle. + */ + int MinWidth() const + { + int w, dum; GetMinSize( w, dum ); return w; + } + + /*! + * Returns the minimum height in pixels of the client rectangle. + */ + int MinHeight() const + { + int dum, h; GetMinSize( dum, h ); return h; + } + + /*! # + */ + void GetMinSize( int& w, int& h ) const; + + /*! # + */ + void SetMinWidth( int w ) + { + SetMinSize( w, -1 ); + } + + /*! # + */ + void SetMinWidth() + { + SetMinWidth( Width() ); + } + + /*! # + */ + void SetMinHeight( int h ) + { + SetMinSize( -1, h ); + } + + /*! # + */ + void SetMinHeight() + { + SetMinHeight( Height() ); + } + + /*! # + */ + void SetMinSize( int w, int h ); + + /*! # + */ + void SetMinSize() + { + SetMinSize( Width(), Height() ); + } + + /*! + * Returns the maximum width in pixels of the client rectangle. + */ + int MaxWidth() const + { + int w, dum; GetMaxSize( w, dum ); return w; + } + + /*! + * Returns the maximum height in pixels of the client rectangle. + */ + int MaxHeight() const + { + int dum, h; GetMaxSize( dum, h ); return h; + } + + /*! # + */ + void GetMaxSize( int& w, int& h ) const; + + /*! # + */ + void SetMaxWidth( int w ) + { + SetMaxSize( w, -1 ); + } + + /*! # + */ + void SetMaxWidth() + { + SetMaxWidth( Width() ); + } + + /*! # + */ + void SetMaxHeight( int h ) + { + SetMaxSize( -1, h ); + } + + /*! # + */ + void SetMaxHeight() + { + SetMaxHeight( Height() ); + } + + /*! # + */ + void SetMaxSize( int w, int h ); + + /*! # + */ + void SetMaxSize() + { + SetMaxSize( Width(), Height() ); + } + + /*! # + */ + void SetFixedWidth( int w ) + { + SetFixedSize( w, -1 ); + } + + /*! # + */ + void SetFixedWidth() + { + SetFixedWidth( Width() ); + } + + /*! # + */ + void SetFixedHeight( int h ) + { + SetFixedSize( -1, h ); + } + + /*! # + */ + void SetFixedHeight() + { + SetFixedHeight( Height() ); + } + + /*! # + */ + void SetFixedSize( int w, int h ); + + /*! # + */ + void SetFixedSize() + { + SetFixedSize( Width(), Height() ); + } + + /*! # + */ + bool IsFixedWidth() const + { + return MinWidth() == MaxWidth(); + } + + /*! # + */ + bool IsFixedHeight() const + { + return MinHeight() == MaxHeight(); + } + + /*! # + */ + void SetVariableSize() + { + SetMinSize( 0, 0 ); + SetMaxSize( int_max, int_max ); + } + + /*! # + */ + void SetVariableWidth() + { + SetMinWidth( 0 ); + SetMaxWidth( int_max ); + } + + /*! # + */ + void SetVariableHeight() + { + SetMinHeight( 0 ); + SetMaxHeight( int_max ); + } + + /*! + * Returns the minimum width in pixels of the client rectangle. + */ + int ScaledMinWidth() const + { + int w, dum; GetMinSize( w, dum ); return PhysicalPixelsToLogical( w ); + } + + /*! + * Returns the minimum height in pixels of the client rectangle. + */ + int ScaledMinHeight() const + { + int dum, h; GetMinSize( dum, h ); return PhysicalPixelsToLogical( h ); + } + + /*! # + */ + void GetScaledMinSize( int& w, int& h ) const + { + GetMinSize( w, h ); w = PhysicalPixelsToLogical( w ); h = PhysicalPixelsToLogical( h ); + } + + /*! # + */ + void SetScaledMinWidth( int w ) + { + SetMinSize( LogicalPixelsToPhysical( w ), -1 ); + } + + /*! # + */ + void SetScaledMinHeight( int h ) + { + SetMinSize( -1, LogicalPixelsToPhysical( h ) ); + } + + /*! # + */ + void SetScaledMinSize( int w, int h ) + { + SetMinSize( LogicalPixelsToPhysical( w ), LogicalPixelsToPhysical( h ) ); + } + + /*! + * Returns the maximum width in pixels of the client rectangle. + */ + int ScaledMaxWidth() const + { + int w, dum; GetMaxSize( w, dum ); return PhysicalPixelsToLogical( w ); + } + + /*! + * Returns the maximum height in pixels of the client rectangle. + */ + int ScaledMaxHeight() const + { + int dum, h; GetMaxSize( dum, h ); return PhysicalPixelsToLogical( h ); + } + + /*! # + */ + void GetScaledMaxSize( int& w, int& h ) const + { + GetMaxSize( w, h ); w = PhysicalPixelsToLogical( w ); h = PhysicalPixelsToLogical( h ); + } + + /*! # + */ + void SetScaledMaxWidth( int w ) + { + SetMaxSize( LogicalPixelsToPhysical( w ), -1 ); + } + + /*! # + */ + void SetScaledMaxHeight( int h ) + { + SetMaxSize( -1, LogicalPixelsToPhysical( h ) ); + } + + /*! # + */ + void SetScaledMaxSize( int w, int h ) + { + SetMaxSize( LogicalPixelsToPhysical( w ), LogicalPixelsToPhysical( h ) ); + } + + /*! # + */ + void SetScaledFixedWidth( int w ) + { + SetFixedSize( LogicalPixelsToPhysical( w ), -1 ); + } + + /*! # + */ + void SetScaledFixedHeight( int h ) + { + SetFixedSize( -1, LogicalPixelsToPhysical( h ) ); + } + + /*! # + */ + void SetScaledFixedSize( int w, int h ) + { + SetFixedSize( LogicalPixelsToPhysical( w ), LogicalPixelsToPhysical( h ) ); + } + + /*! # + */ + bool IsHorizontalExpansionEnabled() const; + + /*! # + */ + bool IsVerticalExpansionEnabled() const; + + /*! # + */ + void EnableExpansion( bool horzEnable = true, bool vertEnable = true ); + + /*! # + */ + void DisableExpansion( bool horzDisable = true, bool vertDisable = true ) + { + EnableExpansion( !horzDisable, !vertDisable ); + } + + /*! + * Returns the current position of this control in parent coordinates. + * + * The position of a control refers to the upper left corner of its frame + * rectangle. + * + * \sa X(), Y() + */ + pcl::Point Position() const; + + /*! + * Returns the horizontal position of this control in parent coordinates. + * + * \sa Y(), Position() + */ + int X() const + { + return Position().x; + } + + /*! + * Returns the horizontal position of this control in parent coordinates. + * + * \sa X(), Position() + */ + int Y() const + { + return Position().y; + } + + /*! # + */ + void Move( const pcl::Point& p ) + { + Move( p.x, p.y ); + } + + /*! # + */ + void Move( int x, int y ); + + /*! + Returns true if the mouse cursor is over this control. + */ + bool IsUnderMouse() const; + + /*! # + */ + void BringToFront(); + + /*! # + */ + void SendToBack(); + + /*! # + */ + void StackUnder( Control& ); + + /*! # + */ + pcl::Sizer Sizer() const; + + /*! # + * \deprecated Use Control::Sizer() in newly produced code. + */ + pcl::Sizer GetSizer() const + { + return this->Sizer(); + } + + /*! # + */ + void SetSizer( pcl::Sizer& ); + + /*! # + */ + pcl::Point GlobalToLocal( const pcl::Point& p ) const + { + pcl::Point p1 = p; GlobalToLocal( p1.x, p1.y ); return p1; + } + + /*! # + */ + void GlobalToLocal( int& x, int& y ) const; + + /*! # + */ + pcl::Point LocalToGlobal( const pcl::Point& p ) const + { + pcl::Point p1 = p; LocalToGlobal( p1.x, p1.y ); return p1; + } + + /*! # + */ + void LocalToGlobal( int& x, int& y ) const; + + /*! # + */ + pcl::Point ParentToLocal( const pcl::Point& p ) const + { + pcl::Point p1 = p; ParentToLocal( p1.x, p1.y ); return p1; + } + + /*! # + */ + void ParentToLocal( int& x, int& y ) const; + + /*! # + */ + pcl::Point LocalToParent( const pcl::Point& p ) const + { + pcl::Point p1 = p; LocalToParent( p1.x, p1.y ); return p1; + } + + /*! # + */ + void LocalToParent( int& x, int& y ) const; + + /*! # + */ + pcl::Point ControlToLocal( const Control& w, const pcl::Point& p ) const + { + pcl::Point p1 = p; ControlToLocal( w, p1.x, p1.y ); return p1; + } + + /*! # + */ + void ControlToLocal( const Control&, int& x, int& y ) const; + + /*! # + */ + pcl::Point LocalToControl( const Control& w, const pcl::Point& p ) const + { + pcl::Point p1 = p; LocalToControl( w, p1.x, p1.y ); return p1; + } + + /*! # + */ + void LocalToControl( const Control&, int& x, int& y ) const; + + /*! # + */ + Control& ChildByPos( const pcl::Point& p ) const + { + return ChildByPos( p.x, p.y ); + } + + /*! # + */ + Control& ChildByPos( int x, int y ) const; + + /*! # + */ + pcl::Rect ChildrenRect() const; + + /*! # + */ + bool IsAncestorOf( const Control& ) const; + + /*! + * Returns a reference to the parent control, or Control::Null() if this + * control has no parent. + */ + Control& Parent() const; + + /*! # + */ + void SetParent( Control& ); + + /*! + * Returns a reference to the top-level window that owns this control, + * either directly or through its parent. + */ + Control& Window() const; + + /*! # + */ + virtual bool IsEnabled() const; + + /*! # + */ + virtual void Enable( bool enabled = true ); + + /*! # + */ + void Disable( bool disabled = true ) + { + Enable( !disabled ); + } + + /*! # + */ + bool IsMouseTrackingEnabled() const; + + /*! # + */ + void EnableMouseTracking( bool = true ); + + /*! # + */ + void DisableMouseTracking( bool disable = true ) + { + EnableMouseTracking( !disable ); + } + + /*! # + */ + bool IsVisible() const; + + /*! # + */ + void SetVisible( bool visible ) + { + if ( visible ) + Show(); + else + Hide(); + } + + /*! # + */ + void Show(); + + /*! # + */ + pcl::Rect VisibleRect() const; + + /*! # + */ + bool IsHidden() const + { + return !IsVisible(); + } + + /*! # + */ + void Hide(); + + /*! # + */ + bool IsMaximized() const; + + /*! # + */ + bool IsMinimized() const; + + /*! # + */ + bool IsModal() const; + + /*! # + */ + bool IsWindow() const; + + /*! # + */ + bool IsActiveWindow() const; + + /*! # + */ + void ActivateWindow(); + + /*! # + */ + bool IsFocused() const; + + /*! # + */ + void Focus( bool focus = true ); + + /*! # + */ + void Unfocus() + { + Focus( false ); + } + + /*! # + */ + FocusStyles FocusStyle() const; + + /*! # + */ + void SetFocusStyle( FocusStyles ); + + /*! # + */ + Control& FocusedChild() const; + + /*! # + */ + Control& ChildToFocus() const; + + /*! # + */ + void SetChildToFocus( Control& ); + + /*! # + */ + Control& NextSiblingToFocus() const; + + /*! # + */ + void SetNextSiblingToFocus( Control& ); + + /*! # + */ + bool CanUpdate() const; + + /*! # + */ + void EnableUpdates( bool enable = true ); + + /*! # + */ + void DisableUpdates( bool disable = true ) + { + EnableUpdates( !disable ); + } + + /*! # + */ + void Update(); + + /*! # + */ + void Update( const pcl::Rect& r ) + { + Update( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void Update( int x0, int y0, int x1, int y1 ); + + /*! # + */ + void Repaint(); + + /*! # + */ + void Repaint( const pcl::Rect& r ) + { + Repaint( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void Repaint( int x0, int y0, int x1, int y1 ); + + /*! + * Recomputes all style properties for this control: colors, fonts, + * spacings, margings, etc. + * + * Call this function to ensure that the screen rendition of this control + * applies all current settings; for example, after setting a new CSS style + * sheet with SetStyleSheet(). + */ + void Restyle(); + + /*! + * Make sure the control has valid geometry and layout, even if it has never + * been shown on the screen. + * + * Control layouts and geometries are not computed, in general, until the + * control has been shown on the screen, either explicitly or implicitly. By + * calling this member function one can ensure that the control has computed + * a valid layout, including all of its child controls, even if it has never + * been shown, so for example a subsequent call to Width() or ClientRect() + * will provide actual values. + * + * This function can be quite slow, especially for complex controls such as + * process interfaces, so it should only be used when necessary, never on a + * regular basis. Calling this member function for a control that is already + * visible on the screen has no effect. + */ + void EnsureLayoutUpdated(); + + /*! # + */ + void Scroll( const pcl::Point& d ) + { + Scroll( d.x, d.y ); + } + + /*! # + */ + void Scroll( int dx, int dy ); + + /*! # + */ + void Scroll( const pcl::Point& d, const pcl::Rect& r ) + { + Scroll( d.x, d.y, r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void Scroll( int dx, int dy, int x0, int y0, int x1, int y1 ); + + /*! # + */ + pcl::Cursor Cursor() const; + + /*! # + * \deprecated Use Control::Cursor() in newly produced code. + */ + pcl::Cursor GetCursor() const + { + return this->Cursor(); + } + + /*! # + */ + void SetCursor( const pcl::Cursor& ); + + /*! # + */ + void SetCursorToParent(); + + /*! # + */ + String StyleSheet() const; + + /*! # + */ + void SetStyleSheet( const String& css ); + + /*! # + */ + RGBA BackgroundColor() const; + + /*! # + */ + void SetBackgroundColor( RGBA ); + + /*! # + */ + RGBA ForegroundColor() const; + + /*! # + */ + void SetForegroundColor( RGBA ); + + /*! # + */ + RGBA CanvasColor(); + + /*! # + */ + void SetCanvasColor( RGBA ); + + /*! # + */ + RGBA AlternateCanvasColor() const; + + /*! # + */ + void SetAlternateCanvasColor( RGBA ); + + /*! # + */ + RGBA TextColor() const; + + /*! # + */ + void SetTextColor( RGBA ); + + /*! # + */ + RGBA ButtonColor() const; + + /*! # + */ + void SetButtonColor( RGBA ); + + /*! # + */ + RGBA ButtonTextColor() const; + + /*! # + */ + void SetButtonTextColor( RGBA ); + + /*! # + */ + RGBA HighlightColor() const; + + /*! # + */ + void SetHighlightColor( RGBA ); + + /*! # + */ + RGBA HighlightedTextColor() const; + + /*! # + */ + void SetHighlightedTextColor( RGBA ); + + /*! # + */ + pcl::Font Font() const; + + /*! + * \deprecated Use Control::Font() in newly produced code. + */ + pcl::Font GetFont() const + { + return this->Font(); + } + + /*! # + */ + void SetFont( const pcl::Font& ); + + /*! # + */ + double WindowOpacity() const; + + /*! # + */ + void SetWindowOpacity( double ); + + /*! # + */ + String WindowTitle() const; + + /*! # + */ + void SetWindowTitle( const String& ); + + /* + * Information areas on processing interface control bars. + */ + + /*! # + */ + String InfoText() const; + + /*! # + */ + void SetInfoText( const String& ); + + /*! # + */ + void ClearInfoText() + { + SetInfoText( String() ); + } + + /* + * Track View check boxes on processing interface control bars. + */ + + /*! # + */ + bool IsTrackViewActive() const; + + /*! # + */ + void SetTrackViewActive( bool = true ); + + /*! # + */ + void ActivateTrackView() + { + SetTrackViewActive( true ); + } + + /*! # + */ + void DeactivateTrackView() + { + SetTrackViewActive( false ); + } + + /* + * Real-Time Preview check boxes on processing interface control bars. + */ + + /*! # + */ + bool IsRealTimePreviewActive() const; + + /*! # + */ + void SetRealTimePreviewActive( bool = true ); + + /*! # + */ + void ActivateRealTimePreview() + { + SetRealTimePreviewActive( true ); + } + + /*! # + */ + void DeactivateRealTimePreview() + { + SetRealTimePreviewActive( false ); + } + + // + + /*! # + */ + String ToolTip() const; + + /*! # + */ + void SetToolTip( const String& ); + + /*! + * Shows a new tool tip window. + * + * \param x,y Position (horizontal, vertical) of the new tool tip + * window in global coordinates. + * + * \param text Tool tip text. Can be either a plain text string or + * include HTML tags with CSS style properties. If this is an + * empty string the tool tip window will be hidden, if already + * visible. + * + * \param control If this is not a null control, the tool tip window will + * be hidden as soon as the cursor moves out of the control + * boundaries or, if specified, out of the \a rect rectangle in + * local coordinates. + * + * \param rect If a non-void rectangle is specified, the tool tip + * window will be hidden as soon as the cursor moves out of it. + * If a non-null \a control is specified, the coordinates of + * \a rect are local to it; otherwise global coordinates are + * assumed. + * + * The new tool tip window will be shown (or hidden if an empty text is + * specified) immediately. + */ + static void ShowToolTip( int x, int y, const String& text, + const Control& control = Control::Null(), const Rect& rect = Rect( 0 ) ); + + /*! + * Shows a new tool tip window. + * + * This function is equivalent to + * ShowToolTip( pos.x, pos.y, text, control, rect ). + */ + static void ShowToolTip( const Point& pos, const String& text, + const Control& control = Control::Null(), const Rect& rect = Rect( 0 ) ) + { + ShowToolTip( pos.x, pos.y, text, control, rect ); + } + + /*! + * Hides the tool tip window, if one is currently visible. + */ + static void HideToolTip(); + + /*! + * Returns the tool tip window's text, if a tool tip window is currently + * visible. + */ + static String ToolTipText(); + + // + + /*! + * Returns the ratio between physical screen pixels and device-independent + * logical screen units for the parent top-level window of this %Control + * object. This ratio is used as a scaling factor by the + * LogicalPixelsToPhysical() and PhysicalPixelsToLogical() functions, which + * are used internally by automatic size scaling member functions + * such as SetScaledFixedSize(), ScaledMinWidth(), etc. + * + * The returned value is greater than or equal to one. Typical pixel ratios + * are 1.5 and 2.0 for high-density displays such as 4K and 5K monitors, + * respectively, or 1.0 for normal 96 dpi monitors. + * + * On macOS, this function normally returns 1.0 for Retina displays working + * in high-dpi modes, since the operating system performs the conversion + * from logical to physical pixels automatically. The ResourcePixelRatio() + * member function returns the actual ratio between physical and logical + * screen pixels on macOS. + * + * \ingroup ui_scaling_functions + * \sa LogicalPixelsToPhysical(), PhysicalPixelsToLogical(), + * ResourcePixelRatio() + */ + double DisplayPixelRatio() const; + + /*! + * Returns the ratio between physical screen pixels and pixels of + * device-independent image resources reproduced on the parent top-level + * window of this %Control object. This ratio is used as a scaling factor by + * the ScaledResource() member function. + * + * The returned value is greater than or equal to one. Typical resource + * pixel ratios are 1.5 and 2.0 for high-density displays such as 4K and 5K + * monitors, respectively, 2.0 for Retina displays, or 1.0 for normal 96 dpi + * monitors. + * + * On macOS with Retina monitors working in high-dpi modes, this function + * returns a value greater than one (typically 2.0), while + * DisplayPixelRatio() normally returns one by default. This is because in + * high-dpi modes, macOS works in logical display coordinates to represent + * text, control sizes and distances. However, image resources must be + * provided with pixel data in the physical screen resolution. On X11 and + * Windows platforms, where no automatic display scaling is performed, this + * member function is equivalent to DisplayPixelRatio(). + * + * Portable code should use the value returned by this member function to + * scale image resources drawn on controls, such as icons and bitmaps. The + * ScaledResource() function can be used to select the appropriate file + * paths from PixInsight core resources. The LogicalPixelsToResource() + * function can be used to calculate scaled dimensions of graphical elements + * generated dynamically from scalable resources, e.g. with + * Bitmap::FromSVGFile() and similar routines. + * + * \ingroup ui_scaling_functions + * \sa LogicalPixelsToResource(), ResourcePixelsToLogical(), + * ScaledResource(), DisplayPixelRatio(), + */ + double ResourcePixelRatio() const; + + /*! + * Returns the specified bitmap \a resource path adapted to be represented + * with the physical display pixel ratio of this control. Calling this + * function is equivalent to: + * + * \code pcl::UIScaledResource( ResourcePixelRatio(), resource ); \endcode + * + * Example: + * + * \code + * Dialog dlg; + * Bitmap bmp( dlg.ScaledResource( ":/browser/enabled.png" ) ); + * \endcode + * + * \ingroup ui_scaling_functions + * \sa ResourcePixelRatio() + */ + template + String ScaledResource( R resource ) const + { + return UIScaledResource( ResourcePixelRatio(), resource ); + } + + /*! + * Returns a CSS source code fragment transformed with scaled dimensions in + * pixels and scaled resource file paths, and optionally point sizes + * converted to scaled pixel sizes. + * + * \param cssCode A string containing the input CSS source code. The + * function will return a transformed version of this + * string. + * + * \param fontDPI If greater than zero, this is the font resolution, in + * dots per inch (dpi), for transformation of point sizes + * to scaled pixel sizes. If this parameter is zero (the + * default value), this routine will use the font + * resolution currently selected in core user preferences + * (which is the value of the "Application/FontResolution" + * global integer variable; see PixInsightSettings). If + * this parameter is a negative integer, no point-to-pixel + * conversions will be applied. + * + * Calling this function is equivalent to: + * + * \code + * pcl::UIScaledStyleSheet( DisplayPixelRatio(), ResourcePixelRatio(), cssCode, fontDPI ); + * \endcode + * + * Example: + * + * \code + * Data_TreeBox.SetStyleSheet( ScaledStyleSheet( + * "QTreeView {" + * " font-family: DejaVu Sans Mono, Monospace;" + * " font-size: 10pt;" + * " background-image: url(:/image-window/transparent.png);" + * "}" + * "QTreeView::item {" + * " padding: 4px 8px 4px 8px;" + * "}" + * "QHeaderView::section {" + * " padding: 2px 8px 2px 8px;" + * "}" + * ) ); + * \endcode + * + * If the display and resource pixel ratios of \c Data_TreeBox were 1.5 (for + * example, on a 4K monitor), and the current font resolution were 100 dpi, + * the code above would be equivalent to: + * + * \code + * Data_TreeBox.SetStyleSheet( + * "QTreeView {" + * " font-family: DejaVu Sans Mono, Monospace;" + * " font-size: 21px;" + * " background-image: url(:/image-window/1.5/transparent.png);" + * "}" + * "QTreeView::item {" + * " padding: 6px 12px 6px 12px;" + * "}" + * "QHeaderView::section {" + * " padding: 3px 12px 3px 12px;" + * "}" + * ); + * \endcode + * + * \ingroup ui_scaling_functions + * \sa DisplayPixelRatio(), ResourcePixelRatio(), ScaledResource() + */ + template + String ScaledStyleSheet( S cssCode, int fontDPI = 0 ) const + { + return UIScaledStyleSheet( DisplayPixelRatio(), ResourcePixelRatio(), cssCode, fontDPI ); + } + + /*! + * Returns a cursor hot spot point with coordinates scaled according to the + * physical display pixel ratio of this control. + * + * Standard cursor images in PixInsight are scaled in a special way to + * guarantee that cursors always have a unique central pixel, irrespective + * of the applied display pixel ratios. This is functionally equivalent to + * ensure that cursors always have odd dimensions. + * + * According to this rule, a standard cursor is a square image with the + * following dimensions in pixels: + * + * 21, 33, 43, 53, 63, 75, 85 + * + * respectively for the standard scaling ratios 1.0, 1.5, 2.0, 2.5, 3.0, 3.5 + * and 4.0. For dynamic cursors this function must be used to calculate + * scaled cursor hot spot coordinates, instead of simply scaling by + * multiplication with ResourcePixelRatio() and rounding. This also + * guarantees source code compatibility with future versions of PixInsight, + * where standard cursor dimensions might change. + * + * \ingroup ui_scaling_functions + * \sa ResourcePixelRatio(); + */ + Point ScaledCursorHotSpot( int xHot, int yHot ) const + { + double r = ResourcePixelRatio(); + return Point( RoundInt( r*(xHot + 0.499) ), RoundInt( r*(yHot + 0.499) ) ); + } + + /*! + * Returns a cursor hot spot point with coordinates scaled according to the + * physical display pixel ratio of this control. + * + * This function is equivalent to: + * + * \code ScaledCursorHotSpot( hotSpot.x, hotSpot.y ); \endcode + * + * \ingroup ui_scaling_functions + */ + Point ScaledCursorHotSpot( const Point& hotSpot ) const + { + return ScaledCursorHotSpot( hotSpot.x, hotSpot.y ); + } + + /*! + * Returns the specified \a size in logical device-independent pixel units + * converted to physical device pixels. + * + * \ingroup ui_scaling_functions + * \sa DisplayPixelRatio(), PhysicalPixelsToLogical(), + * LogicalPixelsToResource() + */ + int LogicalPixelsToPhysical( int size ) const + { + return RoundInt( DisplayPixelRatio()*size ); + } + + /*! + * Returns the specified \a size in physical device pixels converted to + * logical device-independent pixel units. + * + * \ingroup ui_scaling_functions + * \sa DisplayPixelRatio(), LogicalPixelsToPhysical(), + * ResourcePixelsToLogical() + */ + int PhysicalPixelsToLogical( int size ) const + { + return RoundInt( size/DisplayPixelRatio() ); + } + + /*! + * Returns the specified \a size in logical device-independent pixel units + * converted to resource pixel units. + * + * The returned value corresponds to physical display device pixels on all + * supported operating systems and desktop managers. + * + * \ingroup ui_scaling_functions + * \sa ResourcePixelRatio(), ResourcePixelsToLogical(), + * LogicalPixelsToPhysical() + */ + int LogicalPixelsToResource( int size ) const + { + return RoundInt( ResourcePixelRatio()*size ); + } + + /*! + * Returns the specified \a size in resource pixel units converted to + * logical device-independent pixel units. + * + * \ingroup ui_scaling_functions + * \sa ResourcePixelRatio(), LogicalPixelsToResource(), + * PhysicalPixelsToLogical() + */ + int ResourcePixelsToLogical( int size ) const + { + return RoundInt( size/ResourcePixelRatio() ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnDestroy( Control& sender ); + // void OnShow( Control& sender ); + // void OnHide( Control& sender ); + // void OnGetFocus( Control& sender ); + // void OnLoseFocus( Control& sender ); + // void OnEnter( Control& sender ); + // void OnLeave( Control& sender ); + // void OnMove( Control& sender, const pcl::Point& newPos, const pcl::Point& oldPos ); + // void OnResize( Control& sender, int newWidth, int newHeight, int oldWidth, int oldHeight ); + // void OnPaint( Control& sender, const pcl::Rect& updateRect ); + // void OnKeyPress( Control& sender, int key, unsigned modifiers, bool& wantsKey ); + // void OnKeyRelease( Control& sender, int key, unsigned modifiers, bool& wantsKey ); + // void OnMouseMove( Control& sender, const pcl::Point& pos, unsigned buttons, unsigned modifiers ); + // void OnMouseDoubleClick( Control& sender, const pcl::Point& pos, unsigned buttons, unsigned modifiers ); + // void OnMousePress( Control& sender, const pcl::Point& pos, int button, unsigned buttons, unsigned modifiers ); + // void OnMouseRelease( Control& sender, const pcl::Point& pos, int button, unsigned buttons, unsigned modifiers ); + // void OnMouseWheel( Control& sender, const pcl::Point& pos, int delta, unsigned buttons, unsigned modifiers ); + // void OnFileDrag( Control& sender, const pcl::Point& pos, const StringList& files, unsigned modifiers, bool& wantsFiles ) + // void OnFileDrop( Control& sender, const pcl::Point& pos, const StringList& files, unsigned modifiers ) + // void OnViewDrag( Control& sender, const pcl::Point& pos, const View& view, unsigned modifiers, bool& wantsView ) + // void OnViewDrop( Control& sender, const pcl::Point& pos, const View& view, unsigned modifiers ) + // void OnChildCreate( Control& sender, Control& child ); + // void OnChildDestroy( Control& sender, Control& child ); + + /*! + * \defgroup control_event_handlers Control Event Handlers + */ + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*event_handler)( Control& sender ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*close_event_handler)( Control& sender, bool& allowClose ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*move_event_handler)( Control& sender, const pcl::Point& newPos, const pcl::Point& oldPos ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*resize_event_handler)( Control& sender, int newWidth, int newHeight, int oldWidth, int oldHeight ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*paint_event_handler)( Control& sender, const pcl::Rect& updateRect ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*keyboard_event_handler)( Control& sender, int key, unsigned modifiers, bool& wantsKey ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*mouse_event_handler)( Control& sender, const pcl::Point& pos, unsigned buttons, unsigned modifiers ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*mouse_button_event_handler)( Control& sender, const pcl::Point& pos, int button, unsigned buttons, unsigned modifiers ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*mouse_wheel_event_handler)( Control& sender, const pcl::Point& pos, int delta, unsigned buttons, unsigned modifiers ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*file_drag_event_handler)( Control& sender, const pcl::Point& pos, const StringList& files, unsigned modifiers, bool& wantsFiles ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*file_drop_event_handler)( Control& sender, const pcl::Point& pos, const StringList& files, unsigned modifiers ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*view_drag_event_handler)( Control& sender, const pcl::Point& pos, const View& view, unsigned modifiers, bool& wantsView ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*view_drop_event_handler)( Control& sender, const pcl::Point& pos, const View& view, unsigned modifiers ); + + /*! # + * \ingroup control_event_handlers + */ + typedef void (Control::*child_event_handler)( Control& sender, Control& child ); + + /*! # + * \ingroup control_event_handlers + */ + void OnDestroy( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnShow( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnHide( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnClose( close_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnGetFocus( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnLoseFocus( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnEnter( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnLeave( event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnMove( move_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnResize( resize_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnPaint( paint_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnKeyPress( keyboard_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnKeyRelease( keyboard_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnMouseMove( mouse_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnMouseDoubleClick( mouse_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnMousePress( mouse_button_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnMouseRelease( mouse_button_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnMouseWheel( mouse_wheel_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnFileDrag( file_drag_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnFileDrop( file_drop_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnViewDrag( view_drag_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnViewDrop( view_drop_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnChildCreate( child_event_handler, Control& ); + + /*! # + * \ingroup control_event_handlers + */ + void OnChildDestroy( child_event_handler, Control& ); + + // ------------------------------------------------------------------------- + +private: + + struct EventHandlers + { + event_handler onDestroy = nullptr; + event_handler onShow = nullptr; + event_handler onHide = nullptr; + close_event_handler onClose = nullptr; + event_handler onGetFocus = nullptr; + event_handler onLoseFocus = nullptr; + event_handler onEnter = nullptr; + event_handler onLeave = nullptr; + move_event_handler onMove = nullptr; + resize_event_handler onResize = nullptr; + paint_event_handler onPaint = nullptr; + keyboard_event_handler onKeyPress = nullptr; + keyboard_event_handler onKeyRelease = nullptr; + mouse_event_handler onMouseMove = nullptr; + mouse_event_handler onMouseDoubleClick = nullptr; + mouse_button_event_handler onMousePress = nullptr; + mouse_button_event_handler onMouseRelease = nullptr; + mouse_wheel_event_handler onMouseWheel = nullptr; + file_drag_event_handler onFileDrag = nullptr; + file_drop_event_handler onFileDrop = nullptr; + view_drag_event_handler onViewDrag = nullptr; + view_drop_event_handler onViewDrop = nullptr; + child_event_handler onChildCreate = nullptr; + child_event_handler onChildDestroy = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + +protected: + + /*! + * \internal + * Private constructor from a low-level opaque server handle. + */ + Control( void* h ) : UIObject( h ) + { + } + + /*! + * \internal + * Reimplemented from UIObject. Throws an Error exception because Control + * objects are unique, and hence cannot be duplicated. + */ + void* CloneHandle() const override; + + friend class BitmapBox; + friend class CheckBox; + friend class CodeEditor; + friend class ComboBox; + friend class ControlEventDispatcher; + friend class Dialog; + friend class Edit; + friend class Frame; + friend class GraphicsContextBase; + friend class GroupBox; + friend class ImageView; + friend class Label; + friend class PushButton; + friend class RadioButton; + friend class ScrollBox; + friend class Sizer; + friend class Slider; + friend class SpinBox; + friend class TabBox; + friend class TextBox; + friend class ToolButton; + friend class TreeBox; + friend class ViewList; + friend class WebView; +}; + +// ---------------------------------------------------------------------------- + +template inline +int CanonicalControlHeightImplementation() +{ + Control container; + VerticalSizer sizer; + C control; + + sizer.Add( control ); + container.SetSizer( sizer ); + container.Restyle(); + container.AdjustToContents(); + container.SetFixedSize(); + return container.Height(); +} + +/*! + * \defgroup aux_control_functions_and_classes Control Helper Functions and Classes + */ + +/*! + * \def CanonicalControlHeight( control_type ) + * \brief Returns the canonical height in pixels for a specified control type. + * + * The canonical height is the height in pixels that a control of the specified + * type would have once adjusted into a VerticalSizer container and a parent + * control object. This macro is useful to calculate the height of a control in + * advance, before actually creating its component sub-controls. + * + * \ingroup aux_control_functions_and_classes + */ +#define CanonicalControlHeight( control_type ) \ + CanonicalControlHeightImplementation() + +// ---------------------------------------------------------------------------- + +#define __PCL_NO_ALIAS_HANDLERS \ + if ( IsAlias() ) \ + throw Error( "Aliased controls cannot set event handlers." ) + +// ---------------------------------------------------------------------------- + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Control_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Control.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Convolution.h b/3rdparty/include/pcl/Convolution.h new file mode 100644 index 0000000..e73ac9d --- /dev/null +++ b/3rdparty/include/pcl/Convolution.h @@ -0,0 +1,359 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Convolution.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_Convolution_h +#define __PCL_Convolution_h + +/// \file pcl/Convolution.h + +#include +#include + +#include +#include +#include +#include +#include + +#define __PCL_CONVOLUTION_TINY_WEIGHT 1.0e-20 + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Convolution + * \brief Discrete two-dimensional nonseparable convolution in the spatial + * domain + * + * %Convolution implements a fully multithreaded, two-dimensional discrete + * nonseparable convolution algorithm. It performs automatic fixing of + * border artifacts by applying Neumann boundary conditions (mirroring). + * + * \note ImageTransformation is a virtual base class of %Convolution. + * + * \sa SeparableConvolution, FFTConvolution, KernelFilter + */ +class PCL_CLASS Convolution : public InterlacedTransformation, + public ThresholdedTransformation, + public ParallelProcess +{ // NB: ImageTransformation is a virtual base class +public: + + /*! + * Default constructor. + * + * \note This constructor yields an uninitialized instance that cannot be + * used before explicit association with a KernelFilter instance. + */ + Convolution() = default; + + /*! + * Constructs a %Convolution instance with the specified filter. + * + * \param filter Response function, or convolution filter. The + * specified object does not have to remain valid while this + * instance is actively used, since %Convolution owns a + * private copy of the filter (note that KernelFilter is a + * reference-counted class). + */ + Convolution( const KernelFilter& filter ) + { + SetFilter( filter ); + } + + /*! + * Copy constructor. + */ + Convolution( const Convolution& x ) + : InterlacedTransformation( x ) + , ThresholdedTransformation( x ) + , ParallelProcess( x ) + , m_weight( x.m_weight ) + , m_highPass( x.m_highPass ) + , m_rawHighPass( x.m_rawHighPass ) + , m_rescaleHighPass( x.m_rescaleHighPass ) + { + if ( !x.m_filter.IsNull() ) + m_filter = x.m_filter->Clone(); + } + + /*! + * Move constructor. + */ + Convolution( Convolution&& ) = default; + + /*! + * Destroys this %Convolution object. + */ + virtual ~Convolution() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Convolution& operator =( const Convolution& x ) + { + if ( &x != this ) + { + (void)InterlacedTransformation::operator =( x ); + (void)ThresholdedTransformation::operator =( x ); + (void)ParallelProcess::operator =( x ); + if ( x.m_filter.IsNull() ) + m_filter.Destroy(); + else + m_filter = x.m_filter->Clone(); + m_weight = x.m_weight; + m_highPass = x.m_highPass; + m_rawHighPass = x.m_rawHighPass; + m_rescaleHighPass = x.m_rescaleHighPass; + } + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Convolution& operator =( Convolution&& ) = default; + + /*! + * Returns a reference to the kernel filter currently associated with this + * %Convolution object. + * + * If this object has not been initialized, this member function returns an + * empty kernel filter. + */ + const KernelFilter& Filter() const + { + PCL_PRECONDITION( !m_filter.IsNull() ) + return *m_filter; + } + + /*! + * Sets a new kernel \a filter to be applied by this %Convolution object. + */ + void SetFilter( const KernelFilter& filter ) + { + m_filter = filter.Clone(); + CacheFilterProperties(); + } + + /*! + * Returns the current filter weight. The filter weight is computed each + * time a kernel filter is associated with this object. It is only + * applied for low-pass filters as a normalization factor. For more + * information, see the documentation for KernelFilter::Weight(). + * + * The filter weight and other filter properties are cached in private data + * members for quick reference. + */ + double FilterWeight() const + { + return m_weight; + } + + /*! + * Returns true if the kernel filter currently associated with this + * %Convolution object is a high-pass filter; false if it is a low-pass + * filter. For more information, see the documentation for + * kernelFilter::IsHighPassFilter(). + * + * Each time a kernel filter is associated with this object, its high-pass + * nature is checked and stored, along with other filter properties, in + * private data members. This allows for quick lookup of critical filter + * characteristics without degrading performance. + */ + bool IsHighPassFilter() const + { + return m_highPass; + } + + /*! + * Returns true iff out-of-range values will be rescaled for normalization of + * images after convolution with a high-pass filter. + * + * A high-pass filter has negative coefficients. As a result, some pixels in + * the convolved image may have negative values. Saturated pixels (values + * above one) can also result, depending on the filter coefficients. The + * standard behavior is to truncate out-of-range pixel values to the [0,1] + * range, which preserves the dynamics of the convolved image, so high-pass + * rescaling is disabled by default. When high-pass rescaling is enabled, + * the resulting image is \e normalized (that is, rescaled to [0,1] only if + * there are out-of-range values) and hence all the data after convolution + * are preserved at the cost of reducing the overall contrast of the image. + * Finally, if raw high-pass convolution has been enabled, + * out-of-range values are neither truncated nor rescaled irrespective of + * the value returned by this function. See the documentation for + * IsRawHighPassEnabled() for more information. + */ + bool IsHighPassRescalingEnabled() const + { + return m_rescaleHighPass; + } + + /*! + * Enables (or disables) high-pass rescaling of out-of-range convolved pixel + * values. See the documentation for IsHighPassRescalingEnabled() for more + * information. + */ + void EnableHighPassRescaling( bool enable = true ) + { + m_rescaleHighPass = enable; + } + + /*! + * Disables (or enables) high-pass rescaling of out-of-range convolved pixel + * values. See the documentation for IsHighPassRescalingEnabled() for more + * information. + */ + void DisableHighPassRescaling( bool disable = true ) + { + EnableHighPassRescaling( !disable ); + } + + /*! + * Returns true iff raw high-pass convolution is enabled. When raw + * high-pass convolution is enabled, out-of-range values after convolution + * with a high-pass filter are neither truncated nor normalized. Note that + * this is only relevant to convolution of floating point data. + * + * Raw high-pass convolution is disabled by default. For more information on + * out-of-range convolution results, refer to the documentation for + * IsHighPassRescalingEnabled(). + */ + bool IsRawHighPassEnabled() const + { + return m_rawHighPass; + } + + /*! + * Enables (or disables) raw high-pass convolution. See the documentation + * for IsRawHighPassEnabled() for more information. + */ + void EnableRawHighPass( bool enable = true ) + { + m_rawHighPass = enable; + } + + /*! + * Disables (or enables) raw high-pass convolution. See the documentation + * for IsRawHighPassEnabled() for more information. + */ + void DisableRawHighPass( bool disable = true ) + { + EnableRawHighPass( !disable ); + } + + /*! + * Returns the length in pixels of the overlapping regions between adjacent + * areas processed by parallel execution threads. The overlapping distance + * is a function of the filter size and the interlacing distance. + */ + int OverlappingDistance() const + { + PCL_PRECONDITION( !m_filter.IsNull() ) + return m_filter->Size() + (m_filter->Size() - 1)*(InterlacingDistance() - 1); + } + +protected: + + /* + * The response function for convolution is defined as a kernel filter. + */ + AutoPointer m_filter; + + /* + * Cached filter properties. + */ + double m_weight = 0; // filter weight for low-pass normalization + bool m_highPass = false; // true if this is a high-pass filter + + /* + * User-selectable options + */ + bool m_rawHighPass = false; // neither truncate nor normalize out-of-range values + bool m_rescaleHighPass = false; // truncate out-of-range values instead of normalize + + /* + * In-place 2-D nonseparable convolution algorithm in the spatial domain. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; + +private: + + void CacheFilterProperties() + { + PCL_PRECONDITION( !m_filter.IsNull() ) + PCL_PRECONDITION( !m_filter->IsEmpty() ) + ValidateFilter(); + m_highPass = m_filter->IsHighPassFilter(); + m_weight = m_filter->Weight(); + if ( pcl::Abs( m_weight ) < __PCL_CONVOLUTION_TINY_WEIGHT ) + m_weight = 1; + } + + void ValidateFilter() const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Convolution_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Convolution.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Crop.h b/3rdparty/include/pcl/Crop.h new file mode 100644 index 0000000..67afd52 --- /dev/null +++ b/3rdparty/include/pcl/Crop.h @@ -0,0 +1,261 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Crop.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_Crop_h +#define __PCL_Crop_h + +/// \file pcl/Crop.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + \namespace pcl::CropMode + \brief Image cropping modes for the Crop geometric transformation + + + + + + +
CropMode::RelativeMargins Cropping margins are relative to current image dimensions
CropMode::AbsolutePixels Absolute cropping margins in pixels
CropMode::AbsoluteCentimeters Absolute cropping margins in centimeters
CropMode::AbsoluteInches Absolute cropping margins in inches
+*/ +namespace CropMode +{ + enum value_type + { + RelativeMargins, // Cropping margins are relative to current image dimensions + AbsolutePixels, // Absolute cropping margins in pixels + AbsoluteCentimeters, // Absolute cropping margins in centimeters + AbsoluteInches // Absolute cropping margins in inches + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Crop + * \brief %Image cropping/expansion algorithm + * + * %Crop is a noninterpolating geometric transformation class that allows + * cropping an image or expanding it by specifying separate cropping margins + * for each side. When a cropping margin is negative the image is cropped, and + * when it is positive, the image is expanded. + */ +class PCL_CLASS Crop : public GeometricTransformation, + public ImageResolution +{ +public: + + /*! + * Represents a cropping mode. + */ + typedef CropMode::value_type crop_mode; + + /*! + * Constructs a %Crop object with the specified cropping margins for + * the \a left, \a top, \a right and \a bottom sides. + */ + Crop( double left = 0, double top = 0, double right = 0, double bottom = 0 ) + : m_margins( left, top, right, bottom ) + , m_mode( CropMode::RelativeMargins ) + { + } + + /*! + * Constructs a %Crop object whose cropping margins are defined by the + * components of a rectangle \a r. + */ + template + Crop( const GenericRectangle& r ) + : m_margins( r ) + , m_mode( CropMode::RelativeMargins ) + { + } + + /*! + * Copy constructor. + */ + Crop( const Crop& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Crop& operator =( const Crop& ) = default; + + /*! + * Returns a rectangle whose components correspond to the current cropping + * margins of this %Crop object. + */ + DRect Margins() const + { + return m_margins; + } + + /*! + * Sets the cropping margins equal to the components of a specified + * rectangle \a r. + */ + template + void SetMargins( const GenericRectangle& r ) + { + m_margins = r; + } + + /*! + * Sets the specified \a left, \a top, \a right and \a bottom cropping + * margins. + */ + void SetMargins( int left, int top, int right, int bottom ) + { + m_margins = Rect( left, top, right, bottom ); + } + + /*! + * Returns the current cropping mode of this %Crop object. + */ + crop_mode Mode() const + { + return m_mode; + } + + /*! + * Returns true iff this %Crop object interprets its cropping margins + * relative to current image dimensions. Returns false if cropping margins + * are interpreted as absolute increments. + */ + bool IsRelative() const + { + return m_mode == CropMode::RelativeMargins; + } + + /*! + * Returns true iff this %Crop object interprets its cropping margins as + * absolute increments. Returns false if cropping margins are interpreted + * relative to current image dimensions. + */ + bool IsAbsolute() const + { + return !IsRelative(); + } + + /*! + * Sets the cropping \a mode for this %Crop object. + */ + void SetMode( crop_mode mode ) + { + m_mode = mode; + } + + /*! + * Returns the current vector of per-channel filling values for uncovered + * image regions. + * + * See the documentation for SetFillValues() for more information. + */ + const DVector& FillValues() const + { + return m_fillValues; + } + + /*! + * Sets a vector of per-channel filling values for uncovered image regions. + * + * Uncovered regions result when a %Crop instance extends an image due to + * positive cropping margins. + * + * By default, there are no filling values defined (and hence the returned + * vector is empty by default). When the %Crop instance is executed and a + * filling value is not defined for a channel of the target image, uncovered + * regions are filled with the minimum sample value in the native range of + * the image (usually zero). + */ + void SetFillValues( const DVector& fillValues ) + { + m_fillValues = fillValues; + } + + /*! + */ + void GetNewSizes( int& width, int& height ) const override; + +protected: + + DRect m_margins; + crop_mode m_mode; + DVector m_fillValues; + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Crop_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Crop.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Cryptography.h b/3rdparty/include/pcl/Cryptography.h new file mode 100644 index 0000000..9bca685 --- /dev/null +++ b/3rdparty/include/pcl/Cryptography.h @@ -0,0 +1,1103 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Cryptography.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_Cryptography_h +#define __PCL_Cryptography_h + +/// \file pcl/Cryptography.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup cryptography_classes Cryptographic Hashing and Encryption Classes + */ + +/*! + * \class CryptographicHash + * \brief Abstract base class for cryptographic hashing algorithm + * implementations + * + * %CryptographicHash defines a common interface for implementations of + * cryptographic hashing algorithms such as MD-5, SHA-1 or SHA-256. + * + * \ingroup cryptography_classes + * \sa MD5, SHA1, SHA224, SHA256, SHA384, SHA512, CryptographicHashFactory + */ +class PCL_CLASS CryptographicHash +{ +public: + + /*! + * Default constructor. + */ + CryptographicHash() = default; + + /*! + * Destroys a %CryptographicHash object. + */ + virtual ~CryptographicHash() + { + } + + /*! + * Copy constructor. This constructor is disabled because %CryptographicHash + * objects are unique. + */ + CryptographicHash( const CryptographicHash& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %CryptographicHash + * objects are unique. + */ + CryptographicHash& operator =( const CryptographicHash& ) = delete; + + /*! + * Returns the name of this cryptographic hashing algorithm. + */ + virtual String AlgorithmName() const = 0; + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + */ + virtual size_type HashLength() const = 0; + + /*! + * Initializes this cryptographic hash generator. + */ + virtual void Initialize() = 0; + + /*! + * Updates the hash generator with a new \a data chunk of the specified + * \a length in bytes. + */ + virtual void Update( const void* data, size_type length ) = 0; + + /*! + * Updates the hash generator with data from a container with contiguous + * storage. + * + * The \c C template argument must be a class with PCL container semantics + * (the Begin() and Size() member functions are required). Typically the + * ByteArray class is used, although any array-like class with contiguous + * storage is appropriate, including Array, String, Vector and Matrix. + */ + template + void Update( const C& data ) + { + Update( data.Begin(), data.Size() ); + } + + /*! + * Terminates hash generation and returns the computed message digest + * as a ByteArray instance. + */ + ByteArray Finalize() + { + ByteArray hash( HashLength() ); + Finalize( hash.Begin() ); + return hash; + } + + /*! + * Returns the hash sequence (message digest) corresponding to a \a data + * block of the specified \a length in bytes, stored in the specified + * \a hash array. The specified array must provide room for at least + * HashLength() bytes, that is, the length in bytes of the message digest + * produced by this hashing algorithm. + */ + void Hash( uint8* hash, const void* data, size_type length ) + { + Initialize(); + Update( data, length ); + Finalize( hash ); + } + + /*! + * Returns the hash sequence (message digest) corresponding to a \a data + * block of the specified \a length in bytes, as a ByteArray instance. + */ + ByteArray Hash( const void* data, size_type length ) + { + ByteArray hash( HashLength() ); + Hash( hash.Begin(), data, length ); + return hash; + } + + /*! + * Returns the hash sequence (message digest) corresponding to a container + * \a data with contiguous storage as a ByteArray instance. + * + * The \c C template argument must be a class with PCL container semantics + * (the Begin() and Size() member functions are required). Typically the + * ByteArray class is used, although any array-like class with contiguous + * storage is appropriate, including Array, String, Vector and Matrix. + */ + template + ByteArray Hash( const C& data ) + { + return Hash( data.Begin(), data.Size() ); + } + +protected: + + /*! + * Terminates hash generation and returns the computed message digest + * (hash value) stored in the specified \a hash array. The specified array + * must provide room for at least HashLength() bytes, that is, the length in + * bytes of the message digest produced by this hashing algorithm. + */ + virtual void Finalize( void* hash ) = 0; + + friend class CryptographicHashFactory; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MD5 + * \brief Implementation of the %MD5 cryptographic hashing algorithm + * + * \b References + * + * Message Digest algorithm 5 (%MD5) was designed by Ronald Rivest in 1991. + * %MD5 is a widely-used Internet standard published as RFC-1321 by RSA: + * + * http://tools.ietf.org/html/rfc1321 + * + * An %MD5 message digest (or %MD5 hash value) is 128 bits (16 bytes) long. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, SHA1, SHA224, SHA256, SHA384, SHA512, + * CryptographicHashFactory + */ +class PCL_CLASS MD5 : public CryptographicHash +{ +public: + + /*! + * Constructs an %MD5 hash generator. + */ + MD5() = default; + + /*! + * Destroys an %MD5 hash generator. + */ + virtual ~MD5(); + + /*! + * Returns the name of this cryptographic hashing algorithm: "MD5". + */ + String AlgorithmName() const override + { + return "MD5"; + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + * + * As reimplemented in %MD5, this function returns 16, the length in bytes + * of an %MD5 digest. + */ + size_type HashLength() const override + { + return 16; + } + + /*! + */ + void Initialize() override; + + /*! + */ + void Update( const void* data, size_type length ) override; + +private: + + void* m_context = nullptr; + + /*! + */ + void Finalize( void* hash ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SHA1 + * \brief Implementation of the SHA-1 cryptographic hashing algorithm + * + * \b References + * + * The initial Secure Hash Algorithm (SHA) was published by NIST in 1993 as the + * Secure Hash Standard, FIPS PUB 180. The SHA-1 algorithm was defined in a + * revised version published in 1995, FIPS PUB 180-1. The latest specification + * has been released in FIPS PUB 180-4: + * + * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf + * + * An SHA-1 message digest (or SHA-1 hash value) is 160 bits (20 bytes) long. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, MD5, SHA224, SHA256, SHA384, SHA512, + * CryptographicHashFactory + */ +class PCL_CLASS SHA1 : public CryptographicHash +{ +public: + + /*! + * Constructs an SHA-1 hash generator. + */ + SHA1() = default; + + /*! + * Destroys an SHA-1 hash generator. + */ + virtual ~SHA1(); + + /*! + * Returns the name of this cryptographic hashing algorithm: "SHA1". + */ + String AlgorithmName() const override + { + return "SHA1"; + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + * + * As reimplemented in %SHA1, this function returns 20, the length in bytes + * of an SHA-1 digest. + */ + size_type HashLength() const override + { + return 20; + } + + /*! + */ + void Initialize() override; + + /*! + */ + void Update( const void* data, size_type length ) override; + +private: + + void* m_context = nullptr; // RFC4634 + + /*! + */ + void Finalize( void* hash ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SHA224 + * \brief Implementation of the SHA-224 cryptographic hashing algorithm + * + * \b References + * + * The SHA-2 family of secure hash functions (SHA-256, SHA-384, and SHA-512) + * was specified by NIST in 2002 with the publication of FIPS PUB 180-2. The + * SHA-224 variant was released in a change notice for FIPS PUB 180-2 in 2004. + * FIPS PUB 180-2 has been superseded by FIPS PUB 180-3 and FIPS PUB 180-4: + * + * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf + * + * An SHA-224 message digest is 224 bits (28 bytes) long. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, MD5, SHA1, SHA256, SHA384, SHA512, + * CryptographicHashFactory + */ +class PCL_CLASS SHA224 : public CryptographicHash +{ +public: + + /*! + * Constructs an SHA-224 hash generator. + */ + SHA224() = default; + + /*! + * Destroys an SHA-224 hash generator. + */ + virtual ~SHA224(); + + /*! + * Returns the name of this cryptographic hashing algorithm: "SHA224". + */ + String AlgorithmName() const override + { + return "SHA224"; + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + * + * As reimplemented in %SHA224, this function returns 28, the length in + * bytes of an SHA-224 digest. + */ + size_type HashLength() const override + { + return 28; + } + + /*! + */ + void Initialize() override; + + /*! + */ + void Update( const void* data, size_type length ) override; + +private: + + void* m_context = nullptr; // RFC4634 + + /*! + */ + void Finalize( void* hash ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SHA256 + * \brief Implementation of the SHA-256 cryptographic hashing algorithm + * + * \b References + * + * The SHA-2 family of secure hash functions (SHA-256, SHA-384, and SHA-512) + * was specified by NIST in 2002 with the publication of FIPS PUB 180-2. FIPS + * PUB 180-2 has been superseded by FIPS PUB 180-3 and FIPS PUB 180-4: + * + * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf + * + * An SHA-256 message digest is 256 bits (32 bytes) long. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, MD5, SHA1, SHA224, SHA384, SHA512, + * CryptographicHashFactory + */ +class PCL_CLASS SHA256 : public CryptographicHash +{ +public: + + /*! + * Constructs an SHA-256 hash generator. + */ + SHA256() = default; + + /*! + * Destroys an SHA-256 hash generator. + */ + virtual ~SHA256(); + + /*! + * Returns the name of this cryptographic hashing algorithm: "SHA256". + */ + String AlgorithmName() const override + { + return "SHA256"; + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + * + * As reimplemented in %SHA256, this function returns 32, the length in + * bytes of an SHA-256 digest. + */ + size_type HashLength() const override + { + return 32; + } + + /*! + */ + void Initialize() override; + + /*! + */ + void Update( const void* data, size_type length ) override; + +private: + + void* m_context = nullptr; // RFC4634 + + /*! + */ + void Finalize( void* hash ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SHA384 + * \brief Implementation of the SHA-384 cryptographic hashing algorithm + * + * \b References + * + * The SHA-2 family of secure hash functions (SHA-384, SHA-384, and SHA-512) + * was specified by NIST in 2002 with the publication of FIPS PUB 180-2. FIPS + * PUB 180-2 has been superseded by FIPS PUB 180-3 and FIPS PUB 180-4: + * + * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf + * + * An SHA-384 message digest is 384 bits (48 bytes) long. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, MD5, SHA1, SHA224, SHA256, SHA512, + * CryptographicHashFactory + */ +class PCL_CLASS SHA384 : public CryptographicHash +{ +public: + + /*! + * Constructs an SHA-384 hash generator. + */ + SHA384() = default; + + /*! + * Destroys an SHA-384 hash generator. + */ + virtual ~SHA384(); + + /*! + * Returns the name of this cryptographic hashing algorithm: "SHA384". + */ + String AlgorithmName() const override + { + return "SHA384"; + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + * + * As reimplemented in %SHA384, this function returns 48, the length in + * bytes of an SHA-384 digest. + */ + size_type HashLength() const override + { + return 48; + } + + /*! + */ + void Initialize() override; + + /*! + */ + void Update( const void* data, size_type length ) override; + +private: + + void* m_context = nullptr; // RFC4634 + + /*! + */ + void Finalize( void* hash ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SHA512 + * \brief Implementation of the SHA-512 cryptographic hashing algorithm + * + * \b References + * + * The SHA-2 family of secure hash functions (SHA-384, SHA-384, and SHA-512) + * was specified by NIST in 2002 with the publication of FIPS PUB 180-2. FIPS + * PUB 180-2 has been superseded by FIPS PUB 180-3 and FIPS PUB 180-4: + * + * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf + * + * An SHA-512 message digest is 512 bits (64 bytes) long. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, MD5, SHA1, SHA224, SHA256, SHA384, + * CryptographicHashFactory + */ +class PCL_CLASS SHA512 : public CryptographicHash +{ +public: + + /*! + * Constructs an SHA-512 hash generator. + */ + SHA512() = default; + + /*! + * Destroys an SHA-512 hash generator. + */ + virtual ~SHA512(); + + /*! + * Returns the name of this cryptographic hashing algorithm: "SHA512". + */ + String AlgorithmName() const override + { + return "SHA512"; + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + * + * As reimplemented in %SHA512, this function returns 64, the length in + * bytes of an SHA-512 digest. + */ + size_type HashLength() const override + { + return 64; + } + + /*! + */ + void Initialize() override; + + /*! + */ + void Update( const void* data, size_type length ) override; + +private: + + void* m_context = nullptr; // RFC4634 + + /*! + */ + void Finalize( void* hash ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class CryptographicHashFactory + * \brief Selectable cryptographic hashing algorithm + * + * %CryptographicHashFactory implements a cryptographic hashing algorithm that + * can be selected upon construction among all of the algorithms implemented in + * the PixInsight/PCL platform. This currently includes MD-5, SHA-1, SHA-224, + * SHA-256, SHA-384, and SHA-512. + * + * \ingroup cryptography_classes + * \sa CryptographicHash, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 + */ +class PCL_CLASS CryptographicHashFactory : public CryptographicHash +{ +public: + + /*! + * Constructs a %CryptographicHashFactory object to implement the specified + * hashing algorithm. + * + * \param algorithmName Name of a supported cryptographic hashing algorithm. + * Currently this parameter can be one of: "md5", + * "sha1", "sha224", "sha256", "sha384", and "sha512". + * Comparisons are performed on trimmed strings and + * case-insensitive. + * + * If an invalid or unsupported algorithm name is specified, this + * constructor throws an Error exception. + */ + CryptographicHashFactory( const IsoString& algorithmName ) + { + switch ( algorithmName.Trimmed().CaseFolded().Hash32() ) + { + case 0x445dd715: m_hash = new MD5; break; + case 0x3cac24af: m_hash = new SHA1; break; + case 0x7e50b015: m_hash = new SHA224; break; + case 0xcbbce793: m_hash = new SHA256; break; + case 0x858a0d3d: m_hash = new SHA384; break; + case 0xb24dfd53: m_hash = new SHA512; break; + default: + throw Error( "CryptographicHashFactory: Unknown/unsupported algorithm \'" + algorithmName + '\'' ); + } + } + + CryptographicHashFactory( const IsoString::ustring_base& algorithmName ) + : CryptographicHashFactory( IsoString( algorithmName ) ) + { + } + + /*! + * Destroys a %CryptographicHashFactory object. + */ + virtual ~CryptographicHashFactory() + { + } + + /*! + * Returns the name of this cryptographic hashing algorithm. + */ + String AlgorithmName() const override + { + return m_hash->AlgorithmName(); + } + + /*! + * Returns the length in bytes of a hash sequence (or message digest) + * calculated with this cryptographic hashing algorithm. + */ + size_type HashLength() const override + { + return m_hash->HashLength(); + } + + /*! + * Initializes this cryptographic hash generator. + */ + void Initialize() override + { + m_hash->Initialize(); + } + + /*! + * Updates the hash generator with a new \a data chunk of the specified + * \a length in bytes. + */ + void Update( const void* data, size_type length ) override + { + m_hash->Update( data, length ); + } + +private: + + AutoPointer m_hash; + + void Finalize( void* hash ) override + { + m_hash->Finalize( hash ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Cipher + * \brief Abstract base class for cipher algorithm implementations + * + * %Cipher defines a common interface for implementations of algorithms + * performing encryption and decryption of generic data. + * + * Currently we have implemented the AES-256 cipher with CBC/ECB encryption and + * decryption on the PixInsight platform, available as the AES256 class. + * + * \ingroup cryptography_classes + * \sa AES256 + */ +class PCL_CLASS Cipher +{ +public: + + /*! + * Default constructor. + */ + Cipher() = default; + + /*! + * Copy constructor. + */ + Cipher( const Cipher& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Cipher& operator =( const Cipher& ) = default; + + /*! + * Destroys a %Cipher object. + */ + virtual ~Cipher() + { + } + + /*! + * Returns the name of this cipher algorithm. + */ + virtual String AlgorithmName() const = 0; + + /*! + * Returns the length in bytes of a key in this cipher algorithm. + */ + virtual size_type KeyLength() const = 0; + + /*! + * Buffer encryption. + * + * \param[out] output Starting address of the output buffer, where the + * encrypted data (or cipher text) will be stored. + * + * \param input Starting address of the input buffer, where the original + * data (or plain text) is stored. + * + * \param length The buffer length in bytes. + */ + virtual void Encrypt( void* output, const void* input, size_type length ) const = 0; + + /*! + * Buffer decryption. + * + * \param[out] output Starting address of the output buffer, where the + * decrypted data (or plain text) will be stored. + * + * \param input Starting address of the input buffer, where the encrypted + * data (or cipher text) is stored. + * + * \param length The buffer length in bytes. + */ + virtual void Decrypt( void* output, const void* input, size_type length ) const = 0; + + /*! + * Container encryption. + * + * \param[out] output Starting address of the output buffer, where the + * encrypted data (or cipher text) will be stored. + * + * \param input Reference to a container where the original data (or + * plain text) is stored as a contiguous block. The + * input container will be treated as a contiguous sequence + * of bytes, ignoring the data type of the items contained. + * + * The \c C template argument must be a class with PCL container semantics + * (the Begin() and Size() member functions are required). Typically the + * ByteArray class is used, although any array-like class with contiguous + * storage is appropriate, including Array, String, Vector and Matrix. + */ + template + void Encrypt( void* output, const C& input ) const + { + Encrypt( output, input.Begin(), input.Size() ); + } + + /*! + * Out-of-place container encryption. + * + * \param input Reference to a container where the original data (or + * plain text) is stored as a contiguous block. The + * input container will be treated as a contiguous sequence + * of bytes, ignoring the data type of the items contained. + * + * The \c C template argument must be a class with PCL container semantics + * (the Begin() and Size() member functions are required). Typically the + * ByteArray class is used, although any array-like class with contiguous + * storage is appropriate, including Array, String, Vector and Matrix. + * + * Returns a ByteArray object with the encrypted data, or cipher + * text. The returned object can be used to decrypt the data with the + * Decrypt() member function. + */ + template + ByteArray Encrypt( const C& input ) const + { + ByteArray output( input.Size() ); + Encrypt( output.Begin(), input.Begin(), input.Size() ); + return output; + } + + /*! + * Container decryption. + * + * \param[out] output Starting address of the output buffer, where the + * decrypted data (or plain text) will be stored. + * + * \param input Reference to a container where the encrypted data (or + * cipher text) is stored as a contiguous block. The + * input container will be treated as a contiguous sequence + * of bytes, ignoring the data type of the items contained. + * + * The \c C template argument must be a class with PCL container semantics + * (the Begin() and Size() member functions are required). Typically the + * ByteArray class is used, although any array-like class with contiguous + * storage is appropriate, including Array, String, Vector and Matrix. + */ + template + void Decrypt( void* output, const C& input ) const + { + Decrypt( output, input.Begin(), input.Size() ); + } + + /*! + * Out-of-place container decryption. + * + * \param input Reference to a container where the encrypted data (or + * cipher text) is stored as a contiguous block. The + * input container will be treated as a contiguous sequence + * of bytes, ignoring the data type of the items contained. + * + * The \c C template argument must be a class with PCL container semantics + * (the Begin() and Size() member functions are required). Typically the + * ByteArray class is used, although any array-like class with contiguous + * storage is appropriate, including Array, String, Vector and Matrix. + * + * Returns a ByteArray object with the decrypted data, or plain + * text), as a contiguous sequence of bytes. + */ + template + ByteArray Decrypt( const C& input ) const + { + ByteArray output( input.Size() ); + Decrypt( output.Begin(), input.Begin(), input.Size() ); + return output; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class AES256 + * \brief AES-256 cipher + * + * The %AES256 class is a FIPS-197 compliant implementation of the Advanced + * Encryption Standard (AES) cipher using 256-bit keys. + * + * \b References + * + * The AES (Advanced Encryption Standard) block cipher algorithm (originally + * called \e Rijndael) was designed by Vincent Rijmen and Joan Daemen: + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + * + * \ingroup cryptography_classes + */ +class PCL_CLASS AES256 : public Cipher +{ +public: + + enum { key_length = 32, block_length = 16 }; + + /*! + * Represents a 256-bit cipher key for the AES-256 algorithm. + */ + typedef uint8 key_type[ key_length ]; + + /*! + * Represents a 16-byte ECB encryption/decription block for the AES-256 + * algorithm. + */ + typedef uint8 block_type[ block_length ]; + + /*! + * Constructs an AES-256 cipher object. + * + * \param key Starting address of a contiguous block of 32 bytes, which + * will be treated as the 256-bit cipher key. The first 32 + * bytes stored at this address will be wiped out (replaced + * with zeros) by this constructor. + * + * \note For enhanced security, this constructor wipes out the specified + * cipher \a key, filling it with 32 zero bytes. If you want to preserve the + * key (which in general is a bad idea for security reasons), make + * a safe copy before invoking this constructor. + */ + AES256( void* key ) + { + SetKey( key ); + } + + /*! + * Constructs an AES-256 cipher object. + * + * \param key 256-bit cipher key specified as an 8-bit string. The + * contents of this string Will be wiped out (filled with + * null characters) by this constructor. + * + * The AES-256 cipher key will be initialized with the lowercase hexadecimal + * representation of 20 successive MD5 checksum operations applied to the + * specified \a key string (note that an %MD5 checksum is a sequence of 16 + * bytes, whose hexadecimal representation has 32 characters, or 256 bits). + * + * \note For enhanced security, this constructor wipes out the specified + * cipher \a key string, filling it with null characters. If you want to + * preserve the original key (which in general is a bad idea for + * security reasons), make a copy and ensure it references its string data + * uniquely before invoking this constructor. + */ + AES256( IsoString& key ) + { + ByteArray h = MD5().Hash( key ); + key.SecureFill(); + for ( int i = 1; i < 20; ++i ) + h = MD5().Hash( h ); + IsoString k = IsoString::ToHex( h ); + h.Fill( uint8( 0 ) ); + SetKey( k.Begin() ); + } + + /*! + * Copy constructor. + */ + AES256( const AES256& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + AES256& operator =( const AES256& ) = default; + + /*! + * Destroys an AES-256 cipher object. + */ + virtual ~AES256() + { + } + + /*! + * Returns "AES256", the name of this cipher algorithm. + */ + String AlgorithmName() const override + { + return "AES256"; + } + + /*! + * Returns 32, the length in bytes of a key in the AES-256 cipher algorithm. + */ + size_type KeyLength() const override + { + return 32; + } + + /*! + * AES-256 buffer encryption (CBC mode). + * + * \param[out] output Starting address of the output buffer, where the + * encrypted data (or cipher text) will be stored. + * + * \param input Starting address of the input buffer, where the original + * data (or plain text) is stored. + * + * \param length The buffer length in bytes. Must be an integer multiple of + * 16 bytes. + * + * If the specified \a length is not an integer multiple of 16 bytes, this + * function throws an Error exception. If necessary, the source data must + * be padded with zeros or spaces, as required to achieve a valid length. + */ + void Encrypt( void* output, const void* input, size_type length ) const override; + + /*! + * AES buffer decryption (CBC mode). + * + * \param[out] output Starting address of the output buffer, where the + * decrypted data (or plain text) will be stored. + * + * \param input Starting address of the input buffer, where the encrypted + * data (or cipher text) is stored. + * + * \param length The buffer length in bytes. Must be an integer multiple of + * 16 bytes. + * + * If the specified \a length is not an integer multiple of 16 bytes, this + * function throws an Error exception. + */ + void Decrypt( void* output, const void* input, size_type length ) const override; + + /*! + * AES block encryption (ECB mode). + * + * \param[out] output Starting address of the encrypted 16-byte block. + * + * \param input Starting address of the input 16-byte block. + */ + void EncryptBlock( void* output, const void* input ) const; + + /*! + * AES block decryption (ECB mode). + * + * \param[out] output Starting address of the decrypted 16-byte block. + * + * \param input Starting address of the input 16-byte block. + */ + void DecryptBlock( void* output, const void* input ) const; + +private: + + uint32 m_erk[ 60 ]; // encryption round keys, 4*(Nr+1) elements + uint32 m_drk[ 60 ]; // decryption round keys, 4*(Nr+1) elements + + /*! + * \internal + * Sets a new encryption/decryption key. Generates the round key tables and + * wipes out 32 contiguous bytes starting at \a key. + */ + void SetKey( void* key ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Cryptography_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Cryptography.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/CubicSplineInterpolation.h b/3rdparty/include/pcl/CubicSplineInterpolation.h new file mode 100644 index 0000000..a698935 --- /dev/null +++ b/3rdparty/include/pcl/CubicSplineInterpolation.h @@ -0,0 +1,357 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/CubicSplineInterpolation.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_CubicSplineInterpolation_h +#define __PCL_CubicSplineInterpolation_h + +/// \file pcl/CubicSplineInterpolation.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_x this->m_x +#define m_y this->m_y + +/*! + * \class CubicSplineInterpolation + * \brief Generic interpolating cubic spline + * + * Interpolation with piecewise cubic polynomials. Spline interpolation is + * usually preferred to interpolation with high-degree polynomials, which are + * subject to oscillations caused by the Runge's phenomenon. + * + * \sa AkimaInterpolation, LinearInterpolation + */ +template +class PCL_CLASS CubicSplineInterpolation : public UnidimensionalInterpolation +{ +public: + + typedef typename UnidimensionalInterpolation::vector_type vector_type; + + /*! + * Constructs an empty %CubicSplineInterpolation instance, which cannot be + * used for interpolation prior to initialization. + */ + CubicSplineInterpolation() = default; + + /*! + * Copy constructor. + */ + CubicSplineInterpolation( const CubicSplineInterpolation& ) = default; + + /*! + * Move constructor. + */ + CubicSplineInterpolation( CubicSplineInterpolation&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~CubicSplineInterpolation() + { + } + + /*! + * Gets the boundary conditions of this interpolating cubic spline. + * + * \param[out] y1 First derivative of the interpolating cubic spline at + * the first data point x[0]. + * + * \param[out] yn First derivative of the interpolating cubic spline at + * the last data point x[n-1]. + */ + void GetBoundaryConditions( double& y1, double& yn ) const + { + y1 = m_dy1; + yn = m_dyn; + } + + /*! + * Sets the boundary conditions of this interpolating cubic spline. + * + * \param y1 First derivative of the interpolating cubic spline at the + * first data point x[0]. + * + * \param yn First derivative of the interpolating cubic spline at the + * last data point x[n-1]. + */ + void SetBoundaryConditions( double y1, double yn ) + { + Clear(); + m_dy1 = y1; + m_dyn = yn; + } + + /*! + * Generation of an interpolating cubic spline. + * + * \param x %Vector of x-values:\n + * \n + * \li If \a x is not empty: Must be a vector of monotonically + * increasing, distinct values: x[0] < x[1] < ... < x[n-1].\n + * \li If \a x is empty: This function will generate a natural cubic + * spline with implicit x[i] = i for i = {0,1,...,n-1}. + * + * \param y %Vector of function values for i = {0,1,...,n-1}. + * + * When \a x is an empty vector, a natural spline is always + * generated: boundary conditions are ignored and taken as zero at both ends + * of the data sequence. + * + * The length of the \a y vector (and also the length of a nonempty \a x + * vector) must be \e n >= 2. + */ + void Initialize( const vector_type& x, const vector_type& y ) override + { + if ( y.Length() < 2 ) + throw Error( "CubicSplineInterpolation::Initialize(): Less than two data points specified." ); + + try + { + Clear(); + UnidimensionalInterpolation::Initialize( x, y ); + + int n = this->Length(); + m_dy2 = DVector( n ); + m_current = -1; // prepare for 1st interpolation + DVector w( n ); // working vector + + if ( m_x ) + { + /* + * Cubic splines with explicit x[i] for i = {0,...,n-1}. + */ + if ( m_dy1 == 0 && m_dyn == 0 ) + { + /* + * Natural cubic spline. + */ + m_dy2[0] = m_dy2[n-1] = w[0] = 0; + + for ( int i = 1; i < n-1; ++i ) + { + double s = (double( m_x[i] ) - double( m_x[i-1] )) / (double( m_x[i+1] ) - double( m_x[i-1] )); + double p = s*m_dy2[i-1] + 2; + m_dy2[i] = (s - 1)/p; + w[i] = (double( m_y[i+1] ) - double( m_y[i ] )) / (double( m_x[i+1] ) - double( m_x[i ] )) + - (double( m_y[i ] ) - double( m_y[i-1] )) / (double( m_x[i ] ) - double( m_x[i-1] )); + w[i] = (6*w[i]/(double( m_x[i+1] ) - double( m_x[i-1] )) - s*w[i-1])/p; + } + + for ( int i = n-2; i > 0; --i ) // N.B. w[0] is not defined + m_dy2[i] = m_dy2[i]*m_dy2[i+1] + w[i]; + } + else + { + /* + * Cubic spline with prescribed end point derivatives. + */ + w[0] = 3/(double( m_x[1] ) - double( m_x[0] )) + * ((double( m_y[1] ) - double( m_y[0] ))/(double( m_x[1] ) - double( m_x[0] )) - m_dy1); + + m_dy2[0] = -0.5; + + for ( int i = 1; i < n-1; ++i ) + { + double s = (double( m_x[i] ) - double( m_x[i-1] )) / (double( m_x[i+1] ) - double( m_x[i-1] )); + double p = s*m_dy2[i-1] + 2; + m_dy2[i] = (s - 1)/p; + w[i] = (double( m_y[i+1] ) - double( m_y[i ] )) / (double( m_x[i+1] ) - double( m_x[i ] )) + - (double( m_y[i ] ) - double( m_y[i-1] )) / (double( m_x[i ] ) - double( m_x[i-1] )); + w[i] = (6*w[i]/(double( m_x[i+1] ) - double( m_x[i-1] )) - s*w[i-1])/p; + } + + m_dy2[n-1] = (3/(double( m_x[n-1] ) - double( m_x[n-2] )) + * (m_dyn - (double( m_y[n-1] ) - double( m_y[n-2] ))/(double( m_x[n-1] ) - double( m_x[n-2] ))) - w[n-2]/2) + / (1 + m_dy2[n-2]/2); + + for ( int i = n-2; i >= 0; --i ) + m_dy2[i] = m_dy2[i]*m_dy2[i+1] + w[i]; + } + } + else + { + /* + * Natural cubic spline with + * implicit x[i] = i for i = {0,1,...,n-1}. + */ + m_dy2[0] = m_dy2[n-1] = w[0] = 0; + + for ( int i = 1; i < n-1; ++i ) + { + double p = m_dy2[i-1]/2 + 2; + m_dy2[i] = -0.5/p; + w[i] = double( m_y[i+1] ) - 2*double( m_y[i] ) + double( m_y[i-1] ); + w[i] = (3*w[i] - w[i-1]/2)/p; + } + + for ( int i = n-2; i > 0; --i ) // N.B. w[0] is not defined + m_dy2[i] = m_dy2[i]*m_dy2[i+1] + w[i]; + } + } + catch ( ... ) + { + Clear(); + throw; + } + } + + /*! + * Cubic spline interpolation. Returns an interpolated value at the + * specified point \a x. + */ + double operator()( double x ) const override + { + PCL_PRECONDITION( IsValid() ) + + int n = this->Length(); + + if ( m_x ) + { + /* + * Cubic spline with explicit x[i] for i = {0,...,n-1}. + */ + + /* + * Bracket the evaluation point x by binary search of the closest + * pair of data points, if needed. m_current < 0 signals first-time + * evaluation since initialization. + */ + int j0 = m_current, j1; + if ( j0 < 0 || x < m_x[j0] || m_x[j0+1] < x ) + for ( j0 = 0, j1 = n-1; j1-j0 > 1; ) + { + int m = (j0 + j1) >> 1; + if ( x < m_x[m] ) + j1 = m; + else + j0 = m; + } + else + j1 = j0 + 1; + m_current = j0; + + /* + * Distance h between the closest neighbors. Will be zero (or + * insignificant) if two or more x values are equal with respect to + * the machine epsilon for type T. + */ + double h = double( m_x[j1] ) - double( m_x[j0] ); + if ( 1 + h == 1 ) + return 0.5*(double( m_y[j0] ) + double( m_y[j1] )); + + double a = (double( m_x[j1] ) - x)/h; + double b = (x - double( m_x[j0] ))/h; + return a*double( m_y[j0] ) + + b*double( m_y[j1] ) + + ((a*a*a - a)*m_dy2[j0] + (b*b*b - b)*m_dy2[j1])*h*h/6; + } + else + { + /* + * Natural cubic spline with implicit x[i] = i for i = {0,1,...,n-1}. + */ + int j0 = pcl::Range( pcl::TruncInt( x ), 0, n-1 ); + int j1 = pcl::Min( n-1, j0+1 ); + double a = j1 - x; + double b = x - j0; + return a*double( m_y[j0] ) + + b*double( m_y[j1] ) + + ((a*a*a - a)*m_dy2[j0] + (b*b*b - b)*m_dy2[j1])/6; + } + } + + /*! + * Resets this cubic spline interpolation, deallocating all internal + * working structures. + */ + void Clear() override + { + UnidimensionalInterpolation::Clear(); + m_dy2.Clear(); + } + + /*! + * Returns true iff this interpolation is valid, i.e. if it has been + * correctly initialized and is ready to interpolate function values. + */ + bool IsValid() const override + { + return m_dy2; + } + +private: + + double m_dy1 = 0; // 1st derivative of spline at the first data point + double m_dyn = 0; // 1st derivative of spline at the last data point + DVector m_dy2; // second derivatives of the interpolating function at x[i] + mutable int m_current = -1; // index of the current interpolation segment +}; + +#undef m_x +#undef m_y + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_CubicSplineInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/CubicSplineInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Cursor.h b/3rdparty/include/pcl/Cursor.h new file mode 100644 index 0000000..fb13a65 --- /dev/null +++ b/3rdparty/include/pcl/Cursor.h @@ -0,0 +1,297 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Cursor.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_Cursor_h +#define __PCL_Cursor_h + +/// \file pcl/Cursor.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::StdCursor + * \brief Standard cursor shapes available in the PixInsight core application + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
StdCursor::NoCursor No cursor is shown
StdCursor::Arrow Standard arrow cursor (pointing left)
StdCursor::InvArrow Inverted arrow cursor (pointing right)
StdCursor::UpArrow Upwards arrow
StdCursor::DownArrow Downwards arrow
StdCursor::LeftArrow Leftwards arrow
StdCursor::RightArrow Rightwards arrow
StdCursor::Checkmark Checkmark (ok) cursor
StdCursor::Crossmark Crossmark (cancel) cursor
StdCursor::Accept Arrow + checkmark
StdCursor::Reject Arrow + crossmark
StdCursor::Add Arrow + plus sign
StdCursor::Copy Arrow + square
StdCursor::Cross Crosshair
StdCursor::Hourglass Hourglass (native Windows wait cursor)
StdCursor::Watch Watch (native Macintosh wait cursor)
StdCursor::Wait Default wait cursor (same as StdCursor::Watch)
StdCursor::ArrowWait Arrow + hourglass/watch
StdCursor::ArrowQuestion Arrow + question mark
StdCursor::IBeam I-beam cursor (text edition)
StdCursor::VerticalSize Vertical resize
StdCursor::HorizontalSize Horizontal resize
StdCursor::ForwardDiagonalSize Forward diagonal resize (/)
StdCursor::BackwardDiagonalSize Backward diagonal resize (\\)
StdCursor::SizeAll Resize in all directions
StdCursor::VerticalSplit Split vertical
StdCursor::HorizontalSplit Split horizontal
StdCursor::Hand Pointing hand cursor
StdCursor::PointingHand Pointing hand cursor (same as StdCursor::Hand)
StdCursor::OpenHand Open hand cursor (used to inform about dragging operations)
StdCursor::ClosedHand Closed hand cursor (used during active dragging operations)
StdCursor::SquarePlus Plus sign into a square (used for zooming in)
StdCursor::SquareMinus Minus sign into a square (used for zooming out)
StdCursor::CirclePlus Plus sign into a circle (used for zooming in)
StdCursor::CircleMinus Minus sign into a circle (used for zooming out)
StdCursor::Forbidden Stop cursor
+ */ +namespace StdCursor +{ + enum value_type + { + NoCursor, // no cursor is shown + Arrow, // standard arrow cursor (pointing left) + InvArrow, // inverted arrow cursor (pointing right) + UpArrow, // upwards arrow + DownArrow, // downwards arrow + LeftArrow, // leftwards arrow + RightArrow, // rightwards arrow + Checkmark, // checkmark (ok) cursor + Crossmark, // crossmark (cancel) cursor + Accept, // arrow + checkmark + Reject, // arrow + crossmark + Add, // arrow + plus sign + Copy, // arrow + square + Cross, // crosshair + Hourglass, // hourglass (native Windows wait cursor) + Watch, // watch (native Macintosh wait cursor) + Wait = Watch, // wait cursor: we like the watch! :) + ArrowWait, // arrow + hourglass/watch + ArrowQuestion, // arrow + question mark + IBeam, // I-beam cursor (text edition) + VerticalSize, // vertical resize + HorizontalSize, // horizontal resize + ForwardDiagonalSize, // forward diagonal resize (/) + BackwardDiagonalSize, // backward diagonal resize (\) + SizeAll, // resize in all directions + VerticalSplit, // split vertical + HorizontalSplit, // split horizontal + Hand, // pointing hand cursor + PointingHand = Hand, // pointing hand cursor (same as Hand) + OpenHand, // open hand cursor + ClosedHand, // closed hand cursor + SquarePlus, // plus sign into a square (used for zoom in) + SquareMinus, // minus sign into a square (used for zoom out) + CirclePlus, // plus sign into a circle (used for zoom in) + CircleMinus, // minus sign into a circle (used for zoom out) + Forbidden // stop cursor + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class Bitmap; + +// ---------------------------------------------------------------------------- + +/*! + * \class Cursor + * \brief Client-side interface to a PixInsight %Cursor object + * + * ### TODO: Write a detailed description for %Cursor. + */ +class PCL_CLASS Cursor : public UIObject +{ +public: + + /*! + * Represents a standard cursor shape. + */ + typedef StdCursor::value_type std_cursor; + + /*! + * Constructs a %Cursor object with the specified standard cursor \a shape. + */ + Cursor( std_cursor shape = StdCursor::Arrow ); + + /*! + * Constructs a %Cursor object with the specified \a bmp shape and + * hot spot coordinates \a hotSpot. + */ + Cursor( const Bitmap& bmp, const pcl::Point& hotSpot ); + + /*! + * Constructs a %Cursor object with the specified \a bmp shape and + * hot spot coordinates \a hotSpotX and \a hotSpotY. + */ + Cursor( const Bitmap& bmp, int hotSpotX = 0, int hotSpotY = 0 ); + + /*! + * Copy constructor. This object will reference the same server-side cursor + * as the specified instance \a c. + */ + Cursor( const Cursor& c ) : UIObject( c ) + { + } + + /*! + * Move constructor. + */ + Cursor( Cursor&& x ) : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys a %Cursor object. If this object references an existing cursor + * in the PixInsight core application, its reference count is decremented. + * If it becomes unreferenced, it will be garbage-collected. + */ + virtual ~Cursor() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side cursor as the specified + * instance \a c. If the previous cursor becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + Cursor& operator =( const Cursor& c ) + { + SetHandle( c.handle ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Cursor& operator =( Cursor&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null cursor. A null %Cursor object does + * not correspond to an existing cursor object in the PixInsight core + * application. + */ + static Cursor& Null(); + + /*! + * Returns the hot spot coordinates of this %Cursor object. + * + * The hot spot is the active point of the cursor. It is used by + * the operating system to calculate the current cursor position. Hot spot + * coordinates are given relative to the upper left corner of the cursor's + * shape bitmap. + */ + pcl::Point HotSpot() const; + + /*! + * Returns the current cursor position in global coordinates. + */ + static pcl::Point Position(); + + /*! + * Sets the current cursor position to the specified \a x and \a y global + * coordinates. + */ + static void SetPosition( int x, int y ); + + /*! + * Sets the current cursor position in global coordinates. + * + * This function is equivalent to SetPosition( pos.x, pos.y ). + */ + static void SetPosition( const pcl::Point& pos ) + { + SetPosition( pos.x, pos.y ); + } + +private: + + Cursor( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class Control; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Cursor_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Cursor.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Defs.h b/3rdparty/include/pcl/Defs.h new file mode 100644 index 0000000..444fe85 --- /dev/null +++ b/3rdparty/include/pcl/Defs.h @@ -0,0 +1,1206 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Defs.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_Defs_h +#define __PCL_Defs_h + +/// \file pcl/Defs.h + +/*! + * \mainpage notitle + * + *
+ *

+ * PixInsight Class Library + *

+ *

+ * Reference Documentation + *

+ *

+ * Copyright (c) 2003-2021, The PixInsight Development Team. + * All Rights Reserved + *

+ *
+ *
+ *

+ * PixInsight is an advanced image + * processing software platform designed specifically for astronomical + * applications and other technical imaging fields. PixInsight is a + * modular, open-architecture system where the entire processing and file + * handling capabilities are implemented as external installable modules. + *

+ *

+ * The PixInsight core application provides the infrastructure on top of + * which external modules can implement processes, image file formats, + * and their associated user interfaces. The + * PixInsight Class + * Library (PCL) is a C++ development framework to build PixInsight + * modules. + *

+ *

+ * PixInsight modules are special shared libraries (.so files on FreeBSD + * and Linux; .dylib under macOS; .dll files on Windows) that communicate + * with the PixInsight core application through a high-level API provided + * by PCL. Along with a core communication API, PCL includes a + * comprehensive set of image processing algorithms, ranging from + * geometrical transformations to multiscale analysis algorithms, most of + * them available as multithreaded parallel implementations. PCL provides + * also rigorous and efficient implementations of essential astronomical + * algorithms, including state-of-the-art solar system ephemerides, + * vector astrometry, and reduction of positions of solar system and + * stellar objects. + *

+ *

+ * PCL is highly portable code. As of writing this document, it is + * available on the same platforms supported by the PixInsight core + * application: 64-bit FreeBSD, Linux, Mac OS X, and Windows. PixInsight + * modules written around PCL are directly portable to all supported + * platforms without changing a single line of source code. This + * is possible because PCL is a high-level framework. PCL isolates your + * module from platform-specific implementation details: all + * platform-dependent complexities are handled behind the scenes by the + * PixInsight core application and internal PCL routines. + *

+ *

+ * Starting from version 2.0, which was published in December of 2012, + * PCL is an open-source library released under the + * PixInsight + * Class Library License (PCLL). In essence, PCLL is a liberal + * BSD-like license that allows you to develop open-source and + * closed-source, free and commercial PixInsight modules without + * restrictions. As long as you observe all PCLL terms, you can modify + * PCL and use your modified version with or without releasing your + * source code. + *

+ *

+ * The entire source code of PCL, along with all PixInsight modules + * released as open-source products, are available in the + * official PixInsight + * repositories at GitLab. Open-source modules are a good starting + * point for developing new PixInsight modules. PixInsight and PCL are + * supported by a vibrant community on + * PixInsight Forum, which also + * includes a software development section. + *

+ *
+ */ + +/*! + * \namespace pcl + * \brief PCL root namespace. + * + * pcl is the main namespace of the PixInsight Class Library (PCL), where all + * public PCL classes, functions and data are defined. + */ + +// ---------------------------------------------------------------------------- +// General definitions used by all PixInsight modules and programs. +// Included directly by PCL API and PixInsight source modules. +// ---------------------------------------------------------------------------- + +/* + * One and only one platform selection macro has to be defined. + */ +#ifndef __PCL_FREEBSD +# ifndef __PCL_LINUX +# ifndef __PCL_MACOS +# ifndef __PCL_MACOSX +# ifndef __PCL_WINDOWS +# error No platform selection macro has been defined. +# endif +# endif +# endif +# endif +#endif + +/* + * __PCL_MACOS and __PCL_MACOSX are synonyms and both always defined on macOS. + */ +#ifdef __PCL_MACOS +# ifndef __PCL_MACOSX +# define __PCL_MACOSX +# endif +#endif +#ifdef __PCL_MACOSX +# ifndef __PCL_MACOS +# define __PCL_MACOS +# endif +#endif + +/* + * Check for conflicting platform selection macros. + */ +#ifdef __PCL_FREEBSD +# if defined( __PCL_LINUX ) || defined( __PCL_MACOSX ) || defined( __PCL_WINDOWS ) +# error Multiple platform selection macros have been defined. +# endif +#endif +#ifdef __PCL_LINUX +# if defined( __PCL_FREEBSD ) || defined( __PCL_MACOSX ) || defined( __PCL_WINDOWS ) +# error Multiple platform selection macros have been defined. +# endif +#endif +#ifdef __PCL_MACOSX +# if defined( __PCL_FREEBSD ) || defined( __PCL_LINUX ) || defined( __PCL_WINDOWS ) +# error Multiple platform selection macros have been defined. +# endif +#endif +#ifdef __PCL_WINDOWS +# if defined( __PCL_FREEBSD ) || defined( __PCL_LINUX ) || defined( __PCL_MACOSX ) +# error Multiple platform selection macros have been defined. +# endif +#endif + +/* + * __PCL_UNIX is always defined on FreeBSD, Linux and macOS platforms. + */ +#if defined( __PCL_LINUX ) || defined( __PCL_FREEBSD ) || defined( __PCL_MACOSX ) +# ifndef __PCL_UNIX +# define __PCL_UNIX +# endif +#endif + +/* + * __PCL_X11 is always defined on FreeBSD and Linux platforms. + */ +#if defined( __PCL_LINUX ) || defined( __PCL_FREEBSD ) +# ifndef __PCL_X11 +# define __PCL_X11 +# endif +#endif + +/* + * Platform architecture requirements: + * + * - x86_64 / EM64T / AMD64 architecture. + */ +#ifndef __x86_64__ +# ifndef __x86_64 +# ifndef __amd64__ +# ifndef __amd64 +# ifndef _M_X64 +# ifndef _M_AMD64 +# error This version of PCL requires an x86_64 / EM64T / AMD64 architecture. +# endif +# endif +# endif +# endif +# endif +#endif +#ifndef __PCL_X64 +# define __PCL_X64 +#endif + +/* + * Compiler requirements: + * + * - GCC >= 7 on UNIX/Linux + * - Clang >= 5 on UNIX/Linux + * - MSVC++ >= 15.0 / Visual Studio 2017 on Windows + */ +#ifdef __PCL_WINDOWS +# ifdef _MSC_VER +# if _MSC_VER < 1910 +# error This version of PCL requires MSVC++ 15.0 / Visual Studio 2017 or higher on MS Windows platforms. +# endif +# elif __MINGW32__ +# else +# error Unsupported C++ compiler on MS Windows platform. +# endif +#else +# ifdef _MSC_VER +# error _MSC_VER should not be #defined on UNIX/Linux platforms. +# else +# ifdef __clang__ +# if ( __clang_major__ < 5 ) +# error This version of PCL requires Clang 5 or higher on UNIX/Linux platforms. +# endif +# else +# ifdef __GNUC__ +# if ( __GNUC__ < 7 ) +# error This version of PCL requires GCC 7 or higher on UNIX/Linux platforms. +# endif +# else +# error Unsupported C++ compiler on UNIX/Linux platform. +# endif +# endif +# endif +#endif + +/* + * Brain-damaged compilers emit particularly useless warning messages. + * N.B.: This must be done *before* including windows.h + */ +#ifndef __PCL_NO_WARNING_MUTE_PRAGMAS +# ifdef _MSC_VER +# define _CRT_SECURE_NO_DEPRECATE 1 // Deal with MS's attempt at deprecating C standard runtime functions +# pragma warning( disable: 4996 ) // ... +# pragma warning( disable: 4018 ) // '<' : signed/unsigned mismatch +# pragma warning( disable: 4049 ) // More than 64k source lines +# pragma warning( disable: 4150 ) // Deletion of pointer to incomplete type 'type'; no destructor called +# pragma warning( disable: 4244 ) // Conversion from 'type1' to 'type2', possible loss of data +# pragma warning( disable: 4345 ) // Behavior change: an object of POD type constructed... +# pragma warning( disable: 4355 ) // 'this' : used in base member initializer list +# pragma warning( disable: 4521 ) // Multiple copy constructors defined +# pragma warning( disable: 4522 ) // Multiple assignment operators defined +# pragma warning( disable: 4710 ) // Function not inlined +# pragma warning( disable: 4723 ) // Potential divide by 0 +# pragma warning( disable: 4800 ) // 'boolean' : forcing value to bool 'true' or 'false' (performance warning) +# endif +#endif + +/* + * Compiler warning management macros + */ +#ifdef _MSC_VER +# define PCL_WARNINGS_PUSH \ + __pragma(warning(push)) +#else +# define PCL_WARNINGS_PUSH \ + _Pragma("GCC diagnostic push") +#endif + +#ifdef _MSC_VER +# define PCL_WARNINGS_POP \ + __pragma(warning(pop)) +#else +# define PCL_WARNINGS_POP \ + _Pragma("GCC diagnostic pop") +#endif + +#ifdef _MSC_VER +# define PCL_WARNINGS_DISABLE_UNINITIALIZED_VARIABLE \ + __pragma(warning( disable: 6001 )) \ + __pragma(warning( disable: 4700 )) +#else +# define PCL_WARNINGS_DISABLE_UNINITIALIZED_VARIABLE \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +#endif + +// Disable C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data +#ifdef _MSC_VER +# define PCL_WARNINGS_DISABLE_SIZE_T_TO_INT_LOSS \ + __pragma(warning( disable: 4267 )) +#endif + +/* + * Disable unused variable warnings. This solution is portable for all + * compilers supporting C++11 or newer. The function call should be optimized + * away by any reasonable compiler (including MSVC :). + */ +template inline void __pcl_unused__( Args&&... ) {} +#define PCL_UNUSED( x ) __pcl_unused__( x ); + +/* + * Code optimization with unlikely/likely macros: Help the compiler to optimize + * for execution paths that are more likely to run. + */ +#ifndef __PCL_NO_BRANCH_OPTIMIZATION_MACROS +# if defined( __GNUC__ ) || defined( __clang__ ) +# define unlikely( expr ) __builtin_expect( !!(expr), 0 ) +# define likely( expr ) __builtin_expect( !!(expr), 1 ) +# else +# define unlikely( expr ) (expr) +# define likely( expr ) (expr) +# endif +#endif + +/* + * On Windows/MSVC++, _CRT_RAND_S must be #defined for rand_s() to work: + * http://msdn.microsoft.com/en-us/library/sxtz2fa8.aspx + */ +#ifdef _MSC_VER +# define _CRT_RAND_S +#endif + +/* + * C standard definitions. + */ +#ifndef __stddef_h +# include +# ifndef __stddef_h +# define __stddef_h +# endif +#endif + +/* + * C++11: Utility functions. + */ +#ifndef __utility_h +# include +# ifndef __utility_h +# define __utility_h +# endif +#endif + +/* + * C++11: Compile-time type information classes. + */ +#ifndef __type_traits_h +# include +# ifndef __type_traits_h +# define __type_traits_h +# endif +#endif + +/* + * C++11: std::initializer_list. + */ +#ifndef __initializer_list_h +# include +# ifndef __initializer_list_h +# define __initializer_list_h +# endif +#endif + +/* + * Macros that control global symbol visibility. + * + * On UNIX/Linux, compilation with -fvisibility=hidden is required for PCL and + * all PixInsight modules and applications. + */ +#ifdef _MSC_VER // Windows +# define PCL_EXPORT __declspec(dllexport) +# define PCL_MODULE_EXPORT extern "C" PCL_EXPORT +# define PCL_IMPORT __declspec(dllimport) +# define PCL_LOCAL +# define PCL_BEGIN_LOCAL +# define PCL_END_LOCAL +# define PCL_INTERNAL +# define PCL_BEGIN_INTERNAL +# define PCL_END_INTERNAL +#else // Linux/X11, FreeBSD/X11 and Mac OS X +# define PCL_EXPORT __attribute__((visibility ("default"))) +# if defined( __clang__ ) // Clang does not have the "externally_visible" attribute +# define PCL_MODULE_EXPORT extern "C" __attribute__((visibility ("default"))) +# else +# define PCL_MODULE_EXPORT extern "C" __attribute__((visibility ("default"), externally_visible)) +# endif +# define PCL_IMPORT __attribute__((visibility ("default"))) +# define PCL_LOCAL __attribute__((visibility ("hidden"))) +# define PCL_BEGIN_LOCAL _Pragma ( "GCC visibility push( hidden )" ) +# define PCL_END_LOCAL _Pragma ( "GCC visibility pop" ) +# define PCL_INTERNAL __attribute__((visibility ("internal"))) +# define PCL_BEGIN_INTERNAL _Pragma ( "GCC visibility push( internal )" ) +# define PCL_END_INTERNAL _Pragma ( "GCC visibility pop" ) +#endif +#ifdef __PCL_DSO // Using PCL as a dynamic shared object - ### untested/experimental +# ifdef __PCL_BUILDING_PCL_DSO // building the PCL DSO +# define PCL_PUBLIC PCL_EXPORT +# else // linking against the PCL DSO +# define PCL_PUBLIC PCL_IMPORT +# endif +#else // Using PCL as a static library +# define PCL_PUBLIC +#endif + +/* + * The PCL_CLASS, PCL_FUNC and PCL_DATA macros allow us to modify attributes in + * all declarations of PCL API classes, functions and data items, respectively. + */ +#define PCL_CLASS PCL_PUBLIC +#define PCL_FUNC PCL_PUBLIC +#define PCL_DATA PCL_PUBLIC + +/* + * Stringification of macro-expanded arguments needs two levels of macros. + */ +#define PCL_STRINGIFY( x ) #x + +/* + * Fastcall calling convention. + */ +#ifndef __PCL_NO_FASTCALL +# ifdef _MSC_VER +# define PCL_FASTCALL __fastcall +# else +# define PCL_FASTCALL __attribute__((fastcall)) +# endif +#else +# define PCL_FASTCALL +#endif + +/* + * Always inline functions. + */ +#ifndef __PCL_NO_FORCE_INLINE +# ifdef _MSC_VER // Visual Studio +# define PCL_FORCE_INLINE __forceinline +# else +# define PCL_FORCE_INLINE inline __attribute__((always_inline)) +# endif +#else +# define PCL_FORCE_INLINE +#endif + +/* + * Special GCC function optimizations. + */ +#ifndef __PCL_NO_HOT_FUNCTIONS +# ifdef _MSC_VER +# define PCL_HOT_FUNCTION +# else +# define PCL_HOT_FUNCTION __attribute__((hot)) +# endif +#else +# define PCL_HOT_FUNCTION +#endif + +/* + * Aligned memory allocation functions. + */ +#ifdef _MSC_VER +# define PCL_ALIGNED_MALLOC _aligned_malloc +# define PCL_ALIGNED_FREE _aligned_free +#else +# define PCL_ALIGNED_MALLOC _mm_malloc +# define PCL_ALIGNED_FREE _mm_free +#endif + +/* + * 16/32-byte aligned blocks for automatic vectorization. + */ +#ifdef _MSC_VER // Windows +# define PCL_ALIGNED_16 __declspec(align(16)) +# define PCL_ASSUME_ALIGNED_16( x ) x +# define PCL_ALIGNED_32 __declspec(align(32)) +# define PCL_ASSUME_ALIGNED_32( x ) x +#else // GCC and Clang +# define PCL_ALIGNED_16 __attribute__((aligned(16))) +# define PCL_ASSUME_ALIGNED_16( x ) __builtin_assume_aligned( x, 16 ) +# define PCL_ALIGNED_32 __attribute__((aligned(32))) +# define PCL_ASSUME_ALIGNED_32( x ) __builtin_assume_aligned( x, 32 ) +#endif + +/* + * Let the restrict type qualifier be the same for all supported C++ compilers. + */ +#ifdef _MSC_VER +# define __restrict__ __restrict +#endif + +/* + * Compiler pragmas to assume iteration independence for vectorization. + */ +#ifdef _MSC_VER +# define PCL_IVDEP __pragma(loop( ivdep )) +#else +# ifdef __clang__ +# define PCL_IVDEP +# else +# ifdef __GNUC__ +# define PCL_IVDEP _Pragma("GCC ivdep") +# endif +# endif +#endif + +/* + * Loop unrolling pragmas. + */ +#define PCL_PRAGMA( x ) _Pragma( #x ) +#ifdef _MSC_VER +# define PCL_UNROLL( n ) +#else +# ifdef __clang__ +# define PCL_UNROLL( n ) PCL_PRAGMA( clang loop unroll_count( n ) ) +# else +# ifdef __GNUC__ +# define PCL_UNROLL( n ) PCL_PRAGMA( GCC unroll n ) +# endif +# endif +#endif + +/* + * Current function name. + */ +#ifdef _MSC_VER +# define PCL_FUNCTION_NAME __FUNCTION__ +#else +# define PCL_FUNCTION_NAME __func__ +#endif + +/* + * MSVC defines 'max' and 'min' macros that conflict with several standard + * library functions, such as std::numeric_limits<>::max(). + */ +#ifdef _MSC_VER +# ifndef NOMINMAX +# define NOMINMAX 1 // needs to be defined before #include windows.h +# endif +# ifdef max +# undef max +# endif +# ifdef min +# undef min +# endif +#endif + +/* + * Minimum Win32 versions supported. + */ +#ifdef __PCL_WINDOWS +# ifndef __PCL_NO_WIN32_MINIMUM_VERSIONS +# define WINVER 0x0601 // Windows 7 +# define _WIN32_WINNT 0x0601 +# endif +#endif + +/* + * Size and distance types. + */ +#ifndef __PCL_NO_SIZE_AND_DISTANCE_TYPES + +namespace pcl +{ +/*! + * \defgroup size_distance_types Size and Distance Types + */ + +/*! + * A type used to represent block sizes, lengths and absolute positions. + * \ingroup size_distance_types + */ +typedef size_t size_type; + +/*! + * A type used to represent distances and relative positions. + * \ingroup size_distance_types + */ +typedef ptrdiff_t distance_type; + +} // pcl + +#endif // !__PCL_NO_SIZE_AND_DISTANCE_TYPES + +/* + * Portable integer types + */ +#ifndef __PCL_NO_PORTABLE_INTEGER_TYPES + +namespace pcl +{ +/*! + * \defgroup portable_integer_types Portable Integer Types + */ + +/*! + * Signed two's complement 8-bit integer type. + * \ingroup portable_integer_types + */ +typedef signed char int8; + +/*! + * Unsigned 8-bit integer type. + * \ingroup portable_integer_types + */ +typedef unsigned char uint8; + +/*! + * Signed two's complement 16-bit integer type. + * \ingroup portable_integer_types + */ +typedef signed short int16; + +/*! + * Unsigned 16-bit integer type. + * \ingroup portable_integer_types + */ +typedef unsigned short uint16; + +/*! + * Signed two's complement 32-bit integer type. + * \ingroup portable_integer_types + */ +typedef signed int int32; + +/*! + * Unsigned 32-bit integer type. + * \ingroup portable_integer_types + */ +typedef unsigned int uint32; + +#ifdef _MSC_VER // Valid for MS Visual C++ +typedef signed __int64 int64; +typedef unsigned __int64 uint64; +#else // Valid for gcc +/*! + * Signed two's complement 64-bit integer type. + * \ingroup portable_integer_types + */ +typedef signed long long int64; + +/*! + * Unsigned 64-bit integer type. + * \ingroup portable_integer_types + */ +typedef unsigned long long uint64; +#endif // _MSC_VER + +struct PCL_AssertScalarSizes +{ + static_assert( sizeof( int8 ) == 1, "Invalid sizeof( int8 )" ); + static_assert( sizeof( uint8 ) == 1, "Invalid sizeof( uint8 )" ); + static_assert( sizeof( int16 ) == 2, "Invalid sizeof( int16 )" ); + static_assert( sizeof( uint16 ) == 2, "Invalid sizeof( uint16 )" ); + static_assert( sizeof( int32 ) == 4, "Invalid sizeof( int32 )" ); + static_assert( sizeof( uint32 ) == 4, "Invalid sizeof( uint32 )" ); + static_assert( sizeof( int64 ) == 8, "Invalid sizeof( int64 )" ); + static_assert( sizeof( uint64 ) == 8, "Invalid sizeof( uint64 )" ); + static_assert( sizeof( float ) == sizeof( uint32 ), "Invalid sizeof( float )" ); + static_assert( sizeof( double ) == sizeof( uint64 ), "Invalid sizeof( double )" ); +}; + +} // pcl + +/* + * Integer limits + */ +#ifndef __PCL_NO_INTEGER_LIMITS + +/*! + * \defgroup integer_limits Integer Limits + */ + +/*! + * \defgroup integer_conversion_factors Integer Conversion Factors + */ + +#ifdef _MSC_VER // Valid for MS Visual C++ + +#define int8_min (-127i8-1) +#define int8_max 127i8 +#define int8_ofs 128ui8 +#define char_min int8_min +#define char_max int8_max + +#define uint8_max 0xffui8 + +#define int16_min (-32767i16-1) +#define int16_max 32767i16 +#define int16_ofs 32768ui16 +#define short_min int16_min +#define short_max int16_max + +#define uint16_max 0xffffui16 +#define ushort_max uint16_max + +#define uint20_max 0xfffffui32 + +#define uint22_max 0x3fffffui32 + +#define uint24_max 0xffffffui32 + +#define int32_min (-2147483647i32-1) +#define int32_max 2147483647i32 +#define int32_ofs 2147483648ui32 +#define int_min int32_min +#define int_max int32_max + +#define uint32_max 0xffffffffui32 +#define uint_max uint32_max + +#define int64_min (-9223372036854775807i64-1) +#define int64_max 9223372036854775807i64 +#define int64_ofs 9223372036854775808ui64 +#define longlong_min int64_min +#define longlong_max int64_max + +#define uint64_max 0xffffffffffffffffui64 +#define ulonglong_max uint64_max + +#define uint8_to_uint16 257ui16 +#define uint8_to_uint20 4.1120588235294117647058823529412e+03 +#define uint8_to_uint24 65793ui32 +#define uint8_to_uint32 16843009ui32 +#define uint8_to_uint64 72340172838076673ui64 + +#define uint16_to_uint8 3.8910505836575875486381322957198e-03 +#define uint16_to_uint20 1.6000228885328450446326390478370e+01 +#define uint16_to_uint24 2.5600389105058365758754863813230e+02 +#define uint16_to_uint32 65537ui32 +#define uint16_to_uint64 281479271743489ui64 + +#define uint20_to_uint8 2.4318718260496387955081896860024e-04 +#define uint20_to_uint16 6.2499105929475717044560474930262e-02 +#define uint20_to_uint24 1.6000014305128388527287032401116e+01 +#define uint20_to_uint32 4.0960039053000500679493598455046e+03 +#define uint20_to_uint64 1.7592202821648000014305128388527e+13 + +#define uint24_to_uint8 1.5199185323666651467481343000015e-05 +#define uint24_to_uint16 3.9061906281823294271427051510039e-03 +#define uint24_to_uint20 6.2499944120642192402016663671533e-02 +#define uint24_to_uint32 2.5600001519918532366665146748134e+02 +#define uint24_to_uint64 1.0995116933120039061906281823294e+12 + +#define uint32_to_uint8 5.9371814145560333073502484027646e-08 +#define uint32_to_uint16 1.5258556235409005599890138395105e-05 +#define uint32_to_uint20 2.4414039222619971079430536152662e-04 +#define uint32_to_uint24 3.9062497680788509939049489316309e-03 +#define uint32_to_uint64 4294967297ui64 + +#define uint64_to_uint8 1.3823577699190181534344400859741e-17 +#define uint64_to_uint16 3.5526594686918766543265110209534e-15 +#define uint64_to_uint20 5.6843364650699390597549726005894e-14 +#define uint64_to_uint24 9.0949464756281961368912116576494e-13 +#define uint64_to_uint32 2.3283064359965952029459655278022e-10 + +#else // Non-MS C++, i.e. GCC or compatible + +/*! + * The smallest 8-bit signed integer. + * \ingroup integer_limits + */ +#define int8_min (-int8( 127 )-1) + +/*! + * The largest 8-bit signed integer. + * \ingroup integer_limits + */ +#define int8_max int8( 127 ) +#define int8_ofs uint8( 128u ) +#define char_min int8_min +#define char_max int8_max + +/*! + * The largest 8-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint8_max uint8( 0xffu ) + +/*! + * The smallest 16-bit signed integer. + * \ingroup integer_limits + */ +#define int16_min (-int16( 32767 )-1) + +/*! + * The largest 16-bit signed integer. + * \ingroup integer_limits + */ +#define int16_max int16( 32767 ) +#define int16_ofs uint16( 32768u ) +#define short_min int16_min +#define short_max int16_max + +/*! + * The largest 16-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint16_max uint16( 0xffffu ) +#define ushort_max uint16_max + +/*! + * The largest 20-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint20_max uint32( 0xfffffu ) + +/*! + * The largest 22-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint22_max uint32( 0x3fffffu ) + +/*! + * The largest 24-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint24_max uint32( 0xffffffu ) + +/*! + * The smallest 32-bit signed integer. + * \ingroup integer_limits + */ +#define int32_min (-int32( 2147483647 )-1) + +/*! + * The largest 32-bit signed integer. + * \ingroup integer_limits + */ +#define int32_max int32( 2147483647 ) +#define int32_ofs uint32( 2147483648u ) +#define int_min int32_min +#define int_max int32_max + +/*! + * The largest 32-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint32_max uint32( 0xffffffffu ) +#define uint_max uint32_max + +/*! + * The smallest 64-bit signed integer. + * \ingroup integer_limits + */ +#define int64_min (-int64( 9223372036854775807ll )-1) + +/*! + * The largest 64-bit signed integer. + * \ingroup integer_limits + */ +#define int64_max int64( 9223372036854775807ll ) +#define int64_ofs uint64( 9223372036854775808ull ) +#define longlong_min int64_min +#define longlong_max int64_max + +/*! + * The largest 64-bit unsigned integer. + * \ingroup integer_limits + */ +#define uint64_max uint64( 0xffffffffffffffffull ) +#define ulonglong_max uint64_max + +/*! + * Conversion factor from 8-bit unsigned integer to 16-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint8_to_uint16 uint16( 257u ) + +/*! + * Conversion factor from 8-bit unsigned integer to 20-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint8_to_uint20 4.1120588235294117647058823529412e+03 + +/*! + * Conversion factor from 8-bit unsigned integer to 24-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint8_to_uint24 uint32( 65793u ) + +/*! + * Conversion factor from 8-bit unsigned integer to 32-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint8_to_uint32 uint32( 16843009u ) + +/*! + * Conversion factor from 8-bit unsigned integer to 64-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint8_to_uint64 uint64( 72340172838076673ull ) + +/*! + * Conversion factor from 16-bit unsigned integer to 8-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint16_to_uint8 3.8910505836575875486381322957198e-03 + +/*! + * Conversion factor from 16-bit unsigned integer to 20-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint16_to_uint20 1.6000228885328450446326390478370e+01 + +/*! + * Conversion factor from 16-bit unsigned integer to 24-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint16_to_uint24 2.5600389105058365758754863813230e+02 + +/*! + * Conversion factor from 16-bit unsigned integer to 32-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint16_to_uint32 uint32( 65537u ) + +/*! + * Conversion factor from 16-bit unsigned integer to 64-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint16_to_uint64 uint64( 281479271743489ull ) + +/*! + * Conversion factor from 20-bit unsigned integer to 8-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint20_to_uint8 2.4318718260496387955081896860024e-04 + +/*! + * Conversion factor from 20-bit unsigned integer to 16-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint20_to_uint16 6.2499105929475717044560474930262e-02 + +/*! + * Conversion factor from 20-bit unsigned integer to 24-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint20_to_uint24 1.6000014305128388527287032401116e+01 + +/*! + * Conversion factor from 20-bit unsigned integer to 32-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint20_to_uint32 4.0960039053000500679493598455046e+03 + +/*! + * Conversion factor from 20-bit unsigned integer to 64-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint20_to_uint64 1.7592202821648000014305128388527e+13 + +/*! + * Conversion factor from 24-bit unsigned integer to 8-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint24_to_uint8 1.5199185323666651467481343000015e-05 + +/*! + * Conversion factor from 24-bit unsigned integer to 16-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint24_to_uint16 3.9061906281823294271427051510039e-03 + +/*! + * Conversion factor from 24-bit unsigned integer to 20-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint24_to_uint20 6.2499944120642192402016663671533e-02 + +/*! + * Conversion factor from 24-bit unsigned integer to 32-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint24_to_uint32 2.5600001519918532366665146748134e+02 + +/*! + * Conversion factor from 24-bit unsigned integer to 64-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint24_to_uint64 1.0995116933120039061906281823294e+12 + +/*! + * Conversion factor from 32-bit unsigned integer to 8-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint32_to_uint8 5.9371814145560333073502484027646e-08 + +/*! + * Conversion factor from 32-bit unsigned integer to 16-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint32_to_uint16 1.5258556235409005599890138395105e-05 + +/*! + * Conversion factor from 32-bit unsigned integer to 20-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint32_to_uint20 2.4414039222619971079430536152662e-04 + +/*! + * Conversion factor from 32-bit unsigned integer to 24-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint32_to_uint24 3.9062497680788509939049489316309e-03 + +/*! + * Conversion factor from 32-bit unsigned integer to 64-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint32_to_uint64 uint64( 4294967297ull ) + +/*! + * Conversion factor from 64-bit unsigned integer to 8-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint64_to_uint8 1.3823577699190181534344400859741e-17 + +/*! + * Conversion factor from 64-bit unsigned integer to 16-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint64_to_uint16 3.5526594686918766543265110209534e-15 + +/*! + * Conversion factor from 64-bit unsigned integer to 20-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint64_to_uint20 5.6843364650699390597549726005894e-14 + +/*! + * Conversion factor from 64-bit unsigned integer to 24-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint64_to_uint24 9.0949464756281961368912116576494e-13 + +/*! + * Conversion factor from 64-bit unsigned integer to 32-bit unsigned integer. + * \ingroup integer_conversion_factors + */ +#define uint64_to_uint32 2.3283064359965952029459655278022e-10 + +#endif // _MSC_VER + +namespace pcl +{ + +inline double BitMin( int n ) +{ + switch ( n ) + { + case 8: return double( int8_min ); + case 16: return double( int16_min ); + case 32: return double( int32_min ); + case 64: return double( int64_min ); + default: return -double( (uint64( 1 ) << n) >> 1 ); + } +} + +inline double BitMax( int n ) +{ + switch ( n ) + { + case 8: return double( int8_max ); + case 16: return double( int16_max ); + case 32: return double( int32_max ); + case 64: return double( int64_max ); + default: return double( ((uint64( 1 ) << n) >> 1) - 1 ); + } +} + +inline double UBitMax( int n ) +{ + switch ( n ) + { + case 8: return double( uint8_max ); + case 16: return double( uint16_max ); + case 32: return double( uint32_max ); + case 64: return double( uint64_max ); + default: return double( (uint64( 1 ) << n) - 1 ); + } +} + +} // pcl + +#endif // !__PCL_NO_INTEGER_LIMITS + +/* + * Unicode character types. + */ +#ifndef __PCL_NO_UNICODE_CHARACTER_TYPES + +namespace pcl +{ + +/*! + * \defgroup unicode_char_types Unicode Character Types + */ + +/*! + * 16-bit Unicode character (UTF-16) + * \ingroup unicode_char_types + */ +typedef uint16 char16_type; + +/*! + * 32-bit Unicode character (UTF-32) + * \ingroup unicode_char_types + */ +typedef uint32 char32_type; + +} // pcl + +#endif // !__PCL_NO_UNICODE_CHARACTER_TYPES + +/* + * File size and position types. + */ +#ifndef __PCL_NO_FILE_SIZE_AND_POSITION_TYPES + +#ifndef __PCL_WINDOWS +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +# define _LARGEFILE64_SOURCE 1 +#endif + +namespace pcl +{ + +/*! + * \defgroup file_size_and_pos_types File Size and Position Types + * + * File positions are always signed numbers. We support 64-bit file systems. + */ + +/*! + * A type used to store a byte position or a byte offset in a file. + * \ingroup file_size_and_pos_types + */ +typedef int64 fpos_type; + +/*! + * A type used to store the length of a file in bytes. + * \ingroup file_size_and_pos_types + */ +typedef int64 fsize_type; + +} // pcl + +#endif // !__PCL_NO_FILE_SIZE_AND_POSITION_TYPES + +#endif // !__PCL_NO_PORTABLE_INTEGER_TYPES + +/* + * Maximum number of processors allowed. + */ +#define PCL_MAX_PROCESSORS 1023 +#define PCL_MAX_PROCESSORS_BITCOUNT 10 + +// ---------------------------------------------------------------------------- + +#endif // __PCL_Defs_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Defs.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Diagnostics.h b/3rdparty/include/pcl/Diagnostics.h new file mode 100644 index 0000000..91a54ac --- /dev/null +++ b/3rdparty/include/pcl/Diagnostics.h @@ -0,0 +1,130 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Diagnostics.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_Diagnostics_h +#define __PCL_Diagnostics_h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- +// Definitions and macros for implementation of diagnostics code. +// ---------------------------------------------------------------------------- +// ###### THIS HEADER IS FOR INTERNAL USE EXCLUSIVELY - PLEASE IGNORE IT ###### +// ---------------------------------------------------------------------------- + +bool PCL_FUNC IsConsoleDiagnostics(); + +void PCL_FUNC SetConsoleDiagnostics( bool set = true ); + +inline void SetGUIDiagnostics( bool set = true ) +{ + SetConsoleDiagnostics( !set ); +} + +} // pcl + +extern "C" void PCL_FUNC __PCLAssertFail( int, const char*, const char*, int ); + +#define __PCL_ASSERTION 0 +#define __PCL_PRECONDITION 1 +#define __PCL_CHECK 2 + +// ---------------------------------------------------------------------------- +// The value of __PCL_DIAGNOSTICS_LEVEL controls generation of diagnostics +// code, as follows: +// 0 = no diagnostics code is generated (the default value) +// 1 = CHECK code only +// 2 = both CHECK and PRECONDITION code +// ---------------------------------------------------------------------------- + +#ifndef __PCL_DIAGNOSTICS_LEVEL +#define __PCL_DIAGNOSTICS_LEVEL 0 +#endif + +// ---------------------------------------------------------------------------- +// Precondition diagnostics macro. +// This macro must be used when the arguments of a function are required to +// satisfy a given condition p. The default behavior, under diagnostics mode, +// is to terminate program execution if p doesn't hold. +// ---------------------------------------------------------------------------- + +#if __PCL_DIAGNOSTICS_LEVEL > 1 +#define PCL_PRECONDITION( __p ) \ + ((__p) ? (void)0 : \ + (void)__PCLAssertFail( __PCL_PRECONDITION, #__p, __FILE__, __LINE__ )); +#else +#define PCL_PRECONDITION( __p ) +#endif + +// ---------------------------------------------------------------------------- +// Check diagnostics macro. +// This macro should be used at any point where execution cannot continue if a +// given condition p is not satisfied, except when a precondition applies. The +// default behavior is to terminate program execution if p doesn't hold. +// ---------------------------------------------------------------------------- + +#if __PCL_DIAGNOSTICS_LEVEL > 0 +#define PCL_CHECK( __p ) \ + ((__p) ? (void)0 : \ + (void)__PCLAssertFail( __PCL_CHECK, #__p, __FILE__, __LINE__ )); +#else +#define PCL_CHECK( __p ) +#endif + +// ---------------------------------------------------------------------------- + +#endif // __PCL_Diagnostics_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Diagnostics.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Dialog.h b/3rdparty/include/pcl/Dialog.h new file mode 100644 index 0000000..9a91267 --- /dev/null +++ b/3rdparty/include/pcl/Dialog.h @@ -0,0 +1,309 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Dialog.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_Dialog_h +#define __PCL_Dialog_h + +/// \file pcl/Dialog.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::StdDialogCode + * \brief Standard dialog return codes + * + * + * + * + *
StdDialogCode::Ok The dialog has been accepted (e.g., by clicking the OK button)
StdDialogCode::Cancel The dialog has been rejected (e.g., by clicking the Cancel button)
+ */ +namespace StdDialogCode +{ + enum value_type + { + Cancel = 0, // The dialog has been rejected (e.g., by clicking the Cancel button) + Ok = 1 // The dialog has been accepted (e.g., by clicking the OK button) + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Dialog + * \brief Client-side interface to a PixInsight modal dialog + * + * Dialogs are top-level windows that execute modally relative to the main + * window of the PixInsight core application. + */ +class PCL_CLASS Dialog : public Control +{ +public: + + /*! + * Represents a standard dialog return code. + */ + typedef StdDialogCode::value_type std_code; + + /*! + * Constructs a %Dialog object. + * + * If the specified \a parent control is a non-null control, the dialog will + * be shown centered over its parent. Otherwise the dialog window will be + * shown centered on the current workspace. Note that specifying a dialog + * parent does not change the dialog's \e modality: all dialog windows are + * application-modal in PixInsight. See the Execute() and Open() member + * functions for more information. + */ + Dialog( Control& parent = Control::Null() ); + + /*! + * Destroys a %Dialog object. + */ + virtual ~Dialog() + { + } + + /*! + * Shows a modal dialog and executes a separate event loop. + * + * This function creates a new event loop and does not return until the loop + * has exited and the dialog has been closed. During the event loop, the + * dialog behaves as an application modal window: Only the dialog + * window allows user interaction while the rest of the GUI is blocked in + * the PixInsight core application. To exit the modal event loop, the Ok() + * and Cancel() member functions can be used to return the standard dialog + * exit codes StdDialogCode::Ok and StdDialogCode::Cancel, respectively. + * + * This function returns a dialog return code. Although dialog + * return codes are arbitrary (they can be forced to any integer value with + * the Return() member function), dialogs with standard OK and Cancel + * buttons should always return a standard code, as defined in the + * StdDialogCode namespace. + * + * For a non-blocking alternative to use dialog windows, see the Open() + * member function. + * + * \sa Ok(), Cancel(), Return(), Open() + */ + int Execute(); + + /*! + * Shows a modal dialog window. + * + * This function opens the dialog window and returns immediately, allowing + * normal execution to continue without entering a separate event loop. As + * happens with Dialog::Execute(), this member function creates a modal + * dialog that blocks the rest of the PixInsight core application for GUI + * user interaction. The essential difference between both member functions + * is that Open() does not enter a new event loop. Typically, this function + * is used to provide feedback to the user during long procedures, as well + * as the possibility to interrupt or pause those procedures. For example, + * a progress dialog can be shown as a modal window during a file + * copy operation, or while a long calculation routine is being executed. + * + * \sa Execute() + */ + void Open(); + + /*! + * Closes this modal dialog and forces a return value \a retCode for the + * Execute() member function. + */ + void Return( int retCode ); + + /*! + * This is a convenience member function equivalent to:\n + * Return( StdDialogCode::Ok ) + */ + void Ok() + { + Return( StdDialogCode::Ok ); + } + + /*! + * This is a convenience member function equivalent to:\n + * Return( StdDialogCode::Cancel ) + */ + void Cancel() + { + Return( StdDialogCode::Cancel ); + } + + /*! + * Returns true iff this dialog is user-resizable. User-resizable dialogs can + * be resized interactively with the mouse and standard window controls. + */ + bool IsUserResizable() const; + + /*! + * Enables or disables user resizing for this dialog. + */ + void EnableUserResizing( bool = true ); + + /*! + * Disables or enables user resizing for this dialog. + * + * This is a convenience member function, equivalent to: + * EnableUserResizing( !disable ) + */ + void DisableUserResizing( bool disable = true ) + { + EnableUserResizing( !disable ); + } + + /*! + * Processes pending user interface events. + * + * This member function is a convenience wrapper with the same functionality + * as ProcessInterface::ProcessEvents(). + */ + static void ProcessEvents( bool excludeUserInputEvents = false ); + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnExecute( Dialog& sender ); + // void OnReturn( Dialog& sender, int retVal ); + + /*! + * \defgroup dialog_event_handlers Dialog Event Handlers + */ + + /*! + * Defines the prototype of a dialog execution event handler. + * + * A dialog execution event is generated when a dialog control is executed + * by invoking its Execute() member function. + * + * \param sender The dialog that sends an execution event. + * + * \ingroup dialog_event_handlers + */ + typedef void (Control::*execute_event_handler)( Dialog& sender ); + + /*! + * Defines the prototype of a dialog return event handler. + * + * A dialog return event is generated when a dialog control terminates + * execution by invoking its Return() member function. + * + * \param sender The dialog that sends a return event. + * + * \param retCode Return code passed to the Return() member function. This + * is also the return value of Execute(). + * + * \ingroup dialog_event_handlers + */ + typedef void (Control::*return_event_handler)( Dialog& sender, int retCode ); + + /*! + * Sets the execution event handler for this dialog. + * + * \param handler The dialog execution event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive execution events from + * this dialog. + * + * \ingroup dialog_event_handlers + */ + void OnExecute( execute_event_handler handler, Control& receiver ); + + /*! + * Sets the return event handler for this dialog. + * + * \param handler The dialog return event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive return events from this + * dialog. + * + * \ingroup dialog_event_handlers + */ + void OnReturn( return_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + execute_event_handler onExecute = nullptr; + return_event_handler onReturn = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class DialogEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Dialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Dialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/DisplayFunction.h b/3rdparty/include/pcl/DisplayFunction.h new file mode 100644 index 0000000..99cfcb7 --- /dev/null +++ b/3rdparty/include/pcl/DisplayFunction.h @@ -0,0 +1,463 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/DisplayFunction.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_DisplayFunction_h +#define __PCL_DisplayFunction_h + +/// \file pcl/DisplayFunction.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * Default clipping increment in sigma units. + */ +#define __PCL_AUTOSTRETCH_DEFAULT_CLIP -2.80 + +/* + * Default target mean background in the [0,1] range. + */ +#define __PCL_AUTOSTRETCH_DEFAULT_TBGD 0.25 + +/* + * Whether to apply a single transformation to nominal RGB channels, or + * separate per-channel transformations. + */ +#define __PCL_AUTOSTRETCH_DEFAULT_LINK false + +// ---------------------------------------------------------------------------- + +/*! + * \class DisplayFunction + * \brief Adaptive histogram transformations for image visualization. + * + * %DisplayFunction implements a set of histogram transformations for + * visualization of linear images. + */ +class PCL_CLASS DisplayFunction : public ImageTransformation +{ +public: + + /*! + * Default constructor. Constructs an identity display function. + */ + DisplayFunction() + : m_m( 4 ), m_s( 4 ), m_h( 4 ), m_l( 4 ), m_r( 4 ) + { + Reset(); + } + + /*! + * Constructs a display function with the specified parameters. + * + * \param m Vector of midtones balance parameters. + * \param s Vector of shadows clipping point parameters. + * \param h Vector of highlights clipping point parameters. + * \param l Vector of shadows dynamic range expansion parameters. + * \param r Vector of highlights dynamic range expansion parameters. + * + * Each argument vector can have from zero to four components (additional + * vector components are ignored, and missing components are replaced with + * default identity transformation parameters). Vector indices 0, 1, 2 and 3 + * correspond to the red/gray, green, blue and lightness components for + * histogram transformations. + * + * For detailed information on parameter values and valid ranges, see the + * HistogramTransformation class. + */ + template + DisplayFunction( const V& m, const V& s, const V& h, const V& l = V(), const V& r = V() ) + : m_m( 4 ), m_s( 4 ), m_h( 4 ), m_l( 4 ), m_r( 4 ) + { + Reset(); + for ( int i = 0; i < 4 && i < int( m.Length() ); ++i ) m_m[i] = Range( double( m[i] ), 0.0, 1.0 ); + for ( int i = 0; i < 4 && i < int( s.Length() ); ++i ) m_s[i] = Range( double( s[i] ), 0.0, 1.0 ); + for ( int i = 0; i < 4 && i < int( h.Length() ); ++i ) m_h[i] = Range( double( h[i] ), 0.0, 1.0 ); + for ( int i = 0; i < 4 && i < int( l.Length() ); ++i ) m_l[i] = Max( 0.0, double( l[i] ) ); + for ( int i = 0; i < 4 && i < int( r.Length() ); ++i ) m_r[i] = Min( 1.0, double( r[i] ) ); + for ( int i = 0; i < 4; ++i ) + if ( m_h[i] < m_s[i] ) + pcl::Swap( m_s[i], m_h[i] ); + } + + /*! + * Copy constructor. + */ + DisplayFunction( const DisplayFunction& ) = default; + + /*! + * Move constructor. + */ + DisplayFunction( DisplayFunction&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + DisplayFunction& operator =( const DisplayFunction& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + DisplayFunction& operator =( DisplayFunction&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~DisplayFunction() + { + } + + /*! + * Array subscript operator. Returns an histogram transformation for the + * specified channel index \a i, which must be in the range [0,3]. + * + * Channel indices 0, 1, 2 and 3 correspond to the red/gray, green, blue and + * lightness components, respectively. If an out-of-range channel index is + * specified, this operator returns an identity histogram transformation. + */ + HistogramTransformation operator []( int i ) const + { + PCL_PRECONDITION( 0 <= i && i < 4 ) + PCL_CHECK( m_m.Length() == 4 && m_s.Length() == 4 && m_h.Length() == 4 && m_l.Length() == 4 && m_r.Length() == 4 ) + if ( i >= 0 && i < 4 ) + return HistogramTransformation( m_m[i], m_s[i], m_h[i], m_l[i], m_r[i] ); + return HistogramTransformation(); + } + + /*! + * Returns a dynamic array of histogram transformations. + * + * The returned object contains four HistogramTransformation instances, + * where array indexes 0, 1, 2 and 3 correspond to the red/gray, green, blue + * and lightness components, respectively. + */ + Array HistogramTransformations() const + { + return Array() << operator[]( 0 ) + << operator[]( 1 ) + << operator[]( 2 ) + << operator[]( 3 ); + } + + /*! + * Gets a copy of all display function parameters in the specified vectors. + * + * \param[out] m Vector of midtones balance parameters. + * \param[out] s Vector of shadows clipping point parameters. + * \param[out] h Vector of highlights clipping point parameters. + * \param[out] l Vector of shadows dynamic range expansion parameters. + * \param[out] r Vector of highlights dynamic range expansion parameters. + * + * On output, each vector will have four components with the histogram + * transformation parameters for the red/gray, green, blue and lightness + * image components at vector indexes 0, 1, 2 and 3, respectively. + */ + template + void GetDisplayFunctionParameters( V& m, V& s, V& h, V& l, V& r ) const + { + m = m_m; s = m_s; h = m_h; l = m_l; r = m_r; + } + + /*! + * Returns true only if this object defines an identity display function for + * the specified channel index \a i. + * + * An identity display function is a no-op: it does not alter the pixel data + * or properties of the target images to which it is applied. + */ + bool IsIdentityTransformation( int i ) const + { + PCL_PRECONDITION( 0 <= i && i < 4 ) + PCL_CHECK( m_m.Length() == 4 && m_s.Length() == 4 && m_h.Length() == 4 && m_l.Length() == 4 && m_r.Length() == 4 ) + return i >= 0 && i < 4 && m_m[i] == 0.5 && m_s[i] == 0 && m_h[i] == 1 && m_l[i] == 0 && m_r[i] == 1; + } + + /*! + * Returns true iff this is an identity display function for the four + * image components (red/gray, green, blue and lightness). + * + * An identity display function is a no-op: it does not alter the pixel data + * or properties of the target images to which it is applied. + */ + bool IsIdentityTransformation() const + { + return IsIdentityTransformation( 0 ) + && IsIdentityTransformation( 1 ) + && IsIdentityTransformation( 2 ) + && IsIdentityTransformation( 3 ); + } + + /*! + * Returns the clipping point parameter of this transformation, in sigma + * units from the central value. + */ + double ClippingPoint() const + { + return m_clip; + } + + /*! + * Sets the clipping point parameter of this transformation, in sigma units + * from the central value. The default clipping point is -2.8. + */ + void SetClippingPoint( double clip ) + { + m_clip = clip; + } + + /*! + * Returns the target background parameter of this transformation in the + * normalized [0,1] range. + */ + double TargetBackground() const + { + return m_tbkg; + } + + /* + * Sets the target background parameter of this transformation in the + * normalized [0,1] range. The default target background is 0.25. + */ + void SetTargetBackground( double tbkg ) + { + m_tbkg = Range( tbkg, 0.0, 1.0 ); + } + + /*! + * Returns true iff this transformation will compute a single adaptive + * histogram transformation for the nominal channels of an RGB color image. + * Returns false if adaptive per-channel transformations will be calculated + * separately. + */ + bool LinkedRGB() const + { + return m_link; + } + + /*! + * Sets the 'linked RGB' parameter of this transformation. When this + * parameter is true, a single adaptive histogram transformation will be + * computed for the nominal channels of an RGB color image. When this + * parameter is false, separate adaptive transformations will be calculated + * for each channel. + */ + void SetLinkedRGB( bool link = true ) + { + m_link = link; + } + + /*! + * Computes adaptive display functions, also known as auto-stretch + * functions, based on statistical estimates of scale and location. + * + * \param sigma Vector of scale estimates. This is typically a vector of + * normalized MAD values (median absolute deviation from the + * median) or similar robust dispersion estimates. + * + * \param center Vector of location estimates. Typically the median is used + * as a robust estimator of central tendency. + * + * Both vectors must have one or three components, respectively for a + * monochrome (grayscale) or RGB color image. Avoid using non-robust + * statistical estimators such as the standard deviation or the mean, which + * can easily lead to completely wrong results. + * + * To obtain results coherent with other implementations, scale estimates + * should be normalized to be consistent with the standard deviation of a + * normal distribution. For example, if MAD values are used, they should be + * multiplied by 1.4826 before calling this function. + */ + template + void ComputeAutoStretch( const V& sigma, const V& center ) + { + PCL_CHECK( m_m.Length() == 4 && m_s.Length() == 4 && m_h.Length() == 4 && m_l.Length() == 4 && m_r.Length() == 4 ) + + if ( sigma.IsEmpty() || center.IsEmpty() ) + { + Reset(); + return; + } + + int n = (sigma.Length() < 3 || center.Length() < 3) ? 1 : 3; + + if ( m_link ) + { + /* + * Try to find out how many channels look like channels of an inverted + * image. + * + * We know a channel is inverted because the main histogram peak is + * located over the right-hand half of the histogram. Seems simplistic + * but this is consistent with most real-world images. + */ + int invertedChannels = 0; + for ( int i = 0; i < n; ++i ) + if ( center[i] > 0.5 ) + ++invertedChannels; + + double c = 0, m = 0; + if ( invertedChannels < n ) + { + // Noninverted image + for ( int i = 0; i < n; ++i ) + { + if ( 1 + sigma[i] != 1 ) + c += center[i] + m_clip * sigma[i]; + m += center[i]; + } + m_s[0] = m_s[1] = m_s[2] = Range( c/n, 0.0, 1.0 ); + m_m[0] = m_m[1] = m_m[2] = HistogramTransformation::MTF( m_tbkg, m/n - m_s[0] ); + m_l[0] = m_l[1] = m_l[2] = 0.0; + m_h[0] = m_h[1] = m_h[2] = m_r[0] = m_r[1] = m_r[2] = 1.0; + } + else + { + // Inverted image + for ( int i = 0; i < n; ++i ) + { + c += (1 + sigma[i] != 1) ? center[i] - m_clip * sigma[i] : 1.0; + m += center[i]; + } + m_h[0] = m_h[1] = m_h[2] = Range( c/n, 0.0, 1.0 ); + m_m[0] = m_m[1] = m_m[2] = HistogramTransformation::MTF( m_h[0] - m/n, m_tbkg ); + m_s[0] = m_s[1] = m_s[2] = m_l[0] = m_l[1] = m_l[2] = 0.0; + m_r[0] = m_r[1] = m_r[2] = 1.0; + } + } + else + { + /* + * Unlinked RGB/K channnels: Compute automatic stretch functions for + * individual RGB/K channels separately. + */ + for ( int i = 0; i < n; ++i ) + if ( center[i] < 0.5 ) + { + // Noninverted channel + m_s[i] = (1 + sigma[i] != 1) ? Range( center[i] + m_clip * sigma[i], 0.0, 1.0 ) : 0.0; + m_m[i] = HistogramTransformation::MTF( m_tbkg, center[i] - m_s[i] ); + m_l[i] = 0.0; + m_h[i] = m_r[i] = 1.0; + } + else + { + // Inverted channel + m_h[i] = (1 + sigma[i] != 1) ? Range( center[i] - m_clip * sigma[i], 0.0, 1.0 ) : 1.0; + m_m[i] = HistogramTransformation::MTF( m_h[i] - center[i], m_tbkg ); + m_s[i] = m_l[i] = 0.0; + m_r[i] = 1.0; + } + } + } + + /*! + * Resets all display function parameters to yield an identity + * transformation. + */ + void Reset() + { + m_m = 0.5; + m_s = m_l = 0.0; + m_h = m_r = 1.0; + } + + /*! + * Exchanges two %DisplayFunction objects. + */ + friend void Swap( DisplayFunction& x, DisplayFunction& y ) + { + pcl::Swap( x.m_m, y.m_m ); + pcl::Swap( x.m_s, y.m_s ); + pcl::Swap( x.m_h, y.m_h ); + pcl::Swap( x.m_l, y.m_l ); + pcl::Swap( x.m_r, y.m_r ); + pcl::Swap( x.m_clip, y.m_clip ); + pcl::Swap( x.m_tbkg, y.m_tbkg ); + pcl::Swap( x.m_link, y.m_link ); + } + +private: + + DVector m_m; // midtones balance + DVector m_s; // shadows clipping point + DVector m_h; // highlights clipping point + DVector m_l; // shadows dynamic range expansion + DVector m_r; // highlights dynamic range expansion + double m_clip = __PCL_AUTOSTRETCH_DEFAULT_CLIP; // auto-stretch clipping point + double m_tbkg = __PCL_AUTOSTRETCH_DEFAULT_TBGD; // auto-stretch target background + bool m_link = __PCL_AUTOSTRETCH_DEFAULT_LINK; // auto-stretch linked RGB + + /* + * Display function transformation. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_DisplayFunction_h + +// ---------------------------------------------------------------------------- +// EOF pcl/DisplayFunction.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/DrizzleData.h b/3rdparty/include/pcl/DrizzleData.h new file mode 100644 index 0000000..19fda5c --- /dev/null +++ b/3rdparty/include/pcl/DrizzleData.h @@ -0,0 +1,1496 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/DrizzleData.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_DrizzleData_h +#define __PCL_DrizzleData_h + +/// \file pcl/DrizzleData.h + +#include + +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS XMLDocument; +class PCL_CLASS XMLElement; + +/*! + * \class DrizzleData + * \brief Drizzle integration data parser and generator + * + * %DrizzleData implements support for the %XML drizzle data format (XDRZ + * format, .xdrz file suffix). + * + * A drizzle image integration process has been formalized as the following + * chain of subtasks on the PixInsight/PCL platform: + * + * \li 1. Demosaicing. Only required if the input data set has been mosaiced + * with a color filter array (CFA), such as a Bayer or X-Trans filter. + * + * \li 2. Image registration. Generates image alignment information in the form + * of alignment matrices (projective transformations) and/or two-dimensional + * surface splines (for arbitrary distortion correction, global and local + * distortion correction models). + * + * \li 3. Image integration. Generates statistical data for each channel of the + * integrated image. This includes estimates of location and scale, statistical + * weights and pixel rejection data. + * + * \li 4. Drizzle integration. The input data for the drizzle algorithm is the + * input image for subtasks 1 (CFA drizzle) or 2 (normal drizzle). The + * information generated by subtasks 2 and 3 is used to perform a drizzle image + * integration process by inverse coordinate projection with image weighting, + * image normalization, and pixel rejection. + * + * An XDRZ file stores all of the data generated by the above drizzle + * integration subtasks as an %XML document. The %DrizzleData class is a + * high-level interface for parsing and generation of these special files. + * + * This class also implements an internal read-only compatibility layer with + * the old plain text drizzle data format (.drz file suffix) used by versions + * of PixInsight before the 1.8.5 standard distribution. By using the class + * constructor or the Parse() member function to load and parse an existing + * file, the correct file format is detected automatically. + * + * \sa NormalizationData + */ +class PCL_CLASS DrizzleData +{ +public: + + /*! + * Represents a vector surface spline interpolation/approximation in two + * dimensions. This class is used to implement image alignment with + * arbitrary distortion correction. + */ + typedef PointSurfaceSpline vector_spline; + + /*! + * Represents a coordinate interpolating/approximating surface spline used + * for image registration with arbitrary distortion correction. + */ + typedef vector_spline::spline spline; + + /*! + * An ordered list of image coordinates. Used to store reference image + * coordinates or image displacements in local distortion models. Also used + * to store interpolation node coordinates for adaptive normalization. + */ + typedef Array point_list; + + /*! + * An ordered list of statistical weights corresponding to points in a local + * distortion model. + */ + typedef Array weight_vector; + + /*! + * A list of coordinates corresponding to pixels rejected by an image + * integration task. + */ + typedef Array rejection_coordinates; + + /*! + * A set of per-channel pixel rejection coordinates. + */ + typedef Array rejection_data; + + /*! + * Default constructor. Constructs an empty %DrizzleData object. + */ + DrizzleData() = default; + + /*! + * Copy constructor. + */ + DrizzleData( const DrizzleData& ) = default; + + /*! + * Move constructor. + */ + DrizzleData( DrizzleData&& ) = default; + + /*! + * Constructs a new %DrizzleData instance by loading and parsing a file. + * + * \param filePath Path to an existing file that will be parsed. The file + * contents can be in %XML drizzle data format (normally, + * a file with the .xdrz suffix), or in old plain text + * format (typically with the .drz suffix). This + * constructor will detect the format in use from the + * first bytes of the file, and will decode it + * correspondingly. + * + * \param ignoreIntegrationData If true, all drizzle data relative to the + * image integration task will be ignored. This includes + * statistical location and scale estimates for image + * normalization, image weights, and pixel rejection data. + * + * 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. + */ + DrizzleData( const String& filePath, bool ignoreIntegrationData = false ) + { + Parse( filePath, ignoreIntegrationData ); + } + + /*! + * Constructs a new %DrizzleData instance by parsing a well-formed %XML + * document. + * + * \param xml Reference to the source %XML document. This constructor + * expects an %XML document in valid %XML drizzle data + * format (.xdrz). + * + * \param ignoreIntegrationData If true, all drizzle data relative to the + * image integration task will be ignored. This includes + * statistical location and scale estimates for image + * normalization, image weights, and pixel rejection data. + * + * 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. + */ + DrizzleData( const XMLDocument& xml, bool ignoreIntegrationData = false ) + { + Parse( xml, ignoreIntegrationData ); + } + + /*! + * Constructs a new %DrizzleData instance by parsing an %XML element. + * + * \param element Reference to the source %XML element. This constructor + * expects an %XML document tree in valid %XML drizzle + * data format (.xdrz) rooted at this element. + * + * \param ignoreIntegrationData If true, all drizzle data relative to the + * image integration task will be ignored. This includes + * statistical location and scale estimates for image + * normalization, image weights, and pixel rejection data. + * + * This constructor validates the data retrieved from the specified %XML + * element. It throws an Error exception in the event of invalid data. + */ + DrizzleData( const XMLElement& element, bool ignoreIntegrationData = false ) + { + Parse( element, ignoreIntegrationData ); + } + + /*! + * Virtual destructor. + */ + virtual ~DrizzleData() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + DrizzleData& operator =( const DrizzleData& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + DrizzleData& operator =( DrizzleData&& ) = default; + + /*! + * Returns the full path to the unregistered image file corresponding to the + * drizzle source image represented by this instance. + * + * The file identified by this function stores the input image of the image + * registration task. This file can be used as input for a drizzle + * integration task. + * + * \sa SetSourceFilePath() + */ + const String& SourceFilePath() const + { + return m_sourceFilePath; + } + + /*! + * Sets the path to the unregistered image file corresponding to the drizzle + * image represented by this instance. + * + * \sa SourceFilePath() + */ + void SetSourceFilePath( const String& filePath ) + { + m_sourceFilePath = File::FullPath( filePath ); + } + + /*! + * Returns the full path to the mosaiced/unregistered image file + * corresponding to the drizzle source image represented by this instance. + * + * The file identified by this function stores the input image of the image + * demosaicing task. This file can be used as input for a CFA drizzle + * integration task. + * + * \sa SetCFASourceFilePath(), CFASourcePattern(), CFASourceChannel() + */ + const String& CFASourceFilePath() const + { + return m_cfaSourceFilePath; + } + + /*! + * Sets the path to the mosaiced/unregistered image file corresponding t + * the drizzle source image represented by this instance. + * + * \sa CFASourceFilePath(), SetCFASourcePattern(), SetCFASourceChannel() + */ + void SetCFASourceFilePath( const String& filePath ) + { + m_cfaSourceFilePath = File::FullPath( filePath ); + } + + /*! + * Returns a string representation of the color filter array (CFA) used by + * the mosaiced/unregistered image file corresponding to the drizzle source + * image represented by this instance. + * + * The CFA corresponds to the file represented by CFASourceFilePath(). For + * the standard Bayer filters, this function returns "RGGB", "BGGR", "GBRG", + * and "GRBG". + * + * \sa SetCFASourcePattern(), CFASourceChannel(), CFASourceFilePath() + */ + const String& CFASourcePattern() const + { + return m_cfaSourcePattern; + } + + /*! + * Defines the color filter array (CFA) used by the mosaiced/unregistered + * image file corresponding to the drizzle source image represented by this + * instance. + * + * See CFASourcePattern() for more information on CFA representations. + * + * \sa CFASourcePattern(), SetCFASourceChannel(), SetCFASourceFilePath() + */ + void SetCFASourcePattern( const String& cfaPattern ) + { + m_cfaSourcePattern = cfaPattern; + } + + /*! + * Returns the channel index selected for the CFA mosaiced/unregistered + * image file corresponding to the drizzle source image represented by this + * instance. + * + * The returned value is the zero-based index of an image channel in a color + * filter array (CFA) source frame, where typically 0 corresponds to red, 1 + * to green and 2 to blue. This member function returns a value < 0 if no + * channel index has been defined. + * + * The CFA channel index can be defined for drizzle integration of separate + * color components working with color filter array (CFA) images. This is + * useful for correction of non-isotropic channel misalignments, such as + * those caused by chromatic aberration or atmospheric dispersion, by + * computing image registration transformations with distortion corrections + * among color components for each source frame. When a channel index has + * been defined, the final CFA drizzle integration generates a monochrome + * single-channel image instead of an RGB image. + * + * \sa SetCFASourceChannel(), CFASourceFilePath(), CFASourcePattern() + */ + int CFASourceChannel() const + { + return m_cfaSourceChannel; + } + + /*! + * Defines the channel index selected for the CFA mosaiced/unregistered + * image file corresponding to the drizzle source image represented by this + * instance. + * + * The specified \a channel can be < 0 to disable the CFA channel index + * feature. See CFASourceChannel() for more information on CFA channel + * indexes and their role for CFA drizzle integrations. + * + * \sa CFASourceChannel(), SetCFASourceFilePath(), SetCFASourcePattern() + */ + void SetCFASourceChannel( int channel ) + { + m_cfaSourceChannel = Range( channel, -1, int( int32_max ) ); + } + + /*! + * Returns the full path to the registered image file corresponding to the + * drizzle source image represented by this instance, or an empty string if + * that file path is not available. + * + * The file identified by this function stores the output image of the image + * registration task. This file can be used as input for a regular + * (non-drizzle) integration task. + * + * \note This file should not be used as input for drizzle + * integration, since it has already been registered and interpolated. Use + * SourceFilePath() or CFASourceFilePath() as input for drizzle or CFA + * drizzle, respectively. + * + * \sa SetAlignmentTargetFilePath() + */ + const String& AlignmentTargetFilePath() const + { + return m_alignTargetFilePath; + } + + /*! + * Sets the path to the registered image file corresponding to the drizzle + * image represented by this instance. + * + * \sa AlignmentTargetFilePath() + */ + void SetAlignmentTargetFilePath( const String& filePath ) + { + m_alignTargetFilePath = File::FullPath( filePath ); + } + + /*! + * Returns the width in pixels of the registration reference image. + * + * \sa ReferenceHeight(), SetReferenceDimensions() + */ + int ReferenceWidth() const + { + return m_referenceWidth; + } + + /*! + * Returns the height in pixels of the registration reference image. + * + * \sa ReferenceWidth(), SetReferenceDimensions() + */ + int ReferenceHeight() const + { + return m_referenceHeight; + } + + /*! + * Sets new registration reference 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. + */ + int NumberOfChannels() const + { + return m_location.Length(); + } + + /*! + * Returns the origin of image alignment coordinates. The returned point + * corresponds to image coordinates {0,0} in the coordinate system used for + * image registration. + * + * \sa SetAlignmentOrigin() + */ + const DPoint& AlignmentOrigin() const + { + return m_alignmentOrigin; + } + + /*! + * Defines the origin of image alignment coordinates. This function is + * reserved for image registration tasks involved in drizzle integration + * processes. + * + * \note The default alignment origin coordinates are {0.5,0.5}, that is, + * the center of the top-left pixel in the image coordinate system. These + * coordinates ensure compatibility with old versions of drizzle data + * serializations and standard image registration tools on the PixInsight + * platform. + */ + void SetAlignmentOrigin( const DPoint& p0 ) + { + m_alignmentOrigin = p0; + } + + /*! + * Returns the 3x3 alignment matrix for the drizzle source image represented + * by this instance. The returned matrix defines a projective geometric + * transformation, also known as \e homography. + * + * \sa SetAlignmentMatrix() + */ + const Matrix& AlignmentMatrix() const + { + return m_H; + } + + /*! + * Defines a new 3x3 alignment matrix. This function is reserved for image + * registration tasks involved in drizzle integration processes. + * + * \sa AlignmentMatrix() + */ + void SetAlignmentMatrix( const Matrix& H ) + { + m_H = H; + } + + /*! + * Returns true iff this instance defines a 3x3 alignment matrix for the + * projective image registration transformation. + * + * \sa AlignmentMatrix(), HasAlignmentSplines() + */ + bool HasAlignmentMatrix() const + { + return !m_H.IsEmpty(); + } + + /*! + * Returns the vector surface spline interpolation/approximation device in + * two dimensions for the drizzle source image represented by this instance. + * These splines define an image registration transformation with + * corrections for arbitrary distortions. + * + * \sa SetAlignmentSplines(), SetAlignmentInverseSplines() + */ + const vector_spline& AlignmentSplines() const + { + return m_S; + } + + /*! + * Sets a new vector surface spline interpolation/approximation device. This + * member function is reserved for image registration tasks involved in + * drizzle integration processes. + * + * \sa AlignmentSplines(), AlignmentInverseSplines() + */ + void SetAlignmentSplines( const vector_spline& S ) + { + m_S = S; + } + + /*! + * Returns true iff this instance defines a vector surface spline + * interpolation/approximation device. + * + * \sa AlignmentSplines(), HasAlignmentInverseSplines(), + * HasAlignmentMatrix() + */ + bool HasAlignmentSplines() const + { + return m_S.IsValid(); + } + + /*! + * Returns the inverse vector surface spline interpolation/approximation + * device in two dimensions for the drizzle source image represented by this + * instance. These splines define an inverse image registration + * transformation with corrections for arbitrary distortions. + * + * \sa SetAlignmentInverseSplines(), SetAlignmentSplines() + */ + const vector_spline& AlignmentInverseSplines() const + { + return m_Sinv; + } + + /*! + * Sets a new inverse vector surface spline interpolation/approximation + * device. This member function is reserved for image registration tasks + * involved in drizzle integration processes. + * + * \sa AlignmentInverseSplines(), AlignmentSplines() + */ + void SetAlignmentInverseSplines( const vector_spline& Sinv ) + { + m_Sinv = Sinv; + } + + /*! + * Returns true iff this instance defines an inverse vector surface spline + * interpolation/approximation device. + * + * \sa AlignmentInverseSplines(), HasAlignmentSplines(), + * HasAlignmentMatrix() + */ + bool HasAlignmentInverseSplines() const + { + return m_Sinv.IsValid(); + } + + /*! + * Stores a copy of the local distortion model in the specified arrays. + * + * \param[out] P1 Reference to an array of points where the function will + * store a copy of the reference image coordinates of the + * local distortion model. + * + * \param[out] D2 Reference to an array of points where the function will + * store a copy of the set of pixels displacements of the + * local distortion model. + * + * \param[out] P2 Reference to an array of points where the function will + * store a copy of the reference image coordinates of the + * inverse local distortion model. + * + * \param[out] D1 Reference to an array of points where the function will + * store a copy of the set of pixels displacements of the + * inverse local distortion model. + * + * \param[out] W Reference to an array of scalars where the function + * will store a copy of the set of statistical weights + * associated with the local distortion model. This array + * can be empty if the local distortion model is + * unweighted. + * + * \param order Reference to a variable that will be assigned the + * derivability order for surface interpolation + * generation. Normally this is a surface spline + * derivative order. + * + * \param regularization Reference to a variable that will be assigned the + * recommended regularization factor for surface + * interpolation generation. Normally this is a thin plate + * spline smoothness factor. + * + * \param extrapolate Reference to a variable that will be assigned true + * if the local distortion model has to be extrapolated + * over the entire reference image; false if the model can + * only be interpolated within the containing rectangle of + * the set \a P. + * + * If this instance does not transport a valid local distortion model, the + * specified arrays \a P1, \a D2, \a P2 and \a D1 will be empty after + * calling this function. + * + * \sa SetLocalDistortionModel(), HasLocalDistortionModel() + */ + void GetLocalDistortionModel( point_list& P1, point_list& D2, + point_list& P2, point_list& D1, + weight_vector& W, + int& order, float& regularization, bool& extrapolate ) + { + P1 = m_LP1; + D2 = m_LD2; + P2 = m_LP2; + D1 = m_LD1; + W = m_LW; + order = m_localDistortionOrder; + regularization = m_localDistortionRegularization; + extrapolate = m_localDistortionExtrapolation; + } + + /*! + * Defines a new local distortion model. This function is reserved for + * image registration tasks involved in drizzle integration processes. + * + * \param P1 Reference to an array of points in reference image + * coordinates. + * + * \param D2 Reference to an array of point displacements in taget image + * coordinates. + * + * \param P2 Reference to an array of points in target image coordinates. + * + * \param D1 Reference to an array of point displacements in reference + * image coordinates. + * + * \param W Reference to an array of statistical weights associated with + * the points in the local distortion model. This array can be + * empty if the local distortion model is unweighted. If + * nonempty, this array must have the same length as \a P1. + * + * \param order Derivability order for surface interpolation generation. + * Normally this is a surface spline derivative order. The + * default value is 2, which is the usual choice for generation + * of thin plate splines. + * + * \param regularization The regularization factor for surface + * interpolation generation, which should be ≥ 0. Normally + * this is a thin plate spline smoothness factor. Set to zero to + * disable surface spline regularization. The default value is + * 0.01 for regularization at the centipixel level. + * + * \param extrapolate True if the local distortion model has to be + * extrapolated over the entire reference image; false if the + * model can only be interpolated within the containing + * rectangle of the set \a P. Extrapolation is enabled by + * default. + * + * Each point in the reference array \a P1 must have a counterpart in the + * array \a D2. Point displacements are intended to be applied to projected + * reference coordinates on the registration target image. The same applies + * to the inverse local distortion model \a P2 and \a D1, but points in + * \a P2 are target image coordinates and points in \a D1 are projected + * displacements in reference image coordinates. + * + * \sa GetLocalDistortionModel(), HasLocalDistortionModel() + */ + void SetLocalDistortionModel( const point_list& P1, const point_list& D2, + const point_list& P2, const point_list& D1, + const weight_vector& W, + int order = 2, float regularization = 0.01F, bool extrapolate = true ) + { + PCL_PRECONDITION( P1.Length() == D2.Length() ) + PCL_PRECONDITION( P2.Length() == D1.Length() ) + PCL_PRECONDITION( W.IsEmpty() || W.Length() >= P1.Length() ) + m_LP1 = P1; + m_LD2 = D2; + m_LP2 = P2; + m_LD1 = D1; + m_LW = W; + m_localDistortionOrder = Max( 2, order ); + m_localDistortionRegularization = Max( .0F, regularization ); + m_localDistortionExtrapolation = extrapolate; + } + + /*! + * Returns true iff this instance defines a local distortion model + * consisting of a list of reference points and their corresponding pixel + * displacements in image coordinates. + */ + bool HasLocalDistortionModel() const + { + return !m_LP1.IsEmpty(); + } + + /*! + * Returns a string serialization of metadata items corresponding to the + * drizzle source image represented by this instance. Metadata items are + * normally generated and serialized by a regular integration task. + * + * \sa SetMetadata() + */ + const String& Metadata() const + { + return m_metadata; + } + + /*! + * Defines a string serialization of metadata items for the drizzle source + * image represented by this instance. + * + * \sa Metadata() + */ + void SetMetadata( const String& metadata ) + { + m_metadata = metadata.Trimmed(); + } + + /*! + * Returns the vector of per-channel robust estimates of location for the + * drizzle source image represented by this instance. + * + * See Scale() for a description of the output normalization procedure. + * + * Typically, the components of the vector returned by this function are + * median values, or similar robust estimates of location, computed for each + * channel of the image identified by AlignmentTargetFilePath(). These + * estimates are normally generated by a regular integration task. + * + * \sa SetLocation(), ReferenceLocation(), Scale(), AdaptiveNormalizationLocation() + */ + const DVector& Location() const + { + return m_location; + } + + /*! + * Sets a new vector of per-channel robust estimates of location for the + * drizzle source image represented by this instance. This function is + * reserved for image integration tasks involved in drizzle integration + * processes. + * + * \sa Location(), ReferenceLocation(), SetScale(), SetAdaptiveNormalizationLocation() + */ + void SetLocation( const DVector& v ) + { + m_location = v; + } + + /*! + * Returns the vector of per-channel robust estimates of location for the + * reference integration image associated with the drizzle source image + * represented by this instance. + * + * See Scale() for a description of the output normalization procedure. + * + * Typically, the components of the vector returned by this function are + * median values, or similar robust estimates of location, computed for each + * channel of an image used as reference by a regular integration task. + * + * \sa SetLocation(), ReferenceLocation(), Scale(), + * ReferenceAdaptiveNormalizationLocation() + */ + const DVector& ReferenceLocation() const + { + return m_referenceLocation; + } + + /*! + * Sets a new vector of per-channel robust estimates of location for the + * reference integration image. This function is reserved for image + * integration tasks involved in drizzle integration processes. + * + * \sa ReferenceLocation(), Location(), SetScale(), + * SetReferenceAdaptiveNormalizationLocation() + */ + void SetReferenceLocation( const DVector& v ) + { + m_referenceLocation = v; + } + + /*! + * Returns the vector of per-channel scaling factors for the drizzle source + * image represented by this instance. + * + * For normalization of output pixel samples in a channel c of the drizzle + * image, the following equation should be implemented: + * + * vc' = (vc - Lc)*Sc + L0c + * + * where vc is the source pixel sample, Lc is the location estimate given by + * Location()[c], Sc is the scaling factor given by Scale()[c], L0c is the + * reference location estimate given by ReferenceLocation()[c], and vc' is + * the normalized pixel sample value. + * + * Typically, the components of the vector returned by this function are the + * result of dividing reference scale estimates by robust estimates of + * dispersion, such as MAD or the square root of the biweight midvariance, + * among many others, computed for each channel of the image identified by + * AlignmentTargetFilePath(). Scaling factors are normally generated by a + * regular integration task. + * + * \sa SetScale(), Location(), ReferenceLocation(), + * GetAdaptiveNormalizationScaleVectors() + */ + const DVector& Scale() const + { + if ( !m_scale.IsEmpty() ) + return m_scale; + if ( m_unitScale.IsEmpty() ) + m_unitScale = DVector( 1.0, NumberOfChannels() ); + return m_unitScale; + } + + /*! + * Sets a new vector of per-channel scaling factors for the drizzle source + * image represented by this instance. This function is reserved for image + * integration tasks involved in drizzle integration processes. + * + * \sa Scale(), SetLocation(), SetAdaptiveNormalizationScaleVectors() + */ + void SetScale( const DVector& v ) + { + m_scale = v; + } + + /*! + * Returns the vector of adaptive normalization node coordinates. + * + * Adaptive normalization is based on surface interpolation of location and + * scale estimates computed for regions of interest distributed over source + * and reference images. This function returns the list of 2-D interpolation + * node coordinates. See GetAdaptiveNormalizationScaleVectors() for a + * complete description of the adaptive output normalization procedure. + * + * \sa SetAdaptiveNormalizationCoordinates() + */ + const point_list& AdaptiveNormalizationCoordinates() const + { + return m_adaptiveCoordinates; + } + + /*! + * Sets the vector of adaptive normalization node coordinates. This function + * is reserved for image integration tasks involved in drizzle integration + * processes. + * + * \sa AdaptiveNormalizationCoordinates() + */ + void SetAdaptiveNormalizationCoordinates( const point_list& points ) + { + m_adaptiveCoordinates = points; + } + + /*! + * Returns the vectors of per-channel adaptive estimates of location for the + * drizzle source image represented by this instance. + * + * See GetAdaptiveNormalizationScaleVectors() for a complete description of + * the adaptive output normalization procedure. + * + * Typically, the components of the multivector structure returned by this + * function are median values, or similar robust estimates of location, + * computed on a regular grid for each channel of the image identified by + * AlignmentTargetFilePath(). These estimates are normally generated by a + * regular integration task. + * + * \sa SetAdaptiveNormalizationLocationVectors() + */ + const MultiVector& AdaptiveNormalizationLocationVectors() const + { + return m_adaptiveLocation; + } + + /*! + * Sets new vectors of per-channel adaptive estimates of location for the + * drizzle source image represented by this instance. This function is + * reserved for image integration tasks involved in drizzle integration + * processes. + * + * \sa AdaptiveNormalizationLocationVectors() + */ + void SetAdaptiveNormalizationLocationVectors( const MultiVector& m ) + { + m_adaptiveLocation = m; + } + + /*! + * Provides the vectors of per-channel adaptive scale factors for the + * drizzle source image represented by this instance. + * + * \param[out] sLow Reference to a multivector where a copy of the + * current set of low adaptive scale factor vectors + * will be stored. + * + * \param[out] sHigh Reference to a multivector where a copy of the + * current set of high adaptive scale factor vectors + * will be stored. + * + * For a channel index c and position vector i on a given input drizzle + * integration image, the adaptive normalization function is given by: + * + *
+    * v'(c,i) = v(c,i) * (a*U(S0(c,i)) + (1-a)*U(S1(c,i)))
+    *                  + (a*U(Z0(c,i)) + (1-a)*U(Z1(c,i)))
+    * 
+ * + * where: + * + * S0 is a matrix of low adaptive scale factors,\n + * S1 is a matrix of high adaptive scale factors,\n + * Z0 is a matrix of low adaptive zero offset coefficients,\n + * Z1 is a matrix of high adaptive zero offset coefficients,\n + * U is a scale-dependent interpolation functional,\n + * v is the source pixel value,\n + * v' is the resulting normalized pixel value,\n + * a is an indicator function given by: + * + *
+    * a = 1   if v(c,i) ≤ U(L(c,i))
+    * a = 0   if v(c,i) > U(L(c,i))
+    * 
+ * + * and L is a matrix of adaptive location estimates. + * + * Typically, the components of the multivector structures provided by this + * function are the result of dividing reference scale estimates by robust + * estimates of dispersion, such as MAD or the square root of the biweight + * midvariance, among many others, computed for each channel of the image + * identified by AlignmentTargetFilePath(). Scale factors are normally + * generated by a regular integration task. + * + * \sa SetAdaptiveNormalizationScaleVectors() + */ + void GetAdaptiveNormalizationScaleVectors( MultiVector& sLow, MultiVector& sHigh ) const + { + sLow = m_adaptiveScaleLow; + sHigh = m_adaptiveScaleHigh; + } + + /*! + * Sets new vectors of per-channel adaptive scaling factors for the drizzle + * source image represented by this instance. This function is reserved for + * image integration tasks involved in drizzle integration processes. + * + * \sa GetAdaptiveNormalizationScaleVectors() + */ + void SetAdaptiveNormalizationScaleVectors( const MultiVector& sLow, const MultiVector& sHigh ) + { + m_adaptiveScaleLow = sLow; + m_adaptiveScaleHigh = sHigh; + } + + /*! + * Provides the vectors of per-channel adaptive zero offset coefficients for + * the drizzle source image represented by this instance. + * + * \param[out] mLow Reference to a multivector where a copy of the + * current set of low adaptive zero offset coefficient + * vectors will be stored. + * + * \param[out] mHigh Reference to a multivector where a copy of the + * current set of high adaptive zero offset coefficient + * vectors will be stored. + * + * See GetAdaptiveNormalizationScaleVectors() for a complete description of + * the output adaptive normalization procedure. + * + * \sa SetAdaptiveNormalizationZeroOffsetVectors() + */ + void GetAdaptiveNormalizationZeroOffsetVectors( MultiVector& mLow, MultiVector& mHigh ) const + { + mLow = m_adaptiveZeroOffsetLow; + mHigh = m_adaptiveZeroOffsetHigh; + } + + /*! + * Sets new vectors of per-channel adaptive zero offsets for the drizzle + * source image represented by this instance. This function is reserved for + * image integration tasks involved in drizzle integration processes. + * + * \sa GetAdaptiveNormalizationZeroOffsetVectors() + */ + void SetAdaptiveNormalizationZeroOffsetVectors( const MultiVector& mLow, const MultiVector& mHigh ) + { + m_adaptiveZeroOffsetLow = mLow; + m_adaptiveZeroOffsetHigh = mHigh; + } + + /*! + * Returns true iff this instance transports adaptive normalization data, + * i.e. vectors of adaptive normalization coordinates and multivectors of + * adaptive normalization location estimates, scale factors and zero offset + * coefficients. + */ + bool HasAdaptiveNormalizationData() const + { + return !m_adaptiveCoordinates.IsEmpty() && + !m_adaptiveLocation.IsEmpty() && + !m_adaptiveScaleLow.IsEmpty() && + !m_adaptiveScaleHigh.IsEmpty() && + !m_adaptiveZeroOffsetLow.IsEmpty() && + !m_adaptiveZeroOffsetHigh.IsEmpty(); + } + + /*! + * Returns a positive value in the range [0,1] to be subtracted from the + * image represented by this instance. + */ + double Pedestal() const + { + return m_pedestal; + } + + /*! + * Defines a positive value in the range [0,1] to be subtracted from the + * image represented by this instance. This function is reserved for image + * integration tasks involved in drizzle integration processes. + */ + void SetPedestal( double p ) + { + m_pedestal = Range( p, 0.0, 1.0 ); + } + + /*! + * Returns the vector of per-channel statistical weights for the drizzle + * image represented by this instance. + * + * Typically, the components of the returned vector are efficient + * statistical weights computed for each channel of the image identified by + * AlignmentTargetFilePath(). These weights are normally generated by a + * regular integration task. + * + * \sa SetWeight(), Location(), ReferenceLocation(), Scale() + */ + const DVector& Weight() const + { + if ( !m_weight.IsEmpty() ) + return m_weight; + if ( m_unitWeight.IsEmpty() ) + m_unitWeight = DVector( 1.0, NumberOfChannels() ); + return m_unitWeight; + } + + /*! + * Sets a new vector of per-channel statistical weights for the drizzle + * image represented by this instance. This function is reserved for image + * integration tasks involved in drizzle integration processes. + * + * \sa Weight(), SetLocation(), SetReferenceLocation(), SetScale() + */ + void SetWeight( const DVector& v ) + { + m_weight = v; + } + + /*! + * Returns true iff this %DrizzleData object transports image integration + * data for normalization and image combination. This includes at least + * location and reference location estimates, and optionally (but usually + * present) scaling factors and statistical image weights. + */ + bool HasIntegrationData() const + { + return !m_location.IsEmpty(); + } + + /*! + * Returns true iff this %DrizzleData object transports per-channel + * statistical image weights. If no weight information is available, the + * Weight() member function will return a reference to an internal vector + * with all components set to one. + */ + bool HasImageWeightsData() const + { + return !m_weight.IsEmpty(); + } + + /*! + * Returns the vector of per-channel low pixel rejection counts for the + * drizzle source image represented by this instance. + * + * The components of the returned vector are the total amounts of rejected + * low pixels for each channel of the image identified by + * AlignmentTargetFilePath(). Pixel rejection counts are normally generated + * by a regular image integration task. + * + * \sa RejectionHighCount(), RejectionMap() + */ + const UI64Vector& RejectionLowCount() const + { + return m_rejectionLowCount; + } + + /*! + * Returns the vector of per-channel high pixel rejection counts for the + * drizzle source image represented by this instance. + * + * The components of the returned vector are the total amounts of rejected + * high pixels for each channel of the image identified by + * AlignmentTargetFilePath(). Pixel rejection counts are normally generated + * by a regular image integration task. + * + * \sa RejectionLowCount(), RejectionMap() + */ + const UI64Vector& RejectionHighCount() const + { + return m_rejectionHighCount; + } + + /*! + * Returns a reference to a pixel rejection map generated for the drizzle + * image represented by this instance. + * + * This member function returns a reference to an 8-bit unsigned integer + * image known as drizzle rejection map. Each channel of the + * rejection map corresponds to the same channel of the image represented by + * this object. For a channel index c, a pixel sample of a rejection map can + * have the following values: + * + * \li 0 (no bit set): The corresponding pixel has not been rejected for + * image channel c. + * + * \li Bit 0 set: High statistical rejection: The pixel has been rejected + * above the estimated central value of its pixel integration stack using a + * statistical rejection algorithm (such as sigma clipping). + * + * \li Bit 1 set: Low statistical rejection: The pixel has been rejected + * below the estimated central value of its pixel integration stack using a + * statistical rejection algorithm (such as sigma clipping). + * + * \li Bit 2 set: High range rejection: The pixel has been rejected because + * its value is greater than or equal to a prescribed upper limit. + * + * \li Bit 3 set: Low range rejection: The pixel has been rejected because + * its value is smaller than or equal to a prescribed lower limit. + * + * \li Bit 4 set: High large-scale rejection: The pixel belongs to a bright + * large-scale image structure that has been rejected using multiscale + * analysis techniques. + * + * \li Bit 5 set: Low large-scale rejection: The pixel belongs to a dark + * large-scale image structure that has been rejected using multiscale + * analysis techniques. + * + * Bits 6 and 7 are reserved for future extensions and should be zero in the + * current implementation. + * + * Rejection maps are automatically generated from pixel rejection data + * stored in .xdrz files. Pixel rejection data are normally generated by a + * regular image integration task. + * + * If no pixel rejection information is available in this instance, this + * function returns a reference to an empty image. + * + * \sa SetRejectionMap(), HasRejectionData(), IsRejected() + */ + const UInt8Image& RejectionMap() const + { + return m_rejectionMap; + } + + /*! + * Returns true iff the pixel at the specified pixel coordinates has been + * rejected for the drizzle source image represented by this instance. + * + * \sa RejectionMap(), HasRejectionData() + */ + bool IsRejected( const Point& position, int channel = 0 ) const + { + return m_rejectionMap.Includes( position ) + && m_rejectionMap.IsValidChannelIndex( channel ) + && (m_rejectionMap( position, channel ) & 0x3F) != 0; + } + + /*! + * Defines per-channel pixel rejection data for the drizzle source image + * represented by this instance. The specified \a map image is a drizzle + * rejection map as described in RejectionMap(). + * + * \sa RejectionMap(), HasRejectionData() + */ + void SetRejectionMap( const UInt8Image& map ) + { + m_rejectionMap = map; + } + + /*! + * Returns true iff pixel rejection information is available for the drizzle + * image represented by this instance. + */ + bool HasRejectionData() const + { + return !m_rejectionMap.IsEmpty(); + } + + /*! + * Returns the UTC time this drizzle 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 drizzle integration data transported by this instance, + * yielding an empty %DrizzleData object. + */ + void Clear(); + + /*! + * Clears the image integration data transported by this instance. This + * includes statistical location and scale estimates for image + * normalization, image weights, pixel rejection data, and adaptive + * normalization data. + */ + void ClearIntegrationData(); + + /*! + * Loads and parses a drizzle data file. + * + * \param filePath Path to an existing file that will be parsed. The file + * contents can be in %XML drizzle data format (normally, + * a file with the .xdrz suffix), or in old plain text + * format (typically with the .drz suffix). This function + * will detect the format in use from the first bytes read + * from the file, and will decode it correspondingly. + * + * \param ignoreIntegrationData If true, all drizzle data relative to the + * image integration task will be ignored. This includes + * statistical location and scale estimates for image + * normalization, image weights, and pixel rejection data. + * + * 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 ignoreIntegrationData = false ); + + /*! + * Parses a well-formed %XML document. + * + * \param xml Reference to the source %XML document. This member + * function expects an %XML document in valid %XML + * drizzle data format (.xdrz). + * + * \param ignoreIntegrationData If true, all drizzle data relative to the + * image integration task will be ignored. This includes + * statistical location and scale estimates for image + * normalization, image weights, and pixel rejection data. + * + * 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 ignoreIntegrationData = false ); + + /*! + * Parses an %XML element. + * + * \param element Reference to the source %XML element. This member + * function expects an %XML document tree in valid %XML + * drizzle data format (.xdrz) rooted at this element. + * + * \param ignoreIntegrationData If true, all drizzle data relative to the + * image integration task will be ignored. This includes + * statistical location and scale estimates for image + * normalization, image weights, and pixel rejection data. + * + * 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 ignoreIntegrationData = false ); + + /*! + * Returns true if drizzle data compression is enabled for serializations + * performed with this object. + * + * Drizzle data compression is enabled by default for newly constructed + * %DrizzleData objects. Currently the LZ4 compression codec is applied for + * serialization of pixel rejection data. + * + * \sa EnableCompression(), DisableCompression() + */ + bool IsCompressionEnabled() const + { + return m_compressionEnabled; + } + + /*! + * Enables compression of serialized drizzle data. + * + * \sa IsCompressionEnabled(), DisableCompression() + */ + void EnableCompression( bool enable = true ) + { + m_compressionEnabled = enable; + } + + /*! + * Disables compression of serialized drizzle data. + * + * \sa IsCompressionEnabled(), EnableCompression() + */ + void DisableCompression( bool disable = true ) + { + EnableCompression( !disable ); + } + + /*! + * Serializes the drizzle integration data transported by this object as a + * new %XML document in .xdrz 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 drizzle integration data transported by this object as a + * new %XML document file in .xdrz format. 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_sourceFilePath; + String m_cfaSourceFilePath; + String m_cfaSourcePattern; + int m_cfaSourceChannel = -1; + String m_alignTargetFilePath; + int m_referenceWidth = -1; + int m_referenceHeight = -1; + DPoint m_alignmentOrigin = 0.5; + Matrix m_H; + vector_spline m_S; + vector_spline m_Sinv; + point_list m_LP1; + point_list m_LD2; + point_list m_LP2; + point_list m_LD1; + weight_vector m_LW; + int m_localDistortionOrder = 2; + float m_localDistortionRegularization = 0.01F; + bool m_localDistortionExtrapolation = true; + String m_metadata; + double m_pedestal = 0.0; + Vector m_location; + Vector m_referenceLocation; + Vector m_scale; + mutable Vector m_unitScale; + Vector m_weight; + mutable Vector m_unitWeight; + point_list m_adaptiveCoordinates; + MultiVector m_adaptiveLocation; + MultiVector m_adaptiveScaleLow; + MultiVector m_adaptiveScaleHigh; + MultiVector m_adaptiveZeroOffsetLow; + MultiVector m_adaptiveZeroOffsetHigh; + UI64Vector m_rejectionLowCount; + UI64Vector m_rejectionHighCount; + UInt8Image m_rejectionMap; + TimePoint m_creationTime; + bool m_compressionEnabled = true; + + // Working data for spline deserialization. + spline m_Sx; + spline m_Sy; + spline m_Sxinv; + spline m_Syinv; + + // Working data for old text format compatibility. + rejection_data m_rejectLowData; + rejection_data m_rejectHighData; + + void ParseRejectionMap( const XMLElement& ); + void SerializeRejectionMap( XMLElement* ) const; + + static void ParseSpline( spline&, const XMLElement& ); + static void SerializeSpline( XMLElement*, const spline& ); + + static point_list ParsePoints( const XMLElement& ); + void SerializePoints( XMLElement*, const point_list& ) const; + + static weight_vector ParseDistortionWeights( const XMLElement& ); + void SerializeDistortionWeights( XMLElement*, const weight_vector& ) const; + + static ByteArray ParseMaybeCompressedData( const XMLElement& ); + void SerializeMaybeCompressedData( XMLElement* root, + const void* data, size_type size, size_type itemSize = 1 ) const; + + /*! + * \internal + * \class DrizzleData::PlainTextDecoder + * \brief Read-only compatibility with old plain text .drz files + */ + class PlainTextDecoder + { + public: + + PlainTextDecoder( DrizzleData* data, bool ignoreIntegrationData ) + : m_data( data ) + , m_ignoreIntegrationData( ignoreIntegrationData ) + { + } + + virtual ~PlainTextDecoder() + { + } + + void Decode( IsoString&, size_type start = 0, size_type end = 0 ); + + protected: + + PlainTextDecoder() = default; + + private: + + DrizzleData* m_data = nullptr; + bool m_ignoreIntegrationData = false; + + virtual void ProcessBlock( IsoString&, const IsoString&, size_type, size_type ); + + static rejection_coordinates ParseRejectionCoordinates( IsoString&, size_type, size_type ); + static rejection_data ParseRejectionData( IsoString&, size_type, size_type ); + static spline ParseSurfaceSpline( IsoString&, size_type, size_type ); + }; + + class PlainTextSplineDecoder : public PlainTextDecoder + { + public: + + PlainTextSplineDecoder( spline& S ) + : m_S( S ) + { + } + + virtual ~PlainTextSplineDecoder() + { + } + + private: + + spline& m_S; + + void ProcessBlock( IsoString&, const IsoString&, size_type, size_type ) override; + }; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_DrizzleData_h + +// ---------------------------------------------------------------------------- +// EOF pcl/DrizzleData.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Edit.h b/3rdparty/include/pcl/Edit.h new file mode 100644 index 0000000..5b0a589 --- /dev/null +++ b/3rdparty/include/pcl/Edit.h @@ -0,0 +1,391 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Edit.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_Edit_h +#define __PCL_Edit_h + +/// \file pcl/Edit.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Edit + * \brief Client-side interface to a PixInsight %Edit control + * + * %Edit controls are single-line plain text edit controls. + */ +class PCL_CLASS Edit : public Frame +{ +public: + + /*! + * Constructs an %Edit object with the specified \a text, as a child control + * of \a parent. + */ + Edit( const String& text = String(), Control& parent = Control::Null() ); + + /*! + * Destroys an %Edit control. + */ + virtual ~Edit() + { + } + + /*! + * Returns the current edit text. + */ + String Text() const; + + /*! + * Sets the current button text. + */ + void SetText( const String& ); + + /*! + * Removes all the text in this %edit control. + */ + void Clear() + { + SetText( String() ); + } + + /*! + * Returns true iff this %Edit control is in read-only mode. + */ + bool IsReadOnly() const; + + /*! + * Enables or disables the read-only mode for this %Edit control. + */ + void SetReadOnly( bool = true ); + + /*! + * Disables or enables the read-only mode for this %Edit control. + * + * This is a convenience member function, equivalent to: + * SetReadOnly( !rw ) + */ + void SetReadWrite( bool rw = true ) + { + SetReadOnly( !rw ); + } + + /*! + * Returns true iff the text in this %Edit control has been modified. + */ + bool IsModified() const; + + /*! + * Sets or clears the modified status for this %Edit control. + */ + void SetModified( bool = true ); + + /*! + * Clears or sets the modified status for this %Edit control. + * + * This is a convenience member function, equivalent to: + * SetModified( !clear ) + */ + void ClearModified( bool clear = true ) + { + SetModified( !clear ); + } + + /*! + * Returns true iff this %Edit control is in password display mode. + * + * In password mode, the text in an edit control is always displayed as a + * sequence of asterisks. This does not affect the actual text; the password + * mode only changes the way characters are displayed. + * + * \sa EnablePasswordMode(), DisablePasswordMode() + */ + bool IsPasswordMode() const; + + /*! + * Enables the password display mode for this %Edit control. + * + * \sa IsPasswordMode(), DisablePasswordMode() + */ + void EnablePasswordMode( bool = true ); + + /*! + * Disables the password display mode for this %Edit control. + * + * This is a convenience member function, equivalent to: + * EnablePasswordMode( !disable ) + * + * \sa IsPasswordMode(), EnablePasswordMode() + */ + void DisablePasswordMode( bool disable = true ) + { + EnablePasswordMode( !disable ); + } + + /*! + * Returns the maximum allowed length for the text in this %Edit control. + */ + int MaxLength() const; + + /*! + * Sets the maximum allowed length for the text in this %Edit control. + * + * The default length limit is \c int_max, which in practice represents no + * length limit. + */ + void SetMaxLength( int ); + + /*! + * Enables unlimited length for the text in this %Edit control. + * + * This is a convenience member function, equivalent to: + * SetMaxLength( int_max ) + */ + void SetUnlimitedLength() + { + SetMaxLength( int_max ); + } + + /*! + * Selects all the text in this %edit control. + */ + void SelectAll( bool = true ); + + /*! + * Clears the existing selection, if any, in this %edit control. + * + * \note This member function does not delete the selected text; it only + * removes the selection. + */ + void Unselect( bool unsel = true ) + { + SelectAll( !unsel ); + } + + /*! + * Gets the limits of the current selection in this %Edit control. + * + * \param[out] selStart The index of the first selected character. + * \param[out] selEnd The index of the last selected character plus one. + * + * When \a selStart is equal to \a selEnd, there is no selection in this + * edit control. + */ + void GetSelection( int& selStart, int& selEnd ) const; + + /*! + * Sets the limits of the current selection in this %Edit control. + * + * \param selStart The index of the first selected character. + * \param selEnd The index of the last selected character plus one. + * + * When \a selStart is equal to \a selEnd, there is no selection in this + * edit control. + */ + void SetSelection( int selStart, int selEnd ); + + /*! + * Returns true iff there are one or more selected characters in this %Edit + * control. + */ + bool HasSelection() const + { + int s0, s1; + GetSelection( s0, s1 ); + return s0 != s1; + } + + /*! + * Returns the currently selected text, or an empty string if there is no + * selection in this %Edit control. + */ + String SelectedText() const; + + /*! + * Returns the current caret position in this %Edit control. + */ + int CaretPosition() const; + + /*! + * Sets the current caret position in this %Edit control. + */ + void SetCaretPosition( int ); + + /*! + * Moves the caret to the beginning of the text line in this %Edit control. + */ + void Home() + { + SetCaretPosition( 0 ); + } + + /*! + * Moves the caret to the end of the text line in this %Edit control. + */ + void End() + { + SetCaretPosition( int_max ); + } + + /*! + * Returns true iff the text in this %Edit control is right-aligned. + */ + bool IsRightAligned() const; + + /*! + * Returns true iff the text in this %Edit control is left-aligned. + */ + bool IsLeftAligned() const + { + return !IsRightAligned(); + } + + /*! + * Enables or disables right-alignment for the text in this %edit control. + */ + void SetRightAlignment( bool right = true ); + + /*! + * Disables or enables right-alignment for the text in this %edit control. + * + * This is a convenience member function, equivalent to: + * SetRightAlignment( !left ) + */ + void SetLeftAlignment( bool left = true ) + { + SetRightAlignment( !left ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnEditCompleted( Edit& sender ); + // void OnReturnPressed( Edit& sender ); + // void OnTextUpdated( Edit& sender, const String& text ); + // void OnCaretPositionUpdated( Edit& sender, int oldPos, int newPos ); + // void OnSelectionUpdated( Edit& sender, int newStart, int newEnd ); + + /*! # + */ + typedef void (Control::*edit_event_handler)( Edit& sender ); + + /*! # + */ + typedef void (Control::*text_event_handler)( Edit& sender, const String& ); + + /*! # + */ + typedef void (Control::*caret_event_handler)( Edit& sender, int oldPos, int newPos ); + + /*! # + */ + typedef void (Control::*selection_event_handler)( Edit& sender, int newStart, int newEnd ); + + /*! # + */ + void OnEditCompleted( edit_event_handler, Control& ); + + /*! # + */ + void OnReturnPressed( edit_event_handler, Control& ); + + /*! # + */ + void OnTextUpdated( text_event_handler, Control& ); + + /*! # + */ + void OnCaretPositionUpdated( caret_event_handler, Control& ); + + /*! # + */ + void OnSelectionUpdated( selection_event_handler, Control& ); + +private: + + struct EventHandlers + { + edit_event_handler onEditCompleted = nullptr; + edit_event_handler onReturnPressed = nullptr; + text_event_handler onTextUpdated = nullptr; + caret_event_handler onCaretPositionUpdated = nullptr; + selection_event_handler onSelectionUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class EditEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Edit_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Edit.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ElapsedTime.h b/3rdparty/include/pcl/ElapsedTime.h new file mode 100644 index 0000000..89f813b --- /dev/null +++ b/3rdparty/include/pcl/ElapsedTime.h @@ -0,0 +1,401 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ElapsedTime.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_ElapsedTime_h +#define __PCL_ElapsedTime_h + +/// \file pcl/ElapsedTime.h + +#include +#include + +#include + +#if !defined( __PCL_LINUX ) && !defined( __PCL_FREEBSD ) +# include +# include +# define PCL_CLOCK_ID 0 +#endif + +#ifdef __PCL_LINUX +# include +# ifdef CLOCK_MONOTONIC_RAW // since kernel 2.6.28 +# define PCL_CLOCK_ID CLOCK_MONOTONIC_RAW +# else +# define PCL_CLOCK_ID CLOCK_MONOTONIC +# endif +#endif + +#ifdef __PCL_FREEBSD +# include +# ifdef CLOCK_MONOTONIC_PRECISE // since FreeBSD 10.1 +# define PCL_CLOCK_ID CLOCK_MONOTONIC_PRECISE +# else +# define PCL_CLOCK_ID CLOCK_MONOTONIC +# endif +#endif + +#ifdef __PCL_MACOSX +# include +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ElapsedTime + * \brief High-resolution time stamp. + * + * %ElapsedTime is a platform-independent, monotonically nondecreasing + * high-resolution time stamp based on hardware time resources that are + * independent on any external time reference. The underlying implementation + * uses monotonic clock services on Linux and FreeBSD (via clock_gettime() + * system calls), performance counters on Windows, and Mach absolute time + * system services on macOS. + * + * Example of use: + * + * \code + * ElapsedTime T; + * for ( int i = 0; i < 100000; ++i ) + * foo(); + * double t1 = T(); + * T.Reset(); + * for ( int i = 0; i < 100000; ++i ) + * bar(); + * double t2 = T(); + * Console out; + * out.WriteLn( "Execution times (100K function calls): ); + * out.WriteLn( "foo(): " + ElapsedTime::ToString( t1 ) ); + * out.WriteLn( "bar(): " + ElapsedTime::ToString( t2 ) ); + * \endcode + * + * Timing resolution should be better than one microsecond on all platforms, + * but the actual resolution achieved is hardware and system dependent. + * + * This class is thread-safe: it can be instantiated and its member functions + * can be safely invoked from multiple running threads. + */ +class PCL_CLASS ElapsedTime +{ +public: + + /*! + * Constructs a new %ElapsedTime object and initializes it with the current + * system time, which will be the starting point of subsequent time interval + * evaluations. + */ + ElapsedTime() + { + Reset(); + } + + /*! + * Copy constructor. + */ + ElapsedTime( const ElapsedTime& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ElapsedTime& operator =( const ElapsedTime& ) = default; + + /*! + * Returns the time interval elapsed since the last object initialization, + * expressed in seconds. An %ElapsedTime object is initialized either when + * it is constructed, or through a subsequent call to the Reset() member + * function. + */ + double operator ()() const + { + return TimeStamp() - m_start; + } + + /*! + * Initializes this %ElapsedTime object with a new time stamp, which will be + * the starting point of subsequent time interval evaluations. + */ + void Reset() + { + m_start = TimeStamp(); + } + + /*! + * Returns an 8-bit string representation of the time interval elapsed since + * the last object initialization. See operator()() and + * ToIsoString( double ) for detailed information. + */ + IsoString ToIsoString() const + { + return ToIsoString( operator()() ); + } + + /*! + * Returns a Unicode string representation of the time interval elapsed + * since the last object initialization. See operator()() and + * ToIsoString( double ) for detailed information. + */ + String ToString() const + { + return ToString( operator()() ); + } + + /*! + * IsoString conversion operator. Equivalent to ToIsoString(). + */ + operator IsoString() const + { + return ToIsoString(); + } + + /*! + * String conversion operator. Equivalent to ToString(). + */ + operator String() const + { + return ToString(); + } + + /*! + * Returns a 64-bit, monotonically nondecreasing time stamp. + * + * The returned value is the time elapsed in seconds since an arbitrary, + * platform-dependent starting time that will remain invariant during the + * current execution of the calling module. + * + * With the current implementation, accuracy of timestamps should be better + * than one microsecond on all supported platforms. + */ + static double TimeStamp() + { +#if defined( __PCL_LINUX ) || defined( __PCL_FREEBSD ) + + /* + * Linux/FreeBSD implementation based on clock_gettime(). + */ + timespec ts; + (void)clock_gettime( PCL_CLOCK_ID, &ts ); + return ts.tv_sec + ts.tv_nsec*1.0e-09; + +#endif // __PCL_LINUX || __PCL_FREEBSD + +#ifdef __PCL_MACOSX + + /* + * macOS implementation based on Mach absolute time system services. + * + * https://developer.apple.com/library/mac/qa/qa1398/_index.html + * http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x + */ + static Mutex mutex; + static AtomicInt initialized; + static double absoluteToSeconds; + static uint64 offset; + + if ( !initialized ) + { + volatile AutoLock lock( mutex ); + if ( initialized.Load() == 0 ) + { + mach_timebase_info_data_t timeBase = { 0 }; + mach_timebase_info( &timeBase ); + absoluteToSeconds = 1.0e-09*(double( timeBase.numer )/timeBase.denom); + offset = mach_absolute_time(); + initialized.Store( 1 ); + } + } + + uint64 t = mach_absolute_time(); + return (t - offset)*absoluteToSeconds; + +#endif // __PCL_MACOSX + +#ifdef __PCL_WINDOWS + + /* + * Windows implementation based on Win32 performance counters. + * + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905%28v=vs.85%29.aspx + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904%28v=vs.85%29.aspx + * http://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows + * http://stackoverflow.com/questions/1676036/what-should-i-use-to-replace-gettimeofday-on-windows + */ + static Mutex mutex; + static AtomicInt initialized; + static double countsToSeconds; + static uint64 offset; + + if ( !initialized ) + { + volatile AutoLock lock( mutex ); + if ( initialized.Load() == 0 ) + { + uint64 performanceFrequency; + QueryPerformanceFrequency( (LARGE_INTEGER*)&performanceFrequency ); + countsToSeconds = 1.0/performanceFrequency; + QueryPerformanceCounter( (LARGE_INTEGER*)&offset ); + initialized.Store( 1 ); + } + } + + uint64 t; + QueryPerformanceCounter( (LARGE_INTEGER*)&t ); + return (t - offset)*countsToSeconds; + +#endif // __PCL_WINDOWS + } + + /*! + * Returns an 8-bit string representation of the specified time interval + * in seconds. + * + * The returned string has one of the following formats: + * + * + * + * + * + * + * + * + *
(1) u.uuu us u.uuu is the time t in microseconds if t < 0.001 s
(2) m.mmm ms m.mmm is the time t in milliseconds if t < 1.0 s
(3) s.sss s s.sss is the time t in seconds if t < 60.0 s
(4) mm:ss.ss Zero-padded minutes and seconds if t < 3600 s
(5) hh:mm:ss.s Same as (4) with zero-padded hours if t < 86400 s
(6) d:hh:mm:ss Same as (5) with elapsed days if t >= 86400
+ * + * If \a width > 0 and t ≤ 60, the integer part of the represented + * microseconds, milliseconds or seconds will be right-padded in a field of + * \a width space characters. + * + * The output format is chosen automatically to generate the most + * significant representation. If the specified interval is negative (toward + * the past), a minus sign is prepended to the returned string. + */ + static IsoString ToIsoString( double seconds, int width = 0 ) + { + return ToString( seconds, width, (IsoString*)0 ); + } + + /*! + * Returns a Unicode string representation of the specified time interval + * \a s in seconds. See ToIsoString( double ) for information on the + * representation format. + */ + static String ToString( double s, int width = 0 ) + { + return ToString( s, width, (String*)0 ); + } + + /*! + * Returns the time interval in seconds elapsed between the starting points + * of two %ElapsedTime objects \a t1 and \a t2. The result is positive if + * \a t2 precedes \a t1, negative if \a t1 precedes \a t2, zero if and only + * if either \a t1 and \a t2 are references to the same instance, or if one + * of the objects has been constructed as a copy of the other. + */ + friend double operator -( const ElapsedTime& t1, const ElapsedTime& t2 ) + { + return t1.m_start - t2.m_start; + } + +private: + + double m_start; // timestamp in seconds + + template + static S ToString( double s, int w, S* ) + { + if ( s < 0.001 ) + return S().Format( "%*.3f us", Max( 5, w+4 ), s*1000000 ); + + if ( s < 1 ) + return S().Format( "%*.3f ms", Max( 5, w+4 ), s*1000 ); + + if ( s < 60 ) + return S().Format( "%*.3f s", Max( 5, w+4 ), s ); + + int sign = (s < 0) ? -1 : +1; + s = Abs( s ); + + if ( s < 3600 ) + { + int m = TruncInt( s/60 ); + s -= m*60; + return S().Format( "%02d:%05.2f", m*sign, s ); + } + + if ( s < 86400 ) + { + int h = TruncInt( s/3600 ); + s -= h*3600; + int m = TruncInt( s/60 ); + s -= m*60; + return S().Format( "%02d:%02d:%04.1f", h*sign, m, s ); + } + + int d = TruncInt( s/86400 ); + s -= d*86400; + int h = TruncInt( s/3600 ); + s -= h*3600; + int m = TruncInt( s/60 ); + s -= m*60; + return S().Format( "%d:%02d:%02d:%02d", d*sign, h, m, RoundInt( s ) ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ElapsedTime_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ElapsedTime.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/EndianConversions.h b/3rdparty/include/pcl/EndianConversions.h new file mode 100644 index 0000000..bb9fb9e --- /dev/null +++ b/3rdparty/include/pcl/EndianConversions.h @@ -0,0 +1,168 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/EndianConversions.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_EndianConversions_h +#define __PCL_EndianConversions_h + +/// \file pcl/EndianConversions.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup endianness_conversion_and_detection Endianness Conversion and Detection Functions + */ + +/*! + * Converts a 16-bit unsigned integer from big endian to little endian byte + * storage order. + * + * \ingroup endianness_conversion_and_detection + */ +inline uint16 BigToLittleEndian( uint16 x ) +{ + return (x << 8) | (x >> 8); +} + +/*! + * Converts a 32-bit unsigned integer from big endian to little endian byte + * storage order. + * + * \ingroup endianness_conversion_and_detection + */ +inline uint32 BigToLittleEndian( uint32 x ) +{ + return (RotL( x, 8 ) & 0x00ff00ffu) | (RotR( x, 8 ) & 0xff00ff00u); + +} + +/*! + * Converts a 64-bit unsigned integer from big endian to little endian byte + * storage order. + * + * \ingroup endianness_conversion_and_detection + */ +inline uint64 BigToLittleEndian( uint64 x ) +{ + return (uint64( BigToLittleEndian( uint32( x ) ) ) << 32) | uint64( BigToLittleEndian( uint32( x >> 32 ) ) ); +} + +/*! + * A convenience synonym function for little-to-big endian conversions, which + * we define for the sake of code legibility. It is obviously equivalent to + * BigToLittleEndian( x ). + * + * \ingroup endianness_conversion_and_detection + */ +template inline T LittleToBigEndian( T x ) +{ + return BigToLittleEndian( x ); +} + +// ---------------------------------------------------------------------------- + +union __pcl_endian_check__ { uint32 w; uint8 b[ sizeof( uint32 ) ]; }; + +constexpr __pcl_endian_check__ __pcl_endian_check_sample__ = { 0xdeadbeef }; + +#ifdef __clang__ + +inline bool IsLittleEndianMachine() +{ + return __pcl_endian_check_sample__.b[0] == 0xef; +} + +inline bool IsBigEndianMachine() +{ + return __pcl_endian_check_sample__.b[0] == 0xde; +} + +#else + +// Clang fails here with "read of member 'b' of union with active member 'w' is +// not allowed in a constant expression". + +/*! + * Returns true iff the caller is running on a little-endian architecture. + * + * \ingroup endianness_conversion_and_detection + */ +constexpr bool IsLittleEndianMachine() +{ + return __pcl_endian_check_sample__.b[0] == 0xef; +} + +/*! + * Returns true iff the caller is running on a big-endian architecture. + * + * \ingroup endianness_conversion_and_detection + */ +constexpr bool IsBigEndianMachine() +{ + return __pcl_endian_check_sample__.b[0] == 0xde; +} + +#endif // __clang__ + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_EndianConversions_h + +// ---------------------------------------------------------------------------- +// EOF pcl/EndianConversions.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/EphemerisFile.h b/3rdparty/include/pcl/EphemerisFile.h new file mode 100644 index 0000000..8c33149 --- /dev/null +++ b/3rdparty/include/pcl/EphemerisFile.h @@ -0,0 +1,2304 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/EphemerisFile.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_EphemerisFile_h +#define __PCL_EphemerisFile_h + +/// \file pcl/EphemerisFile.h + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ + class JSEphemerisFileObject; + class JSEphemerisHandleObject; +} +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS XMLElement; + +// ---------------------------------------------------------------------------- + +/*! + * \struct EphemerisMetadata + * \brief %Metadata items available in ephemeris files (XEPH format). + * + * This structure holds metadata items that can be stored in ephemeris files + * (current XEPH format version 1.0). For an existing ephemeris file, available + * metadata are extracted directly from %XML file headers. Currently all items + * are optional, so all data members of this structure can be empty strings. + * + * For generation of new XEPH files, the creationTime and creatorOS members of + * this structure will be ignored, since the corresponding metadata items will + * always be defined automatically by the EphemerisFile::Serialize() routine. + * The specified creatorApplication member, if empty, will be replaced in the + * same routine with a default value identifying the current PCL version. + * + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS EphemerisMetadata +{ + TimePoint creationTime; //!< The date this file was created. + String creatorOS; //!< The operating system on which this file was created. + String creatorApplication; //!< The software application or program that created this file. + String title; //!< A title that represents or identifies this XEPH file. + String briefDescription; //!< A brief (single-line) description of this XEPH file. + String description; //!< A full description of the data stored in this XEPH file. + String organizationName; //!< The name of the organization responsible for this file. + String authors; //!< The names of one or more persons or groups that have created the data in this file. + String copyright; //!< Copyright information applicable to the data stored in this XEPH file. +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct EphemerisConstant + * \brief A numerical constant defined in an ephemeris file (XEPH format). + * + * This structure implements a simple name/value pair used to store and + * manipulate numerical constants defined in ephemeris files (current XEPH + * format version 1.0). These constants are primarily intended to support JPL + * DE/LE fundamental ephemerides, where we need access to the set of numerical + * integration constants defined by JPL. + * + * Comparisons between %EphemerisConstant instances are performed on the their + * names and are case-insensitive. + * + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS EphemerisConstant +{ + IsoString name; //!< The constant name (case-insensitive). + double value; //!< The constant value. + + /*! + * Memberwise constructor. + */ + EphemerisConstant( const IsoString& n = IsoString(), double v = 0 ) + : name( n ) + , value( v ) + { + } + + /*! + * Copy constructor. + */ + EphemerisConstant( const EphemerisConstant& ) = default; + + /*! + * Move constructor. + */ + EphemerisConstant( EphemerisConstant&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + EphemerisConstant& operator =( const EphemerisConstant& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + EphemerisConstant& operator =( EphemerisConstant&& ) = default; + + /*! + * Equality operator. Returns the result of the case-insensitive equality + * operator applied to the \a name members. + */ + bool operator ==( const EphemerisConstant& x ) const + { + return name.CompareIC( x.name ) == 0; + } + + /*! + * Less-than relational operator. Returns the result of the case-insensitive + * less-than operator applied to the \a name members of this object and the + * specified instance \a x. + */ + bool operator <( const EphemerisConstant& x ) const + { + return name.CompareIC( x.name ) < 0; + } +}; + +/*! + * \class pcl::EphemerisConstantList + * \brief Dynamic list of ephemeris numerical constants. + * + * %EphemerisConstantList is used as the internal implementation of numerical + * constants associated with an %EphemerisFile instance, that is, with an + * ephemeris file in the XEPH format. %EphemerisConstantList is a template + * instantiation of Array\<\> for the EphemerisConstant class. + * + * \ingroup solar_system_ephemerides + */ +typedef Array EphemerisConstantList; + +// ---------------------------------------------------------------------------- + +/*! + * \struct SerializableEphemerisData + * \brief Chebyshev polynomial expansion coefficients for ephemeris serialization. + * + * This structure holds (possibly truncated) Chebyshev polynomial expansions + * suitable for generation of an ephemeris file in XEPH format with the + * EphemerisFile::Serialize() static member function. + * + * In an ephemeris file, the complete time span covered by the file is usually + * subdivided into many small chunks or subspans, each of them with a + * relatively short polynomial expansion. The duration of each subspan is + * defined in a way such that the movement of the object for which positions + * are being calculated within the time subspan is sufficiently smooth to be + * fitted by truncated Chebyshev polynomials with relatively few coefficients + * (typically in the range of 15 to 30 coefficients) to achieve a prescribed + * accuracy. + * + * \sa EphemerisFile::Serialize() + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS SerializableEphemerisData +{ + /*! + * Starting point of the time span covered by this Chebyshev polynomial + * expansion. + */ + TimePoint startTime; + + /*! + * Chebyshev polynomial expansion. If the coefficient series has been + * truncated, only the truncated series will be stored in the XEPH file, + * that is, truncated coefficients will be ignored. + * + * \sa ChebyshevFit::Truncate() + */ + ChebyshevFit expansion; + + /*! + * Memberwise constructor. + */ + SerializableEphemerisData( TimePoint t, const ChebyshevFit& T ) + : startTime( t ) + , expansion( T ) + { + } + + /*! + * Copy constructor. + */ + SerializableEphemerisData( const SerializableEphemerisData& ) = default; + + /*! + * Move constructor. + */ + SerializableEphemerisData( SerializableEphemerisData&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SerializableEphemerisData& operator =( const SerializableEphemerisData& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SerializableEphemerisData& operator =( SerializableEphemerisData&& ) = default; +}; + +/*! + * \class pcl::SerializableEphemerisDataList + * \brief Dynamic list of Chebyshev polynomial expansions for ephemeris serialization. + * + * %SerializableEphemerisDataList is a dynamic list of + * SerializableEphemerisData instances to cover the entire time span of an + * ephemeris file being serialized. Each instance in the list must cover a time + * subspan in ascending time order without gaps. The value of the \a startTime + * member of the first instance in the list must be equal to the lower bound of + * the time span covered by the file, and the \a startTime member of each + * subsequent instance in the list is equal to the upper bound of the subspan + * covered by the previous instance. These conditions are enforced by the + * EphemerisFile::Serialize() static member function, which is the standard + * resource for generation of ephemeris files in XEPH format. + * + * \ingroup solar_system_ephemerides + */ +typedef Array SerializableEphemerisDataList; + +// ---------------------------------------------------------------------------- + +/*! + * \struct SerializableEphemerisObjectData + * \brief A set of Chebyshev polynomial expansions and associated ancillary + * data for ephemeris serialization. + * + * This structure associates a unique pair of object and origin identifiers, an + * optional object name, an optional descriptive text, and one or two ordered + * sequences of Chebyshev polynomial expansions for calculation of ephemerides + * within a prescribed time span. These data are suitable for generation of an + * ephemeris file in XEPH format with the EphemerisFile::Serialize() static + * member function. + * + * The first sequence of Chebyshev polynomial expansions is mandatory for + * calculation of ephemeris function values (typically, the components of a + * position vector as a function of time). An additional sequence of expansions + * for the first derivative (typically, the components of a velocity vector) is + * optional. Derivative expansions should be used when the velocity of an + * object is known very accurately upon ephemeris generation, and this high + * accuracy must be preserved. + * + * All ephemeris data stored in XEPH files must be referred to the + * International Celestial Reference System (ICRS/J2000.0). + * + * \sa EphemerisFile::Serialize() + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS SerializableEphemerisObjectData +{ + /*! + * Unique identifier of the object or item for which ephemeris data have + * been generated. This should be a short string to uniquely identify the + * object in the context of the ephemeris file being serialized. For + * example, standard XEPH files serializing JPL DE/LE ephemerides use a + * two/three letter convention for object identifiers: 'Me', 'Ve', 'EMB', + * 'Ea', 'Ma', etc, respectively for Mercury, Venus, Earth-Moon barycenter, + * Earth, Mars, etc. Object identifiers are considered as case-sensitive in + * XEPH files. + */ + IsoString objectId; + + /*! + * Identifier of the origin of coordinates (case-sensitive). This can be the + * unique identifier of a solar system object, or the identifier of an + * arbitrary object or location, which will be treated as + * implementation-specific, that is, specific to the data being serialized + * and to the procedures employed to generate them. + * + * For example, if the ephemeris data being serialized are geocentric, this + * member should be "Ea", which is the unique identifier of the Earth's + * center in standard fundamental ephemerides files. Similarly, if the + * ephemerides are heliocentric, this member should be "Sn". If the + * ephemeris data are with respect to the solar system barycenter, this + * member must be "SSB", also for coherence with fundamental ephemerides. + */ + IsoString originId; + + /*! + * Optional Name of the object or item for which ephemeris data have been + * generated. This can be an arbitrary string, such as 'Saturn', 'Iris', or + * 'C/1996 B2'. However, bear in mind that ephemeris data can be accessed + * both by object identifiers and object names, so there should be no + * duplicate names. Object names are considered as case-insensitive in XEPH + * files, so all of 'Jupiter', 'jupiter' and 'JUPITER' are equivalent. + */ + String objectName; + + /*! + * Optional information about the object and/or the ephemeris data being + * serialized. + */ + String description; + + /*! + * Two dynamic lists of Chebyshev polynomial expansions. The first list is + * mandatory for approximation of function values (typically, the components + * of a position vector). The second list is optional for approximation of + * first derivatives (typically, the components of a velocity vector). Both + * sequences must cover the entire ephemeris time span with arbitrary + * subspans in ascending time order without any gaps. + */ + SerializableEphemerisDataList data[ 2 ]; + + /* + * Absolute magnitude. H is the visual magnitude of the object as seen at 1 + * au of the Earth, 1 au from the Sun, and with a phase angle of 0 degrees. + * + * References + * + * E. Bowell et al., Asteroids II, R. P. Binzel et al. (eds.), The + * University of Arizona Press, Tucson, 1989, pp. 549-554. + * + * Urban, Sean E., Kenneth Seidelmann, P., ed. (2013), The Explanatory + * Supplement to the Astronomical Almanac 3rd Edition, Section 10.4.3. + */ + Optional H; + + /* + * Slope parameter. See the H data member for references. + */ + Optional G; + + /* + * Color index B-V in magnitudes. + */ + Optional B_V; + + /* + * Diameter of the object in km. + */ + Optional D; + + /*! + * Memberwise constructor. + */ + SerializableEphemerisObjectData( const IsoString& id, + const IsoString& origin, + const String& name = String(), + const String& desc = String() ) + : objectId( id.Trimmed() ) + , originId( origin.Trimmed() ) + , objectName( name.Trimmed() ) + , description( desc ) + { + } + + /*! + * Copy constructor. + */ + SerializableEphemerisObjectData( const SerializableEphemerisObjectData& ) = default; + + /*! + * Move constructor. + */ + SerializableEphemerisObjectData( SerializableEphemerisObjectData&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SerializableEphemerisObjectData& operator =( const SerializableEphemerisObjectData& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SerializableEphemerisObjectData& operator =( SerializableEphemerisObjectData&& ) = default; +}; + +/*! + * \class pcl::SerializableEphemerisObjectDataList + * \brief Dynamic list of per-object data for ephemeris serialization. + * \ingroup solar_system_ephemerides + */ +typedef Array SerializableEphemerisObjectDataList; + +// ---------------------------------------------------------------------------- + +/*! + * \struct EphemerisObject + * \brief Identifiers and descriptive data of an object available in an + * ephemeris file. + * + * This structure associates the unique identifier, origin identifier, name and + * description of an object or item available for ephemeris calculations. All + * of the data members in this structure are specific to a particular ephemeris + * file. A dynamic list of %EphemerisObject instances (EphemerisObjectList) is + * returned by the EphemerisFile::Objects() member function. + * + * \sa EphemerisFile::Objects() + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS EphemerisObject +{ + /*! + * Unique identifier of an object or item for which ephemeris data are + * available. This is a short string that uniquely identifies the object in + * the context of an ephemeris file. + * + * For example, standard XEPH files serializing JPL DE/LE ephemerides use a + * two/three letter convention for object identifiers: 'Me', 'Ve', 'EMB', + * 'Ea', 'Ma', etc, respectively for Mercury, Venus, Earth-Moon barycenter, + * Earth, Mars, etc. Object identifiers are considered as case-sensitive in + * XEPH files. + */ + IsoString objectId; + + /*! + * Identifier of the origin of coordinates (case-sensitive). This can be the + * unique identifier of a solar system object, or the identifier of an + * arbitrary object or location, specific to a particular ephemeris file. + * + * For example, if the object provides geocentric coordinates, this member + * should be "Ea", which is the unique identifier of the Earth's center in + * standard fundamental ephemerides files. Similarly, if the ephemerides are + * heliocentric, this member should be "Sn". If the ephemeris data are with + * respect to the solar system barycenter, this member must be "SSB", also + * for coherence with fundamental ephemerides. + */ + IsoString originId; + + /*! + * Optional Name of the object or item for which ephemeris data are + * available. This can be an arbitrary string, such as 'Saturn', 'Iris', or + * 'C/1996 B2'. Object names are considered as case-insensitive in XEPH + * files, so all of 'Jupiter', 'jupiter' and 'JUPITER' are equivalent. + */ + String objectName; + + /*! + * Optional information about the object and/or the ephemeris data. + */ + String objectDescription; + + /*! + * Absolute magnitude. H is the visual magnitude of the object as seen at 1 + * au of the Earth, 1 au from the Sun, and with a phase angle of 0 degrees. + * + * References + * + * E. Bowell et al., Asteroids II, R. P. Binzel et al. (eds.), The + * University of Arizona Press, Tucson, 1989, pp. 549-554. + * + * Urban, Sean E., Kenneth Seidelmann, P., ed. (2013), The Explanatory + * Supplement to the Astronomical Almanac 3rd Edition, Section 10.4.3. + */ + Optional H; + + /*! + * Slope parameter. See the H data member for references. + */ + Optional G; + + /*! + * Color index B-V in magnitudes. + */ + Optional B_V; + + /*! + * Diameter of the object in km. + */ + Optional D; + + /*! + * Memberwise constructor. + */ + EphemerisObject( const IsoString& objectId_, + const IsoString& originId_, + const String& objectName_ = String(), + const String& objectDescription_ = String(), + Optional H_ = Optional(), + Optional G_ = Optional(), + Optional B_V_ = Optional(), + Optional D_ = Optional() ) + : objectId( objectId_ ) + , originId( originId_ ) + , objectName( objectName_ ) + , objectDescription( objectDescription_ ) + , H( H_ ) + , G( G_ ) + , B_V( B_V_ ) + , D( D_ ) + { + } + + /*! + * Copy constructor. + */ + EphemerisObject( const EphemerisObject& ) = default; + + /*! + * Move constructor. + */ + EphemerisObject( EphemerisObject&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + EphemerisObject& operator =( const EphemerisObject& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + EphemerisObject& operator =( EphemerisObject&& ) = default; +}; + +/*! + * \class pcl::EphemerisObjectList + * \brief Dynamic list of object identifiers and descriptions. + * \ingroup solar_system_ephemerides + */ +typedef Array EphemerisObjectList; + +// ---------------------------------------------------------------------------- + +/*! + * \class EphemerisFile + * \brief Solar system ephemerides from XEPH files. + * + * This class implements ephemerides of solar system bodies computed from data + * stored in XEPH (Extensible Ephemeris Data format) files. It also implements + * serialization of ephemeris data in the XEPH file format. + * + * On the PixInsight/PCL platform, the XEPH file format allows for efficient + * ephemeris calculations through Chebyshev polynomial expansions stored as raw + * binary data. An XEPH file stores multiple arrays of Chebyshev coefficient + * series accessible by means of fast indexed file search algorithms and + * structures, along with auxiliary data and metadata required for ephemeris + * calculations. + * + * Calculation of state vectors (such as position and velocity vectors) for + * specific objects is performed through a dedicated client subclass, namely + * EphemerisFile::Handle. This class implements transparent file seek and read + * operations, as well as fast, lock-free multithreaded evaluation of Chebyshev + * polynomials. + * + * XEPH ephemeris files allow for calculation of rectangular coordinates + * referred to the axes of the International Celestial Reference System + * (ICRS/J2000.0). Positions are given in au and velocities in au/day for all + * solar system objects, except planetocentric coordinates of natural + * satellites, including the geocentric Moon, for which positions and + * velocities are given in kilometers and km/day, respectively. Angles + * (nutations and librations) are given in radians, and time differences (such + * as TT-TDB) in seconds. + * + * An XEPH file storing up-to-date JPL DE/LE ephemeris data is part of all + * standard PixInsight distributions since 1.8.5 versions released Fall 2018. + * As of writing this documentation, the standard XEPH file provides the + * complete JPL DE440/LE440 ephemerides. See the + * EphemerisFile::FundamentalEphemerides() static member function for detailed + * information. + * + * \ingroup solar_system_ephemerides + */ +class PCL_CLASS EphemerisFile +{ +public: + + /*! + * Default constructor. + * + * Constructs an invalid instance that cannot be used until initialized by + * calling the Open() member function. + */ + EphemerisFile() = default; + + /*! + * Constructs an &EphemerisFile instance initialized from the specified + * ephemeris data file in XEPH format. + * + * In the event of errors or invalid data, this constructor will throw the + * appropriate Error exception. + */ + EphemerisFile( const String& filePath ) + { + Open( filePath ); + } + + /*! + * Move constructor. + */ + EphemerisFile( EphemerisFile&& x ) + : m_file( std::move( x.m_file ) ) + , m_startTime( x.m_startTime ) + , m_endTime( x.m_endTime ) + , m_constants( std::move( x.m_constants ) ) + , m_index( std::move( x.m_index ) ) + { + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + EphemerisFile& operator =( EphemerisFile&& x ) + { + m_file = std::move( x.m_file ); + m_startTime = x.m_startTime; + m_endTime = x.m_endTime; + m_constants = std::move( x.m_constants ); + m_index = std::move( x.m_index ); + return *this; + } + + /*! + * Deleted copy constructor. %EphemerisFile instances are unique, hence + * cannot be copied. + */ + EphemerisFile( const EphemerisFile& ) = delete; + + /*! + * Deleted copy assignment operator. %EphemerisFile instances are unique, + * hence cannot be copied. + */ + EphemerisFile& operator =( const EphemerisFile& ) = delete; + + /*! + * Virtual destructor. + */ + virtual ~EphemerisFile() noexcept( false ); + + /*! + * Initializes this object to give access to the specified ephemeris data + * file in XEPH format. + * + * This member function opens an existing file at the specified \a filePath, + * loads and parses its XML header, and loads the file indexes ready for + * fast access to ephemeris data. The file will remain open until this + * object is destroyed, or until a new call to this function is made. + * + * If a previous file was already opened by this instance, it will be closed + * and all associated control and file indexing structures will be destroyed + * and deallocated, before accessing the new file. + * + * \warning If this object has active ephemeris calculation handles, no + * action will be taken and an Error exception will be thrown. See + * EphemerisFile::Handle and NumberOfHandles(). + */ + void Open( const String& filePath ); + + /*! + * Closes the ephemeris file represented by this object and resets all + * internal structures to a default, uninitialized state. + * + * If a previous file was already opened by this instance, it will be closed + * and all associated control and file indexing structures will be destroyed + * and deallocated. If no file is currently open, calling this member has no + * effect. + * + * \warning If this object has active ephemeris calculation handles, no + * action will be taken and an Error exception will be thrown. See + * EphemerisFile::Handle and NumberOfHandles(). + */ + void Close(); + + /*! + * Returns true iff this object has an open ephemeris file and is ready for + * ephemeris data retrieval. + */ + bool IsOpen() const + { + return m_file.IsOpen(); + } + + /*! + * Returns the path of the ephemeris file represented by this object. + * Returned file paths are always absolute, full file paths. + */ + const String& FilePath() const + { + return m_file.FilePath(); + } + + /*! + * Starting point of the time span covered by this ephemeris, or the + * earliest time point for which ephemerides can be calculated using this + * object. + */ + TimePoint StartTime() const + { + return m_startTime; + } + + /*! + * Ending point of the time span covered by this ephemeris, or the latest + * time point for which ephemerides can be calculated using this object. + */ + TimePoint EndTime() const + { + return m_endTime; + } + + /*! + * Returns a reference to the dynamic list of constants stored in the + * ephemeris data file represented by this object. These constants are + * name/value pairs, where keys are 8-bit strings and values are double + * precision floating point numbers. + * + * Typically, for XEPH files that store fundamental JPL DE/LE ephemerides + * this member function returns the list of constants used by the + * corresponding DE/LE numerical integration. + * + * The returned list is sorted by constant name in ascending order. + */ + const EphemerisConstantList& Constants() const + { + return m_constants; + } + + /*! + * Returns true iff this instance knows a numerical constant with the + * specified \a name. + */ + bool IsConstantAvailable( const IsoString& name ) const + { + return BinarySearch( m_constants.Begin(), m_constants.End(), + EphemerisConstant( name ) ) != m_constants.End(); + } + + /*! + * Returns the value of an ephemeris constant given by its \a name. + * + * If no constant is available with the specified \a name + * (case-insensitive) in the XEPH file represented by this object, this + * function throws an Error exception. + */ + double ConstantValue( const IsoString& name ) const + { + EphemerisConstantList::const_iterator i = + BinarySearch( m_constants.Begin(), m_constants.End(), EphemerisConstant( name ) ); + if ( i == m_constants.End() ) + throw Error( "Undefined ephemeris constant '" + name + '\'' ); + return i->value; + } + + /*! + * Returns a dynamic list of EphemerisObject instances describing all of the + * objects available in this file for ephemeris calculations. + * + * The returned list is sorted by object and origin identifiers (in that + * order of precedence) in ascending order. + */ + EphemerisObjectList Objects() const + { + EphemerisObjectList objects; + for ( const Index& ix : m_index ) + objects << EphemerisObject( ix.objectId, ix.originId, + ix.objectName, ix.objectDescription, + ix.H, ix.G, ix.B_V, ix.D ); + return objects; + } + + /*! + * Returns true iff this instance contains ephemeris data for the specified + * \a object, given by its identifier or name, with respect to the specified + * \a origin. + * + * The specified \a object string can be either an object identifier + * (case-sensitive), or an object name (case-insensitive) encoded as UTF-8. + * For example, all of 'Ju', 'Jupiter', 'jupiter' and 'JUPITER' refer to + * Jupiter in a standard XEPH file storing fundamental JPL DE/LE + * ephemerides. In this example, 'Ju' is a case-sensitive object identifier, + * thus 'ju' and 'JU' are not valid and this function would return false for + * both of them. + * + * \a origin is the identifier of an origin of coordinates. If an empty + * string is specified (which is the default parameter value), this function + * will return true if the file contains any ephemeris data for the + * specified \a object, irrespective of the origin. Otherwise an exact match + * of the \a origin identifier will be required. + * + * See the FundamentalEphemerides() static member function for information + * about the objects supported by standard XEPH files storing fundamental + * ephemerides. + */ + bool IsObjectAvailable( const IsoString& object, const IsoString& origin = IsoString() ) const + { + Array::const_iterator i = BinarySearch( m_index.Begin(), m_index.End(), Index( object, origin ) ); + if ( i != m_index.End() ) + return true; + String name = object.UTF8ToUTF16(); + for ( const Index& index : m_index ) + if ( index.objectName.CompareIC( name ) == 0 ) + if ( origin.IsEmpty() || index.originId == origin ) + return true; + return false; + } + + /*! + * Returns the name of the specified \a object, with respect to the + * specified \a origin. + * + * Both \a object and \a origin must be object identifiers. If \a origin is + * an empty string (which is the default parameter value), this function + * will return the name of the first object found with the specified + * identifier, irrespective of the origin. Otherwise an exact match of the + * \a origin identifier will be required. + * + * If no object with the required conditions is available in this ephemeris + * file, this function returns an empty string. + */ + String ObjectName( const IsoString& object, const IsoString& origin = IsoString() ) const + { + Array::const_iterator i = BinarySearch( m_index.Begin(), m_index.End(), Index( object, origin ) ); + if ( i != m_index.End() ) + return i->objectName; + return String(); + } + + /*! + * Returns a reference to the (immutable) metadata items available in the + * ephemeris data file loaded by this object. + */ + const EphemerisMetadata& Metadata() const + { + return m_metadata; + } + + /*! + * Returns the number of handles currently active for this ephemeris file. + * + * If an %EphemerisFile object has active handles, also known as \e child + * \e handles, destroying it will most likely lead to a crash, since any + * activity performed by a child handle will make reference to a nonexistent + * parent object. + * + * This function is thread-safe. + * + * \sa pcl::EphemerisFile::Handle + */ + int NumberOfHandles() const + { + return m_handleCount.Load(); + } + + /*! + * Generates a file to store solar system ephemeris data in XEPH format. + * + * \param filePath Path to the file that will be generated in the local + * filesystem. The file name should carry the '.xeph' + * suffix. + * + * \param startTime Lower bound of the entire time span for which the + * ephemeris data being serialized is valid. + * + * \param endTime Upper bound of the entire time span for which the + * ephemeris data being serialized is valid. + * + * \param data Reference to an array of per-object ephemeris data, + * including Chebyshev polynomial expansions for the + * ephemeris function (such as position) and, + * optionally, for its first derivative (such as + * velocity), as well as object identifiers and object + * names. + * + * \param metadata Reference to an EphemerisMetadata structure with + * optional metadata information that will be included + * in the generated XEPH file. + * + * \param constants Reference to an array of name/value pairs used to + * represent a set of numerical constants relevant to + * the ephemerides being serialized If an empty array + * is specified (as the default parameter value), no + * numerical constant will be included in the generated + * XEPH file. + * + * The entire time span covered by an ephemeris file, from \a startTime to + * \a endTime, is usually subdivided into many small chunks or subspans, + * each of them with a relatively short polynomial expansion. The duration + * of each subspan is defined in a way such that the motion of the object + * for which positions are being calculated is sufficiently smooth to be + * fitted within the time subspan by truncated Chebyshev polynomials with + * relatively few coefficients (typically in the range of 15 to 30 + * coefficients) to achieve a prescribed accuracy. The faster and more + * perturbed the object's motion is, the more and shorter subspans are + * necessary to fit an accurate representation of the object's orbit. + * + * In the event of invalid, incongruent or malformed data, or if an I/O + * error occurs, this function will throw an Error exception. + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + static void Serialize( const String& filePath, + TimePoint startTime, TimePoint endTime, + const SerializableEphemerisObjectDataList& data, + const EphemerisMetadata& metadata = EphemerisMetadata(), + const EphemerisConstantList& constants = EphemerisConstantList() ); + + /*! + * Returns a reference to the global fundamental ephemerides file currently + * defined by the running PixInsight platform. + * + * Under normal running conditions, the returned object provides ephemeris + * data for at least the following objects: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
IdentifierName
MeMercury
VeVenus
EMBEarth-Moon barycenter
MaMars' barycenter
JuJupiter's barycenter
SaSaturn's barycenter
UrUranus' barycenter
NeNeptune's barycenter
PlPluto's barycenter
MnMoon's geometric center with respect to Earth's center.
SnSun's geometric center
EaEarth's geometric center
+ * + * With the only exception of the Moon ("Mn" identifier), ephemeris data for + * all of the objects above are provided relative to the solar system + * barycenter ("SSB" identifier). + * + * Additional items may also be available, depending on specific file + * versions and compilations: + * + * + * + * + * + * + *
IdentifierName
LbrLunar librations (Euler angles) in radians
NutNutation angles in radians
TT_TDBTT-TDB difference at the geocenter in seconds.
+ * + * As of writing this documentation, the standard fundamental ephemeris file + * provides the complete JPL's DE440/LE440 ephemerides, but nutations, + * librations and time differences are not included. + * + * The fundamental ephemeris file can be overridden by the caller module. + * See the OverrideFundamentalEphemerides() member function for more + * information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& FundamentalEphemerides(); + + /*! + * Returns a reference to the global short-term fundamental ephemerides file + * currently defined by the running PixInsight platform. + * + * See the FundamentalEphemerides() static member function for information + * on fundamental ephemerides and their status in current versions of + * PixInsight. + * + * Under normal running conditions, the returned object should be a + * shortened version (that is, covering a shorter time span) of the standard + * fundamental ephemerides file. As of writing this documentation, the + * standard short-term fundamental ephemeris file provides DE440/LE440 + * ephemerides for the period from 1850 January 1.0 to 2150 December 32.0. + * + * The short-term fundamental ephemeris file can be overridden by the caller + * module. See the OverrideShortTermFundamentalEphemerides() member function + * for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& ShortTermFundamentalEphemerides(); + + /*! + * Returns a reference to the global asteroid ephemerides file currently + * defined by the running PixInsight platform. + * + * Under normal running conditions, the returned object provides ephemeris + * data for a set of asteroids with relevant masses. In a standard asteroid + * ephemeris file, object identifiers are asteroid numbers and object names + * are asteroid designations; for example: + * + * + * + * + * + * + * + * + * + * + * + * + * + *
IdentifierName
1Ceres
2Pallas
3Juno
4Vesta
5Astraea
......
702Alauda
703Noemi
704Interamnia
......
+ * + * Asteroid ephemeris data are provided relative to the solar system + * barycenter ("SSB" identifier), with position and velocity coordinates + * coherent with global fundamental ephemerides. + * + * As of writing this documentation, the standard asteroid ephemeris file + * provides the complete set of 343 asteroids used for the numerical + * integration of DE430 ephemerides, with barycentric coordinates coherent + * with DE440. + * + * The asteroid ephemeris file can be overridden by the caller module. See + * the OverrideAsteroidEphemerides() member function for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& AsteroidEphemerides(); + + /*! + * Returns a reference to the global short-term asteroid ephemerides file + * currently defined by the running PixInsight platform. + * + * See the AsteroidEphemerides() static member function for information + * on asteroid ephemerides and their status in current versions of + * PixInsight. + * + * Under normal running conditions, the returned object should be a + * shortened version (that is, covering a shorter time span) of the standard + * asteroid ephemerides file. As of writing this documentation, the + * standard short-term asteroid ephemeris file covers the period from 1950 + * January 1.0 to 2100 January 32.0. + * + * The short-term asteroid ephemeris file can be overridden by the caller + * module. See the OverrideShortTermAsteroidEphemerides() member function + * for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& ShortTermAsteroidEphemerides(); + + /*! + * Returns a reference to the global Kuiper belt objects (KBOs) ephemerides + * file currently defined by the running PixInsight platform. + * + * As of writing this documentation (March 2021), the default KBO + * ephemerides file includes the set of 30 most massive known + * trans-Neptunian objects used in JPL's DE440 numerical integration: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
IdentifierName
19521Chaos
20000Varuna
28978Ixion
423012001 UR163
50000Quaoar
555652002 AW197
556372002 UX25
845222002 TC302
90377Sedna
90482Orcus
905682004 GV9
120347Salacia
136108Haumea
136199Eris
136472Makemake
1454522005 RN43
174567Varda
2089962003 AZ84
225088Gonggong
2309652004 XA192
2783612007 JJ43
3072612002 MS4
4555022003 UZ413
5236392010 RE64
5283812008 ST291
2004 XR190
2006 QH181
2010 FX86
2010 KZ39
2010 RF43
+ * + * KBO ephemeris data are provided relative to the solar system barycenter + * ("SSB" identifier), with position and velocity coordinates coherent with + * global fundamental ephemerides. These ephemerides have been generated by + * numerical integration with starting state vectors provided by official + * NASA/JPL asteroid databases. + * + * The KBO ephemeris file can be overridden by the caller module. See the + * OverrideKBOEphemerides() member function for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& KBOEphemerides(); + + /*! + * Returns a reference to the global short-term Kuiper belt objects (KBOs) + * ephemerides file currently defined by the running PixInsight platform. + * + * See the KBOEphemerides() static member function for information on + * asteroid ephemerides and their status in current versions of PixInsight. + * + * Under normal running conditions, the returned object should be a + * shortened version (that is, covering a shorter time span) of the standard + * KBO ephemerides file. As of writing this documentation, the standard + * short-term asteroid ephemeris file covers the period from 1950 January + * 1.0 to 2100 January 32.0. + * + * The short-term KBO ephemeris file can be overridden by the caller module. + * See the OverrideShortTermKBOEphemerides() member function for more + * information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& ShortTermKBOEphemerides(); + + /*! + * Returns a reference to the global nutation model ephemeris file currently + * defined by the running PixInsight platform. + * + * Under normal running conditions, the returned object provides Chebyshev + * polynomial expansions for the current IAU nutation model. As of writing + * this documentation, the standard nutation model file provides the IAU + * 2006/2000A_R nutation model (MHB2000 luni-solar and planetary nutation + * with adjustments to match the IAU 2006 precession). + * + * The returned object should provide at least one object with the "IAUNut" + * identifier, which can be used to approximate the implemented nutation + * theory with a child EphemerisFile::Handle object. + * + * The nutation model ephemeris file can be overridden by the caller module. + * See the OverrideNutationModel() member function for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& NutationModel(); + + /*! + * Returns a reference to the global short-term nutation model ephemeris + * file currently defined by the running PixInsight platform. + * + * See the NutationModel() static member function for information on + * nutation model ephemerides and their status in current versions of + * PixInsight. + * + * Under normal running conditions, the returned object should be a + * shortened version (that is, covering a shorter time span) of the standard + * nutation model ephemerides file. As of writing this documentation, the + * standard short-term nutation model file provides the IAU 2006/2000A_R + * nutation model for the period from 1850 January 1.0 to 2150 December + * 32.0. + * + * The returned object should provide at least one object with the "IAUNut" + * identifier, which can be used to approximate the implemented nutation + * theory with a child EphemerisFile::Handle object. + * + * The short-term nutation model ephemeris file can be overridden by the + * caller module. See the OverrideShortTermNutationModel() member function + * for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + */ + static const EphemerisFile& ShortTermNutationModel(); + + /*! + * Returns the path to the global database file of observed Delta T values. + * + * Delta T is the difference TT-UT1 in seconds. In current versions of + * PixInsight the Delta T database is a plain text file generated with values + * taken from the following online references: + * + * For the period 1657-1973.0:\n + * http://maia.usno.navy.mil/ser7/historic_deltat.data + * + * For the period 1973 Feb 1 to the beginning of the current year:\n + * http://maia.usno.navy.mil/ser7/deltat.data + * + * For predicted Delta T values until 2025 approximately (as of writing this + * documentation, October 2018):\n + * http://maia.usno.navy.mil/ser7/deltat.preds + * + * Delta T data files are expected to follow a simple format where each text + * line provides a TT/DeltaT pair. The exact format is described at the top + * of the corresponding file included in the current PixInsight + * distribution. + * + * Outside of the period from 1657 to the current year, the current + * PixInsight/PCL implementation uses polynomial expressions taken from + * Five Millennium Canon of Solar Eclipses, by Fred Espenak and + * Jean Meeus (NASA/TP–2006–214141, Revision 1.0, 2007). + * + * The Delta T database file can be overridden by the caller module. See the + * OverrideDeltaTDataFilePath() member function for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + * + * \sa TimePoint::DeltaT() + */ + static String DeltaTDataFilePath(); + + /*! + * Returns the path to the global database file of Delta AT values. + * + * Delta AT is the difference TAI-UTC in seconds. In current versions of + * PixInsight the Delta AT database is a plain text file generated with + * values taken from the following online reference: + * + * http://maia.usno.navy.mil/ser7/tai-utc.dat + * + * Delta AT data files are expected to follow a simple format where each + * text line provides a UTC/DeltaAT pair. The exact format is described at + * the top of the corresponding file included in the current PixInsight + * distribution. + * + * The Delta AT database file can be overridden by the caller module. See + * the OverrideDeltaATDataFilePath() member function for more information. + * + * This static member function is thread-safe. It can be called safely from + * multiple execution threads running concurrently. + * + * \sa TimePoint::DeltaAT() + */ + static String DeltaATDataFilePath(); + + /*! + * Returns the path to the global database file of CIP positions referred to + * the ITRS. + * + * The position of the Celestial Intermediate Pole (CIP) in the + * International Terrestrial Reference System (ITRS) is necessary to compute + * polar motion corrections applied to topocentric coordinates of solar + * system bodies. These corrections are relevant for the topocentric + * position of the Moon at the milliarcsecond level. + * + * In current versions of PixInsight the CIP_ITRS database is a plain text + * file generated with values provided by the IERS Rapid Service/Prediction + * Center. As of writing this documentation, the main online reference is: + * + * http://hpiers.obspm.fr/iers/eop/eopc01/eopc01.iau2000.1846-now + */ + static String CIP_ITRSDataFilePath(); + + /*! + * Override the default fundamental ephemerides file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide fundamental solar system ephemerides. See + * the FundamentalEphemerides() member function for a comprehensive + * description. + * + * After calling this member function, all fundamental ephemerides will be + * calculated using the specified XEPH file, which will be installed + * automatically upon the first call to FundamentalEphemerides(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideFundamentalEphemerides( const String& filePath ); + + /*! + * Override the default short-term fundamental ephemerides file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide fundamental solar system ephemerides. See + * the FundamentalEphemerides() member function for a comprehensive + * description. + * + * After calling this member function, all short-term fundamental + * ephemerides will be calculated using the specified XEPH file, which will + * be installed automatically upon the first call to + * ShortTermFundamentalEphemerides(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideShortTermFundamentalEphemerides( const String& filePath ); + + /*! + * Override the default asteroid ephemerides file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide asteroid ephemerides coherent with the + * global fundamental ephemerides being used. See the AsteroidEphemerides() + * member function for a more comprehensive description. + * + * After calling this member function, all asteroid ephemerides will be + * calculated using the specified XEPH file, which will be installed + * automatically upon the first call to AsteroidEphemerides(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideAsteroidEphemerides( const String& filePath ); + + /*! + * Override the default short-term asteroid ephemerides file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide asteroid ephemerides coherent with the + * global fundamental ephemerides being used. See the AsteroidEphemerides() + * member function for a more comprehensive description. + * + * After calling this member function, all short-term asteroid ephemerides + * will be calculated using the specified XEPH file, which will be installed + * automatically upon the first call to ShortTermAsteroidEphemerides(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideShortTermAsteroidEphemerides( const String& filePath ); + + /*! + * Override the default Kuiper belt objects (KBOs) ephemerides file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide KBO ephemerides coherent with the global + * fundamental ephemerides being used. See the KBOEphemerides() member + * function for a more comprehensive description. + * + * After calling this member function, all KBO ephemerides will be + * calculated using the specified XEPH file, which will be installed + * automatically upon the first call to KBOEphemerides(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideKBOEphemerides( const String& filePath ); + + /*! + * Override the default short-term Kuiper belt objects (KBOs) ephemerides + * file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide KBO ephemerides coherent with the global + * fundamental ephemerides being used. See the KBOEphemerides() member + * function for a more comprehensive description. + * + * After calling this member function, short-term KBO ephemerides will be + * calculated using the specified XEPH file, which will be installed + * automatically upon the first call to ShortTermKBOEphemerides(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideShortTermKBOEphemerides( const String& filePath ); + + /*! + * Override the global nutation model ephemeris file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide estimates of nutation angles compliant + * with the current IAU nutation model. See the NutationModel() member + * function for more details. + * + * After calling this member function, the nutation model used for ephemeris + * calculations will be provided by the specified XEPH file, which will + * be installed automatically upon the first call to NutationModel(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideNutationModel( const String& filePath ); + + /*! + * Override the global short-term nutation model ephemeris file. + * + * The specified \a filePath must be a valid path to an existing file in + * XEPH format, which must provide estimates of nutation angles compliant + * with the current IAU nutation model. See the NutationModel() member + * function for more details. + * + * After calling this member function, the nutation model used for + * short-term ephemeris calculations will be provided by the specified XEPH + * file, which will be installed automatically upon the first call to + * ShortTermNutationModel(). + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideShortTermNutationModel( const String& filePath ); + + /*! + * Override the global Delta T database. + * + * The specified \a filePath must be a valid path to an existing file in a + * plain text database format compatible with the standard Delta T database + * included in PixInsight distributions. See the DeltaTDataFilePath() member + * function for more details. + * + * After calling this member function, Delta T values will be calculated by + * interpolation from the data provided by the specified file, which will be + * loaded and parsed automatically upon the first call (explicit or + * implicit) to TimePoint::DeltaT(). However, for performance and + * modularization reasons, once a Delta T database has been loaded there is + * no way to change it, so calling this function again will have no effect. + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideDeltaTDataFilePath( const String& filePath ); + + /*! + * Override the global Delta AT database. + * + * The specified \a filePath must be a valid path to an existing file in a + * plain text database format compatible with the standard Delta AT database + * included in PixInsight distributions. See the DeltaATDataFilePath() + * member function for more details. + * + * After calling this member function, Delta AT values will be calculated by + * interpolation from the data provided by the specified file, which will be + * loaded and parsed automatically upon the first call (explicit or + * implicit) to TimePoint::DeltaAT(). However, for performance and + * modularization reasons, once a Delta AT database has been loaded there is + * no way to change it, so calling this function again will have no effect. + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideDeltaATDataFilePath( const String& filePath ); + + /*! + * Override the global database of CIP positions in the ITRS. + * + * The specified \a filePath must be a valid path to an existing file in a + * plain text database format compatible with the standard CIP_ITRS database + * included in PixInsight distributions. See the CIP_ITRSDataFilePath() + * member function for more details. + * + * After calling this member function, CIP coordinates in the ITRS will be + * calculated by interpolation from the data provided by the specified file, + * which will be loaded and parsed automatically upon the first call + * (explicit or implicit) to Position::CIP_ITRS(). However, for performance + * and modularization reasons, once a CIP_ITRS database has been loaded + * there is no way to change it, so calling this function again will have no + * effect. + * + * This function is useful to build standalone applications that don't + * depend on a running PixInsight core application, which is necessary to + * retrieve the default file names and directories from global settings. + */ + static void OverrideCIP_ITRSDataFilePath( const String& filePath ); + +private: + + /*! + * \internal + * Expansion index node structure. + */ + struct IndexNode + { + int32 jdi = 0; // Starting point of time span covered by this expansion, int( JD ). + float jdf = 0; // Ditto, frac( JD ). + uint8 n[ 4 ] = {}; // For each component: number of Chebyshev coefficients in this expansion. + int64 position = 0; // File byte position of first Chebyshev coefficient. + + constexpr bool operator ==( const IndexNode& n ) const + { + return jdi == n.jdi && jdf == n.jdf; + } + + constexpr bool operator <( const IndexNode& n ) const + { + return jdi < n.jdi || jdi == n.jdi && jdf < n.jdf; + } + + constexpr int NumberOfComponents() const + { + return (n[0] > 0) ? ((n[1] > 0) ? ((n[2] > 0) ? ((n[3] > 0) ? 4 : 3) : 2) : 1) : 0; + } + + constexpr int NumberOfCoefficients() const + { + return n[0] + n[1] + n[2] + n[3]; + } + + TimePoint StartTime() const + { + return TimePoint( jdi, jdf ); + } + }; + + /*! + * \internal + * Expansion index structure. + */ + struct Index + { + IsoString objectId; // Object identifier (mandatory, case-sensitive). + IsoString originId; // Identifier of the origin of coordinates (mandatory, case-sensitive). + String objectName; // Object name (optional, case-insensitive). + String objectDescription; // Object description (optional, arbitrary) + Optional H; // Absolute magnitude. + Optional G; // Slope parameter. + Optional B_V; // Color index B-V in magnitudes. + Optional D; // Diameter of the object in km. + Array nodes[ 2 ]; // Expansion indexes: 0=function 1=derivative. + + Index( const IsoString& objectId_, + const IsoString& originId_ = IsoString(), + const String& objectName_ = String(), + const String& objectDescription_ = String() ) + : objectId( objectId_.Trimmed() ) + , originId( originId_.Trimmed() ) + , objectName( objectName_.Trimmed() ) + , objectDescription( objectDescription_.Trimmed() ) + { + } + + bool operator ==( const Index& x ) const + { + return objectId == x.objectId && originId == x.originId; + } + + bool operator <( const Index& x ) const + { + return (objectId != x.objectId) ? objectId < x.objectId : originId < x.originId; + } + + bool HasDerivative() const + { + return !nodes[1].IsEmpty(); + } + }; + + mutable File m_file; + mutable AtomicInt m_handleCount; + mutable Mutex m_mutex; + TimePoint m_startTime; + TimePoint m_endTime; + EphemerisMetadata m_metadata; + EphemerisConstantList m_constants; + Array m_index; + + // Current data files. + // If empty, i.e. if not overridden, use platform defaults. + static String s_ephFilePath; + static String s_ephFilePath_s; + static String s_astFilePath; + static String s_astFilePath_s; + static String s_kboFilePath; + static String s_kboFilePath_s; + static String s_nutFilePath; + static String s_nutFilePath_s; + static String s_deltaTFilePath; + static String s_deltaATFilePath; + static String s_cipITRSFilePath; + + /*! + * \internal + * Returns a pointer to an Index structure for the specified object + * identifier or name, with respect to the specified origin of coordinates. + */ + const Index* FindObject( const IsoString& object, const IsoString& origin ) const + { + if ( origin.IsEmpty() ) + { + for ( const Index& index : m_index ) + if ( index.objectId == object ) + return &index; + } + else + { + Array::const_iterator i = BinarySearch( m_index.Begin(), m_index.End(), Index( object, origin ) ); + if ( i != m_index.End() ) + return i; + } + String name = object.UTF8ToUTF16(); + for ( const Index& index : m_index ) + if ( index.objectName.CompareIC( name ) == 0 ) + if ( origin.IsEmpty() || index.originId == origin ) + return &index; + throw Error( "Unavailable object '" + name + "\' with origin '" + String( origin ) + "'." ); + } + +public: + + /*! + * \class pcl::EphemerisFile::Handle + * \brief Calculation of ephemerides from data stored in XEPH files. + * + * This subclass provides access to ephemeris data for a specific object + * available in an ephemeris file. It can perform basic ephemeris + * calculations, including state vectors and its first derivatives (such as + * position and velocity), and performs all the low-level file seek and read + * operations transparently and efficiently. + * + * Data stored in an XEPH ephemeris file generates rectangular coordinates + * referred to the axes of the International Celestial Reference System + * (ICRS/J2000.0). Positions are given in au and velocities in au/day for + * all solar system objects, except planetocentric coordinates of natural + * satellites, including the geocentric Moon, for which positions and + * velocities are given in kilometers and km/day, respectively. Angles + * (nutations and librations) are given in radians, and time differences + * (such as TT-TDB) in seconds. + * + * For performance reasons, this class is not thread-safe. However, as far + * as a given instance is never used concurrently from two or more threads, + * multiple instances of this class can be used from different running + * threads, including instances constructed to calculate ephemerides for the + * same object. This allows for the implementation of performance-intensive, + * lock-free multithreaded ephemeris calculation tasks. + */ + class PCL_CLASS Handle + { + public: + + /*! + * Constructs a new %Handle object. + * + * \param parent Reference to an open EphemerisFile object providing + * access to an ephemeris data file in XEPH format. + * + * \param object The identifier or name of the object for which this + * instance will compute ephemerides. + * + * \param origin The identifier of the origin of coordinates. If an + * empty string is specified (which is the default + * parameter value), this object will be created for the + * first occurrence of ephemeris data available for + * \a object in the \a parent file, irrespective of the + * origin. In such case, if \a parent is a standard + * fundamental ephemerides file, the origin is the solar + * system barycenter (identified as "SSB"). + * + * For a detailed description of object names and identifiers, see + * EphemerisFile::IsObjectAvailable(). + * + * If the specified \a parent ephemeris file is not open, or if no + * ephemeris data are available for the specified \a object and \a origin + * in the \a parent ephemeris file, this constructor will throw an Error + * exception. + */ + Handle( const EphemerisFile& parent, const IsoString& object, const IsoString& origin = IsoString() ) + { + if ( !parent.IsOpen() ) + throw Error( "Cannot create a handle to a closed ephemeris file." ); + m_parent = &parent; + m_parent->m_handleCount.Increment(); + m_index = m_parent->FindObject( object, origin ); + } + + /*! + * Copy constructor. + */ + Handle( const Handle& x ) + { + m_parent = x.m_parent; + m_index = x.m_index; + m_node[0] = x.m_node[0]; + m_node[1] = x.m_node[1]; + m_node[2] = x.m_node[2]; + if ( m_parent != nullptr ) + m_parent->m_handleCount.Increment(); + } + + /*! + * Move constructor. + */ + Handle( Handle&& x ) + { + m_parent = x.m_parent; + x.m_parent = nullptr; + m_index = x.m_index; + m_node[0] = x.m_node[0]; + m_node[1] = x.m_node[1]; + m_node[2] = x.m_node[2]; + } + + /*! + * virtual destructor. + */ + virtual ~Handle() + { + if ( m_parent != nullptr ) + m_parent->m_handleCount.Decrement(); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Handle& operator =( const Handle& x ) + { + if ( m_parent != nullptr ) + m_parent->m_handleCount.Decrement(); + m_parent = x.m_parent; + m_index = x.m_index; + m_node[0] = x.m_node[0]; + m_node[1] = x.m_node[1]; + m_node[2] = x.m_node[2]; + if ( m_parent != nullptr ) + m_parent->m_handleCount.Increment(); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Handle& operator =( Handle&& x ) + { + if ( m_parent != nullptr ) + m_parent->m_handleCount.Decrement(); + m_parent = x.m_parent; + x.m_parent = nullptr; + m_index = x.m_index; + m_node[0] = x.m_node[0]; + m_node[1] = x.m_node[1]; + m_node[2] = x.m_node[2]; + return *this; + } + + /*! + * Computes a state vector for the specified time point \a t. + * + * \param[out] p Reference to a vector where the components of the + * computed state will be stored. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Rectangular coordinates for position are provided in au, except for + * the geocentric Moon, for which positions are provided in km. + * + * Angles are provided in radians. + * + * TT-TDB differences are provided in seconds. + * + * The reference system is ICRS/J2000.0. + * + * If \a t is either an invalid (uninitialized) TimePoint instance, or a + * time point outside the time span available from the parent ephemeris + * file, this member function throws an Error exception. + */ + void ComputeState( Vector& p, TimePoint t ) + { + Update( t, 0 ); + p = m_node[0].expansion( t - m_node[0].startTime ); + } + + /*! + * Computes a state vector and its first derivative for the specified + * time point \a t. + * + * \param[out] p Reference to a vector where the components of the + * computed state will be stored. + * + * \param[out] v Reference to a vector where the components of the + * computed first derivative will be stored. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Rectangular coordinates for position and velocity are provided in au + * and au/day, respectively, except for the geocentric Moon, for which + * position and velocity are provided in km and km/day, respectively. + * + * Angles and their variations are provided in radians and radians/day. + * + * Time differences (such as TT-TDB) and their variations are provided in + * seconds and seconds/day. + * + * The reference system is ICRS/J2000.0. + * + * If the parent ephemeris file provides Chebyshev expansions of state + * vector derivatives for the object being calculated, the components of + * \a v will be calculated directly from these expansions. Otherwise the + * components of \a v will be approximated by numerical differentiation + * of the Chebyshev expansions for state vectors. + * + * If \a t is either an invalid (uninitialized) TimePoint instance, or a + * time point outside the time span available from the parent ephemeris + * file, this member function throws an Error exception. + */ + void ComputeState( Vector& p, Vector& v, TimePoint t ) + { + ComputeState( p, t ); + ComputeFirstDerivative( v, t ); + } + + /*! + * Computes the first derivative of the state vector for the specified + * time point \a t. + * + * \param[out] v Reference to a vector where the components of the + * computed first derivative will be stored. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Rectangular coordinates for velocity are provided in au/day, except + * for the geocentric Moon, for which velocity is provided in km/day. + * + * Angle variations are provided in radians/day. + * + * Time difference variations are provided in seconds/day. + * + * The reference system is ICRS/J2000.0. + * + * If the parent ephemeris file provides Chebyshev expansions of state + * vector derivatives for the object being calculated, the components of + * \a v will be calculated directly from these expansions. Otherwise the + * components of \a v will be approximated by numerical differentiation + * of the Chebyshev expansions for state vectors. + * + * If \a t is either an invalid (uninitialized) TimePoint instance, or a + * time point outside the time span available from the parent ephemeris + * file, this member function throws an Error exception. + */ + void ComputeFirstDerivative( Vector& v, TimePoint t ) + { + if ( HasDerivative() ) + Update( t, 1 ); + else if ( m_node[1].current != m_node[0].current ) + { + m_node[1].current = m_node[0].current; + m_node[1].startTime = m_node[0].startTime; + m_node[1].endTime = m_node[0].endTime; + m_node[1].expansion = m_node[0].expansion.Derivative(); + } + v = m_node[1].expansion( t - m_node[1].startTime ); + } + + /*! + * Computes the second derivative of the state vector for the specified + * time point \a t. + * + * \param[out] a Reference to a vector where the components of the + * computed second derivative will be stored. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Rectangular coordinates for acceleration are provided in au/day^2, + * except for the geocentric Moon, for which acceleration is provided in + * km/day^2. + * + * Angular second derivatives are provided in radians/day^2. + * + * Time second derivatives are provided in seconds/day^2. + * + * The reference system is ICRS/J2000.0. + * + * The components of the second derivative will be approximated by + * numerical differentiation of the Chebyshev expansions for the first + * derivative. The latter can be either provided directly by the parent + * ephemeris file, or also approximated by numerical differentiation. + * + * If \a t is either an invalid (uninitialized) TimePoint instance, or a + * time point outside the time span available from the parent ephemeris + * file, this member function throws an Error exception. + */ + void ComputeSecondDerivative( Vector& a, TimePoint t ) + { + if ( HasDerivative() ) + Update( t, 1 ); + else if ( m_node[1].current != m_node[0].current ) + { + m_node[1].current = m_node[0].current; + m_node[1].startTime = m_node[0].startTime; + m_node[1].endTime = m_node[0].endTime; + m_node[1].expansion = m_node[0].expansion.Derivative(); + } + if ( m_node[2].current != m_node[0].current ) + { + m_node[2].current = m_node[0].current; + m_node[2].startTime = m_node[0].startTime; + m_node[2].endTime = m_node[0].endTime; + m_node[2].expansion = m_node[1].expansion.Derivative(); + } + a = m_node[2].expansion( t - m_node[2].startTime ); + } + + /*! + * Computes a state vector for the specified time point \a t. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Returns the computed state function value. + * + * See ComputeState( Vector&, TimePoint ) for complete information. + */ + Vector StateVector( TimePoint t ) + { + Vector p; + ComputeState( p, t ); + return p; + } + + /*! + * Computes a state vector and its first derivative for the specified + * time point \a t. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Returns a two-component multivector, where the first component vector + * is the state function's value and the second is its first derivative. + * + * See ComputeState( Vector&, Vector&, TimePoint ) for complete + * information. + */ + MultiVector StateVectors( TimePoint t ) + { + Vector p, v; + ComputeState( p, v, t ); + return MultiVector( p, v ); + } + + /*! + * Computes the first derivative of a state vector for the specified time + * point \a t. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Returns the computed first derivative vector. + * + * See ComputeFirstDerivative( Vector&, TimePoint ) for complete + * information. + */ + Vector FirstDerivative( TimePoint t ) + { + Vector v; + ComputeFirstDerivative( v, t ); + return v; + } + + /*! + * Computes the second derivative of a state vector for the specified + * time point \a t. + * + * \param t The requested time point in the TDB time scale + * (rigorously, this is Teph as defined by JPL, but is + * equivalent to TDB or TT for all practical purposes). + * + * Returns the computed second derivative vector. + * + * See ComputeSecondDerivative( Vector&, TimePoint ) for complete + * information. + */ + Vector SecondDerivative( TimePoint t ) + { + Vector v; + ComputeSecondDerivative( v, t ); + return v; + } + + /*! + * Returns a reference to the parent ephemeris file object. The parent + * object was specified upon construction. + */ + const EphemerisFile& ParentFile() const + { + return *m_parent; + } + + /*! + * Returns the unique identifier of the object for which this handle can + * compute ephemerides. + */ + const IsoString& ObjectId() const + { + return m_index->objectId; + } + + /*! + * Returns the unique identifier of the origin of the coordinates + * computed by this object. For example, if this member function returns + * "Ea" or "Sn", the computed coordinates are geocentric or heliocentric, + * respectively. If this function returns "SSB", the origin of + * coordinates is the solar system barycenter. This happens, for example, + * with all standard XEPH files providing fundamental ephemerides. + */ + const IsoString& OriginId() const + { + return m_index->originId; + } + + /*! + * Returns the name of the object for which this handle can compute + * ephemerides. The returned value can be an empty string if no + * information about the object name is available in the parent ephemeris + * file. + */ + const String& ObjectName() const + { + return m_index->objectName; + } + + /*! + * Returns the lower bound of the time span for which this instance can + * calculate ephemerides using the ephemeris data already available. If + * a time point outside this span is requested, new file seek and read + * operations must be performed. + * + * \param i Expansion index: 0 to select function values (such as + * position), 1 to select function derivatives (such as + * velocity). + */ + TimePoint StartTime( int i = 0 ) const + { + return m_node[Range( i, 0, 1 )].startTime; + } + + /*! + * Returns the upper bound of the time span for which this instance can + * calculate ephemerides using the ephemeris data already available. If + * a time point outside this span is requested, new file seek and read + * operations must be performed. + * + * \param i Expansion index: 0 to select function values (such as + * position), 1 to select function derivatives (such as + * velocity). + */ + TimePoint EndTime( int i = 0 ) const + { + return m_node[Range( i, 0, 1 )].endTime; + } + + /*! + * Returns true iff the parent ephemeris file provides Chebyshev + * expansions of state vector derivatives for the object for which this + * handle computes ephemerides. + * + * When no expansions for derivatives are available, derivatives are + * approximated by numerical differentiation of the Chebyshev expansions + * for state vectors. + */ + bool HasDerivative() const + { + return m_index->HasDerivative(); + } + + /*! + * Returns the absolute magnitude of the object. H is the visual + * magnitude of the object as seen at 1 au of the Earth, 1 au from the + * Sun, and with a phase angle of 0 degrees. + * + * References + * + * E. Bowell et al., Asteroids II, R. P. Binzel et al. (eds.), + * The University of Arizona Press, Tucson, 1989, pp. 549-554. + * + * Urban, Sean E., Kenneth Seidelmann, P., ed. (2013), The + * Explanatory Supplement to the Astronomical Almanac 3rd Edition, + * Section 10.4.3. + */ + const Optional& H() const + { + return m_index->H; + } + + /*! + * Slope parameter. See H() for references. + */ + const Optional& G() const + { + return m_index->G; + } + + /*! + * Color index B-V, in magnitudes. + */ + const Optional& B_V() const + { + return m_index->B_V; + } + + /*! + * Diameter of the object in km. When available, this is normally an IRAS + * diameter for an asteroid. + */ + const Optional& D() const + { + return m_index->D; + } + + private: + + struct NodeInfo + { + int current = -1; + TimePoint startTime; + TimePoint endTime; + ChebyshevFit expansion; + }; + + const EphemerisFile* m_parent = nullptr; + const EphemerisFile::Index* m_index = nullptr; + NodeInfo m_node[ 3 ]; + uint64 m_uniqueId = UniqueId(); + + static uint64 UniqueId(); + + /*! + * \internal + * Updates internal data for the specified time point \a t and function + * index \a i. Performs file seek and read operations only when required + * to load a new set of Chebyshev polynomial coefficients. + */ + void Update( TimePoint t, int index ) + { + if ( !t.IsValid() ) + throw Error( "Invalid time point." ); + if ( t < m_parent->StartTime() || t > m_parent->EndTime() ) + throw Error( "Time point out of range." ); + + const Array& nodes = m_index->nodes[index]; + NodeInfo& info = m_node[index]; + + for ( int N = int( nodes.Length() ), l = 0, r = N-1; ; ) + { + int m = (l + r) >> 1; + const IndexNode& node = nodes[m]; + TimePoint t0 = node.StartTime(); + if ( t < t0 ) + r = m; + else + { + if ( m == N-1 || t < nodes[m+1].StartTime() ) + { + if ( m != info.current ) + { + ChebyshevFit::coefficient_series coefficients; + { + volatile AutoLock lock( m_parent->m_mutex ); + m_parent->m_file.SetPosition( node.position ); + for ( int i = 0, n = node.NumberOfComponents(); i < n; ++i ) + { + Vector c( node.n[i] ); + m_parent->m_file.Read( reinterpret_cast( c.Begin() ), c.Size() ); + coefficients << c; + } + } + info.current = m; + info.startTime = t0; + info.endTime = (m < N-1) ? nodes[m+1].StartTime() : m_parent->EndTime(); + info.expansion = ChebyshevFit( coefficients, 0, info.endTime - info.startTime ); + } + break; + } + + l = m + 1; + } + } + } + + friend class PCL_CLASS Position; + }; + +private: + +#if defined( __clang__ ) +# pragma GCC diagnostic ignored "-Wunused-private-field" +#endif + + /* + * For the core JavaScript engine we need garbage-collector-safe + * asynchronous destruction of these objects. + */ + mutable bool m_finalized = false; + + /* + * In the core JavaScript engine we must identify static objects that can be + * shared and must never be destroyed. This includes fundamental + * ephemerides, nutation, etc. + */ + mutable bool m_internal = false; + +#if defined( __clang__ ) +# pragma GCC diagnostic warning "-Wunused-private-field" +#endif + + class DeserializeObjectThread : public Thread + { + public: + + DeserializeObjectThread( const Array& elements + , File& file, fsize_type fileSize, fsize_type minPos + , int startIndex, int endIndex ) + : m_elements( elements ) + , m_startIndex( startIndex ) + , m_endIndex( endIndex ) + , m_file( file ) + , m_fileSize( fileSize ) + , m_minPos( minPos ) + { + } + + void Run() override; + + const Array& Objects() const + { + return m_index; + } + + bool Succeeded() const + { + return m_success; + } + + const Exception* ExceptionThrown() const + { + return m_exception.Ptr(); + } + + private: + + const Array& m_elements; + int m_startIndex, m_endIndex; + File& m_file; + fsize_type m_fileSize, m_minPos; + Array m_index; + AutoPointer m_exception; + bool m_success = false; + }; + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + friend class pi::JSEphemerisFileObject; + friend class pi::JSEphemerisHandleObject; +#endif +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_EphemerisFile_h + +// ---------------------------------------------------------------------------- +// EOF pcl/EphemerisFile.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ErrorHandler.h b/3rdparty/include/pcl/ErrorHandler.h new file mode 100644 index 0000000..261de0d --- /dev/null +++ b/3rdparty/include/pcl/ErrorHandler.h @@ -0,0 +1,184 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ErrorHandler.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_ErrorHandler_h +#define __PCL_ErrorHandler_h + +/// \file pcl/ErrorHandler.h + +#include + +#include + +#include // std::bad_alloc + +// ---------------------------------------------------------------------------- + +#ifdef __PCL_SILENTLY_REPLACE_USER_ERROR_MACROS + +#undef ERROR_HANDLER +#undef ERROR_CLEANUP + +#else + +#ifdef ERROR_HANDLER +#error ERROR_HANDLER macro: Already defined! +#endif + +#ifdef ERROR_CLEANUP +#error ERROR_CLEANUP macro: Already defined! +#endif + +#endif + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup error_handling_macros Error Handling Macros + */ + +// ---------------------------------------------------------------------------- + +/*! + * \def ERROR_HANDLER + * \brief Standard PCL error handler macro + * + * Use the ERROR_HANDLER macro after try blocks in all PCL programs and + * modules. + * + * \ingroup error_handling_macros + */ +#define ERROR_HANDLER \ + catch ( pcl::FatalError& ) \ + { \ + /* Launch fatal errors to the hyperspace... */ \ + throw; \ + } \ + catch ( pcl::ProcessAborted& ) \ + { \ + /* Abort process: Let the PI application do the GUI output */ \ + } \ + catch ( pcl::CaughtException& ) \ + { \ + /* Exceptions already caught and managed: simply ignore them */ \ + } \ + catch ( pcl::Exception& x ) \ + { \ + /* Other PCL exceptions */ \ + x.Show(); \ + } \ + catch ( pcl::String& s ) \ + { \ + /* Nonstandard ways of throwing things... */ \ + try \ + { \ + throw pcl::Error( s ); \ + } \ + catch ( pcl::Exception& x ) \ + { \ + x.Show(); \ + } \ + } \ + catch ( std::bad_alloc& ) \ + { \ + /* Standard bad allocation exception */ \ + try \ + { \ + throw pcl::Error( "Out of memory" ); \ + } \ + catch ( pcl::Exception& x ) \ + { \ + x.Show(); \ + } \ + } \ + catch ( ... ) \ + { \ + /* Catch-all */ \ + try \ + { \ + throw pcl::Error( "Unknown exception" ); \ + } \ + catch ( pcl::Exception& x ) \ + { \ + x.Show(); \ + } \ + } + +// ---------------------------------------------------------------------------- + +/*! + * \def ERROR_CLEANUP + * \brief Standard PCL error handler macro with cleanup code + * + * Use ERROR_CLEANUP in the same way as the ERROR_HANDLER macro, when you need + * to specify a local clean up code, e.g. to delete dynamically allocated local + * variables. + * + * \ingroup error_handling_macros + */ +#define ERROR_CLEANUP( cleanup_code ) \ + catch ( ... ) \ + { \ + cleanup_code; \ + \ + try \ + { \ + throw; \ + } \ + ERROR_HANDLER \ + } + +// ---------------------------------------------------------------------------- + +#endif // __PCL_ErrorHandler_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ErrorHandler.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Exception.h b/3rdparty/include/pcl/Exception.h new file mode 100644 index 0000000..6a8015a --- /dev/null +++ b/3rdparty/include/pcl/Exception.h @@ -0,0 +1,671 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Exception.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_Exception_h +#define __PCL_Exception_h + +/// \file pcl/Exception.h + +#include + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup standard_exception_classes Standard Exception Classes + */ + +/*! + * \class Exception + * \brief Root base class for all PCL exception classes + * + * All exceptions thrown by PCL classes and functions are descendants of the + * %Exception class. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS Exception +{ +public: + + /*! + * Constructs an %Exception object. + */ + Exception() = default; + + /*! + * Copy constructor. + */ + Exception( const pcl::Exception& ) = default; + + /*! + * Destroys an %Exception object. + */ + virtual ~Exception() + { + } + + /*! + * Returns an error class for this exception. + */ + virtual String ExceptionClass() const + { + return String(); + } + + /*! + * Returns an error or warning message corresponding to this exception. + */ + virtual String Message() const + { + return String(); + } + + /*! + * Returns a formatted representation of the information transported by this + * %Exception object. + */ + virtual String FormatInfo() const; + + /*! + * Returns a caption text suitable to represent the information in this + * %Exception object. + */ + virtual String Caption() const; + + /*! + * Shows a representation of the information transported by this exception. + * + * Exception information can be shown as text on the platform console or + * using graphical interfaces, depending on a global setting controlled with + * the EnableConsoleOutput() and EnableGUIOutput() static member functions. + * + * \sa IsConsoleOutputEnabled(), IsGUIOutputEnabled() + */ + virtual void Show() const; + + /*! + * Prints a representation of the information transported by this exception + * exclusively as plain text on the platform console. + * + * This function ignores current settings defined through previous calls to + * EnableConsoleOutput() and EnableGUIOutput(). + */ + PCL_FORCE_INLINE void ShowOnConsole() const + { + /* + * N.B.: This function must always be expanded inline. Otherwise, neither + * UNIX synchronous signal handlers nor Win32 structured exception + * handlers can throw C++ exceptions. + */ + bool wasConsoleOutput = IsConsoleOutputEnabled(); + bool wasGUIOutput = IsGUIOutputEnabled(); + EnableConsoleOutput(); + DisableGUIOutput(); + + Exception::Show(); + + EnableConsoleOutput( wasConsoleOutput ); + EnableGUIOutput( wasGUIOutput ); + } + + /*! + * Returns true iff console text output is enabled for %Exception. + * + * When console output is enabled, exception information is presented as + * text on the PixInsight core application's console. Console exception + * output is always enabled by default. + * + * \sa IsGUIOutputEnabled(), EnableConsoleOutput(), EnableGUIOutput() + */ + static bool IsConsoleOutputEnabled(); + + /*! + * Enables console output for %Exception. + * + * \sa IsConsoleOutputEnabled(), DisableConsoleOutput(), + * IsGUIOutputEnabled(), EnableGUIOutput() + */ + static void EnableConsoleOutput( bool = true ); + + /*! + * Disables console output for %Exception. + * + * \sa IsConsoleOutputEnabled(), EnableConsoleOutput(), + * IsGUIOutputEnabled(), EnableGUIOutput() + */ + static void DisableConsoleOutput( bool disable = true ) + { + EnableConsoleOutput( !disable ); + } + + /*! + * Returns true iff GUI output is enabled for %Exception. + * + * When GUI output is enabled, exception information is presented through + * message boxes and other modal, graphical interface elements. GUI + * exception output is always disabled by default. + * + * \sa IsConsoleOutputEnabled(), EnableConsoleOutput(), EnableGUIOutput() + */ + static bool IsGUIOutputEnabled(); + + /*! + * Enables GUI output for %Exception. + * + * \sa IsGUIOutputEnabled(), DisableGUIOutput(), IsConsoleOutputEnabled(), + * EnableConsoleOutput() + */ + static void EnableGUIOutput( bool = true ); + + /*! + * Disables GUI output for %Exception. + * + * \sa IsGUIOutputEnabled(), EnableGUIOutput(), IsConsoleOutputEnabled(), + * EnableConsoleOutput() + */ + static void DisableGUIOutput( bool disable = true ) + { + EnableGUIOutput( !disable ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Error + * \brief A simple exception with an associated error message. + * + * %Error is a general exception message very frequently used by PCL classes + * and functions. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS Error : public pcl::Exception +{ +public: + + /*! + * Constructs an %Error object with an empty error message. + */ + Error() = default; + + /*! + * Copy constructor. + */ + Error( const Error& ) = default; + + /*! + * Constructs an %Error object with the specified error \a message. + */ + Error( const String& message ) + : m_message( message ) + { + } + + /*! + * Returns descriptive information for this %Error object. The default + * implementation returns the message specified upon construction. A derived + * class can reimplement this function to provide additional information + * items such as file names, object identifiers, source code positions, date + * and time representations, etc. + */ + String Message() const override + { + return m_message; + } + + /*! + */ + String Caption() const override + { + return "Error"; + } + +protected: + + String m_message; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class FatalError + * \brief Errors that cause immediate program termination + * + * %FatalError indicates an error situation that cannot be resumed and requires + * immediate program termination. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS FatalError : public Error +{ +public: + + /*! + * Constructs a %FatalError object with an empty message. + */ + FatalError() = default; + + /*! + * Constructs a %FatalError object with the specified \a message. + */ + FatalError( const String& message ) + : Error( message ) + { + } + + /*! + * "Promote" any exception to have "fatal consequences". + */ + FatalError( const pcl::Exception& x ) + : Error( x.Message() ) + { + } + + /*! + * Copy constructor. + */ + FatalError( const pcl::FatalError& ) = default; + + /*! + */ + String Caption() const override + { + return "Fatal Error"; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class NotImplemented + * \brief An exception that indicates an unsupported feature + * + * Throw one of these when you have an object that can't do something. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS NotImplemented : public Error +{ +public: + + /*! + * Constructs a %NotImplemented instance. + * + * \param object The object that does not implement something + * + * \param notImplemented A description of what \a object does not + * implement. + */ + template + NotImplemented( const T& object, const String& notImplemented ) + : Error( String( IsoString( typeid( object ).name() ) +#ifdef __PCL_WINDOWS + .MBSToWCS() +#else + .UTF8ToUTF16() +#endif + ) + ": Not implemented: " + notImplemented ) + { + } + + /*! + * Copy constructor. + */ + NotImplemented( const NotImplemented& ) = default; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ParseError + * \brief Base class for exceptions thrown by parsing routines + * + * A %ParseError indicates an syntactic or semantic error found while + * interpreting some code or trying to translate some text into an object. + * + * For example, String and IsoString throw %ParseError exceptions to indicate + * syntax errors while converting strings to numbers. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS ParseError : public Error +{ +public: + + /*! + * Constructs an empty %ParseError object: no error message and no position + * information. + */ + ParseError() = default; + + /*! + * Copy constructor. + */ + ParseError( const ParseError& ) = default; + + /*! + * Constructs a %ParseError object. + * + * \param message The error message. HTML entities are not interpreted as + * ISO 8859-1 characters, and console tags are ignored, even if + * the exception is to be represented on a PixInsight console. + * HTML entities and console tags are always written literally. + * This limitation is necessary to ensure representativeness of + * source code fragments shown in exception messages. + * + * \param beingParsed The string being parsed, or an empty string if the + * error is not associated to a particular source code string. + * + * \param errorPosition The position >= 0 of the first offending character + * in the string \a beingParsed, or < 0 if no specific position + * can be associated with the error. + */ + ParseError( const String& message, const String& beingParsed = String(), int errorPosition = -1 ) + : Error( message ) + , m_beingParsed( beingParsed ) + , m_errorPosition( errorPosition ) + { + } + + /*! + */ + String Message() const override; + + /*! + */ + void Show() const override; + +protected: + + String m_beingParsed; + int m_errorPosition = -1; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SourceCodeError + * \brief Base class for exceptions thrown by source code interpreters + * + * A %SourceCodeError represents a syntax error thrown by a source code parser + * or interpreter, such as a scripting engine or an XML decoder. + * + * %SourceCodeError provides an error message string associated to a line + * number and a column number that locate the error in the source code text + * being processed. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS SourceCodeError : public Error +{ +public: + + /*! + * Constructs an empty %SourceCodeError object: no error message and no + * source code location information. + */ + SourceCodeError() = default; + + /*! + * Copy constructor. + */ + SourceCodeError( const SourceCodeError& ) = default; + + /*! + * Constructs a %SourceCodeError object. + * + * \param message The error message. HTML entities are not interpreted as + * ISO 8859-1 characters, and console tags are ignored, even if + * the exception is to be represented on a PixInsight console. + * HTML entities and console tags are always written literally. + * This limitation is necessary to ensure representativeness of + * source code fragments in exception messages. + * + * \param line The line number (starting from 1) corresponding to the + * position of this error in the source code text, or <= 0 if no + * specific source code line can be associated with this error. + * The default value is -1, meaning that no line number is + * specified by default. + * + * \param column The column number (starting from 1) corresponding to + * the position of this error in the source code text, or <= 0 + * if no specific source code column can be associated with this + * error. The default value is -1, meaning that no column number + * is specified by default. + */ + template + SourceCodeError( const String& message, T1 line = -1, T1 column = -1 ) + : Error( message ) + , m_lineNumber( Range( int( line ), -1, int_max ) ) + , m_columnNumber( Range( int( column ), -1, int_max ) ) + { + } + + /*! + * Returns the line number in the source code text being processed, + * corresponding to this exception. + * + * If a valid source code line can be associated with this exception, the + * returned value should be >= 1. Otherwise, if no text line can be + * determined for this exception, -1 is returned. + * + * \sa ColumnNumber() + */ + int LineNumber() const + { + return m_lineNumber; + } + + /*! + * Returns the column number in the source code text being processed, + * corresponding to this exception. + * + * If a valid source code column can be associated with this exception, the + * returned value should be >= 1. Otherwise, if no text column can be + * determined for this exception, -1 is returned. + * + * \sa LineNumber() + */ + int ColumnNumber() const + { + return m_columnNumber; + } + + /*! + * Sets the source code \a line number and \a column (optional) for this + * exception. + * + * Valid (meaningful) source code coordinates must be >= 1. When a value < 0 + * is specified, the corresponding coordinate is interpreted to be + * unavailable for the current exception. + * + * This member function is useful when nested sections of a source code + * block are being processed recursively; for example in XML decoders. + * + * \sa AddToPosition() + */ + template + void SetPosition( T1 line, T1 column = -1 ) + { + m_lineNumber = Range( int( line ), -1, int_max ); + m_columnNumber = Range( int( column ), -1, int_max ); + } + + /*! + * Adds the specified \a lines and \a columns (optional) increments to the + * source code coordinates for this exception. + * + * Valid (meaningful) source code coordinates must be >= 1. When a value + * <= 0 results from a call to this function, the corresponding coordinate + * is interpreted to be unavailable for the current exception. + * + * This member function is useful when nested sections of a source code + * block are being processed recursively; for example in XML decoders. + * + * \sa SetPosition() + */ + template + void AddToPosition( T1 lines, T1 columns = 0 ) + { + SetPosition( m_lineNumber+int( lines ), m_columnNumber+int( columns ) ); + } + + /*! + */ + String Message() const override; + + /*! + */ + void Show() const override; + +protected: + + int m_lineNumber = -1; + int m_columnNumber = -1; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class CaughtException + * \brief An exception that has already been handled + * + * %CaughtException is used to signal exceptions requiring no additional + * processing. %CaughtException is useful to terminate a process (by branching + * execution to a catch() block) without causing generation of further error + * messages. + * + * \ingroup standard_exception_classes + */ +class PCL_CLASS CaughtException : public pcl::Exception +{ +public: + + /*! + * Constructs a %CaughtException object. + */ + CaughtException() = default; + + /*! + * Copy constructor. + */ + CaughtException( const pcl::CaughtException& ) = default; +}; + +} // pcl + +// ---------------------------------------------------------------------------- + +/*! + * \def PCL_DECLARE_EXCEPTION_CLASS + * \brief A macro to implement simple exception classes derived from Exception + * + * \param className The identifier of the exception class. + * + * \param exceptionClass The name of the exception class, as presented in + * formatted representations. + * + * \param message The error message shown for this exception class. + * + * Use this macro to define and implement exceptions classes that show + * constant error or warning messages. + * + * In many cases using the %Error exception class is preferable to create new + * exception classes with this macro. + * + * \ingroup standard_exception_classes + */ +#define PCL_DECLARE_EXCEPTION_CLASS( className, exceptionClass, message ) \ + class PCL_CLASS className : public pcl::Exception \ + { \ + public: \ + className() = default; \ + className( const className& ) = default; \ + pcl::String ExceptionClass() const override \ + { \ + return exceptionClass; \ + } \ + pcl::String Message() const override \ + { \ + return message; \ + } \ + } + +// ---------------------------------------------------------------------------- + +namespace pcl +{ + +/*! + * \class pcl::ProcessAborted + * \brief An exception class signaling the interruption of a process + * + * %ProcessAborted is thrown by processes that have been aborted by the user. + * + * \ingroup standard_exception_classes + */ + +PCL_DECLARE_EXCEPTION_CLASS( ProcessAborted, "Process aborted", String() ); + +} // pcl + +#endif // __PCL_Exception_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Exception.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ExternalProcess.h b/3rdparty/include/pcl/ExternalProcess.h new file mode 100644 index 0000000..d1e4218 --- /dev/null +++ b/3rdparty/include/pcl/ExternalProcess.h @@ -0,0 +1,852 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ExternalProcess.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_ExternalProcess_h +#define __PCL_ExternalProcess_h + +/// \file pcl/ExternalProcess.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ExternalProcessError + * \brief External process error conditions. + * + * + * + * + * + * + * + * + *
ExternalProcessError::FailedToStart The external process failed to start.
ExternalProcessError::Crashed The external process crashed.
ExternalProcessError::TimedOut A wait operation timed out.
ExternalProcessError::ReadError An error occurred while trying to read data from a process' stdout or stderr streams.
ExternalProcessError::WriteError An error occurred while trying to write data to a process' stdin stream.
ExternalProcessError::UnknownError An unknown error occurred trying to execute or communicate with an external process.
+ */ +namespace ExternalProcessError +{ + enum value_type + { + FailedToStart, + Crashed, + TimedOut, + ReadError, + WriteError, + UnknownError + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class ExternalProcess + * \brief Execution of external programs. + * + * %ExternalProcess is essentially a PCL wrapper to Qt's QProcess class, which + * the PixInsight core application uses as the underlying implementation for + * management of external processes on the PixInsight platform. + * + * ### TODO: Write a detailed description for %ExternalProcess. + */ +class PCL_CLASS ExternalProcess : public UIObject +{ +public: + +#ifndef __PCL_WINDOWS + /*! + * The type of a platform-dependent Process Identifier (PID). + * + * On Linux/UNIX (Linux, FreeBSD and Mac OS X), a PID is a 64-bit integer. + * + * On Windows platforms, a PID is a pointer to a _PROCESS_INFORMATION + * structure (hence, on 64-bit Windows platforms a PID is also a 64-bit + * integer number). + */ + typedef int64 pid_type; +#else + typedef void* pid_type; +#endif + + /*! + * The type used to represent error conditions in external processes. + */ + typedef ExternalProcessError::value_type error_code; + + /*! + * Constructs an %ExternalProcess object. + */ + ExternalProcess(); + + /*! + * Destroys the client-side %ExternalProcess instance and dereferences the + * server-side object. If the server-side object becomes unreferenced, it + * will be garbage-collected and eventually destroyed by the core + * application. + */ + virtual ~ExternalProcess() + { + } + + /*! + * Copy constructor. Copy semantics are disabled for %ExternalProcess + * because this class represents unique server-side objects. + */ + ExternalProcess( const ExternalProcess& ) = delete; + + /*! + * Copy assignment. Copy semantics are disabled for %ExternalProcess because + * this class represents unique server-side objects. + */ + ExternalProcess& operator =( const ExternalProcess& ) = delete; + + /*! + * Move constructor. Move semantics are disabled for %ExternalProcess + * because of parent-child server-side object relations. + */ + ExternalProcess( ExternalProcess&& ) = delete; + + /*! + * Move assignment. Move semantics are disabled for %ExternalProcess because + * of parent-child server-side object relations. + */ + ExternalProcess& operator =( ExternalProcess&& ) = delete; + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since external processes are unique objects, calling this member function + * has no effect. + */ + void EnsureUnique() override + { + } + + /*! + * Returns a reference to a null %ExternalProcess instance. A null + * %ExternalProcess does not correspond to an existing external process in + * the PixInsight core application. + */ + static ExternalProcess& Null(); + + /*! + * Attempts to execute an external process. + * + * \param program Path to the executable file. + * + * \param arguments Optional list of command-line arguments that will be + * passed to the executable. Arguments containing spaces + * will be enclosed by quotes automatically. The default + * value is an empty list. + * + * If the specified \a program cannot be executed for some reason (for + * example, because the specified \a program does not exist, or because the + * calling process doesn't have enough privileges), this function throws an + * Error exception. + * + * This function implicitly opens the standard input, output and error I/O + * streams (stdin, stdout and stderr, respectively) of the running process. + * You can read from and write to the process using the Read() and Write() + * member functions of %ExternalProcess, respectively. You can also close + * the I/O streams using the CloseXX() member functions. + */ + void Start( const String& program, const StringList& arguments = StringList() ); + + /*! + * Waits for the process to start execution. + * + * \param ms Maximum waiting time in milliseconds. If a negative + * value is specified, this function will never time out. + * The default waiting time is 6000 ms (six seconds). + * + * This function suspends the calling task for at most the specified time, + * or forever if a negative time value is specified. Returns true if the + * process started before the specified time elapsed. Returns false if the + * process timed out. In the latter case, this function can be called again + * to continue waiting for the process to start. + * + * \warning When called from the root thread, this function can freeze the + * entire PixInsight graphical interface. For asynchronous external process + * execution, consider calling WaitForXX() functions from a separate thread. + * Be aware that if you specify a large waiting time or a negative value, + * this function may crash the calling thread. + */ + bool WaitForStarted( int ms = 6000 ); + + /*! + * Waits for the running process to finish execution. + * + * \param ms Maximum waiting time in milliseconds. If a negative + * value is specified, this function will never time out. + * The default waiting time is 6000 ms (six seconds). + * + * This function suspends the calling task for at most the specified time, + * or forever if a negative time value is specified. Returns true if the + * process finished its execution before the specified time elapsed. Returns + * false if the process timed out. In the latter case, this function can be + * called again to continue waiting for the process to finish. + * + * \warning When called from the root thread, this function can freeze the + * entire PixInsight graphical interface. For asynchronous external process + * execution, consider calling WaitForXX() functions from a separate thread. + * Be aware that if you specify a large waiting time or a negative value, + * this function may crash the calling thread. + */ + bool WaitForFinished( int ms = 6000 ); + + /*! + * Waits for the running process to send data. + * + * \param ms Maximum waiting time in milliseconds. If a negative + * value is specified, this function will never time out. + * The default waiting time is 6000 ms (six seconds). + * + * This function suspends the calling task for at most the specified time, + * or forever if a negative time value is specified. Returns true if the + * process sent some data through one of its output streams (standard output + * or standard error) before the specified time elapsed. Returns false if + * the process timed out. In the latter case, this function can be called + * again to continue waiting for the process to generate output data. When + * new output data is available from the process, it can be read immediately + * by calling one of the Read() member functions. + * + * \warning When called from the root thread, this function can freeze the + * entire PixInsight graphical interface. For asynchronous external process + * execution, consider calling WaitForXX() functions from a separate thread. + * Be aware that if you specify a large waiting time or a negative value, + * this function may crash the calling thread. + */ + bool WaitForDataAvailable( int ms = 6000 ); + + /*! + * Waits for the running process to receive data. + * + * \param ms Maximum waiting time in milliseconds. If a negative + * value is specified, this function will never time out. + * The default waiting time is 6000 ms (six seconds). + * + * This function suspends the calling task for at most the specified time, + * or forever if a negative time value is specified. Returns true if the + * process received the data sent previously through its input stream (the + * process' standard input) before the specified time elapsed. + * Returns false if the process timed out. In the latter case, this function + * can be called again to continue waiting for the process to fetch its + * input data. Data can be sent to a running process by calling one of the + * Write() member functions. + * + * \warning When called from the root thread, this function can freeze the + * entire PixInsight graphical interface. For asynchronous external process + * execution, consider calling WaitForXX() functions from a separate thread. + * Be aware that if you specify a large waiting time or a negative value, + * this function may crash the calling thread. + */ + bool WaitForDataWritten( int ms = 6000 ); + + /*! + * Attempts to terminate the running process. + * + * On Linux/UNIX platforms (Linux, FreeBSD and Mac OS X) a SIGTERM signal is + * sent to the process. + * + * On Windows, this function sends WM_CLOSE messages to all top-level + * windows owned by the process and to its main thread. Console Windows + * applications that don't have a message loop, or GUI Windows applications + * that don't process WM_CLOSE messages adequately, cannot be terminated by + * calling this member function. In these cases, the only way to terminate + * the running process is by calling Kill(). + * + * \note Note that there is no guarantee that the running process will + * terminate after calling this function. + */ + void Terminate(); + + /*! + * Forces termination of the running process. + * + * On Linux/UNIX platforms (Linux, FreeBSD and Mac OS X) a SIGKILL signal is + * sent to the process. + * + * On Windows, the TerminateProcess() API function is called to force + * process termination. + * + * \warning Unconditional termination of processes is always risky and + * should be avoided. For example, the running program wil not have an + * opportunity to close open files or save modified data. This function + * should only be used as a last resort to terminate a process. + */ + void Kill(); + + /*! + * Closes the standard input stream (stdin) of the running process. + * + * After calling this function, you no longer can write to the process using + * one of the Write() member functions (doing so will always throw an Error + * exception due to an I/O error). + * + * There are programs that require you to close the input stream explicitly. + * An example is the 'cat' UNIX utility. For example, if you enter the 'cat' + * command from a UNIX terminal, the program starts reading data from its + * stdin stream (which is the terminal in this example) until you press the + * "Ctrl+D" combination to close it. + * + * \note This function can only be called for a running process. If the + * process is not running, an Error exception is thrown. + */ + void CloseStandardInput(); + + /*! + * Closes the standard output stream (stdout) of the running process. + * + * After calling this function, you no longer can read data from the process + * through its stdin stream. Calling this function can be useful to save + * memory for processes that generate large amounts of output data, or if a + * running process starts producing loads of data that you don't want to + * process anymore. + * + * \note This function can only be called for a running process. If the + * process is not running, an Error exception is thrown. + */ + void CloseStandardOutput(); + + /*! + * Closes the standard error stream (stderr) of the running process. + * + * After calling this function, you no longer can read data from the process + * through its stderr stream. Calling this function can be useful to save + * memory for processes that generate large amounts of output data, or if a + * running process starts producing loads of data that you don't want to + * process anymore. + * + * \note This function can only be called for a running process. If the + * process is not running, an Error exception is thrown. + */ + void CloseStandardError(); + + /*! + * Redirects the standard output stream (stdout) of the process to the + * specified file. + * + * \param filePath Path to the file where the process will write its + * standard output data. + * + * \param append If true and the specified file already exists, its + * contents will be preserved and newly generated data + * will be appended. If false, the existing file will be + * overwritten and its previous contents will be lost. The + * default value is false (overwrite). + * + * Example: + * + * \code + * ExternalProcess p1, p2; + * p1.RedirectStandardOutput( "/tmp/foo.txt" ); + * p1.Start( "ls", StringList() << "-la" << "*.bar" ); + * \endcode + * + * The above code snippet is equivalent to this command: + * + * ls -la *.bar >/tmp/foo.txt + * + * \note This member function can only be called before running the process, + * i.e. before calling Start(). Otherwise an Error exception is thrown. + */ + void RedirectStandardOutput( const String& filePath, bool append = false ); + + /*! + * Redirects the standard output stream (stdout) of the process to the + * specified process. + * + * \param process Reference to a process where this process will write + * its standard output data. + * + * This function can be used to build a \e pipe between two programs. For + * example: + * + * \code + * ExternalProcess p1, p2; + * p1.RedirectStandardOutput( p2 ); + * p1.Start( "cat", StringList() << "*.bar" ); + * p2.Start( "grep", StringList() << "\'foo\'" ); + * \endcode + * + * would produce the same result as this command: + * + * cat *.bar |grep 'foo' + * + * \note This member function can only be called before running both + * processes, i.e. before calling Start() for this process \e and the + * specified \a process. Otherwise an Error exception is thrown. + */ + void RedirectStandardOutput( ExternalProcess& process ); + + /*! + * Redirects the standard error output stream (stderr) of the process to the + * specified file. + * + * \param filePath Path to the file where the process will write its + * standard error data. + * + * \param append If true and the specified file already exists, its + * contents will be preserved and newly generated data + * will be appended. If false, the existing file will be + * overwritten and its previous contents will be lost. The + * default value is false (overwrite). + * + * For more information on redirection of process output, see the + * RedirectStandardOutput() functions. + */ + void RedirectStandardError( const String& filePath, bool append = false ); + + /*! + * Redirects the standard input stream (stdin) of the process from the + * specified file. + * + * \param filePath Path to an existing file from which the process will + * read its standard input data. The current contents of + * the file won't be modified or affected in any way by + * calling this function. + * + * Example: + * + * \code + * ExternalProcess p; + * p.RedirectStandardInput( "/tmp/foo.txt" ); + * p.Start( "grep", StringList() << "\'bar\'" ); + * \endcode + * + * The above code snippet is equivalent to this command: + * + * grep 'bar' \ + * + * \note This member function can only be called before running the process, + * i.e. before calling Start(). Otherwise an Error exception is thrown. + */ + void RedirectStandardInput( const String& filePath ); + + /*! + * Returns the working directory (aka folder) of this process. + */ + String WorkingDirectory() const; + + /*! + * Sets the working directory for this process. + * + * \param dirPath Path to an existing directory, which will be the + * working directory of the process when it is started. + * + * \note This member function can only be called before running the process, + * i.e. before calling Start(). Otherwise an Error exception is thrown. + */ + void SetWorkingDirectory( const String& dirPath ); + + /*! + * Returns true iff the process is running. An %ExternalProcess object + * represents a running process briefly (usually) after calling its Start() + * member function, when the IsStarting() function returns false, and just + * before an OnStarted() event is generated. + */ + bool IsRunning() const; + + /*! + * Returns true iff the process is starting. An %ExternalProcess object + * enters the starting state after calling its Start() member function, but + * before the actual process is running. + */ + bool IsStarting() const; + + /*! + * Returns true iff the running process has crashed. + */ + bool HasCrashed() const; + + /*! + * Returns the platform-dependent Process Identifier (PID) of the running + * process. See the ExternalProcess::pid_type type definition for more + * information. + * + * If the process is not running this member function returns zero. + */ + pid_type PID() const; + + /*! + * Returns the exit code of the finished process. This is normally the + * return value of the process' main() function. + */ + int ExitCode() const; + + /*! + * Returns the number of bytes waiting to be read from this running process. + * If the process is not running, this member function returns zero. + * + * When this function returns a nonzero value, the available data can be + * read by calling one of the Read() member functions. + */ + size_type BytesAvailable() const; + + /*! + * Returns the number of bytes pending to be written to this running + * process. If the process is not running, this function returns zero. + * + * If this function returns a nonzero value, it is because one of the + * Write() member functions has been called previously for this process with + * nonempty data. + */ + size_type BytesToWrite() const; + + /*! + * Reads all the data available from the standard output stream (stdout) of + * this process, and returns them as a ByteArray object. + * + * If the process has not sent any new data through its stdout stream, or if + * the process is not running, an empty %ByteArray is returned. Note that + * after the reading operation the stdout stream is cleared, i.e. the data + * can only be read once. + */ + ByteArray StandardOutput(); + + /*! + * Reads all the data available from the standard error stream (stderr) of + * this process, and returns them as a ByteArray object. + * + * If the process has not sent any new data through its stderr stream, or if + * the process is not running, an empty %ByteArray is returned. Note that + * after the reading operation the stderr stream is cleared, i.e. the data + * can only be read once. + */ + ByteArray StandardError(); + + /*! + * Reads all the data available from the standard output and standard error + * streams (stdout and stderr, respectively) of this process, and returns + * them as a ByteArray object. + * + * If the process has not sent any new data through its output streams, or + * if the process is not running, an empty %ByteArray is returned. Note that + * after the reading operation, both stdout and stderr streams are cleared, + * i.e. the data can only be read once. + * + * \note In the returned %ByteArray, the data from both stdout and stderr + * streams will be mixed because they are gathered as they are generated. If + * you need the data from both streams separately, call the StandardOutput() + * and StandardError() member functions as appropriate. + */ + ByteArray Read(); + + /*! + * Writes the specified \a data to the standard input stream (stdin) of this + * process. + */ + void Write( const ByteArray& data ); + + /*! + * Writes the specified \a text to the standard input stream (stdin) of this + * process. The specified UTF-16 string will be treated as a sequence of + * bytes, and the terminating null character of the string (two bytes) will + * be excluded. + */ + void Write( const String& text ); + + /*! + * Writes the specified \a text to the standard input stream (stdin) of this + * process. The specified 8-bit string will be treated as a sequence of + * bytes, and the terminating null character of the string will be excluded. + */ + void Write( const IsoString& text ); + + /*! + * Writes the specified \a text to the standard input stream (stdin) of this + * process. The specified 8-bit string will be treated as a sequence of + * bytes, and the terminating null character of the string will be excluded. + */ + void Write( const char* text ); + + /*! + * Writes \a count contiguous bytes starting at the specified \a data + * location to the standard input stream (stdin) of this process. + */ + void Write( const void* data, size_type count ); + + /*! + * Returns the list of environment variables for this process. Environment + * variables are 'name=value' items that most programs can interpret to + * modify their functionality. + * + * If no environment has been set for this process, an empty list is + * returned. + */ + StringList Environment() const; + + /*! + * Sets the \a environment for this process. + * + * The environment is a list of 'name=value' elements, knwon as + * environment variables, that most programs can interpret to + * modify their functionality. + * + * If no environment is explicitly set for a process, it will inherit the + * environment of the calling process. + * + * \note This member function can only be called before running the process, + * i.e. before calling Start(). Otherwise an Error exception is thrown. + */ + void SetEnvironment( const StringList& environment ); + + /*! + * \defgroup external_process_event_handlers ExternalProcess Event Handlers + */ + + /*! + * Defines the prototype of a process event handler. + * + * A process event is generated when an %ExternalProcess instance changes + * its state, or generates a simple notification. + * + * \param sender The object that sends a process event. + * + * \ingroup external_process_event_handlers + */ + typedef void (Control::*process_event_handler)( ExternalProcess& sender ); + + /*! + * Defines the prototype of a process exit event handler. + * + * A process exit event is generated when an %ExternalProcess instance + * notifies that a running process has finished execution. + * + * \param sender The object that sends a process exit event. + * + * \param exitCode The process' exit code. Typically, this is the return + * value of the main() function in the process. + * + * \param exitOk True if the process finished execution normally. False + * if the process crashed. + * + * \ingroup external_process_event_handlers + */ + typedef void (Control::*process_exit_event_handler)( ExternalProcess& sender, int exitCode, bool exitOk ); + + /*! + * Defines the prototype of a process error event handler. + * + * A process error event is generated when an %ExternalProcess instance + * reports an error condition, such as an I/O error, a nonexistent + * executable file or lack of execution permissions. + * + * \param sender The object that sends a process error event. + * + * \param error Identifies the error condition that generated the event. + * + * \ingroup external_process_event_handlers + */ + typedef void (Control::*process_error_event_handler)( ExternalProcess& sender, error_code error ); + + /*! + * Sets the handler for process started events generated by this + * %ExternalProcess object. A process started event is generated when the + * process has just started and is running. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive process started events + * from this object. + * + * \ingroup external_process_event_handlers + */ + void OnStarted( process_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for process finished events generated by this + * %ExternalProcess object. A process finished event is generated when the + * running process has just finished execution. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive process finished events + * from this object. + * + * \ingroup external_process_event_handlers + */ + void OnFinished( process_exit_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for stdout data available events generated by + * this %ExternalProcess object. These events are generated when the running + * process sends data through its standard output stream, and the data is + * ready to be read. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive stdout data available + * events from this object. + * + * \ingroup external_process_event_handlers + */ + void OnStandardOutputDataAvailable( process_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for stderr data available events generated by + * this %ExternalProcess object. These events are generated when the running + * process sends data through its standard error stream, and the data is + * ready to be read. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive stderr data available + * events from this object. + * + * \ingroup external_process_event_handlers + */ + void OnStandardErrorDataAvailable( process_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for process error events generated by this + * %ExternalProcess object. A process error event is generated when the + * process reports an error condition. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive process error events + * from this object. + * + * \ingroup external_process_event_handlers + */ + void OnError( process_error_event_handler handler, Control& receiver ); + + /*! + * Executes a program as a child process and waits for it to terminate. + * + * \param program Path to an existing executable file. + * + * \param arguments Optional list of command-line arguments that will be + * passed to the executable. Arguments containing spaces + * will be enclosed by quotes automatically. The default + * value is an empty list. + * + * Returns the program's exit code. If the specified \a program cannot be + * executed, this member function throws an Error exception. + */ + static int ExecuteProgram( const String& program, const StringList& arguments = StringList() ); + + /*! + * Executes a program as an independent process. + * + * \param program Path to an existing executable file. + * + * \param arguments Optional list of command-line arguments that will be + * passed to the executable. Arguments containing spaces + * will be enclosed by quotes automatically. The default + * value is an empty list. + * + * \param workingDirectory Path to an existing directory, which will be the + * working directory of the process. The default value is + * an empty string. + * + * The program is executed as a standalone process, also known as a + * \e daemon on Linux/UNIX. It can continue running after the calling + * application terminates. + * + * Returns the platform-dependent process identifier (PID) of the running + * process. If the specified \a program cannot be executed, this member + * function throws an Error exception. + */ + static pid_type StartProgram( const String& program, + const StringList& arguments = StringList(), + const String& workingDirectory = String() ); + +private: + + struct EventHandlers + { + process_event_handler onStarted = nullptr; + process_exit_event_handler onFinished = nullptr; + process_event_handler onStandardOutputDataAvailable = nullptr; + process_event_handler onStandardErrorDataAvailable = nullptr; + process_error_event_handler onError = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + ExternalProcess( void* ); + void* CloneHandle() const override; + + friend class ExternalProcessPrivate; + friend class ExternalProcessEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ExternalProcess_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ExternalProcess.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FFT1D.h b/3rdparty/include/pcl/FFT1D.h new file mode 100644 index 0000000..c6f84bb --- /dev/null +++ b/3rdparty/include/pcl/FFT1D.h @@ -0,0 +1,838 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FFT1D.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_FFT1D_h +#define __PCL_FFT1D_h + +/// \file pcl/FFT1D.h + +/* + * The FFT routines used in this PCL version are based on the KISS FFT library + * by Mark Borgerding: http://sourceforge.net/projects/kissfft/ + * + * KISS FFT LICENSE INFORMATION + * ============================ + * + * Copyright (c) 2003-2013 Mark Borgerding + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the author nor the names of any contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) 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. + */ + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class FFT1DBase +{ +protected: + + static int OptimizedLength( int, fcomplex* ); + static int OptimizedLength( int, dcomplex* ); + static int OptimizedLength( int, float* ); + static int OptimizedLength( int, double* ); + + static void* Create( int, fcomplex* ); + static void* Create( int, dcomplex* ); + static void* Create( int, float* ); + static void* Create( int, double* ); + + static void* CreateInv( int, fcomplex* ); + static void* CreateInv( int, dcomplex* ); + static void* CreateInv( int, float* ); + static void* CreateInv( int, double* ); + + static void Destroy( void* ); + + static void Transform( void*, fcomplex*, const fcomplex* ); + static void Transform( void*, dcomplex*, const dcomplex* ); + static void Transform( void*, fcomplex*, const float* ); + static void Transform( void*, dcomplex*, const double* ); + static void Transform( void*, float*, const fcomplex* ); + static void Transform( void*, double*, const dcomplex* ); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup fft_1d Fast Fourier Transform Direction Specifiers + */ + +/*! + * \def PCL_FFT_FORWARD + * \brief Indicates a Fourier transform. + * \ingroup fft_1d + */ +#define PCL_FFT_FORWARD -1 + +/*! + * \def PCL_FFT_BACKWARD + * \brief Indicates an inverse Fourier transform. + * \ingroup fft_1d + */ +#define PCL_FFT_BACKWARD +1 + +// ---------------------------------------------------------------------------- + +/*! + * \class AbstractFFT + * \brief Abstract base class of all fast Fourier transform classes + * + * The %AbstractFFT template class implements basic properties and functions + * shared by all %FFT PCL classes. + * + * \sa GenericFFT, GenericRealFFT + */ +template +class PCL_CLASS AbstractFFT : public FFT1DBase +{ +public: + + /*! + * Represents a scalar in the context of this %FFT class. + */ + typedef T scalar; + + /*! + * Represents a complex number in the context of this %FFT class. + */ + typedef Complex complex; + + /*! + * Represents a vector of real numbers. + */ + typedef GenericVector vector; + + /*! + * Represents a vector of complex numbers. + */ + typedef GenericVector complex_vector; + + /*! + * Represents the container type used to store an out-of-place discrete + * Fourier transform. + */ + typedef complex_vector transform; + + /*! + * Constructs an %AbstractFFT object of the specified \a length. + */ + AbstractFFT( int length ) + : m_length( length ) + { + } + + /*! + * Virtual destructor. + * + * Destroys all internal control structures in this %AbstractFFT object, + * including the current discrete Fourier transform, if it exists. + */ + virtual ~AbstractFFT() + { + Release(); + } + + /*! + * Returns the transform length of this %AbstractFFT object. The length is + * the number of data items that can be transformed, and is specified in the + * constructors of all %FFT classes. + */ + int Length() const + { + return m_length; + } + + /*! + * Returns a duplicate of the current discrete Fourier transform as a vector + * of complex values. + * + * For complex FFTs, the returned vector has Length() elements. For real + * transforms, the returned vector has Length()/2 + 1 elements. + * + * If no %FFT has been performed on this object, this function returns an + * empty vector. + */ + transform DFT() const + { + return m_dft; + } + + /*! + * Returns a reference to the mutable current discrete Fourier transform in + * this object. The transform is a vector of complex values. + * + * For complex FFTs, the returned vector has Length() elements. For real + * transforms, the returned vector has Length()/2 + 1 elements. + * + * If no %FFT has been performed on this object, this function returns a + * reference to an empty vector. + */ + transform& DFT() + { + return m_dft; + } + + /*! + * Returns a pointer to the immutable first element in the current discrete + * Fourier transform. The transform is a set of consecutive complex numbers + * stored at the address returned by this member function. + * + * For complex FFTs, the transform is a sequence of Length() elements. For + * real transforms, there are only Length()/2 + 1 elements. + * + * If no %FFT has been performed on this object, this member function + * returns zero. + */ + const complex* operator *() const + { + return *m_dft; + } + + /*! + * Returns a pointer to the mutable first element in the current discrete + * Fourier transform. The transform is a set of consecutive complex numbers + * stored at the address returned by this member function. + * + * For complex FFTs, the transform is a sequence of Length() elements. For + * real transforms, there are only Length()/2 + 1 elements. + * + * If no %FFT has been performed on this object, this member function + * returns zero. + */ + complex* operator *() + { + return *m_dft; + } + + /*! + * Destroys all internal control structures in this %AbstractFFT object, + * including the current discrete Fourier transform, if it exists. + */ + virtual void Release() + { + if ( m_handle != nullptr ) + this->Destroy( m_handle ), m_handle = nullptr; + if ( m_handleInv != nullptr ) + this->Destroy( m_handleInv ), m_handleInv = nullptr; + m_dft = transform(); + } + +private: + + int m_length; + +protected: + + mutable void* m_handle = nullptr; // Opaque pointers to internal control structures + mutable void* m_handleInv = nullptr; + transform m_dft; // DFT of complex or real data +}; + +// ---------------------------------------------------------------------------- + +#define m_handle this->m_handle +#define m_handleInv this->m_handleInv +#define m_dft this->m_dft +#define m_length this->Length() + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericFFT + * \brief Generic fast Fourier transform of complex data + * + * The %GenericFFT template class performs forward and inverse, out-of-place + * fast Fourier transforms of complex data. + * + * For fast Fourier transforms of real-valued data, see the GenericRealFFT + * template class. + * + * \sa AbstractFFT, GenericRealFFT + */ +template +class PCL_CLASS GenericFFT : public AbstractFFT +{ +public: + + /*! + * Identifies the base class of this %FFT class. + */ + typedef AbstractFFT base; + + /*! + * Represents a scalar in the context of this %FFT class. + */ + typedef typename base::scalar scalar; + + /*! + * Represents a complex number in the context of this %FFT class. + */ + typedef typename base::complex complex; + + /*! + * Represents a vector of real numbers. + */ + typedef typename base::vector vector; + + /*! + * Represents a vector of complex numbers. + */ + typedef typename base::complex_vector complex_vector; + + /*! + * Represents the container type used to store an out-of-place discrete + * Fourier transform. + */ + typedef typename base::transform transform; + + /*! + * Constructs a %GenericFFT object of the specified length \a n. + * + * The current PCL implementation supports FFTs of arbitrary length, but the + * underlying routines have been optimized for performance when the length + * of the input vector can be factorized as follows: + * + * n = 2^n2 * 3^n3 * 4^n4 * 5^n5 + * + * where n2, n3, n4, and n5 are arbitrary positive integers. For best + * performance, you should call GenericFFT::OptimizedLength() to get the + * smallest optimal length for your data, then place them on an array of the + * obtained length, padded with zeros. + */ + GenericFFT( int n ) + : base( n ) + { + } + + /*! + * Virtual destructor. + */ + virtual ~GenericFFT() + { + } + + /*! + * Fast Fourier transform. Performs the %FFT of the specified vector of + * complex values. + * + * The argument \a x must be the starting address of a contiguous block of + * at least Length() elements. + * + * Returns a reference to this object. + */ + GenericFFT& operator <<( const complex* x ) + { + if ( m_dft.IsEmpty() ) + m_dft = transform( m_length ); + if ( m_handle == nullptr ) + m_handle = this->Create( m_length, static_cast( nullptr ) ); + this->Transform( m_handle, *m_dft, x ); + return *this; + } + + /*! + * Inverse fast Fourier transform. Performs the inverse %FFT and stores the + * result in the specified vector of complex values. + * + * The argument \a y must be the starting address of a contiguous block of + * at least Length() elements. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericFFT& operator >>( complex* y ) const + { + if ( m_dft.IsEmpty() ) + throw Error( "Invalid out-of-place inverse FFT: No FFT has been performed." ); + if ( m_handleInv == nullptr ) + m_handleInv = this->CreateInv( m_length, static_cast( nullptr ) ); + this->Transform( m_handleInv, y, *m_dft ); + return *this; + } + + /*! + * Fast Fourier transform. Performs the %FFT of a vector of complex values. + * + * The specified vector \a x must have at least Length() elements. Otherwise + * an Error exception will be thrown. + * + * Returns a reference to this object. + */ + GenericFFT& operator <<( const complex_vector& x ) + { + PCL_PRECONDITION( x.Length() >= m_length ) + if ( x.Length() < m_length ) + throw Error( "Invalid FFT input vector length." ); + return operator <<( *x ); + } + + /*! + * Inverse fast Fourier transform. Performs the inverse %FFT and stores the + * result in a vector of complex values. + * + * The specified vector \a y must have at least Length() elements. Otherwise + * an Error exception will be thrown. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericFFT& operator >>( complex_vector& y ) const + { + if ( y.Length() < m_length ) + throw Error( "Invalid FFT output vector length." ); + return operator >>( *y ); + } + + /*! + * Performs the forward or inverse %FFT of an input vector of complex + * values, and stores the result in a caller-supplied output vector. + * + * \param[in] x Input vector. Must be the starting address of a contiguous + * sequence of at least Length() complex numbers. + * + * \param[out] y Output vector, where the result of the transform will be + * stored. Must be the starting address of a contiguous + * sequence of at least Length() complex numbers. + * + * \param dir Indicates the direction of the Fourier transform:\n + * \n + * + * + * + *
PCL_FFT_FORWARD The direct FFT is calculated.
PCL_FFT_BACKWARD The inverse FFT is calculated.
\n + * \n + * This parameter is optional; the default value is + * PCL_FFT_FORWARD. + * + * The specified arguments \a x and \a y must be the starting addresses of + * two different, non-overlapping contiguous blocks of at least Length() + * elements. + * + * This member function does not change the current Fourier transform in + * this object, if it exists. + * + * Returns a reference to this object. + */ + GenericFFT& operator()( complex* y, const complex* x, int dir = PCL_FFT_FORWARD ) const + { + if ( dir == PCL_FFT_BACKWARD ) + { + if ( m_handleInv == nullptr ) + m_handleInv = this->CreateInv( m_length, static_cast( nullptr ) ); + this->Transform( m_handleInv, y, x ); + } + else + { + if ( m_handle == nullptr ) + m_handle = this->Create( m_length, static_cast( nullptr ) ); + this->Transform( m_handle, y, x ); + } + return const_cast( *this ); + } + + /*! + * Returns the optimized complex %FFT length larger than or equal to + * a given length \a n. The returned length will be optimal to perform a + * %FFT of complex data with the current PCL implementation. The optimized + * length can be used as the argument to the constructor of any %FFT class for + * complex data transforms. + */ + static int OptimizedLength( int n ) + { + return FFT1DBase::OptimizedLength( n, static_cast( nullptr ) ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericRealFFT + * \brief Generic fast Fourier transform of real data + * + * The %GenericRealFFT template class performs forward and inverse, + * out-of-place fast Fourier transforms of real-valued data. For real data in + * the time domain, this class performs nearly twice as fast as Fourier + * transform classes for complex data. + * + * For fast Fourier transforms of complex-valued data, see the GenericFFT + * template class. + * + * \sa AbstractFFT, GenericFFT + */ +template +class PCL_CLASS GenericRealFFT : public AbstractFFT +{ +public: + + /*! + * Identifies the base class of this %FFT class. + */ + typedef AbstractFFT base; + + /*! + * Represents a scalar in the context of this %FFT class. + */ + typedef typename base::scalar scalar; + + /*! + * Represents a complex number in the context of this %FFT class. + */ + typedef typename base::complex complex; + + /*! + * Represents a vector of real numbers. + */ + typedef typename base::vector vector; + + /*! + * Represents a vector of complex numbers. + */ + typedef typename base::complex_vector complex_vector; + + /*! + * Represents the container type used to store an out-of-place discrete + * Fourier transform. + */ + typedef typename base::transform transform; + + /*! + * Constructs a %GenericRealFFT object of the specified \a length. + * + * The current PCL implementation supports FFTs for real data of any even + * length, but the underlying routines have been optimized for performance + * when the length of the input vector can be factorized as follows: + * + * n = 2^n2 * 3^n3 * 4^n4 * 5^n5 + * + * where n2, n3, n4, and n5 are arbitrary positive integers, and n is an + * even integer. For best performance, you should call + * GenericRealFFT::OptimizedLength() to get the smallest optimal length for + * your real data, then place them on an array of the obtained length, + * padded with zeros. + * + * \note We stress the fact that the specified \a length must be an \e even + * integer. + */ + GenericRealFFT( int length ) + : base( length ) + { + PCL_PRECONDITION( (length & 1) == 0 ) + } + + /*! + * Virtual destructor. + */ + virtual ~GenericRealFFT() + { + } + + /*! + * Fast Fourier transform. Performs the %FFT of the specified vector of + * real numbers. + * + * The argument \a x must be the starting address of a contiguous block of + * at least Length() scalars. + * + * Returns a reference to this object. + */ + GenericRealFFT& operator <<( const scalar* x ) + { + if ( m_dft.IsEmpty() ) + m_dft = transform( m_length/2 + 1 ); + if ( m_handle == nullptr ) + m_handle = this->Create( m_length, static_cast( nullptr ) ); + this->Transform( m_handle, *m_dft, x ); + return *this; + } + + /*! + * Inverse fast Fourier transform. Performs the inverse %FFT and stores the + * result in the specified vector of real values. + * + * The value of \a y must be the starting address of a contiguous block of + * at least Length() elements. + * + * If no %FFT has been performed for this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericRealFFT& operator >>( scalar* y ) const + { + if ( m_dft.IsEmpty() ) + throw Error( "Invalid out-of-place inverse FFT: No FFT has been performed." ); + if ( m_handleInv == nullptr ) + m_handleInv = this->CreateInv( m_length, static_cast( nullptr ) ); + this->Transform( m_handleInv, y, *m_dft ); + return *this; + } + + /*! + * Fast Fourier transform. Performs the %FFT of a vector of real numbers. + * + * The specified vector \a x must have at least Length() elements. Otherwise + * an Error exception will be thrown. + * + * Returns a reference to this object. + */ + GenericRealFFT& operator <<( const vector& x ) + { + if ( x.Length() < m_length ) + throw Error( "Invalid FFT input vector length." ); + return operator <<( *x ); + } + + /*! + * Inverse fast Fourier transform. Performs the inverse %FFT and stores the + * result in the specified vector of real values. + * + * The specified vector \a y must have at least Length() elements. Otherwise + * an Error exception will be thrown. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericRealFFT& operator >>( vector& y ) const + { + if ( y.Length() < m_length ) + throw Error( "Invalid FFT output vector length." ); + return operator >>( *y ); + } + + /*! + * Performs the %FFT of an input vector of real numbers, and stores the + * result in a caller-supplied output vector of complex values. + * + * \param[in] x Input vector. Must be the starting address of a contiguous + * sequence of at least Length() scalars. + * + * \param[out] y Output vector, where the result of the transform will be + * stored. Must be the starting address of a contiguous + * sequence of at least Length()/2 + 1 complex numbers. + * + * The specified arguments \a x and \a y must be the starting addresses of + * two different, non-overlapping contiguous blocks of data. The output + * transform will be a sequence of Length()/2 + 1 complex numbers. + * + * This member function does not change the current Fourier transform in + * this object, if any. + * + * Returns a reference to this object. + */ + GenericRealFFT& operator()( complex* y, const scalar* x ) const + { + if ( m_handle == nullptr ) + m_handle = this->Create( m_length, static_cast( nullptr ) ); + this->Transform( m_handle, y, x ); + return const_cast( *this ); + } + + /*! + * Performs the inverse %FFT of an input vector of complex numbers, and + * stores the result in a caller-supplied output vector of real values. + * + * \param[in] x Input vector. Must be the starting address of a contiguous + * sequence of at least Length()/2 + 1 complex numbers, + * corresponding to a discrete real Fourier transform of + * length Length(). + * + * \param[out] y Output vector, where the result of the inverse transform + * will be stored. Must be the starting address of a + * contiguous sequence of at least Length() real numbers. + * + * The specified arguments \a x and \a y must be the starting addresses of + * two different, non-overlapping contiguous blocks of data. The input + * transform must be a sequence of Length()/2 + 1 complex numbers. The + * output inverse transform will be a sequence of Length() real numbers. + * + * This member function does not change the current Fourier transform in + * this object, if any. + * + * Returns a reference to this object. + */ + GenericRealFFT& operator()( scalar* y, const complex* x ) const + { + if ( m_handleInv == nullptr ) + m_handleInv = this->CreateInv( m_length, static_cast( nullptr ) ); + this->Transform( m_handleInv, y, x ); + return const_cast( *this ); + } + + /*! + * Returns the optimized real %FFT length larger than or equal to a + * given length \a n. The returned length will be optimal to perform a %FFT + * of real data with the current PCL implementation. The optimized length + * can be used as the argument to the constructor of any %FFT class for + * real data transforms. + */ + static int OptimizedLength( int n ) + { + return FFT1DBase::OptimizedLength( n, static_cast( nullptr ) ); + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_handle +#undef m_handleInv +#undef m_dft +#undef m_length + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_FFT1D_INSTANTIATE + +/*! + * \defgroup fft_types_1d Fast Fourier Transforms + */ + +/*! + * \class pcl::FFFT + * \ingroup fft_types_1d + * \brief Fast Fourier transform of 32-bit floating point complex data. + * + * %FFFT is a template instantiation of GenericFFT for the \c float type. + */ +typedef GenericFFT FFFT; + +/*! + * \class pcl::DFFT + * \ingroup fft_types_1d + * \brief Fast Fourier transform of 64-bit floating point complex data. + * + * %DFFT is a template instantiation of GenericFFT for the \c double type. + */ +typedef GenericFFT DFFT; + +/*! + * \class pcl::FRealFFT + * \ingroup fft_types_1d + * \brief Fast Fourier transform of 32-bit floating point real data. + * + * %FRealFFT is a template instantiation of GenericRealFFT for \c float. + */ +typedef GenericRealFFT FRealFFT; + +/*! + * \class pcl::DRealFFT + * \ingroup fft_types_1d + * \brief Fast Fourier transform of 64-bit floating point real data. + * + * %DRealFFT is a template instantiation of GenericRealFFT for \c double. + */ +typedef GenericRealFFT DRealFFT; + +/*! + * \class pcl::FFT + * \ingroup fft_types_1d + * \brief Fast Fourier transform of 32-bit floating point complex data. + * + * %FFT is an alias for FFFT. It is a template instantiation of GenericFFT for + * the \c float type. + */ +typedef FFFT FFT; + +/*! + * \class pcl::RealFFT + * \ingroup fft_types_1d + * \brief Fast Fourier transform of 32-bit floating point real data. + * + * %RealFFT is an alias for FRealFFT. It is a template instantiation of + * GenericRealFFT for the \c float type. + */ +typedef FRealFFT RealFFT; + +#endif // __PCL_NO_FFT1D_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FFT1D_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FFT1D.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FFT2D.h b/3rdparty/include/pcl/FFT2D.h new file mode 100644 index 0000000..abe35fa --- /dev/null +++ b/3rdparty/include/pcl/FFT2D.h @@ -0,0 +1,869 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FFT2D.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_FFT2D_h +#define __PCL_FFT2D_h + +/// \file pcl/FFT2D.h + +/* + * The FFT routines used in this PCL version are based on the KISS FFT library + * by Mark Borgerding: http://sourceforge.net/projects/kissfft/ + * + * KISS FFT LICENSE INFORMATION + * ============================ + * + * Copyright (c) 2003-2009 Mark Borgerding + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the author nor the names of any contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) 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. + */ + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class FFT2DBase +{ +protected: + + static void Transform( int, int, fcomplex*, const fcomplex*, int, StatusMonitor*, bool, int ); + static void Transform( int, int, dcomplex*, const dcomplex*, int, StatusMonitor*, bool, int ); + static void Transform( int, int, fcomplex*, const float*, StatusMonitor*, bool, int ); + static void Transform( int, int, dcomplex*, const double*, StatusMonitor*, bool, int ); + static void Transform( int, int, float*, const fcomplex*, StatusMonitor*, bool, int ); + static void Transform( int, int, double*, const dcomplex*, StatusMonitor*, bool, int ); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class AbstractFFT2D + * \brief Abstract base class of all two-dimensional fast Fourier transform classes + * + * The %AbstractFFT2D template class implements basic properties and functions + * shared by all 2-D %FFT PCL classes. + * + * \sa GenericFFT2D, GenericRealFFT2D + */ +template +class PCL_CLASS AbstractFFT2D : public FFT2DBase, public ParallelProcess +{ +public: + + /*! + * Represents a scalar in the context of this %FFT class. + */ + typedef T scalar; + + /*! + * Represents a complex number in the context of this %FFT class. + */ + typedef Complex complex; + + /*! + * Represents a vector of real numbers. + */ + typedef GenericVector vector; + + /*! + * Represents a vector of complex numbers. + */ + typedef GenericVector complex_vector; + + /*! + * Represents a real matrix. + */ + typedef GenericMatrix matrix; + + /*! + * Represents a complex matrix. + */ + typedef GenericMatrix complex_matrix; + + /*! + * Represents a discrete Fourier transform matrix. + */ + typedef complex_matrix transform; + + /*! + * Constructs an %AbstractFFT2D object of the specified dimensions + * \a rows and \a cols. + */ + AbstractFFT2D( int rows, int cols ) + : m_rows( rows ) + , m_cols( cols ) + { + } + + /*! + * Constructs an %AbstractFFT2D object of the specified dimensions + * \a rows and \a cols, using the specified status \a monitor object. + * + * On each transform performed with this object, the status monitor will be + * incremented by the sum of transform dimensions: \a rows + \a cols. + */ + AbstractFFT2D( int rows, int cols, StatusMonitor& monitor ) + : m_rows( rows ) + , m_cols( cols ) + , m_monitor( &monitor ) + { + } + + /*! + * Virtual destructor. + * + * Destroys all internal control structures in this %AbstractFFT2D object, + * including the current discrete Fourier transform, if exists. + */ + virtual ~AbstractFFT2D() + { + Release(); + } + + /*! + * Returns the number of rows in the 2-D transform of this %AbstractFFT2D + * object. Transform dimensions are specified in the constructors of all 2-D + * %FFT classes. + */ + int Rows() const + { + return m_rows; + } + + /*! + * Returns the number of columns in the 2-D transform of this %AbstractFFT2D + * object. Transform dimensions are specified in the constructors of all 2-D + * %FFT classes. + */ + int Cols() const + { + return m_cols; + } + + /*! + * Returns the total number of matrix elements in the 2-D data set of this + * %AbstractFFT2D object, or Rows() multiplied by Cols(). The dimensions are + * specified in the constructors of all 2-D %FFT classes. + */ + int NumberOfElements() const + { + return m_rows*m_cols; + } + + /*! + * Returns a duplicate of the current discrete Fourier transform as a matrix + * of complex values. + * + * For complex data transforms, the returned matrix has Rows()*Cols() + * elements. For real data, the returned matrix has Rows()*(Cols()/2 + 1) + * elements. + * + * If no %FFT has been performed on this object, this function returns an + * empty matrix. + */ + transform DFT() const + { + return m_dft; + } + + /*! + * Returns a non-const reference to the current discrete Fourier transform + * in this object. The transform is a matrix of complex values. + * + * For complex data transforms, the returned matrix has Rows()*Cols() + * elements. For real data, the returned matrix has Rows()*(Cols()/2 + 1) + * elements. + * + * If no %FFT has been performed on this object, this function returns a + * reference to an empty matrix. + */ + transform& DFT() + { + return m_dft; + } + + /*! + * Destroys all internal control structures in this %FFT object, including + * the current Fourier transform, if exists. + */ + virtual void Release() + { + m_dft = transform(); + } + +private: + + // Transform dimensions + int m_rows; + int m_cols; + +protected: + + transform m_dft; // DFT of complex or real data + StatusMonitor* m_monitor = nullptr; +}; + +// ---------------------------------------------------------------------------- + +#define m_dft this->m_dft +#define m_rows this->Rows() +#define m_cols this->Cols() +#define m_monitor this->m_monitor +#define m_parallel this->m_parallel +#define m_maxProcessors this->m_maxProcessors + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericFFT2D + * \brief Generic two-dimensional fast Fourier transform of complex data + * + * The %GenericFFT2D template class performs two-dimensional forward and + * inverse, out-of-place fast Fourier transforms of complex data. + * + * For fast Fourier transforms of 2-D real-valued data, see the + * GenericRealFFT2D template class. + * + * \sa AbstractFFT2D, GenericRealFFT2D + */ +template +class PCL_CLASS GenericFFT2D : public AbstractFFT2D +{ +public: + + /*! + * Identifies the base class of this %FFT class. + */ + typedef AbstractFFT2D base; + + /*! + * Represents a scalar in the context of this %FFT class. + */ + typedef typename base::scalar scalar; + + /*! + * Represents a complex number in the context of this %FFT class. + */ + typedef typename base::complex complex; + + /*! + * Represents a vector of real numbers. + */ + typedef typename base::vector vector; + + /*! + * Represents a vector of complex numbers. + */ + typedef typename base::complex_vector complex_vector; + + /*! + * Represents a real matrix. + */ + typedef typename base::matrix matrix; + + /*! + * Represents a complex matrix. + */ + typedef typename base::complex_matrix complex_matrix; + + /*! + * Represents a discrete Fourier transform matrix. + */ + typedef typename base::transform transform; + + /*! + * Constructs a %GenericFFT2D object of the specified dimensions \a rows and + * \a cols. + * + * The current PCL implementation supports FFTs of arbitrary length, but the + * underlying routines have been optimized for performance when the length + * of the input vector can be factorized as follows: + * + * n = 2^n2 * 3^n3 * 4^n4 * 5^n5 + * + * where n2, n3, n4, and n5 are arbitrary positive integers. For best + * performance, you should call GenericFFT2D::OptimizedLength() to get the + * smallest optimal dimensions for your data, then place them on a matrix of + * the obtained dimensions, padded with zeros. + */ + GenericFFT2D( int rows, int cols ) + : base( rows, cols ) + { + } + + /*! + * Constructs a %GenericFFT2D object of the specified dimensions \a rows and + * \a cols, using the specified status monitoring object \a status. + * + * On each transform performed with this object, the status m_monitor will be + * incremented by the sum of transform dimensions: \a rows + \a cols. + * + * See the GenericFFT2D( int, int ) constructor for more information. + */ + GenericFFT2D( int rows, int cols, StatusMonitor& status ) + : base( rows, cols, status ) + { + } + + /*! + * Virtual destructor. + */ + virtual ~GenericFFT2D() + { + } + + /*! + * Fast Fourier transform. Performs the two-dimensional %FFT of the + * specified matrix of complex values. + * + * The argument \a x must be the starting address of a contiguous block of + * at least NumberOfElements() elements, stored in row order: all elements + * of the first matrix row followed by all elements of the second row, and + * so on. + * + * Returns a reference to this object. + */ + GenericFFT2D& operator <<( const complex* x ) + { + if ( m_dft.IsEmpty() ) + m_dft = transform( m_rows, m_cols ); + this->Transform( m_rows, m_cols, *m_dft, x, PCL_FFT_FORWARD, m_monitor, m_parallel, m_maxProcessors ); + return *this; + } + + /*! + * Inverse fast Fourier transform. Performs the two-dimensional inverse %FFT + * and stores the result in the specified matrix of complex values. + * + * The argument \a y must be the starting address of a contiguous block of + * at least NumberOfElements() elements. The result matrix will be stored in + * row order: all elements of the first matrix row followed by all elements + * of the second row, and so on. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericFFT2D& operator >>( complex* y ) const + { + if ( m_dft.IsEmpty() ) + throw Error( "Invalid out-of-place inverse FFT: No FFT has been performed." ); + this->Transform( m_rows, m_cols, y, *m_dft, PCL_FFT_BACKWARD, m_monitor, m_parallel, m_maxProcessors ); + return *this; + } + + /*! + * Fast Fourier transform. Performs the two-dimensional %FFT of a matrix of + * complex values. + * + * The specified matrix \a x must have Rows() and Cols() dimensions. + * Otherwise an Error exception will be thrown. + * + * Returns a reference to this object. + */ + GenericFFT2D& operator <<( const complex_matrix& x ) + { + PCL_PRECONDITION( x.Rows() == m_rows ) + PCL_PRECONDITION( x.Cols() == m_cols ) + if ( x.Rows() != m_rows || x.Cols() != m_cols ) + throw Error( "Invalid FFT input matrix dimensions." ); + return operator <<( *x ); + } + + /*! + * Inverse fast Fourier transform. Performs the two-dimensional inverse %FFT + * and stores the result in a matrix of complex values. + * + * The specified matrix \a y must have Rows() and Cols() dimensions. + * Otherwise an Error exception will be thrown. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericFFT2D& operator >>( complex_matrix& y ) const + { + PCL_PRECONDITION( y.Rows() == m_rows ) + PCL_PRECONDITION( y.Cols() == m_cols ) + if ( y.Rows() != m_rows || y.Cols() != m_cols ) + throw Error( "Invalid FFT output matrix dimensions." ); + return operator >>( *y ); + } + + /*! + * Performs the forward or inverse two-dimensional %FFT of an input matrix + * of complex values, and stores the result in a caller-supplied output + * matrix. + * + * \param[in] x Input matrix. Must be the starting address of a contiguous + * sequence of at least NumberOfElements() complex numbers, + * stored in row order: all elements of the first row + * followed by all elements of the second row, and so on. + * + * \param[out] y Output matrix, where the result of the transform will be + * stored. Must be the starting address of a contiguous + * sequence of at least NumberOfElements() complex numbers. + * The result will be stored in row order: all elements of + * the first row followed by all elements of the second row, + * and so on. + * + * \param dir Indicates the direction of the Fourier transform:\n + * \n + * + * + * + *
PCL_FFT_FORWARD The FFT is calculated.
PCL_FFT_BACKWARD The inverse FFT is calculated.
\n + * \n + * This parameter is optional; the default value is + * PCL_FFT_FORWARD. + * + * This member function does not change the current Fourier transform in + * this object, if it exists. + * + * Returns a reference to this object. + */ + GenericFFT2D& operator ()( complex* y, const complex* x, int dir = PCL_FFT_FORWARD ) const + { + this->Transform( m_rows, m_cols, y, x, dir, m_monitor, m_parallel, m_maxProcessors ); + return const_cast( *this ); + } + + /*! + * Returns the optimized complex %FFT length larger than or equal to + * a given length \a n. The returned length will be optimal to perform a + * %FFT of complex data with the current PCL implementation. The optimized + * length can be used as the \a rows or \a cols argument to the constructor + * of any two-dimensional %FFT class for complex data transforms. + */ + static int OptimizedLength( int n ) + { + return GenericFFT::OptimizedLength( n ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericRealFFT2D + * \brief Generic two-dimensional fast Fourier transform of real data + * + * The %GenericRealFFT2D template class performs forward and inverse, + * out-of-place fast two-dimensional Fourier transforms of real-valued data. + * For real data in the time domain, this class performs nearly twice as fast + * as Fourier transform classes for complex data. + * + * For two-dimensional fast Fourier transforms of complex-valued data, see the + * GenericFFT2D template class. + * + * \sa AbstractFFT2D, GenericFFT2D + */ +template +class PCL_CLASS GenericRealFFT2D : public AbstractFFT2D +{ +public: + + /*! + * Identifies the base class of this %FFT class. + */ + typedef AbstractFFT2D base; + + /*! + * Represents a scalar in the context of this %FFT class. + */ + typedef typename base::scalar scalar; + + /*! + * Represents a complex number in the context of this %FFT class. + */ + typedef typename base::complex complex; + + /*! + * Represents a vector of real numbers. + */ + typedef typename base::vector vector; + + /*! + * Represents a vector of complex numbers. + */ + typedef typename base::complex_vector complex_vector; + + /*! + * Represents a real matrix. + */ + typedef typename base::matrix matrix; + + /*! + * Represents a complex matrix. + */ + typedef typename base::complex_matrix complex_matrix; + + /*! + * Represents a discrete Fourier transform matrix. + */ + typedef typename base::transform transform; + + /*! + * Constructs a %GenericRealFFT2D object of the specified dimensions \a rows + * and \a cols. + * + * The current PCL implementation supports FFTs for real data of any even + * length, but the underlying routines have been optimized for performance + * when the length of the input vector can be factorized as follows: + * + * n = 2^n2 * 3^n3 * 4^n4 * 5^n5 + * + * where n2, n3, n4, and n5 are arbitrary positive integers, and n is an + * even integer. For best performance, you should call + * GenericRealFFT2D::OptimizedLength() to get the smallest optimal + * dimensions for your real-valued data, then place them on a matrix of the + * obtained dimensions, padded with zeros. + * + * \note We stress the fact that the specified dimensions \a rows and + * \a cols must be \e even integer numbers. + */ + GenericRealFFT2D( int rows, int cols ) + : base( rows, cols ) + { + } + + /*! + * Constructs a %GenericRealFFT2D object of the specified dimensions \a rows + * and \a cols, using the specified status monitoring object \a status. + * + * On each transform performed with this object, the status m_monitor will be + * incremented by the sum of transform dimensions: \a rows + \a cols. + * + * See the GenericRealFFT2D( int, int ) constructor for more information. + */ + GenericRealFFT2D( int rows, int cols, StatusMonitor& status ) + : base( rows, cols, status ) + { + } + + /*! + * Virtual destructor. + */ + virtual ~GenericRealFFT2D() + { + } + + /*! + * Fast Fourier transform. Performs the two-dimensional %FFT of the + * specified matrix of real values. + * + * The argument \a x must be the starting address of a contiguous block of + * at least NumberOfElements() elements, stored in row order: all elements + * of the first matrix row followed by all elements of the second row, and + * so on. + * + * Returns a reference to this object. + */ + GenericRealFFT2D& operator <<( const scalar* x ) + { + if ( m_dft.IsEmpty() ) + m_dft = transform( m_rows, m_cols/2 + 1 ); + this->Transform( m_rows, m_cols, *m_dft, x, m_monitor, m_parallel, m_maxProcessors ); + return *this; + } + + /*! + * Inverse fast Fourier transform. Performs the two-dimensional inverse %FFT + * and stores the result in the specified matrix of real values. + * + * The argument \a y must be the starting address of a contiguous block of + * at least NumberOfElements() elements. The result matrix will be stored in + * row order: all elements of the first matrix row followed by all elements + * of the second row, and so on. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericRealFFT2D& operator >>( scalar* y ) const + { + if ( m_dft.IsEmpty() ) + throw Error( "Invalid out-of-place inverse FFT: No FFT has been performed." ); + this->Transform( m_rows, m_cols, y, *m_dft, m_monitor, m_parallel, m_maxProcessors ); + return *this; + } + + /*! + * Fast Fourier transform. Performs the two-dimensional %FFT of a matrix of + * real numbers. + * + * The specified matrix \a x must have Rows() and Cols() dimensions. + * Otherwise an Error exception will be thrown. + * + * Returns a reference to this object. + */ + GenericRealFFT2D& operator <<( const matrix& x ) + { + PCL_PRECONDITION( x.Rows() == m_rows ) + PCL_PRECONDITION( x.Cols() == m_cols ) + if ( x.Rows() != m_rows || x.Cols() != m_cols ) + throw Error( "Invalid FFT input matrix dimensions." ); + return operator <<( *x ); + } + + /*! + * Inverse fast Fourier transform. Performs the two-dimensional inverse %FFT + * and stores the result in a matrix of real numbers. + * + * The specified matrix \a y must have Rows() and Cols() dimensions. + * Otherwise an Error exception will be thrown. + * + * If no %FFT has been performed on this object (by a previous call to + * operator <<()), this member function throws an Error exception. + * + * Returns a reference to this object. + */ + GenericRealFFT2D& operator >>( matrix& y ) const + { + PCL_PRECONDITION( y.Rows() == m_rows ) + PCL_PRECONDITION( y.Cols() == m_cols ) + if ( y.Rows() != m_rows || y.Cols() != m_cols ) + throw Error( "Invalid FFT output matrix dimensions." ); + return operator >>( *y ); + } + + /*! + * Performs the two-dimensional %FFT of an input matrix of real numbers, and + * stores the result in an output matrix of complex numbers. + * + * \param[in] x Input matrix. Must be the starting address of a contiguous + * sequence of at least NumberOfElements() real numbers, + * stored in row order: all elements of the first row + * followed by all elements of the second row, and so on. + * + * \param[out] y Output matrix, where the result of the transform will be + * stored. Must be the starting address of a contiguous + * sequence of at least Rows()*(Cols()/2 + 1) complex + * numbers. The result will be stored in row order: all + * elements of the first row followed by all elements of the + * second row, and so on, where each row has Cols()/2 + 1 + * complex numbers. + * + * The output matrix will have Rows() rows and Cols()/2 + 1 columns, stored + * in row order. + * + * This member function does not change the current Fourier transform in + * this object, if it exists. + * + * Returns a reference to this object. + */ + GenericRealFFT2D& operator()( complex* y, const scalar* x ) const + { + this->Transform( m_rows, m_cols, y, x, m_monitor, m_parallel, m_maxProcessors ); + return const_cast( *this ); + } + + /*! + * Performs the inverse two-dimensional %FFT of an input matrix of complex + * numbers, and stores the result in an output matrix of real numbers. + * + * \param[in] x Input matrix. Must be the starting address of a contiguous + * sequence of at least Rows()*(Cols()/2 + 1) complex + * numbers, stored in row order: all elements of the first + * row followed by all elements of the second row, and so on, + * where each row must have Cols()/2 + 1 complex numbers. + * + * \param[out] y Output matrix, where the result of the transform will be + * stored. Must be the starting address of a contiguous + * sequence of at least NumberOfElements() real numbers. The + * result will be stored in row order: all elements of the + * first row followed by all elements of the second row, and + * so on. + * + * The input matrix must have Rows() rows and Cols()/2 + 1 columns, stored + * in row order. + * + * This member function does not change the current Fourier transform in + * this object, if it exists. + * + * Returns a reference to this object. + */ + GenericRealFFT2D& operator()( scalar* y, const complex* x ) const + { + this->Transform( m_rows, m_cols, y, x, m_monitor, m_parallel, m_maxProcessors ); + return const_cast( *this ); + } + + /*! + * Returns the optimized complex %FFT length larger than or equal to + * a given length \a n. The returned length will be optimal to perform a + * %FFT of real data with the current PCL implementation. The optimized + * length can be used as the \a rows or \a cols argument to the constructor + * of any two-dimensional %FFT class for real-valued data transforms. + */ + static int OptimizedLength( int n ) + { + return GenericFFT::OptimizedLength( n ); + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_dft +#undef m_rows +#undef m_cols +#undef m_monitor +#undef m_parallel +#undef m_maxProcessors + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup fft_2d Two-Dimensional Fast Fourier Transforms + */ + +#ifndef __PCL_NO_FFT2D_INSTANTIATE + +/*! + * \class pcl::FFFT2D + * \ingroup fft_2d + * \brief Fast Fourier transform of 32-bit floating point complex data. + * + * %FFFT2D is a template instantiation of GenericFFT2D for the \c float type. + */ +typedef GenericFFT2D FFFT2D; + +/*! + * \class pcl::DFFT2D + * \ingroup fft_2d + * \brief Fast Fourier transform of 64-bit floating point complex data. + * + * %DFFT2D is a template instantiation of GenericFFT2D for the \c double type. + */ +typedef GenericFFT2D DFFT2D; + +/*! + * \class pcl::FRealFFT2D + * \ingroup fft_2d + * \brief Fast Fourier transform of 32-bit floating point real data. + * + * %FRealFFT2D is a template instantiation of GenericRealFFT2DT for \c float. + */ +typedef GenericRealFFT2D FRealFFT2D; + +/*! + * \class pcl::DRealFFT2D + * \ingroup fft_2d + * \brief Fast Fourier transform of 64-bit floating point real data. + * + * %DRealFFT2D is a template instantiation of GenericRealFFT2D for \c double. + */ +typedef GenericRealFFT2D DRealFFT2D; + +/*! + * \class pcl::FFT2D + * \ingroup fft_2d + * \brief Fast Fourier transform of 32-bit floating point complex data. + * + * %FFT2D is an alias for FFFT2D. It is a template instantiation of + * GenericFFT2D for the \c float type. + */ +typedef FFFT2D FFT2D; + +/*! + * \class pcl::RealFFT2D + * \ingroup fft_2d + * \brief Fast Fourier transform of 32-bit floating point real data. + * + * %RealFFT2D is an alias for FRealFFT2D. It is a template instantiation of + * GenericRealFFT2D for the \c float type. + */ +typedef FRealFFT2D RealFFT2D; + +#endif // __PCL_NO_FFT2D_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FFT2D_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FFT2D.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FFTConvolution.h b/3rdparty/include/pcl/FFTConvolution.h new file mode 100644 index 0000000..f8c170a --- /dev/null +++ b/3rdparty/include/pcl/FFTConvolution.h @@ -0,0 +1,477 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FFTConvolution.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_FFTConvolution_h +#define __PCL_FFTConvolution_h + +/// \file pcl/FFTConvolution.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup convolution_speed_limits Helper Functions for Selection of + * Convolution Algorithms + */ + +/*! + * \class FFTConvolution + * \brief Fourier-based two-dimensional convolution in the spatial domain + * + * %FFTConvolution implements a fully multithreaded, two-dimensional discrete + * convolution algorithm via fast Fourier transforms. It performs automatic + * fixing of border artifacts by applying Neumann boundary conditions + * (mirroring), and is able to convolve images and response functions of + * arbitrary sizes, only limited by the available memory. + * + * \sa Convolution, SeparableConvolution +*/ +class PCL_CLASS FFTConvolution : public ImageTransformation, public ParallelProcess +{ +public: + + /*! + * Default constructor. + * + * \note This constructor yields an uninitialized instance that cannot be + * used before explicit association with a response function, specified + * either as a KernelFilter object or as an ImageVariant. + */ + FFTConvolution() = default; + + /*! + * Constructs an %FFTConvolution instance with the specified kernel filter. + * + * \param filter Response function, or convolution filter. The + * specified object does not have to remain valid while this + * %FFTConvolution instance is actively used, since it owns a + * private copy of the filter (note that KernelFilter is a + * reference-counted class). + */ + FFTConvolution( const KernelFilter& filter ) + : m_filter( filter.Clone() ) + { + PCL_CHECK( bool( m_filter ) ) + } + + /*! + * Constructs an %FFTConvolution instance with the specified response + * function image. + * + * \param f A reference to an ImageVariant whose transported image is the + * response function, or convolution filter. + * The transported image must remain valid while this + * %FFTConvolution instance is actively used, or until a new + * response function is associated with this instance. The + * specified %ImageVariant doesn't have to remain valid, since a + * %FFTConvolution instance owns a private %ImageVariant that + * transports the response function image. + */ + FFTConvolution( const ImageVariant& f ) + : m_image( f ) + { + PCL_CHECK( bool( m_image ) ) + } + + /*! + * Copy constructor. + */ + FFTConvolution( const FFTConvolution& x ) + : ImageTransformation( x ) + , ParallelProcess( x ) + , m_image( x.m_image ) + , m_outputRealCmp( x.m_outputRealCmp ) + { + if ( x.m_filter ) + m_filter = x.m_filter->Clone(); + } + + /*! + * Move constructor. + */ + FFTConvolution( FFTConvolution&& ) = default; + + /*! + * Destroys this %FFTConvolution object. + */ + virtual ~FFTConvolution() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + FFTConvolution& operator =( const FFTConvolution& x ) + { + if ( &x != this ) + { + (void)ImageTransformation::operator =( x ); + (void)ParallelProcess::operator =( x ); + DestroyFilter(); + if ( x.m_filter ) + m_filter = x.m_filter->Clone(); + else + m_image = x.m_image; + m_outputRealCmp = x.m_outputRealCmp; + } + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + FFTConvolution& operator =( FFTConvolution&& ) = default; + + /*! + * Returns true if this %FFTConvolution uses a KernelFilter object as its + * response function; false if it uses an image. + */ + bool UsingFilter() const + { + return m_filter; + } + + /*! + * Returns a reference to the kernel filter currently associated with this + * %FFTConvolution object. If this object does not use a kernel filter, + * either because it uses an image as its response function, or because this + * object has not been initialized, the returned filter is empty (i.e., it + * has no filter coefficients and zero dimensions). + */ + const KernelFilter& Filter() const + { + PCL_PRECONDITION( bool( m_filter ) ) + return *m_filter; + } + + /*! + * Returns a reference to the filter image currently associated with this + * %FFTConvolution object. The referenced ImageVariant object will transport + * no image if this object does not use a filter image, either because it + * uses a kernel filter as its response function, or because this object has + * not been initialized. + * + * The response function is actually the image transported by the returned + * ImageVariant. It can be an image of any supported data type. + */ + const ImageVariant& FilterImage() const + { + return m_image; + } + + /*! + * Sets a new kernel filter as the response function to be applied by this + * %FFTConvolution object. + * + * The specified object does not have to remain valid while this + * %FFTConvolution instance is actively used, since it owns a private copy + * of the filter (note that KernelFilter is a reference-counted class). + */ + void SetFilter( const KernelFilter& filter ) + { + DestroyFilter(); + m_filter = filter.Clone(); + PCL_CHECK( bool( m_filter ) ) + } + + /*! + * Sets a new filter image as the response function to be applied by this + * %FFTConvolution object. + * + * The image transported by the specified ImageVariant must remain valid + * while this %FFTConvolution instance is actively used, or until a new + * response function is associated with this instance. The %ImageVariant + * doesn't have to remain valid, since this object owns a private + * %ImageVariant that transports the response function image. + */ + void SetFilter( const ImageVariant& filter ) + { + DestroyFilter(); + m_image = filter; + PCL_CHECK( bool( m_image ) ) + } + + /*! + * Returns a pointer to the discrete Fourier transform (DFT) of the + * complex response function used internally by this + * %FFTConvolution object, or nullptr if the response function has not been + * created yet. + * + * The internal DFT of the response function is created and initialized the + * first time this %FFTConvolution object is used to perform a convolution. + * It is reused to save memory and CPU resources, as long as successive + * transformations apply to target images with the same dimensions, or + * otherwise it is re-created on the fly, as necessary. It is destroyed when + * a new filter is associated with this object. + * + * This function returns a pointer to a complex image that stores the DFT + * of the original filter after transforming it to wrap around + * order. This means that the original filter data has been splitted, + * mirrored, and redistributed to occupy the four corners of the complex 2-D + * matrix prior to calculating its DFT. + * + * If this object has not been initialized, the returned pointer is nullptr. + */ + const ComplexImage* ResponseFunctionDFT() const + { + return m_h; + } + + /*! + * Returns true if this object applies to real images by copying the real + * component of the complex convolved result. + * + * Returns false if this object applies to real images by storing the + * magnitude of the complex convolution result. This is the default + * behavior. + * + * \sa IsMagnitudeOutputEnabled(), EnableRealComponentOutput() + */ + bool IsRealComponentOutputEnabled() const + { + return m_outputRealCmp; + } + + /*! + * Returns true if this object applies to real images by storing the + * magnitude of the complex convolution result. This is the default + * behavior. + * + * Returns false if this object applies to real images by copying the real + * component of the complex convolved result. + * + * \sa IsRealComponentOutputEnabled(), EnableMagnitudeOutput() + */ + bool IsMagnitudeOutputEnabled() const + { + return !m_outputRealCmp; + } + + /*! + * Causes this object to apply to real images by copying the real component + * of the complex convolved result. + * + * \sa IsRealComponentOutputEnabled(), EnableMagnitudeOutput() + */ + void EnableRealComponentOutput( bool enable = true ) + { + m_outputRealCmp = enable; + } + + /*! + * Causes this object to apply to real images by storing the magnitude of + * the complex convolution result. This is the default behavior. + * + * \sa IsMagnitudeOutputEnabled(), EnableRealComponentOutput() + */ + void EnableMagnitudeOutput( bool enable = true ) + { + m_outputRealCmp = !enable; + } + + /*! + * Returns the minimum filter size in pixels for which FFT-based + * two-dimensional convolution is consistently faster than nonseparable + * convolution on the current PixInsight/PCL platform, for the specified + * number of parallel execution threads. + * + * The values returned by this function have been determined experimentally + * on reference hardware for optimized execution on machines and builds with + * and without AVX2/FMA3 processor instruction support. + * + * \ingroup convolution_speed_limits + */ + static constexpr int FasterThanNonseparableFilterSize( int numThreads ) + { +#ifdef __PCL_COMPATIBILITY + + // No vectorization + + if ( numThreads >= 32 ) + return 17; + if ( numThreads >= 24 ) + return 15; + if ( numThreads >= 12 ) + return 13; + if ( numThreads >= 8 ) + return 11; + return 9; + +#else + + // Vectorization with SSE4.2 / AVX2 and FMA instructions + + if ( numThreads >= 32 ) + return 29; + if ( numThreads >= 24 ) + return 27; + if ( numThreads >= 16 ) + return 25; + if ( numThreads >= 12 ) + return 21; + if ( numThreads >= 8 ) + return 19; + if ( numThreads >= 4 ) + return 17; + if ( numThreads >= 2 ) + return 15; + return 13; + +#endif + } + + /*! + * Returns the minimum filter size in pixels for which FFT-based + * two-dimensional convolution is consistently faster than separable + * convolution on the current PixInsight/PCL platform, for the specified + * number of parallel execution threads. + * + * The values returned by this function have been determined experimentally + * on reference hardware for optimized execution on machines and builds with + * and without AVX2/FMA3 processor instruction support. + * + * \ingroup convolution_speed_limits + */ + static constexpr int FasterThanSeparableFilterSize( int numThreads ) + { +#ifdef __PCL_COMPATIBILITY + + // No vectorization + + if ( numThreads >= 24 ) + return 191; + if ( numThreads >= 16 ) + return 141; + if ( numThreads >= 12 ) + return 135; + if ( numThreads >= 8 ) + return 95; + if ( numThreads >= 4 ) + return 75; + return 61; + +#else + + // Vectorization with SSE4.2 / AVX2 and FMA instructions + + if ( numThreads >= 16 ) + return 901; + if ( numThreads >= 12 ) + return 831; + if ( numThreads >= 8 ) + return 741; + return 395; + +#endif + } + +protected: + + /* + * The response function for convolution is defined as either a KernelFilter + * instance or as an image. In the latter case, the image transported by the + * ImageVariant must remain valid while this object is actively used. + */ + AutoPointer m_filter; + ImageVariant m_image; + bool m_outputRealCmp = false; + + /* + * Internal DFT of the response function. Initially zero. This matrix is + * generated/reused/regenerated as this object is applied to convolve + * different target images. It is destroyed when a new filter is specified. + */ + mutable AutoPointer m_h; + + /* + * In-place Fourier-based 2-D convolution algorithm. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + + friend class PCL_FFTConvolutionEngine; + +private: + + void DestroyFilter() + { + m_filter.Destroy(); + m_image.Free(); + m_h.Destroy(); + } + + void Validate() const; + void ValidateFilter() const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FFTConvolution_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FFTConvolution.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FFTRegistration.h b/3rdparty/include/pcl/FFTRegistration.h new file mode 100644 index 0000000..807656b --- /dev/null +++ b/3rdparty/include/pcl/FFTRegistration.h @@ -0,0 +1,611 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FFTRegistration.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_FFTRegistration_h +#define __PCL_FFTRegistration_h + +/// \file pcl/FFTRegistration.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class FFTRegistrationEngine + * \brief Base class of %FFT-based image registration algorithms + * + * Image registration based on phase correlation via fast Fourier transforms. + * + * References + * + * \li Araiza, R., Xie, H. & al., 2002. Automatic referencing of multi-spectral + * images. Proceedings of 15th IEEE Southwest Symposium on Image Analysis and + * Interpretation, Santa Fe, USA, 21-25. + * + * \li Xie, H. & al., 2000. Automatic image registration based on a %FFT + * algorithm and IDL/ENVI. Proceedings of the ICORG-2000 International + * Conference on Remote Sensing and GIS/GPS, Hyderabad, India, I-397~I-402. + * + * \li Harold S., Stone T. & al., 2003. Analysis of image registration noise + * due to rotationally dependent aliasing. Journal of Visual Communication and + * Image Representation 14, 114-135. + * + * \li DeCastro, E., Morandi, C., 1987. Registration of translated and rotated + * images using finite Fourier transforms. IEEE Transactions on Pattern + * Analysis and Machine Intelligence 95, 700-703. + */ +class PCL_CLASS FFTRegistrationEngine +{ +public: + + /*! + * Constructs an %FFTRegistrationEngine object. + */ + FFTRegistrationEngine() = default; + + /*! + * Copy constructor. + */ + FFTRegistrationEngine( const FFTRegistrationEngine& ) = default; + + /*! + * Move constructor. + */ + FFTRegistrationEngine( FFTRegistrationEngine&& x ) + : m_fftReference( std::move( x.m_fftReference ) ) + { + } + + /*! + * Destroys an %FFTRegistrationEngine object. + */ + virtual ~FFTRegistrationEngine() + { + } + + /*! + * Returns true iff this engine has been initialized. + */ + bool IsInitialized() const + { + return !m_fftReference.IsEmpty(); + } + + /*! + * Initializes this registration engine for the specified reference image + * \a image. + * + * Once initialized, subsequent calls to Evaluate() will compute + * registration parameters for target images referred to the same reference + * image, until a new initialization is performed, or until the Reset() + * member function is called. + */ + template + void Initialize( const pcl::GenericImage

& image ) + { + Reset(); + m_fftReference = DoInitialize( image ); + } + + /*! + * Initializes this registration engine for the specified reference + * \a image. + * + * This member function behaves like Initialize( const GenericImage

& ), + * except that it receives a reference to ImageVariant. The engine is + * initialized for the image transported by the ImageVariant object. + */ + void Initialize( const ImageVariant& image ) + { + Reset(); + if ( image ) + if ( image.IsComplexSample() ) + switch ( image.BitsPerSample() ) + { + case 32: m_fftReference = DoInitialize( static_cast( *image ) ); break; + case 64: m_fftReference = DoInitialize( static_cast( *image ) ); break; + } + else if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: m_fftReference = DoInitialize( static_cast( *image ) ); break; + case 64: m_fftReference = DoInitialize( static_cast( *image ) ); break; + } + else + switch ( image.BitsPerSample() ) + { + case 8: m_fftReference = DoInitialize( static_cast( *image ) ); break; + case 16: m_fftReference = DoInitialize( static_cast( *image ) ); break; + case 32: m_fftReference = DoInitialize( static_cast( *image ) ); break; + } + } + + /*! + * Returns a reference to the discrete Fourier transform of the reference + * image. + * + * The reference image is the image specified in the last call to + * Initialize(). This function returns an empty image if this registration + * engine has not been initialized. + */ + const ComplexImage& DFTOfReferenceImage() const + { + return m_fftReference; + } + + /*! + * Resets this registration engine and deallocates all internal data + * structures. The engine will have to be initialized before performing new + * evaluations of registration parameters. + */ + void Reset() + { + m_fftReference.FreeData(); + } + + /*! + * Evaluates a target image \a image to compute registration parameters. + * + * Before calling this function, the engina must be initialized by calling + * Initialize() with a reference image. + */ + template + void Evaluate( const pcl::GenericImage

& image ) + { + PCL_PRECONDITION( IsInitialized() ) + if ( IsInitialized() ) + DoEvaluate( image ); + } + + /*! + * Evaluates a target image \a vimg to compute registration parameters. + * + * This member function behaves like Evaluate( const GenericImage

& ), + * except that it receives a reference to ImageVariant. The engine evaluates + * for the image transported by the ImageVariant object. + */ + void Evaluate( const ImageVariant& image ) + { + PCL_PRECONDITION( IsInitialized() ) + if ( IsInitialized() ) + if ( image ) + if ( image.IsComplexSample() ) + switch ( image.BitsPerSample() ) + { + case 32: DoEvaluate( static_cast( *image ) ); break; + case 64: DoEvaluate( static_cast( *image ) ); break; + } + else if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: DoEvaluate( static_cast( *image ) ); break; + case 64: DoEvaluate( static_cast( *image ) ); break; + } + else + switch ( image.BitsPerSample() ) + { + case 8: DoEvaluate( static_cast( *image ) ); break; + case 16: DoEvaluate( static_cast( *image ) ); break; + case 32: DoEvaluate( static_cast( *image ) ); break; + } + } + +protected: + + // DFT of the reference image. + ComplexImage m_fftReference; + + virtual ComplexImage DoInitialize( const pcl::Image& ) = 0; + virtual ComplexImage DoInitialize( const pcl::DImage& ) = 0; + virtual ComplexImage DoInitialize( const pcl::ComplexImage& ) = 0; + virtual ComplexImage DoInitialize( const pcl::DComplexImage& ) = 0; + virtual ComplexImage DoInitialize( const pcl::UInt8Image& ) = 0; + virtual ComplexImage DoInitialize( const pcl::UInt16Image& ) = 0; + virtual ComplexImage DoInitialize( const pcl::UInt32Image& ) = 0; + + virtual void DoEvaluate( const pcl::Image& ) = 0; + virtual void DoEvaluate( const pcl::DImage& ) = 0; + virtual void DoEvaluate( const pcl::ComplexImage& ) = 0; + virtual void DoEvaluate( const pcl::DComplexImage& ) = 0; + virtual void DoEvaluate( const pcl::UInt8Image& ) = 0; + virtual void DoEvaluate( const pcl::UInt16Image& ) = 0; + virtual void DoEvaluate( const pcl::UInt32Image& ) = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup fft_registration_functions FFT-Based Registration Operators + */ + +/*! + * Initializes a %FFT registration engine or evaluates a target image. + * + * \param R %FFT registration engine. + * \param image An image or ImageVariant for initialization or evaluation. + * + * If the engine has not still been initialized, it is initialized for the + * \e reference image \a image. Once the engine has been initialized, it + * evaluates registration parameters for the specified \e target image \a image. + * + * Returns a reference to the %FFT registration engine \a R. + * + * \sa FFTRegistrationEngine + * + * \ingroup fft_registration_functions + */ +template inline +FFTRegistrationEngine& operator <<( FFTRegistrationEngine& R, const O& image ) +{ + if ( !R.IsInitialized() ) + R.Initialize( image ); + else + R.Evaluate( image ); + return R; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class FFTTranslation + * \brief %FFT registration engine: translation + * + * %FFTTranslation evaluates translation image registration parameters. It + * computes the offsets \e dx and \e dy required to register a target image on + * a reference image, using an %FFT-based phase correlation algorithm. + * + * \sa FFTRotationAndScaling, FFTRegistrationEngine + */ +class PCL_CLASS FFTTranslation : public FFTRegistrationEngine +{ +public: + + /*! + * Constructs an %FFTTranslation object. + */ + FFTTranslation() = default; + + /*! + * Destroys an %FFTTranslation object. + */ + virtual ~FFTTranslation() + { + } + + /*! + * Returns true iff this registration engine can evaluate translations + * greater than or equal to one half of the largest dimension of the + * reference image. + * + * \sa EnableLargeTranslations(), DisableLargeTranslations() + */ + bool AreLargeTranslationsEnabled() const + { + return m_largeTranslations; + } + + /*! + * Enables or disables evaluation of large translations (>= one half of the + * reference image dimension). + * + * \warning When large translations are enabled, the engine needs to double + * the sizes of internal working matrices, which \e quadruplicates the + * amount of required memory. + * + * \sa DisableLargeTranslations(), AreLargeTranslationsEnabled() + */ + void EnableLargeTranslations( bool enable = true ) + { + if ( enable != m_largeTranslations ) + { + Reset(); + m_largeTranslations = enable; + } + } + + /*! + * Disables or enables evaluation of large translations (>= one half of the + * reference image dimension). + * + * This is a convenience member function, equivalent to + * EnableLargeTranslations( !disable ) + * + * \warning When large translations are enabled, the engine needs to double + * the sizes of internal working matrices, which \e quadruplicates the + * amount of required memory. + * + * \sa EnableLargeTranslations(), AreLargeTranslationsEnabled() + */ + void DisableLargeTranslations( bool disable = true ) + { + EnableLargeTranslations( !disable ); + } + + /*! + * Returns the evaluated translation increments in pixels. + * + * The returned Point object contains the required offsets in the X and Y + * directions to register the last evaluated target image on the reference + * image set upon initialization. + * + * \sa DeltaX(), DeltaY() + */ + const FPoint& Delta() const + { + return m_delta; + } + + /*! + * Returns the evaluated translation increment in the X direction, in + * pixels. + * + * \sa DeltaY(), Delta() + */ + float DeltaX() const + { + return m_delta.x; + } + + /*! + * Returns the evaluated translation increment in the Y direction, in + * pixels. + * + * \sa DeltaX(), Delta() + */ + float DeltaY() const + { + return m_delta.y; + } + + /*! + * Returns the peak value read from the phase matrix for the last evaluated + * target image. The peak value isn't normalized, that is, it doesn't + * necessarily have to be in the [0,1] range. + */ + float Peak() const + { + return m_peak; + } + +protected: + + // Allow translations > size/2. + // Warning: a lot of memory may be necessary --four times more. + bool m_largeTranslations = false; + + // Evaluation result. + FPoint m_delta = 0.0F; + + // Peak value detected in the phase matrix. + float m_peak = 0.0F; + + ComplexImage DoInitialize( const pcl::Image& ) override; + ComplexImage DoInitialize( const pcl::DImage& ) override; + ComplexImage DoInitialize( const pcl::ComplexImage& ) override; + ComplexImage DoInitialize( const pcl::DComplexImage& ) override; + ComplexImage DoInitialize( const pcl::UInt8Image& ) override; + ComplexImage DoInitialize( const pcl::UInt16Image& ) override; + ComplexImage DoInitialize( const pcl::UInt32Image& ) override; + + void DoEvaluate( const pcl::Image& ) override; + void DoEvaluate( const pcl::DImage& ) override; + void DoEvaluate( const pcl::ComplexImage& ) override; + void DoEvaluate( const pcl::DComplexImage& ) override; + void DoEvaluate( const pcl::UInt8Image& ) override; + void DoEvaluate( const pcl::UInt16Image& ) override; + void DoEvaluate( const pcl::UInt32Image& ) override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class FFTRotationAndScaling + * \brief %FFT registration engine: rotation and scaling + * + * %FFTRotationAndScaling evaluates rotation and scaling image registration + * parameters. It computes the rotation angle and scaling ratio required to + * register a target image on a reference image, using an algorithm based on + * the Fourier-Mellin transform. + * + * \warning This class is currently experimental. It is not guaranteed to + * provide reliable image registration parameters. + * + * \sa FFTTranslation, FFTRegistrationEngine + */ +class PCL_CLASS FFTRotationAndScaling : public FFTRegistrationEngine +{ +public: + + /*! + * Constructs a %FFTRotationAndScaling object. + * + * Scaling ratio evaluation (see EvaluatesScaling()) is disabled by default. + */ + FFTRotationAndScaling() = default; + + /*! + * Destroys a %FFTRotationAndScaling object. + */ + virtual ~FFTRotationAndScaling() + { + } + + /*! + * Returns true iff this engine evaluates scaling ratios. By default, scale + * evaluation is disabled. + */ + bool EvaluatesScaling() const + { + return m_evaluateScaling; + } + + /*! + * Enables evaluation of scaling ratios. + */ + void EnableScalingEvaluation( bool enable = true ) + { + if ( enable != m_evaluateScaling ) + { + Reset(); + m_evaluateScaling = enable; + } + } + + /*! + * Disables evaluation of scaling ratios. + * + * This is a convenience member function, equivalent to + * EnableScalingEvaluation( !disable ) + */ + void DisableScalingEvaluation( bool disable = true ) + { + EnableScalingEvaluation( !disable ); + } + + /*! + * Returns the current low frequency cutoff for this registration engine. + * + * See the documentation for SetLowFrequencyCutoff() for a detailed + * description of low-frequency cutoffs. + */ + float LowFrequencyCutoff() const + { + return m_lowFrequencyCutoff; + } + + /*! + * Returns true iff this engine uses a low-frequency cutoff to reduce the + * effects of rotational aliasing. + */ + bool HasLowFrequencyCutoff() const + { + return LowFrequencyCutoff() > 0; + } + + /*! + * Sets the radius of the low-frequency cutoff. + * + * The evaluation of rotation and scaling registration parameters can + * benefit from a simple low-frequency cutoff operation to reduce rotational + * aliasing on the computed DFTs. The value set by this function is the + * radius of the cutoff \e hole relative to the largest dimension of the + * reference image. The default value is 1/200. A value of zero disables the + * low-frequency cutoff feature. + */ + void SetLowFrequencyCutoff( float r ) + { + m_lowFrequencyCutoff = Range( r, 0.0F, 0.5F ); + } + + /*! + * Returns the evaluated rotation angle in radians. + * + * The returned value is the required rotation angle to register the last + * evaluated target image on the reference image set upon initialization. + */ + float RotationAngle() const + { + return m_rotationAngle; + } + + /*! + * Returns the evaluated scaling ratio. + * + * The returned value is the required scaling ratio to register the last + * evaluated target image on the reference image set upon initialization. + */ + float ScalingRatio() const + { + return m_scalingRatio; + } + +protected: + + // Evaluate rotation+scaling, or just rotation? + bool m_evaluateScaling = false; + + // Low-frequency cutoff, as a fraction of the DFT radius. + float m_lowFrequencyCutoff = 1.0F/200; + + // Evaluation result + float m_rotationAngle = 0.0F; // radians + float m_scalingRatio = 1.0F; // pixels + + ComplexImage DoInitialize( const pcl::Image& ) override; + ComplexImage DoInitialize( const pcl::DImage& ) override; + ComplexImage DoInitialize( const pcl::ComplexImage& ) override; + ComplexImage DoInitialize( const pcl::DComplexImage& ) override; + ComplexImage DoInitialize( const pcl::UInt8Image& ) override; + ComplexImage DoInitialize( const pcl::UInt16Image& ) override; + ComplexImage DoInitialize( const pcl::UInt32Image& ) override; + + void DoEvaluate( const pcl::Image& ) override; + void DoEvaluate( const pcl::DImage& ) override; + void DoEvaluate( const pcl::ComplexImage& ) override; + void DoEvaluate( const pcl::DComplexImage& ) override; + void DoEvaluate( const pcl::UInt8Image& ) override; + void DoEvaluate( const pcl::UInt16Image& ) override; + void DoEvaluate( const pcl::UInt32Image& ) override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FFTRegistration_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FFTRegistration.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FITSHeaderKeyword.h b/3rdparty/include/pcl/FITSHeaderKeyword.h new file mode 100644 index 0000000..e99336b --- /dev/null +++ b/3rdparty/include/pcl/FITSHeaderKeyword.h @@ -0,0 +1,290 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FITSHeaderKeyword.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_FITSHeaderKeyword_h +#define __PCL_FITSHeaderKeyword_h + +/// \file pcl/FITSHeaderKeyword.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class FITSHeaderKeyword + * \brief %FITS header keyword + */ +class PCL_CLASS FITSHeaderKeyword +{ +public: + + IsoString name; //!< Keyword name + IsoString value; //!< Keyword value + IsoString comment; //!< Keyword comment + + /*! + * Constructs a %FITSHeaderKeyword object with empty name, value and comment + * components. + */ + FITSHeaderKeyword() = default; + + /*! + * Copy constructor. + */ + FITSHeaderKeyword( const FITSHeaderKeyword& ) = default; + + /*! + * Move constructor. + */ + FITSHeaderKeyword( FITSHeaderKeyword&& ) = default; + + /*! + * Constructs a %FITSHeaderKeyword object with the specified name, value and + * comment components. + */ + FITSHeaderKeyword( const IsoString& a_name, + const IsoString& a_value = IsoString(), + const IsoString& a_comment = IsoString() ) + : name( a_name ) + , value( a_value ) + , comment( a_comment ) + { + Trim(); + } + + template + FITSHeaderKeyword( const S1& a_name, const S2& a_value, const S3& a_comment ) + : name( IsoString( a_name ) ) + , value( IsoString( a_value ) ) + , comment( IsoString( a_comment ) ) + { + Trim(); + } + + /*! + * Assignment operator. Returns a reference to this object. + */ + FITSHeaderKeyword& operator =( const FITSHeaderKeyword& ) = default; + + /*! + * Returns true iff this %FITS keyword has no %value (i.e., if the value + * member is an empty string). + */ + bool IsNull() const + { + return value.IsEmpty(); + } + + /*! + * Returns true iff this %FITS keyword has a string %value. + * + * A string %value is assumed if the value component begins with a single + * quote ('). + */ + bool IsString() const + { + return value.StartsWith( '\'' ); + } + + /*! + * Returns true iff this %FITS keyword has a boolean %value. + * + * A boolean %value is assumed if the value component is equal to 'T' or 'F' + * for \c true and \c false, respectively. + */ + bool IsBoolean() const + { + return value == 'T' || value == 'F'; + } + + /*! + * Returns true iff this %FITS keyword has a numeric %value. + * + * A numeric %value is assumed if the value component is a valid + * representation of an integer or floating point number. + */ + bool IsNumeric() const + { + return value.IsNumeral(); + } + + /*! + * Gets the numeric %value of this %FITS keyword in the specified variable + * \a v, or zero if this keyword has no numeric %value. + * + * Returns true iff this keyword has a valid numeric %value. This member + * function does not throw exceptions, even if the keyword's value contains + * an illegal numeric representation. + */ + bool GetNumericValue( double& v ) const + { + if ( value.TryToDouble( v ) ) + return true; + v = 0; + return false; + } + + /*! + * Returns the string %value of this %FITS header keyword (irrespective of + * its data type), with delimiters pulled off and leading/trailing + * whitespace trimmed out. + */ + IsoString StripValueDelimiters() const + { + IsoString stripped; + + if ( !value.IsEmpty() && *value == '\'' ) // leading delimiter ? + { + size_type n = value.Length()-1; + if ( value[n] == '\'' ) // trailing delimiter ? + --n; + stripped = value.Substring( 1, n ); + } + else + stripped = value; + + return stripped.Trimmed(); + } + + /*! + * If this keyword has a string value without leading and trailing quotes, + * this member function adds them, as required by the FITS standard. Returns + * true if the value was fixed, false if the value was not changed. + */ + bool FixValueDelimiters() + { + double dum; + if ( !IsNull() ) + if ( !IsString() ) + if ( !IsBoolean() ) + if ( !IsNumeric() || !value.TryToDouble( dum ) ) + { + value.EnsureSingleQuoted(); + return true; + } + return false; + } + + /*! + * Removes leading and trailing spaces in the name, value and comment + * components of this %FITS header keyword. + */ + void Trim() + { + name.Trim(); + value.Trim(); + comment.Trim(); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class pcl::FITSKeywordArray + * \brief Dynamic array of %FITS header keywords + * + * %FITSKeywordArray is a template instantiation of Array for + * FITSHeaderKeyword. + */ +typedef Array FITSKeywordArray; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup fits_keyword_comparison FITS Keyword Comparison Functions + */ + +/*! + * Returns true iff two %FITS header keywords, \a h1 and \a h2, are equal. + * + * Two %FITS keywords are equal if their three components (name, value, + * comment) are equal. However, keyword name comparison is case-insensitive as + * per the %FITS standard. + * + * \ingroup fits_keyword_comparison + */ +inline bool operator ==( const FITSHeaderKeyword& h1, const FITSHeaderKeyword& h2 ) +{ + // Keyword name comparison is case-insensitive as per the FITS standard. + return h1.name.CompareIC( h2.name ) == 0 && h1.value == h2.value && h1.comment == h2.comment; +} + +/*! + * Returns true iff a %FITS header keyword \a h1 is less than other keyword + * \a h2. + * + * This function compares the components of both keywords. The precedence order + * is name, value and comment. Keyword name comparison is case-insensitive as + * per the %FITS standard. + * + * \ingroup fits_keyword_comparison + */ +inline bool operator <( const FITSHeaderKeyword& h1, const FITSHeaderKeyword& h2 ) +{ + int i = h1.name.CompareIC( h2.name ); + return i < 0 || i == 0 && (h1.value < h2.value || h1.value == h2.value && h1.comment < h2.comment); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FITSHeaderKeyword_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FITSHeaderKeyword.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FastRotation.h b/3rdparty/include/pcl/FastRotation.h new file mode 100644 index 0000000..76b8542 --- /dev/null +++ b/3rdparty/include/pcl/FastRotation.h @@ -0,0 +1,241 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FastRotation.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_FastRotation_h +#define __PCL_FastRotation_h + +/// \file pcl/FastRotation.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup fast_rotations Non-interpolating Rotations and Specular \ + * Transformations. + * + * Fast rotations are non-interpolating geometric transformations: + * they carry out image rotation and specular projection operations exclusively + * by copying and swapping pixels. + * + * Since no pixel interpolation is performed, there is absolutely no data + * degradation after an arbitrary number of consecutive fast rotations. + */ + +// ---------------------------------------------------------------------------- + +/*! + * \class Rotate180 + * \brief Rotates images by 180 degrees + * + * \ingroup fast_rotations + */ +class PCL_CLASS Rotate180 : public GeometricTransformation +{ +public: + + /*! + */ + void GetNewSizes( int& w, int& h ) const override + { + // No change + } + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Rotate90CW + * \brief Rotates images by 90 degrees (clockwise) + * + * \ingroup fast_rotations + */ +class PCL_CLASS Rotate90CW : public GeometricTransformation +{ +public: + + /*! + */ + void GetNewSizes( int& w, int& h ) const override + { + pcl::Swap( w, h ); // Permute + } + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Rotate90CCW + * \brief Rotates images by -90 degrees (counter-clockwise) + * + * \ingroup fast_rotations + */ +class PCL_CLASS Rotate90CCW : public GeometricTransformation +{ +public: + + /*! + */ + void GetNewSizes( int& w, int& h ) const override + { + pcl::Swap( w, h ); // Permute + } + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class HorizontalMirror + * \brief Mirrors images horizontally + * + * \ingroup fast_rotations + */ +class PCL_CLASS HorizontalMirror : public GeometricTransformation +{ +public: + + /*! + */ + void GetNewSizes( int& w, int& h ) const override + { + // No change + } + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class VerticalMirror + * \brief Mirrors images vertically + * + * \ingroup fast_rotations + */ +class PCL_CLASS VerticalMirror : public GeometricTransformation +{ +public: + + /*! + */ + void GetNewSizes( int& w, int& h ) const override + { + // No change + } + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FastRotation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FastRotation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/File.h b/3rdparty/include/pcl/File.h new file mode 100644 index 0000000..d7ff397 --- /dev/null +++ b/3rdparty/include/pcl/File.h @@ -0,0 +1,2415 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/File.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_File_h +#define __PCL_File_h + +/// \file pcl/File.h + +#include +#include + +#include +#include +#include +#include + +#ifndef __PCL_FILE_DONT_REMOVE_PREVIOUS_DECLARATION + +/* + * Remove conflicting identifiers from Win32 SDK headers. + */ + +#ifdef CreateFile +#undef CreateFile +#endif + +#ifdef CopyFile +#undef CopyFile +#endif + +#ifdef MoveFile +#undef MoveFile +#endif + +#ifdef CreateDirectory +#undef CreateDirectory +#endif + +#ifdef RemoveDirectory +#undef RemoveDirectory +#endif + +#endif // !__PCL_FILE_DONT_REMOVE_PREVIOUS_DECLARATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup file_utilities File Support Classes and Functions + */ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FileMode + * \brief File access, share and opening/creation modes. + * + * + * + * + * + * + * + * + * + * + * + *
FileMode::Read Read access enabled
FileMode::Write Write access enabled
FileMode::AccessMode Mask to isolate read/write flags
FileMode::ShareRead (Windows only) Sharing for reading enabled
FileMode::ShareWrite (Windows only) Sharing for writing enabled
FileMode::ShareMode (Windows only) Mask to isolate share read/write flags
FileMode::Open Open an existing file
FileMode::Create Create a new file or truncate an existing file
FileMode::OpenMode Mask to isolate open/creation flags
+ * + * \ingroup file_utilities + */ +namespace FileMode +{ + enum mask_type + { + Zero = 0x00000000, + + /* + * Access mode + */ + Read = 0x00000001, + Write = 0x00000002, + AccessMode = 0x0000000F, + + /* + * Share mode (Windows only) + */ + ShareRead = 0x00000010, + ShareWrite = 0x00000020, + ShareMode = 0x000000F0, + + /* + * Open/create mode + */ + Open = 0x00000100, + Create = 0x00000200, + OpenMode = 0x00000F00 + }; +} + +/*! + * \class pcl::FileModes + * \brief A combination of file access, share and opening/creation mode flags + * \ingroup file_utilities + */ +typedef Flags FileModes; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::SeekMode + * \brief File seek modes. + * + * + * + * + * + *
SeekMode::FromBegin Move file pointer relative to the beginning of the file
SeekMode::FromCurrent Move file pointer from the current position
SeekMode::FromEnd Move file pointer relative to the end of the file
+ * + * \ingroup file_utilities + */ +namespace SeekMode +{ + enum value_type + { + FromBegin, // Move relative to the beginning of the file + FromCurrent, // Move from current position + FromEnd, // Move relative to the end of the file + NumberOfSeekModes + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FileAttribute + * \brief File attributes + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
File type
FileAttribute::Block Block special
FileAttribute::Character Character special
FileAttribute::FIFO FIFO special
FileAttribute::Regular Regular file
FileAttribute::Directory Directory
FileAttribute::SymbolicLink Symbolic link
FileAttribute::Socket Socket
FileAttribute::FileType Mask to isolate file type flags
File attributes\n + * These are Windows-exclusive, except ReadOnly and Hidden, which we emulate on UNIX and Linux platforms.
FileAttribute::Archive File is archived
FileAttribute::Compressed File is compressed
FileAttribute::Encrypted File is encrypted
FileAttribute::Hidden File is hidden
FileAttribute::ReadOnly File is read-only
FileAttribute::System File is a system file
FileAttribute::Temporary File is a temporary file
FileAttribute::FileAttributes Mask to isolate file attributes flags
File permissions
FileAttribute::Read Owner can read
FileAttribute::Write Owner can write
FileAttribute::Execute Owner can execute/search
FileAttribute::ReadGroup Group can read
FileAttribute::WriteGroup Group can write
FileAttribute::ExecuteGroup Group can execute/search
FileAttribute::ReadOthers Others can read
FileAttribute::WriteOthers Others can write
FileAttribute::ExecuteOthers Others can execute/search
FileAttribute::FilePermissions Mask to isolate file permission flags
+ * + * \ingroup file_utilities + */ +namespace FileAttribute +{ + enum mask_type + { + /* + * File type. + */ + Block = 0x00000001, // Block special + Character = 0x00000002, // Character special + FIFO = 0x00000004, // FIFO special + Regular = 0x00000008, // Regular file + Directory = 0x00000010, // Directory + SymbolicLink = 0x00000020, // Symbolic link + Socket = 0x00000040, // Socket + FileType = 0x000000FF, + + /* + * File attributes. + * These are Windows-exclusive, except ReadOnly and Hidden, which we + * emulate on UNIX and Linux. + */ + Archive = 0x00001000, // File is archived + Compressed = 0x00002000, // File is compressed + Encrypted = 0x00004000, // File is encrypted + Hidden = 0x00008000, // File is hidden + ReadOnly = 0x00010000, // File is read-only + System = 0x00020000, // File is a system file + Temporary = 0x00040000, // File is a temporary file + FileAttributes = 0x000FF000, + + /* + * File permissions. + */ + Read = 0x00100000, // Owner can read + Write = 0x00200000, // Owner can write + Execute = 0x00400000, // Owner can execute/search + ReadGroup = 0x01000000, // Group can read + WriteGroup = 0x02000000, // Group can write + ExecuteGroup = 0x04000000, // Group can execute/search + ReadOthers = 0x10000000, // Others can read + WriteOthers = 0x20000000, // Others can write + ExecuteOthers = 0x40000000, // Others can execute/search + FilePermissions= 0xFFF00000 + }; +} + +/*! + * \class pcl::FileAttributes + * \brief A combination of file type, attribute and access mode flags + * \ingroup file_utilities + */ +typedef Flags FileAttributes; + +// ---------------------------------------------------------------------------- + +/*! + * \struct FileTime + * \brief File date and time + * + * %FileTime is used to represent the creation, last access and last + * modification times of a file or directory. On most file systems, this object + * represents a time point in the Coordinated Universal Time (UTC) time scale. + * \ingroup file_utilities + */ +struct FileTime +{ + uint16 year : 16; //!< Year + uint8 month : 4; //!< Month [1,12] + uint8 day : 5; //!< Day [1,31] + uint8 hour : 5; //!< Hour [0,23] + int : 2; + uint8 minute : 6; //!< Minute [0,59] + uint8 second : 6; //!< Second [0,59] + int : 4; + uint16 milliseconds : 10; //!< Milliseconds [0,999] + int : 6; + + /*! + * Returns true iff this file time is equal to another object \a t. + */ + bool operator ==( const FileTime& t ) const + { + return second == t.second && minute == t.minute && hour == t.hour && + day == t.day && month == t.month && year == t.year && + milliseconds == t.milliseconds; + } + + /*! + * Returns true iff this file time precedes another object \a t. + */ + bool operator <( const FileTime& t ) const + { + if ( year != t.year ) return year < t.year; + if ( month != t.month ) return month < t.month; + if ( day != t.day ) return day < t.day; + if ( hour != t.hour ) return hour < t.hour; + if ( minute != t.minute ) return minute < t.minute; + if ( second != t.second ) return second < t.second; + if ( milliseconds != t.milliseconds ) return milliseconds < t.milliseconds; + return false; + } + + /*! + * Returns this file date and time as a Julian day number. The returned + * value represents a time point in the UTC time scale on most file systems. + */ + double ToJD() const; + + /*! + * Returns the elapsed time in days since the standard UNIX epoch (1970 + * January 1.0 UTC). + */ + double DaysSinceEpoch() const + { + return ToJD() - 2440587.5; + } + + /*! + * Returns the elapsed time in seconds since the standard UNIX epoch (1970 + * January 1.0 UTC). + */ + double SecondsSinceEpoch() const + { + return 86400*DaysSinceEpoch(); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct FindFileInfo + * \brief %File information structure used by File::Find + * \ingroup file_utilities + * \sa pcl::File::Find + */ +struct FindFileInfo +{ + String name; //!< File or directory name, including the file name extension. + FileAttributes attributes; //!< Item attributes. + fsize_type size; //!< File size in bytes. + int numberOfLinks; //!< Number of existing hard links to this file. + int userId; //!< User id of the file owner. + int groupId; //!< Group id of the file owner. + FileTime created; //!< Creation time. + FileTime lastAccessed; //!< Time of last access. + FileTime lastModified; //!< Time of last change. + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a directory. + */ + bool IsDirectory() const + { + return attributes.IsFlagSet( FileAttribute::Directory ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::Archive attribute set. + */ + bool IsArchive() const + { + return attributes.IsFlagSet( FileAttribute::Archive ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::Compressed attribute set. + */ + bool IsCompressed() const + { + return attributes.IsFlagSet( FileAttribute::Compressed ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::Encrypted attribute set. + */ + bool IsEncrypted() const + { + return attributes.IsFlagSet( FileAttribute::Encrypted ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::Hidden attribute set. + */ + bool IsHidden() const + { + return attributes.IsFlagSet( FileAttribute::Hidden ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::ReadOnly attribute set. + */ + bool IsReadOnly() const + { + return attributes.IsFlagSet( FileAttribute::ReadOnly ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::System attribute set. + */ + bool IsSystem() const + { + return attributes.IsFlagSet( FileAttribute::System ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to a file with the + * FileAttribute::Temporary attribute set. + */ + bool IsTemporary() const + { + return attributes.IsFlagSet( FileAttribute::Temporary ); + } + + /*! + * Returns true iff this %FindFileInfo structure corresponds to an empty file. + */ + bool IsEmpty() const + { + return size == 0; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ReadTextOption + * \brief File text reading options. + * + * + * + * + * + * + *
RemoveEmptyLines Discard empty text lines (after trimming whitespace, when applicable).
TrimTrailingSpaces Delete trailing whitespace characters from input text lines.
TrimLeadingSpaces Delete leading whitespace characters from input text lines.
TrimSpaces Delete both leading and trailing whitespace characters from input text lines.
+ * + * \ingroup file_utilities + * \sa File::ReadLines(), File::ScanLines() + */ +namespace ReadTextOption +{ + enum mask_type + { + RemoveEmptyLines = 0x0001, + TrimTrailingSpaces = 0x0002, + TrimLeadingSpaces = 0x0004, + TrimSpaces = TrimTrailingSpaces | TrimLeadingSpaces + }; +} + +/*! + * \class pcl::ReadTextOptions + * \brief A combination of file text reading mode flags + * \ingroup file_utilities + * \sa File::ReadLines(), File::ScanLines() + */ +typedef Flags ReadTextOptions; + +// ---------------------------------------------------------------------------- + +/*! + * \struct UniqueFileChecks + * \brief A simple POD structure to hold file uniqueness and overwrite + * verification results. + * \ingroup file_utilities + * \sa File::EnsureNewUniqueFilePath() + */ +struct UniqueFileChecks +{ + bool exists = false; + bool overwrite = false; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class File + * \brief A platform-independent interface to the local file system + * + * ### TODO: Write a detailed description for %File. + * + * \ingroup file_utilities + */ +class PCL_CLASS File +{ +public: + + /*! + * Represents a low-level opaque handle to a file. + */ + typedef void* handle; + + /*! + * Represents a file seek mode. + */ + typedef SeekMode::value_type seek_mode; + + /*! + * \class pcl::File::Error + * \brief File I/O exception + * \ingroup file_utilities + */ + class PCL_CLASS Error : public pcl::Error + { + public: + + /*! + * Constructs a %File::Error object with the specified full file + * \a path and error \a message. + */ + Error( const String& filePath, const String& message ) + : pcl::Error( message ) + , m_filePath( filePath ) + { + } + + /*! + * Copy constructor. + */ + Error( const Error& ) = default; + + /*! + */ + String ExceptionClass() const override + { + return "File I/O Error"; + } + + /*! + * Returns the full file path associated to this file error. + */ + virtual String FilePath() const + { + return m_filePath; + } + + /*! + */ + virtual String ErrorMessage() const + { + return m_message; + } + + /*! + */ + String Message() const override + { + String filePath = FilePath(); + String message = m_message; + if ( !filePath.IsEmpty() ) + { + message += ": "; + message += filePath; + } + return message; + } + + private: + + String m_filePath; + }; + + /*! + * \class pcl::File::Find + * \brief Directory search operation + * + * This class can be used as an iterator to find all files and + * subdirectories within a directory tree. + * + * In the following example, the ProcessFiles function calls a functor + * object, specified as the \a processFile function argument, for each file + * found recursively in the specified \a dirPath directory. The functor's + * unique argument is the absolute file path of an existing file. + * + * \code + * template + * void ProcessFiles( const String& dirPath, F processFile ) + * { + * StringList directories; + * pcl::FindFileInfo info; + * for ( File::Find f( dirPath + '/' + '*' ); f.NextItem( info ); ) + * if ( info.IsDirectory() ) + * { + * if ( info.name != "." && info.name != ".." ) + * directories << info.name; + * } + * else if ( !info.attributes.IsFlagSet( FileAttribute::SymbolicLink ) ) + * { + * processFile( File::FullPath( dirPath + '/' + info.name ) ); + * } + * for ( const String& dir : directories ) + * ProcessFiles( dirPath + '/' + dir ); + * } + * \endcode + * + * \ingroup file_utilities + * \sa FindFileInfo + */ + class PCL_CLASS Find + { + public: + + /*! + * Constructs an inactive %File::Find object. + */ + Find() = default; + + /*! + * Constructs a %File::Find object and starts a new directory search + * operation for the specified \a path. + * + * The specified \a path can include wildcards to define a pattern to + * search for a set of directory items. + */ + Find( const String& path ) + { + Begin( path ); + } + + /*! + * Destroys a %File::Find object. If a directory search operation is + * currently active, it is finalized. + */ + ~Find() + { + End(); + } + + /*! + * Copy constructor. This constructor is disabled because %File::Find + * instances are unique. + */ + Find( const Find& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %File::Find + * instances are unique. + */ + Find& operator =( const Find& ) = delete; + + /*! + * Starts a new directory search operation for the specified \a path. + * + * The specified \a path can include wildcards to define a pattern to + * search for a set of directory items. + */ + void Begin( const String& path ); + + /*! + * Attempts to retrieve the next item in the current directory search + * operation. + * + * Returns true if a new item has been retrieved. In such case the + * \a info structure receives the data corresponding to the retrieved + * item. Returns false if there are no more items available, signaling + * the end of the current directory search operation, or if a search + * operation has not been initiated by a previous call to Begin(). In + * such case the \a info structure is not modified. + */ + bool NextItem( FindFileInfo& info ); + + /*! + * Finalizes the current directory search operation, if there is one + * active. + */ + void End(); + + /*! + * Returns the search path of the current directory search operation. + */ + String SearchPath() const + { + return m_searchPath; + } + + private: + + FindFileInfo m_info; + String m_searchPath; +#ifndef __PCL_WINDOWS + String m_searchDir; + String m_searchName; +#endif + void* m_handle = nullptr; + }; + + /*! + * \class pcl::File::Progress + * \brief Abstract base class of file progress objects + * + * The purpose of a file progress object is to provide feedback to the user + * during potentially long file tasks, such as copying, moving and deleting + * large files or file sets. The %File::Progress class provides a simple + * template with a text line, an increasing counter, and the possibility to + * abort a long operation. + * + * \ingroup file_utilities + * \sa File::CopyFile(), File::MoveFile() + */ + class PCL_CLASS Progress + { + public: + + /*! + * Constructs a %File::Progress object. + * + * \param total Total progress count (for example, the total size + * in bytes of a file being copied, or the total + * number of files being deleted). + * + * \param initialText Initial progress text. The default value is an + * empty string. + * + * \param initialValue Initial progress value. The default value is + * zero. + */ + Progress( fsize_type total, const String& initialText = String(), fsize_type initialValue = 0 ) + : m_total( Max( fsize_type( 0 ), total ) ) + , m_current( Range( initialValue, fsize_type( 0 ), m_total ) ) + , m_text( initialText ) + { + } + + /*! + * Destroys a %File::Progress object. + */ + virtual ~Progress() + { + } + + /*! + * Returns the total progress count. + */ + fsize_type Total() const + { + return m_total; + } + + /*! + * Returns the current progress count. + */ + fsize_type Value() const + { + return m_current; + } + + /*! + * Returns the current progress text. + */ + const String& Text() const + { + return m_text; + } + + /*! + * Sets the \a current progress count. + * + * This member function can abort the ongoing task. In such case, a + * ProcessAborted exception is thrown and the IsAborted() member function + * returns true. + */ + void SetValue( fsize_type current ) + { + if ( current >= m_current ) + { + m_current = current; + + if ( !ValueChanged() ) + { + m_abort = true; + throw ProcessAborted(); + } + } + } + + /*! + * Adds \a delta items to the current progress count. + * + * This member function can abort the ongoing task. In such case, a + * ProcessAborted exception is thrown and the IsAborted() member function + * returns true. + */ + void Add( fsize_type delta ) + { + if ( delta >= 0 ) + { + m_current += delta; + + if ( !ValueChanged() ) + { + m_abort = true; + throw ProcessAborted(); + } + } + } + + /*! + * Changes the current progress \a text. + * + * This member function can abort the ongoing task. In such case, a + * ProcessAborted exception is thrown and the IsAborted() member function + * returns true. + */ + void SetText( const String& text ) + { + m_text = text; + + if ( !TextChanged() ) + { + m_abort = true; + throw ProcessAborted(); + } + } + + /*! + * Returns true iff this object aborted a running task. + */ + bool IsAborted() const + { + return m_abort; + } + + protected: + + fsize_type m_total; + fsize_type m_current; + String m_text; + bool m_abort = false; + + /*! + * Function called when the current progress count has been changed. + * Returns true to continue the running task; false to abort. + * + * This is a pure virtual function that must be reimplemented by derived + * classes. + */ + virtual bool ValueChanged() = 0; + + /*! + * Function called when the current progress text has been changed. + * Returns true to continue the running task; false to abort. + * + * This is a pure virtual function that must be reimplemented by derived + * classes. + */ + virtual bool TextChanged() = 0; + }; + + // ------------------------------------------------------------------------- + + /*! + * Constructs a %File object that does not represent an existing file. + */ + File() + { + Initialize(); + } + + /*! + * Constructs a %File object that opens a file at a given \a path with the + * specified \a mode. + */ + File( const String& path, FileModes mode ) + { + PCL_PRECONDITION( !path.IsEmpty() ) + Initialize(); + Open( path, mode ); + } + + /*! + * Move constructor. + */ + File( File&& x ) + : m_fileHandle( x.m_fileHandle ) + , m_filePath( std::move( x.m_filePath ) ) + , m_fileMode( x.m_fileMode ) + { + x.m_fileHandle = s_invalidHandle; + x.m_fileMode = FileMode::Zero; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + File& operator =( File&& x ) + { + if ( &x != this ) + { + if ( IsOpen() ) + Close(); + m_fileHandle = x.m_fileHandle; + m_filePath = std::move( x.m_filePath ); + m_fileMode = x.m_fileMode; + x.m_fileHandle = s_invalidHandle; + x.m_fileMode = FileMode::Zero; + } + return *this; + } + + /*! + * Destroys a %File object. If this instance represents an open file, it is + * closed upon destruction. + */ + virtual ~File() + { + if ( IsOpen() ) + Close(); + } + + /*! + * Copy constructor. This constructor is disabled because files are unique + * objects. + */ + File( const File& ) = delete; + + /*! + * Copy assignment. This operator is disabled because files are unique + * objects. + */ + File& operator =( const File& ) = delete; + + /*! + * Returns true iff this %File object represents an open file. + */ + bool IsOpen() const + { + return IsValidHandle( m_fileHandle ); + } + + /*! + * Returns the path of the file represented by this %File object. + * Returned file paths are always absolute, full file paths. + */ + const String& FilePath() const + { + return m_filePath; + } + + /*! + * Returns the path of the file represented by this %File object. + * + * \deprecated This member function has been deprecated. Use FilePath() in + * newly produced code. + */ + const String& FileName() const + { + return FilePath(); + } + + /*! + * Returns the file mode for this %File object. + */ + FileModes Mode() const + { + return m_fileMode; + } + + /*! + * Returns true iff this file allows read access. + */ + virtual bool CanRead() const + { + return m_fileMode.IsFlagSet( FileMode::Read ); + } + + /*! + * Returns true iff this file allows write access. + */ + virtual bool CanWrite() const + { + return m_fileMode.IsFlagSet( FileMode::Write ); + } + + /*! + * Returns the current file position, relative to the beginning of the file + * represented by this %File object. + */ + virtual fpos_type Position() const; + + /*! + * Sets the file position relative to the file beginning. + */ + virtual void SetPosition( fpos_type pos ); + + /*! + * Moves the file pointer. Returns the resulting pointer position from the + * file beginning. + * + * \param dist Distance to move in bytes. + * \param mode Seek mode. See the SeekMode namespace for valid modes. + */ + fpos_type Seek( fpos_type dist, seek_mode mode = SeekMode::FromCurrent ); + + /*! + * Moves the file pointer after the end of the file. + * Returns the size of this file, that is, the absolute position of the last + * byte plus one. + * + * This is a convenience member function, equivalent to + * Seek( 0, SeekMode::FromEnd ) + */ + fpos_type SeekEnd() + { + return Seek( 0, SeekMode::FromEnd ); + } + + /*! + * Moves the file pointer to the beginning of this file. + * + * This is a convenience member function, equivalent to SetPosition( 0 ) + */ + void Rewind() + { + SetPosition( 0 ); + } + + /*! + * Returns true iff the file pointer has been moved beyond the end of the + * file. + */ + bool IsEOF() const + { + return Position() >= Size(); + } + + /*! + * Returns the length in bytes of this file. + */ + virtual fsize_type Size() const; + + /*! + * Truncates or extends this file to the specified \a length. + */ + virtual void Resize( fsize_type length ); + + /*! + * Reads a contiguous block of \a len bytes into the specified \a buffer. + */ + virtual void Read( void* buffer, fsize_type len ); + + /*! + * Reads an object \a x of type T. + */ + template + void Read( T& x ) + { + Read( (void*)&x, sizeof( T ) ); + } + + /*! + * Reads a set of \a n consecutive objects of type T into the array pointed + * to by \a a. + * + * This is a convenience member function, equivalent to + * Read( (void*)a, n*sizeof( T ) ) + */ + template + void ReadArray( T* a, size_type n ) + { + Read( (void*)a, n*sizeof( T ) ); + } + + /*! + * Reads a numeric variable as a 32-bit signed integer. + */ + template + void ReadI32( T& x ) + { + int32 i; Read( i ); x = T( i ); + } + + /*! + * Reads a numeric variable as a 32-bit unsigned integer. + */ + template + void ReadUI32( T& x ) + { + uint32 i; Read( i ); x = T( i ); + } + + /*! + * Reads a numeric variable as a 64-bit signed integer. + */ + template + void ReadI64( T& x ) + { + int64 i; Read( i ); x = T( i ); + } + + /*! + * Reads a numeric variable as a 64-bit unsigned integer. + */ + template + void ReadUI64( T& x ) + { + uint64 i; Read( i ); x = T( i ); + } + + /*! + * Writes a contiguous block of \a len bytes from the specified \a buffer. + */ + virtual void Write( const void* buffer, fsize_type len ); + + /*! + * Writes an object \a x of type T. + */ + template + void Write( const T& x ) + { + Write( (const void*)&x, sizeof( T ) ); + } + + /*! + * Writes a set of \a n consecutive objects of type T from the array pointed + * to by \a a. + * + * This is a convenience member function, equivalent to + * Write( (const void*)a, n*sizeof( T ) ) + */ + template + void WriteArray( const T* a, size_type n ) + { + Write( (const void*)a, n*sizeof( T ) ); + } + + /*! + * Writes a numeric variable as a 32-bit signed integer. + */ + template + void WriteI32( const T& x ) + { + Write( int32( x ) ); + } + + /*! + * Writes a numeric variable as a 32-bit unsigned integer. + */ + template + void WriteUI32( const T& x ) + { + Write( uint32( x ) ); + } + + /*! + * Writes a numeric variable as a 64-bit signed integer. + */ + template + void WriteI64( const T& x ) + { + Write( int64( x ) ); + } + + /*! + * Writes a numeric variable as a 64-bit unsigned integer. + */ + template + void WriteUI64( const T& x ) + { + Write( uint64( x ) ); + } + + /*! + * Reads a boolean variable. + * + * This function reads a 32-bit integer and assigns true to the variable + * \a b iff the read number is nonzero. + */ + void Read( bool& b ) + { + unsigned i; ReadUI32( i ); b = i != 0; + } + + /*! + * Writes a boolean variable. + * + * This function writes a 32-bit integer with a value of 1 (one) if the + * variable \a b is true, zero otherwise. + */ + void Write( const bool& b ) + { + WriteUI32( b ? 1 : 0 ); + } + + /*! + * Reads a dynamic 8-bit string stored as binary data. The data should have + * been generated by a previous call to Write( const IsoString& ) on the + * file being read. + */ + void Read( IsoString& s ); + + /*! + * Reads a dynamic UTF-16 string stored as binary data. The data should have + * been generated by a previous call to Write( const IsoString& ) on the + * file being read. + */ + void Read( String& s ); + + /*! + * Writes a sequence of 8-bit characters, defined by the range [i,j), as + * binary data. + */ + void Write( const char* i, const char* j ); + + /*! + * Writes a null-terminated 8-bit string as binary data. + */ + void Write( const char* s ) + { + Write( s, s + IsoCharTraits::Length( s ) ); + } + + /*! + * Writes a dynamic 8-bit string as binary data. + */ + void Write( const IsoString& s ) + { + Write( s.Begin(), s.End() ); + } + + /*! + * Writes a sequence of UTF-16 characters, defined by the range [i,j), as + * binary data. + */ + void Write( const char16_type* i, const char16_type* j ); + + /*! + * Writes a null-terminated string of UTF-16 characters as binary data. + */ + void Write( const char16_type* s ) + { + Write( s, s + CharTraits::Length( s ) ); + } + + /*! + * Writes a dynamic UTF-16 string as binary data. + */ + void Write( const String& s ) + { + Write( s.Begin(), s.End() ); + } + +#ifndef __PCL_NO_FLAGS_FILE_IO + + /*! + * Reads a set of flags \a f. + */ + template + static void Read( Flags& f ) + { + Read( f.m_flags ); + } + + /*! + * Reads a set of flags \a f as an unsigned 32-bit integer. + */ + template + static void ReadUI32( Flags& f ) + { + ReadUI32( f.m_flags ); + } + + /*! + * Writes a set of flags \a f. + */ + template + static void Write( Flags f ) + { + Write( f.m_flags ); + } + + /*! + * Writes a set of flags \a f as an unsigned 32-bit integer. + */ + template + static void WriteUI32( Flags f ) + { + WriteUI32( f.m_flags ); + } + +#endif + + /*! + * Writes a sequence of 8-bit characters, defined by the range [i,j), as + * plain text. + */ + void OutText( const char* i, const char* j ) + { + if ( i < j ) + Write( (const void*)i, fsize_type( j - i ) ); + } + + /*! + * Writes a null-terminated 8-bit string as plain text. + */ + void OutText( const char* s ) + { + OutText( s, s + IsoCharTraits::Length( s ) ); + } + + /*! + * Writes a dynamic 8-bit string as plain text. + */ + void OutText( const IsoString& s ) + { + OutText( s.Begin(), s.End() ); + } + + /*! + * Writes a sequence of UTF-16 characters, defined by the range [i,j), as + * plain text. + */ + void OutText( const char16_type* i, const char16_type* j ) + { + if ( i < j ) + Write( (const void*)i, fsize_type( j - i ) << 1 ); + } + + /*! + * Writes a null-terminated UTF-16 string as plain text. + */ + void OutText( const char16_type* s ) + { + OutText( s, s + CharTraits::Length( s ) ); + } + + /*! + * Writes a dynamic UTF16 string as plain text. + */ + void OutText( const String& s ) + { + OutText( s.Begin(), s.End() ); + } + + /*! + * Writes a sequence of 8-bit characters, defined by the range [i,j), as + * plain text. Then writes a newline character. + */ + void OutTextLn( const char* i, const char* j ) + { + OutText( i, j ); Write( '\n' ); + } + + /*! + * Writes a null-terminated 8-bit string as plain text and appends a newline + * character. + */ + void OutTextLn( const char* s ) + { + OutText( s ); Write( '\n' ); + } + + /*! + * Writes an 8-bit newline character ('\n'). + * + * \warning Do not use this member function if you are generating plain text + * encoded as UTF-16, for example in a sequence of calls to + * OutTextLn( const String& s ). In such case you can call:\n + * \n + * \code OutTextLn( String() ); \endcode \n + * \n + * to generate a newline in UTF-16 format. + */ + void OutTextLn() + { + Write( '\n' ); + } + + /*! + * Writes a dynamic 8-bit string as plain text and appends a newline + * character. + */ + void OutTextLn( const IsoString& s ) + { + OutText( s ); Write( '\n' ); + } + + /*! + * Writes a sequence of UTF-16 characters, defined by the range [i,j), as + * plain text. Then writes a newline character. + */ + void OutTextLn( const char16_type* i, const char16_type* j ) + { + OutText( i, j ); Write( char16_type( '\n' ) ); + } + + /*! + * Writes a null-terminated UTF-16 string as plain text and appends a + * newline character. + */ + void OutTextLn( const char16_type* s ) + { + OutText( s ); Write( char16_type( '\n' ) ); + } + + /*! + * Writes a dynamic UTF16 string as plain text and appends a newline + * character. + */ + void OutTextLn( const String& s ) + { + OutText( s ); Write( char16_type( '\n' ) ); + } + + /*! + * Commits any pending write operations. + */ + void Flush(); + + /*! + * Opens or creates a file. + * + * \param path The path to the file to be opened or created. + * + * \param mode Desired file access, share (Windows only) and + * opening/creation mode. By default, an existing file will + * be opened for (exclusive on Windows) read-only access. + */ + virtual void Open( const String& path, FileModes mode = FileMode::Read|FileMode::Open ); + + /*! + * Opens an existing file at the specified \a path. On Windows, the file is + * opened for shared read-only access (on UNIX and Linux, file access is + * handled automatically, so there is no need to define 'sharing modes'). + */ + virtual void OpenForReading( const String& path ) + { + Open( path, FileMode::Read|FileMode::Open|FileMode::ShareRead ); + } + + /*! + * Returns an open existing file at the specified \a path. On Windows, the + * file is opened for shared read-only access (on UNIX and Linux, file + * access is handled automatically, so there is no need to define 'sharing + * modes'). + */ + static File OpenFileForReading( const String& path ) + { + File f; + f.OpenForReading( path ); + return f; + } + + /*! + * Opens an existing file at \a path for exclusive read/write access. + */ + virtual void OpenForReadWrite( const String& path ) + { + Open( path, FileMode::Read|FileMode::Write|FileMode::Open ); + } + + /*! + * Returns an open existing file at the specified \a path, ready for + * exclusive read/write access. + */ + static File OpenFileForReadWrite( const String& path ) + { + File f; + f.OpenForReadWrite( path ); + return f; + } + + /*! + * Creates a file at the specified \a path for exclusive read/write access. + * If a file already exists at the same \a path, its contents will be + * truncated to zero length. + */ + virtual void Create( const String& path ) + { + Open( path, FileMode::Read|FileMode::Write|FileMode::Create ); + } + + /*! + * Returns a newly created file at the specified \a path, ready for + * exclusive read/write access. If a file already exists at the same + * \a path, its contents will be truncated to zero length. + */ + static File CreateFile( const String& path ) + { + File f; + f.Create( path ); + return f; + } + + /*! + * Creates a file at the specified \a path for exclusive write-only access. + * If a file already exists at the same \a path, its contents will be + * truncated to zero length. + */ + virtual void CreateForWriting( const String& path ) + { + Open( path, FileMode::Write|FileMode::Create ); + } + + /*! + * Returns a newly created file at the specified \a path, ready for + * exclusive write-only access. If a file already exists at the same + * \a path, its contents will be truncated to zero length. + */ + static File CreateFileForWriting( const String& path ) + { + File f; + f.CreateForWriting( path ); + return f; + } + + /*! + * Opens a file at the specified \a path if it exists, or creates it + * otherwise. The file will be opened in exclusive read/write mode. + */ + void OpenOrCreate( const String& path ) + { + Open( path, FileMode::Read|FileMode::Write|FileMode::Open|FileMode::Create ); + } + + /*! + * Returns an open file at the specified \a path if it already exists, or a + * newly created file otherwise, ready for exclusive read/write access. + */ + static File OpenOrCreateFile( const String& path ) + { + File f; + f.OpenOrCreate( path ); + return f; + } + + /*! + * Closes an open file. If this file has not been opened, calling this + * member function has no effect. + */ + virtual void Close(); + + /*! + * Removes an existing file at the specified \a filePath. + */ + static void Remove( const String& filePath ); + + /*! + * Creates a new directory at the specified \a dirPath. + * + * If \a createIntermediateDirectories is true (the default value) and + * \a dirPath specifies one or more parent directories that don't exist, + * they are created automatically. + */ + static void CreateDirectory( const String& dirPath, bool createIntermediateDirectories = true ); + + /*! + * Removes an existing \e empty directory at the specified \a dirPath. + * + * The specified directory must be empty, or this function will fail. + */ + static void RemoveDirectory( const String& dirPath ); + + /*! + * Moves and/or renames a file. + * + * \param filePath Current path of the file to move/rename + * + * \param newFilePath New path. If the directory in \a newFilePath is the + * same as in \a filePath, or if no directory is specified, the + * file is just renamed. If a different directory is specified, + * the file is also moved. + * + * \warning This function can only move or rename a file to stay in the same + * physical device. To move a file across devices, use the File::MoveFile() + * static member function. + */ + static void Move( const String& filePath, const String& newFilePath ); + + /*! + * Returns true iff a file at the specified \a filePath exists. + */ + static bool Exists( const String& filePath ); + + /*! + * Returns true iff a directory at the specified \a dirPath exists. + */ + static bool DirectoryExists( const String& dirPath ); + + /*! + * Ensures existence of a file on the local filesystem, guaranteeing that a + * newly created file cannot replace or overwrite an already existing file, + * or clash with an existing directory. + * + * \param[in,out] filePath Path to the file that must exist with + * guaranteed uniqueness. The value of the variable referenced + * by this parameter can be modified on output; see the + * \a canOverwrite parameter and the description below for + * further details. + * + * \param canOverwrite If this parameter is false and the specified + * \a filePath corresponds to an already existing file, the + * string referenced by \a filePath will be replaced on output + * with a new path on the same directory where the file name has + * been modified to guarantee that no file existed with the same + * name upon calling this function. If this parameter is true + * the \a filePath string won't be modified in any way. + * + * After calling this function, a file at the path specified by the output + * value of the \a filePath variable is guaranteed to exist, either because + * such file already existed when the function was called and the + * \a canOverwrite parameter was true, or because a new empty file has been + * created otherwise. Already existing files are never touched or modified + * in any way by this function (beyond the fact that they are accessed to + * verify their existence). + * + * Returns a UniqueFileChecks structure where the \a exists member indicates + * whether the specified \a filePath corresponds to an already existing file + * upon calling this function, and the \a overwrite member is true iff an + * existing file can be overwritten because the specified \a canOverwrite + * parameter is true. + * + * When the \a filePath string is altered to provide a unique file name, the + * file path is made unique by appending the literal representation of an + * unsigned integer, preceded by an underscore character, to the file name + * component. For example, if this function is called as follows when the + * specified file already exists: + * + * \code + * String filePath = "/path/to/foo.bar"; // this file exists + * EnsureNewUniqueFile( filePath ); + * \endcode + * + * then the \c filePath variable could have the value "/path/to/foo_1.bar", + * and a new, empty file would have been created at that path. Successive + * calls would set \c filePath equal to "/path/to/foo_2.bar", + * "/path/to/foo_3.bar", and so on, creating the corresponding new files. + * + * \note This static member function is thread-safe. It will provide + * coherent results when invoked from multiple threads running concurrently. + */ + static UniqueFileChecks EnsureNewUniqueFile( String& filePath, bool canOverwrite = false ); + + /*! + * Ensures existence of a directory on the local filesystem, guaranteeing + * that a new, empty directory will be created in case a file or directory + * at the specified path already existed when the function was called. + * + * \param[in,out] dirPath Path to the directory that must exist with + * guaranteed uniqueness. The value of the variable referenced + * by this parameter can be modified on output; see the + * description below for further details. + * + * After calling this function, a directory at the path specified by the + * output value of the \a dirPath variable is guaranteed to exist, either + * because such directory already existed when the function was called, or + * because a new empty directory has been created otherwise. Already + * existing directories or files are never touched or modified in any way by + * this function (beyond the fact that they are accessed to verify their + * existence). + * + * Returns a UniqueFileChecks structure where the \a exists member indicates + * whether the specified \a dirPath corresponds to an already existing + * directory upon calling this function, and the \a overwrite member is + * always false, reflecting the fact that a directory cannot be overwritten. + * + * If the specified directory already exists, the string referenced by + * \a dirPath will be altered to provide a unique directory name on the same + * parent directory. In such case the path is made unique by appending the + * literal representation of an unsigned integer, preceded by an underscore + * character, to the file name component. For example, if this function is + * called as follows when the specified directory already exists: + * + * \code + * String dirPath = "/path/to/foobar"; // this directory exists + * EnsureNewUniqueDirectory( dirPath ); + * \endcode + * + * then the \c dirPath variable could have the value "/path/to/foobar_1" and + * a new, empty directory would have been created at that path. Successive + * calls would set \c dirPath equal to "/path/to/foobar_2", + * "/path/to/foobar_3", and so on, creating the corresponding new + * directories. + * + * The string referenced by the specified \a dirPath variable can optionally + * end with a directory separator character, which will be preserved in case + * the string is modified. + * + * \note This static member function is thread-safe. It will provide + * coherent results when invoked from multiple threads running concurrently. + */ + static UniqueFileChecks EnsureNewUniqueDirectory( String& dirPath ); + + /*! + * Returns true iff the file at \a filePath exists and the current user has + * read-only access to it. + */ + static bool IsReadOnly( const String& filePath ); + + /*! + * Enables or disables read-only access to a file at the specified + * \a filePath. + */ + static void SetReadOnly( const String& filePath, bool rdOnly = true ); + + /*! + * Disables or enables read-only access to a file at the specified + * \a filePath. + * + * This is a convenience member function, equivalent to + * SetReadOnly( filePath, false ) + */ + static void SetReadWrite( const String& filePath ) + { + SetReadOnly( filePath, false ); + } + + /*! + * Reads the contents of a file at the specified \a filePath and returns + * them as a ByteArray object. + */ + static ByteArray ReadFile( const String& filePath ); + + /*! + * Creates a file with the specified contents. + * + * \param filePath Path to the file that will be created. + * + * \param contents Reference to a ByteArray object providing the contents + * that will be written to the newly created file. + * + * Typically this function is used along with File::ReadFile() to implement + * a file copying routine; for example: + * + * \code + * void CopyFile( const String& targetFilePath, const String& sourceFilePath ) + * { + * File::WriteFile( targetFilePath, File::ReadFile( sourceFilePath ) ); + * } + * \endcode + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + static void WriteFile( const String& filePath, const ByteArray& contents ); + + /*! + * Creates a file with a subset of a ByteArray container. + * + * \param filePath Path to the file that will be created. + * + * \param contents Reference to a ByteArray object providing the contents + * that will be written to the newly created file. + * + * \param start Zero-based index of the first byte to be written. + * + * \param size Number of bytes that will be written. + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + static void WriteFile( const String& filePath, const ByteArray& contents, size_type start, size_type size ); + + /*! + * Creates a file with the specified contents. + * + * \param filePath Path to the file that will be created. + * + * \param data Pointer to the first byte to be written to the newly + * created file. + * + * \param size Number of contiguous bytes, starting from \a data, to + * be written. + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + static void WriteFile( const String& filePath, const void* data, size_type size ); + + /*! + * Reads the contents of a file at the specified \a filePath and returns + * them as plain text stored in a dynamic 8-bit string. + * + * This function is useful to load document files encoded in UTF-8, + * ISO/IEC-8859-1 (or Latin-1), and other 8-bit encodings. + */ + static IsoString ReadTextFile( const String& filePath ); + + /*! + * Creates a file with the specified plain text content. + * + * \param filePath Path to the file that will be created. + * + * \param text Reference to an IsoString object providing the plain + * text that will be written to the newly created file. + * + * This function is useful to generate document files encoded in UTF-8, + * ISO/IEC-8859-1 (or Latin-1), and other 8-bit encodings. + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + static void WriteTextFile( const String& filePath, const IsoString& text ); + + /*! + * Changes the access permissions of a file or directory. + * + * \param targetPath Path to the existing file or directory whose + * permissions will be modified. + * + * \param permissions An ORed combination of file permission flags. See + * the FilePermission namespace for contants. + * + * On UNIX and Linux platforms (FreeBSD, GNU Linux, Mac OS X), the read, + * write and execution permissions can be specified separately for the owner + * user, for the owner group, and for the rest of users. On Windows, only + * generic read and write permissions can be set, and there are no execution + * permissions. + */ + static void SetPermissions( const String& targetPath, FileAttributes permissions ); + + /*! + * Copies access and modification times and access permissions from one + * file or directory item to another. + * + * \param targetPath Path to the target item whose times and permissions + * will be changed. + * + * \param sourcePath Path to the source item whose times and permissions + * will be copied to the target item. + */ + static void CopyTimesAndPermissions( const String& targetPath, const String& sourcePath ); + +#ifndef __PCL_WINDOWS + /*! + * Copies a symbolic link. + * + * \param targetLinkPath Path to the target file. A new symbolic link will + * be created at this path, which will point to the + * same link target as the source link. + * + * \param sourceLinkPath Path to the source link, whose target will be + * copied to the target link. + * + * Note that this function creates a duplicate of the symbolic link itself, + * \e not of its pointed file. + * + * \note This static member function is only defined on UNIX and Linux + * platforms. It does not make sense on Windows, where POSIX symbolic links + * don't exist. + */ + static void CopyLink( const String& targetLinkPath, const String& sourceLinkPath ); +#endif // !__PCL_WINDOWS + + /*! + * Copies a single file. + * + * \param targetFilePath Path to the target file, which must \e not exist. + * If the specified file exists, an Error exception + * will be thrown. + * + * \param sourceFilePath Path to the source file. This file must exist and + * must be different from the specified target file. + * + * \param progress Pointer to an instance of (a derived class of) + * File::Progress. If a non-null pointer is + * specified, the object will be used to provide + * progress information and the possibility of + * aborting the file copy operation. The default + * value is \c nullptr. + * + * The file copy operation is implemented as an iterative block copying + * routine. This means that huge files can be copied with minimal + * consumption of memory resources and no specific file size limit. + * + * Along with the file contents, file access and modification times, as well + * as file access permissions, will also be copied by this function. + * + * This function does not follow symbolic links. It does not copy the file + * pointed to by a symbolic link, but the link itself. This is only relevant + * to platforms that support symbolic links (i.e., all of them but Windows). + * + * If a \a progress object is specified, it receives successive calls to + * File::Progress::Add() with increments in bytes. If the progress object + * aborts the file copy operation, this member function throws a + * ProcessAborted exception. + */ + static void CopyFile( const String& targetFilePath, const String& sourceFilePath, File::Progress* progress = nullptr ); + + /*! + * Moves a single file. + * + * \param targetFilePath Path to the target file, which must \e not exist. + * If the specified file exists, an Error exception + * will be thrown. + * + * \param sourceFilePath Path to the source file. This file must exist and + * must be different from the specified target file. + * + * \param progress Pointer to an instance of (a derived class of) + * File::Progress. If a non-null pointer is + * specified, the object will be used to provide + * progress information and the possibility of + * aborting the file copy operation. The default + * value is \c nullptr. + * + * For file move operations within the same physical device, this function + * implements a simple rename operation. In these cases, the \a progress + * object (if specified) receives a single call to File::Progress::Add() + * with the total file size in bytes. + * + * When a file is moved to a different device, this member function first + * copies the source file to the target location using a routine equivalent + * to Copy(). When the entire file contents have been transferred, the + * source file is removed. + * + * Along with the file contents, file access and modification times, as well + * as file access permissions, will be preserved by this function. + * + * This function does not follow symbolic links. It does not move the file + * pointed to by a symbolic link, but the link itself. This is only relevant + * to platforms that support symbolic links (i.e., all of them but Windows). + * + * If a \a progress object is specified and it aborts the file move + * operation, this member function throws a ProcessAborted exception. In + * such case the source file is guaranteed to remain intact. + */ + static void MoveFile( const String& targetFilePath, const String& sourceFilePath, File::Progress* progress = nullptr ); + + /*! + * Returns true iff two files or directories are mounted on the same physical + * device. + * + * This is relevant to some critical file operations. For example, moving a + * file on the same device is a simple and fast rename operation. However, + * moving a file across devices involves copying the entire file contents. + * + * This function does not follow symbolic links. It does not consider + * mounted devices for files pointed to by symbolic links, but for the links + * themselves. This is only relevant to platforms that support symbolic + * links (all of them but Windows). + */ + static bool SameDevice( const String& path1, const String& path2 ); + + /*! + * Returns true iff two file path specifications refer to the same file on + * the system. + * + * On UNIX and Linux platforms, this function compares the device and inode + * numbers reported by the st_dev and st_ino members of the stat structure, + * respectively. This pair of numbers uniquely identifies every file on the + * system, irrespective of file names. + * + * On Windows platforms, this function verifies the devices that support + * both files and, if they are the same, performs a case-insensitive + * comparison of the canonical absolute versions of the specified paths. + * + * This function does not follow symbolic links. It does not consider + * mounted devices for files pointed to by symbolic links, but for the links + * themselves. This is only relevant to platforms that support symbolic + * links (all of them but Windows). + */ + static bool SameFile( const String& path1, const String& path2 ); + + /*! + * Reads all existing text lines from a file as 8-bit strings (e.g., + * ISO 8859-1 or UTF-8 formats) and returns them as a string list. + * + * \param filePath Path to the source file from which text lines will + * be read. + * + * \param options Optional set of flags (ORed combination) that can be + * specified to control the way text lines are + * extracted and stored. Available flags are defined in + * the ReadTextOption namespace. + * + * Returns a string list (IsoStringList) with all existing lines in the + * specified file. If the file is empty, an empty string list is returned. + * + * This routine automatically detects and processes line ending sequences + * characteristic of all supported platforms: UNIX (LF = 0x0A), Windows + * (CR+LF = 0x0D+0x0A) and legacy Mac (CR = 0x0D). + */ + static IsoStringList ReadLines( const String& filePath, + ReadTextOptions options = ReadTextOptions() ); + + /*! + * Iterates a function through all existing text lines in a file. + * + * \param filePath Path to the source file from which text lines will + * be read. This file is assumed to store text as a + * sequence of 8-bit characters, e.g. ASCII, ISO 8859-1 + * or UTF-8. + * + * \param callback Callback function. This function will be invoked + * once for each text line. The function will receive + * two arguments: a char* with the starting address of + * an 8-bit null terminated string, and a void* which + * is the specified \a data argument. The function will + * return true if the process can continue for the next + * text line; false to stop the iteration. + * + * \param data A void* that will be passed to the callback function + * as its second argument on each call. The default + * value is \c nullptr. + * + * \param options Optional set of flags (ORed combination) that can be + * specified to control the way text lines are explored + * and passed to the callback function. Available flags + * are defined in the ReadTextOption namespace. + * + * Returns the number of text lines that have been scanned, i.e. the number + * of times the callback function has been invoked and has returned true. + * + * This routine avoids all the work associated with creating and storing new + * IsoString objects. When IsoString instances are not necessary to acquire + * the data being read, this routine can be much faster than ReadLines(), + * especially for vey large files. + * + * This routine automatically detects and processes line ending sequences + * characteristic of all supported platforms: UNIX (LF = 0x0A), Windows + * (CR+LF = 0x0D+0x0A) and legacy Mac (CR = 0x0D). + */ + static size_type ScanLines( const String& filePath, + bool (*callback)( char*, void* ), void* data = nullptr, + ReadTextOptions options = ReadTextOptions() ); + + /*! + * Returns the full, absolute local path to the specified \a path. + */ + static String FullPath( const String& path ); + + /*! + * Returns a valid URI with the "file" scheme corresponding to the specified + * local \a path. + * + * The returned URI is valid as specified by RFC 1738 and RFC 8089. The + * following characters will always be percent-encoded when present in the + * specified \a path: + * + * - Non-printable US-ASCII characters in the ranges [00-1F] and [7F-FF]. + * + * - Unsafe characters: ' ', '<', '>', '#', '"', '%', '{', '}', '|', '\\', + * '^', '~', '[', ']', '`' + * + * - Reserved characters: ';', '?', ':', '@', '=', '&'. + * + * The returned URI will include the specified path transformed to a full + * absolute local path with UNIX directory separators, encoded in UTF-8, + * percent-encoded as necessary, and prefixed with the "file://" scheme. + * + * On Windows, a drive letter will always be present, prefixed with a root + * directory specifier, and the colon separator will be used; for example: + * + * file:///c:/path/to/local%20file.txt + * + * \b References: + * + * https://tools.ietf.org/html/rfc1738 \n + * https://tools.ietf.org/html/rfc8089 \n + */ + static IsoString FileURI( const String& path ); + + /*! + * Returns the system temporary storage directory. + * + * On FreeBSD, Linux and macOS, this function returns the value of the + * TMPDIR environment variable if it is defined, nonempty, and is a valid + * path to an existing directory. Otherwise this function returns "/tmp". + * + * On Windows, this function returns the directory designated for storage of + * temporary files. Normally this is the value of the TMP or TEMP + * environment variable. If no valid directory can be retrieved this way + * (which is extremely weird), this function attempts to return the user's + * profile directory, as reported by the USERPROFILE variable. If that also + * fails, "C:/tmp" is returned if it exists, or the current working + * directory as a last resort. + */ + static String SystemTempDirectory(); + + /*! + * Returns the system cache storage directory. + * + * On FreeBSD, Linux and Windows, this function is equivalent to + * SystemTempDirectory(). + * + * On macOS, this function returns the user's local cache folder, namely + * "~/Library/Caches" if it exists (it must), or SystemTempDirectory() + * otherwise. + */ + static String SystemCacheDirectory(); + + /*! + * Returns the home directory of the current user. + * + * On FreeBSD, Linux and macOS, this function returns the value of the HOME + * environment variable if it is defined, nonempty, and is a valid path to + * an existing directory. In the extremely weird case this does not happen, + * the system root directory '/' is returned as a last resort. + * + * On Windows, this function returns the root directory of the current + * user's profile. This is normally the value of the USERPROFILE environment + * variable. In case this fails, the HOMEDRIVE, HOMEPATH and HOME variables + * are checked for validity. If everything fails, the SYSTEMDRIVE variable + * is checked and ultimately "C:/" is returned. + */ + static String HomeDirectory(); + + /*! + * Converts a path from Windows to UNIX syntax. Replaces all occurrences of + * the '\\' Windows separator with the '/' UNIX separator. + */ + static String WindowsPathToUnix( const String& path ); + + /*! + * Converts a path from UNIX to Windows. Replaces all occurrences of + * the '/' UNIX separator with the '\\' Windows separator. + */ + static String UnixPathToWindows( const String& path ); + + /*! + * Returns a nonexistent, randomly generated file name. + * + * \param directory Name of an existing directory where the generated file + * name is guaranteed to be unique. If empty or not + * specified, the current directory of the calling process + * will be used. + * + * \param n Number of random characters in the generated file name. + * Must be at least five characters. The default value is + * twelve characters. + * + * \param prefix An optional prefix that will be prepended to the + * generated file name. + * + * \param postfix An optional postfix that will be appended to the + * generated file name. + * + * This function returns the full absolute path of a nonexistent file name + * generated by concatenation of \a n random characters. For compatibility + * with case-insensitive file systems (FAT, NTFS), only uppercase characters + * and decimal digits are used in the generated file name. + * + * The returned file name is guaranteed to be unique on the specified + * directory (or on the current directory of the calling process if no + * directory is specified) just after this function returns. Note that since + * a high-quality random number generator is used to select file name + * characters, there is no practical chance for a race condition by calling + * this function from several threads concurrently. + */ + static String UniqueFileName( const String& directory = String(), int n = 12, + const String& prefix = String(), const String& postfix = String() ); + + /*! + * Retrieves the storage space available on the device that supports a + * specified directory. + * + * \param dirPath A path specification to an existing directory on the + * local filesystem. On Windows, UNC paths are fully + * supported. Symbolic links are supported on all + * platforms. If a symbolic link is specified, the + * returned values refer to the target device. + * + * \param[out] totalBytes If non-null, the address of a variable that + * receives the total capacity in bytes of the device that + * supports the specified directory. + * + * \param[out] freeBytes If non-null, the address of a variable that + * receives the total number of free bytes on the device + * that supports the specified directory. + * + * Returns the total number of bytes available on the device that supports + * the specified directory. The returned values take into account any disk + * quotas that might apply to the user associated with the calling process. + */ + static uint64 GetAvailableSpace( const String& dirPath, uint64* totalBytes = nullptr, uint64* freeBytes = nullptr ); + + /*! + * Finds a Windows drive specification in the specified \a path. + * + * Returns the character index position of the drive found, or + * String::notFound. + * + * This function only makes sense on Windows. On UNIX and Linux operating + * systems, this function always returns String::notFound. + */ + static size_type FindDrive( const String& path ); + + /*! + * Finds a file name in the specified \a path. + * + * Returns the character index position of the name found, or + * String::notFound. + * + * For example, in '/foo/bar.tar.gz' the file name is 'bar'. + */ + static size_type FindName( const String& path ); + + /*! + * Finds a file extension in the specified \a path. + * + * Returns the character index position of the extension found, or + * String::notFound. + * + * The file extension, or file suffix, is the rightmost substring of \a path + * starting with the last occurrence of a dot character. For example, in + * 'foo.tar.gz' the file extension is '.gz'. + * + * \sa FindCompleteSuffix() + */ + static size_type FindExtension( const String& path ); + + /*! + * A synonym for FindExtension(). + */ + static size_type FindSuffix( const String& path ) + { + return FindExtension( path ); + } + + /*! + * Finds the complete file suffix in the specified \a path. + * + * Returns the character index position of the complete suffix found, or + * String::notFound. + * + * The complete suffix is the rightmost substring of the \a path starting + * with the first occurrence of a dot character. For example, in + * 'foo.tar.gz' the complete suffix is '.tar.gz'. + * + * \sa FindSuffix() + */ + static size_type FindCompleteSuffix( const String& path ); + + /*! + * Extracts a Windows drive specification from the specified \a path. + * + * Returns the extracted drive specification as a new string, or an empty + * string if no drive was found. + * + * This function only makes sense on Windows. On UNIX and Linux operating + * systems, this function always returns an empty string. + */ + static String ExtractDrive( const String& path ); // always empty string on X + + /*! + * Extracts a directory specification from the specified \a path. + * + * Returns the extracted directory specification, or an empty string if no + * directory was found. On Windows, the drive element of the path is not + * included. + * + * Examples: + * + * In '/foo.tar.gz' the directory is '/'. + * In '/foo/bar.tar.gz' the directory is '/foo'. + * In 'foo/bar.tar.gz' the directory is 'foo'. + * In 'C:/Foo/Bar.txt' the directory is '/Foo'. + */ + static String ExtractDirectory( const String& path ); + + /*! + * Extracts a file name from the specified \a path. + * + * Returns the extracted name, or an empty string if no file name was found. + * The file extension or suffix is not included. + * + * Examples: + * + * In '/foo/bar.tar.gz' the name is 'bar.tar'. + * In 'C:/Foo/Bar.txt' the name is 'Bar'. + */ + static String ExtractName( const String& path ); + + /*! + * Extracts a file extension from the specified \a path. + * + * Returns the extracted extension, or an empty string if no file extension + * was found. The returned extension \e includes the initial dot separator. + * + * Examples: + * + * In '/foo/bar.tar.gz' the extension is '.gz'. + * In 'C:/Foo/Bar.txt' the extension is '.txt'. + * + * \sa ExtractCompleteSuffix() + */ + static String ExtractExtension( const String& path ); + + /*! + * A synonym for ExtractExtension(). + */ + static String ExtractSuffix( const String& path ) + { + return ExtractExtension( path ); + } + + /*! + * Extracts the complete file suffix from the specified \a path. + * + * Returns the extracted complete suffix, or an empty string if no file + * suffix was found. The returned string \e includes the initial dot + * separator. + * + * The complete suffix is the ending substring of the file identifier in the + * specified \a path, starting with the first occurrence of a dot character. + * For example, in 'foo.tar.gz' the complete suffix is '.tar.gz'. + * + * \sa ExtractSuffix() + */ + static String ExtractCompleteSuffix( const String& path ); + + /*! + * Extracts the file name and extension from the specified \a path. Calling + * this member function is functionally equivalent to: + * + * File::ExtractName( path ) + File::ExtractExtension( path ) + */ + static String ExtractNameAndExtension( const String& path ); + + /*! + * A synonym for ExtractNameAndExtension(). + */ + static String ExtractNameAndSuffix( const String& path ) + { + return ExtractNameAndExtension( path ); + } + + /*! + * Changes the current file extension in \a filePath to a new extension + * \a ext. If it is not an empty string, the specified extension \e must + * include the initial dot separator. + * + * If the specified new extension \a ext is an empty string, this function + * returns \a filePath with its extension (if any) removed. + * + * Returns the resulting path after changing the file extension to the + * specified value. + */ + static String ChangeExtension( const String& filePath, const String& ext ); + + /*! + * Appends a \a postfix string to the current file name in the specified + * \a filePath. Returns the resulting path. + */ + static String AppendToName( const String& filePath, const String& postfix ); + + /*! + * Prepends a \a prefix string to the current file name in the specified + * \a filePath. Returns the resulting path. + */ + static String PrependToName( const String& filePath, const String& prefix ); + + /*! + * Returns a readable textual representation of a file size with automatic + * units conversion. + * + * \param sizeInBytes The file size in bytes. + * + * \param precision The number of decimal digits used to represent + * floating point numbers. The default value is 3. + * + * \param alsoShowBytes Whether to add the size in bytes to the string + * representation, irrespective of the units used. The + * default value is false. + * + * Examples: + * + * \code + * String s1 = File::SizeAsString( 21771472 ); + * // s1 = "20.763 MiB" + * String s2 = File::SizeAsString( 21771472, 2, true ); + * // s2 = "20.76 MiB (21771472 bytes)" + * String s3 = File::SizeAsString( 4727, 4 ); + * // s3 = "4.6162 KiB" + * \endcode + */ + static String SizeAsString( fsize_type sizeInBytes, int precision = 3, bool alsoShowBytes = false ); + +protected: + + handle m_fileHandle; + String m_filePath; + FileModes m_fileMode; + + static const handle s_invalidHandle; + + void Initialize(); + virtual bool IsValidHandle( handle h ) const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_File_h + +// ---------------------------------------------------------------------------- +// EOF pcl/File.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileDataCache.h b/3rdparty/include/pcl/FileDataCache.h new file mode 100644 index 0000000..82e5f21 --- /dev/null +++ b/3rdparty/include/pcl/FileDataCache.h @@ -0,0 +1,549 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileDataCache.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_FileDataCache_h +#define __PCL_FileDataCache_h + +/// \file pcl/FileDataCache.h + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class FileDataCacheItem + * \brief Element of a file data cache + * + * This class represents a file in a FileDataCache object. This is a basic + * cache item structure to transport a full file path and, the known time of + * last file modification, and the time of last cache access. + */ +class PCL_CLASS FileDataCacheItem +{ +public: + + String path; //!< Full path to the file represented by this item. + TimePoint time; //!< Cached file time. + TimePoint lastUsed; //!< Time this cache item was last used. + + /*! + * Virtual destructor. + */ + virtual ~FileDataCacheItem() + { + } + + /*! + * Assigns data from another cache \a item. + */ + void Assign( const FileDataCacheItem& item ) + { + path = item.path; + time = item.time; + lastUsed = item.lastUsed; + } + + /*! + * Returs true iff this object represents the same file as another cache + * \a item. + */ + bool operator ==( const FileDataCacheItem& item ) const + { + return path == item.path; + } + + /*! + * Returns true iff this object precedes another cache \a item. File cache + * items are sorted by full file paths in ascending order. + */ + bool operator <( const FileDataCacheItem& item ) const + { + return path < item.path; + } + + /*! + * Returns true iff the file represented by this cache item was last + * modified before the specified file time \a t. + * + * \note This member function ignores the milliseconds component of the + * specified FileTime instance, by setting it to zero. This is done to + * prevent wrong cache invalidations caused by unreliable file time + * milliseconds on Windows. + */ + bool ModifiedSince( FileTime t ) const + { + t.milliseconds = 0; + return time < TimePoint( t ); + } + + /*! + * Returns the amount of days elapsed since the time this cache item was + * last used. + */ + double DaysSinceLastUsed() const + { + return TimePoint::Now() - lastUsed; + } + +protected: + + /*! + * Assigns additional data stored in another file cache item. + * + * The default implementation does nothing. This virtual member function + * should be reimplemented by derived classes to ensure persistence of + * reimplementation-specific data. + */ + virtual void AssignData( const FileDataCacheItem& ) + { + } + + /*! + * Returns a string representation of additional data stored in this cache + * item. + * + * The default implementation returns an empty string. This virtual member + * function should be reimplemented by derived classes to allow access to + * reimplementation-specific data. + */ + virtual String DataToString() const + { + return String(); + } + + /*! + * Retrieves additional data from a list of string tokens. Returns true iff + * the data were successfully retrieved. + * + * The default implementation returns true. This virtual member function + * should be reimplemented by derived classes for retrieval of + * reimplementation-specific data. + */ + virtual bool GetDataFromTokens( const StringList& ) + { + return true; + } + + /*! + * Returns true iff the additional data stored in this cache item are valid. + * + * The default implementation returns true. This virtual member function + * should be reimplemented by derived classes for validation of + * reimplementation-specific data. + */ + virtual bool ValidateData() const + { + return true; + } + + /*! + * Returns a string serialization of a floating-point vector. The returned + * string can be deserialized with the GetVector() static member function. + */ + static String VectorToString( const DVector& ); + + /*! + * Deserializes a floating-point vector from the specified list of + * \a tokens, parsing the necessary tokens starting from the specified + * \a start iterator. + */ + static bool GetVector( DVector&, StringList::const_iterator& start, const StringList& tokens ); + + /*! + * Returns a string serialization of a floating-point matrix. The returned + * string can be deserialized with the GetMatrix() static member function. + */ + static String MatrixToString( const DMatrix& ); + + /*! + * Deserializes a floating-point matrix from the specified list of + * \a tokens, parsing the necessary tokens starting from the specified + * \a start iterator. + */ + static bool GetMatrix( DMatrix&, StringList::const_iterator& start, const StringList& tokens ); + + /*! + * Returns a string serialization of a floating-point multivector. The + * returned string can be deserialized with the GetMultiVector() static + * member function. + */ + static String MultiVectorToString( const DMultiVector& ); + + /*! + * Deserializes a floating-point vector from the specified list of + * \a tokens, parsing the necessary tokens starting from the specified + * \a start iterator. + */ + static bool GetMultiVector( DMultiVector&, StringList::const_iterator& start, const StringList& tokens ); + + /*! + * Returns a string serialization of an array of floating-point matrices. + * The returned string can be deserialized with the GetMatrices() static + * member function. + */ + static String MatricesToString( const Array& ); + + /*! + * Deserializes an array of floating-point matrices from the specified list + * of \a tokens, parsing the necessary tokens starting from the specified + * \a start iterator. + */ + static bool GetMatrices( Array&, StringList::const_iterator& start, const StringList& tokens ); + + /* + * Special constructor used for cache search operations. + */ + FileDataCacheItem( const String& p = String() ) : path( p ) + { + } + + /* + * Copy constructor. + */ + FileDataCacheItem( const FileDataCacheItem& ) = default; + +private: + + String ToString() const; + bool FromString( const String& s ); + + bool Load( const IsoString& keyPrefix, int index ); + void Save( const IsoString& keyPrefix, int index ) const; + + friend class FileDataCache; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class FileDataCache + * \brief Abstract base class of file data cache implementations. + * + * This class provides the necessary infrastructure to implement a file cache + * with persistent storage in module settings data. The main cache access + * functions provided by this class (to add, get and find cache items, as well + * as to clear the cache and query cache properties) are implemented as + * thread-safe routines. This supports applications performing parallel disk + * I/O operations. + * + * You'll find examples of use for this class in standard PixInsight modules + * such as ImageIntegration and SubframeSelector. + * + * \sa FileDataCacheItem, Settings + */ +class PCL_CLASS FileDataCache +{ +public: + + /*! + * Constructs a new file data cache with the specified settings \a key and + * maximum cache item duration in \a days. + * + * The specified \a key will be used to store all cache data structures + * associated with this object persistently in module settings data. See the + * Settings class for more information on module settings and settings keys. + * + * \warning If the specified number of \a days is ≤ 0, existing cache + * items will never expire. This is not recommended and can cause + * problems by increasing the size of stored core application settings + * indiscriminately. In general, the default maximum duration of 30 days is + * quite appropriate for most applications. + */ + FileDataCache( const IsoString& key, int days = 30 ); + + /*! + * Virtual destructor. + * + * Destroys and deallocates all file data cache items and internal + * structures associated with this object. Note that this refers to data + * currently stored in memory, not to persistent storage in module settings. + * To destroy data stored persistently, the Purge() member function must be + * called explicitly. + */ + virtual ~FileDataCache() + { + Clear(); + } + + /*! + * Returns an identifying name for this cache object. The default + * implementation returns "File Cache". Derived classes should reimplement + * this function to return more specific identifiers. + */ + virtual String CacheName() const + { + return "File Cache"; + } + + /*! + * Returns the current cache version. The default implementation returns 1. + * + * \sa MinSupportedVersion() + */ + virtual int Version() const + { + return 1; + } + + /*! + * Returns the minimum supported cache version. The default implementation + * returns 1. + * + * No items will be loaded from existing module settings data if their + * version is either less than the value returned by this function, or + * greater than the current cache version. This allows for a basic version + * control system with a range of valid cache versions. + * + * \sa Version() + */ + virtual int MinSupportedVersion() const + { + return 1; + } + + /*! + * Returns true iff this cache is currently enabled. A disabled cache does + * not load existing cache items when the Load() member function is invoked. + */ + bool IsEnabled() const + { + return m_enabled; + } + + /*! + * Enables this file data cache. + * + * Note that enabling a cache does not force a reload of existing cache + * items; the Load() member function must be called to perform that action. + * In the same way, disabling a cache does not remove any cache item, + * neither from existing internal data structures, nor from persistent + * settings storage. + */ + void Enable( bool enable ) + { + m_enabled = enable; + } + + /*! + * Returns the maximum duration in days of a valid cache item. + * + * Existing cache items that have not been accessed during a period larger + * than the value returned by this function will not be loaded from + * persistent settings data. + * + * \sa SetDuration(), NeverExpires() + */ + int Duration() const + { + return m_durationDays; + } + + /*! + * Sets a new maximum duration in days for valid cache items. + * + * \warning If the specified number of \a days is ≤ 0, existing cache + * items will never expire. This is not recommended and can cause + * problems by increasing the size of stored core application settings + * indiscriminately. In general, the default maximum duration of 30 days is + * quite appropriate for most applications. + * + * \sa Duration(), NeverExpires() + */ + void SetDuration( int days ) + { + m_durationDays = Max( 0, days ); + } + + /*! + * Returns true iff existing cache items associated with this object will + * never expire. + * + * \sa Duration(), SetDuration() + */ + bool NeverExpires() const + { + return m_durationDays <= 0; + } + + /*! + * Returns the total number of cache items associated with this object. + * + * The returned value corresponds to the number of cache items currently + * stored in internal data structures. This includes cache items loaded from + * existing module settings data as well as items newly created and possibly + * still not copied to persistent storage. + * + * \note This function is thread-safe. + */ + size_type NumberOfItems() const; + + /*! + * Returns true iff this cache is empty, i.e. if there are no cache items + * associated with this object. + * + * The returned value is the number of items currently stored in internal + * memory data structures. This does not necessarily equals the total number + * of items currently stored in persistent module settings. + * + * \note This function is thread-safe. + */ + bool IsEmpty() const; + + /*! + * Returns the address of a file cache item corresponding to the specified + * file \a path, or nullptr if no such cache item could be found. + * + * \note This function is thread-safe. + * + * \sa Get() + */ + const FileDataCacheItem* Find( const String& path ) const; + + /*! + * Destroys and removes all cache items currently associated with this + * object. + * + * Only items stored in internal memory data structures are removed by this + * function. Persistent storage in module settings data is not altered. + * + * \note This function is thread-safe. + */ + void Clear(); + + /*! + * Adds the specified \a item to this cache. + * + * The item will be stored in internal memory data structures, \e not in + * persistent module settings data. To store cache items persistently, the + * Save() member function must be called for this object. + * + * \note This function is thread-safe. + */ + void Add( const FileDataCacheItem& item ); + + /*! + * Retrieves a copy of the existing cache data corresponding to the + * specified file \a path in the specified \a item. + * + * Returns true iff a cache item for the specified \a path was found in + * internal memory data structures, and its data were copied. If false is + * returned, the specified \a item will not be modified in any way. + * + * \note This function is thread-safe. + * + * \sa Find() + */ + bool Get( FileDataCacheItem& item, const String& path ); + + /*! + * Loads existing cache items from persistent module settings data. + * + * All previously existing cache items stored in internal memory structures + * will be destroyed and deallocated before loading new data. + */ + virtual void Load(); + + /*! + * Writes all cache items associated with this object to persistent module + * settings data. + */ + virtual void Save() const; + + /*! + * Destroys and deallocates all existing cache items, including all items + * currently in internal memory data structures as well as all items stored + * in persistent module settings data. + */ + virtual void Purge() const; + +protected: + + /*! + * Allocates and constructs a new cache item. + * + * Returns a pointer to the newly created cache item. The new item will be + * owned by this object, which will destroy and deallocate it automatically + * when appropriate. + * + * This is a pure virtual member function that must be reimplemented by all + * derived classes. This is because the data transported by a cache item is + * application-specific and cannot be known in advance by this class. + */ + virtual FileDataCacheItem* NewItem() const = 0; + +private: + + typedef ReferenceSortedArray cache_index; + + mutable Mutex m_mutex; + cache_index m_cache; + IsoString m_keyPrefix; + int m_durationDays = 30; // <= 0 -> never expires + bool m_enabled = true; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FileDataCache_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileDataCache.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileDataCachePreferencesDialog.h b/3rdparty/include/pcl/FileDataCachePreferencesDialog.h new file mode 100644 index 0000000..6c57f16 --- /dev/null +++ b/3rdparty/include/pcl/FileDataCachePreferencesDialog.h @@ -0,0 +1,123 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileDataCachePreferencesDialog.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_FileDataCachePreferencesDialog_h +#define __PCL_FileDataCachePreferencesDialog_h + +/// \file pcl/FileDataCache.h + +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS FileDataCache; + +/*! + * \class FileDataCachePreferencesDialog + * \brief A dialog to edit file data cache preferences settings + * + * This dialog allows to define persistence and maximum duration for file data + * cache items associated with a given FileDataCache instance. The dialog also + * allows to clear all cache items in memory and/or persistent storage. + */ +class PCL_CLASS FileDataCachePreferencesDialog : public Dialog +{ +public: + + /*! + * Constructs a new dialog to edit preferences settings for the specified + * \a cache object. + */ + FileDataCachePreferencesDialog( FileDataCache* cache ); + +private: + + FileDataCache* m_cache; + bool m_cacheEnabled; + int m_cacheDuration; + + VerticalSizer Global_Sizer; + HorizontalSizer PersistentCache_Sizer; + CheckBox PersistentCache_CheckBox; + HorizontalSizer CacheDuration_Sizer; + Label CacheDuration_Label; + SpinBox CacheDuration_SpinBox; + HorizontalSizer ClearCache_Sizer; + PushButton ClearCache_PushButton; + HorizontalSizer PurgeCache_Sizer; + PushButton PurgeCache_PushButton; + HorizontalSizer Buttons_Sizer; + PushButton OK_PushButton; + PushButton Cancel_PushButton; + + void Update(); + + void e_ValueUpdated( SpinBox& sender, int value ); + void e_Click( Button& sender, bool checked ); + void e_Return( Dialog& sender, int retVal ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FileDataCachePreferencesDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileDataCachePreferencesDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileDialog.h b/3rdparty/include/pcl/FileDialog.h new file mode 100644 index 0000000..857ce95 --- /dev/null +++ b/3rdparty/include/pcl/FileDialog.h @@ -0,0 +1,535 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileDialog.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_FileDialog_h +#define __PCL_FileDialog_h + +/// \file pcl/FileDialog.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class FileDialogPrivate; +class OpenFileDialogPrivate; +class SaveFileDialogPrivate; +class GetDirectoryDialogPrivate; + +// ---------------------------------------------------------------------------- + +/*! + * \class FileFilter + * \brief A description of a file type and its associated file extensions + * + * %FileFilter is a simple class to describe a file type and enumerate its + * associated file extensions. That information plays a key role in file + * dialogs as OpenFileDialog and SaveFileDialog. + * + * \sa FileDialog, GetDirectoryDialog, OpenFileDialog, SaveFileDialog + */ +class PCL_CLASS FileFilter +{ +public: + + /*! + * Constructs an empty %FileFilter object. + */ + FileFilter() = default; + + /*! + * Constructs a %FileFilter with the specified \a description and list of + * file \a extensions. + */ + FileFilter( const String& description, const StringList extensions ) + { + SetDescription( description ); + AddExtensions( extensions ); + } + + /*! + * Constructs a %FileFilter with the specified \a description and a single + * file \a extension. + */ + FileFilter( const String& description, const String& extension ) + { + SetDescription( description ); + AddExtension( extension ); + } + + /*! + * Copy constructor. + */ + FileFilter( const FileFilter& x ) = default; + + /*! + * Virtual destructor. + */ + virtual ~FileFilter() + { + } + + /*! + * Returns the description of the file type represented by this %FileFilter + * object. Example: "FITS Files". + */ + String Description() const + { + return m_description; + } + + /*! + * Sets the \a description of the file type represented by this %FileFilter + * object. + */ + void SetDescription( const String& description ) + { + m_description = description.Trimmed(); + } + + /*! + * Returns a list of file extensions associated to the file type represented + * by this %FileFilter object. Example: ".fit", ".fits", ".fts". + */ + const StringList& Extensions() const + { + return m_extensions; + } + + /*! + * Adds a file \a extension associated with the file type represented by + * this %FileFilter object. + */ + void AddExtension( const String& extension ); + + /*! + * Adds an ordered list of file \a extensions. + */ + void AddExtensions( const StringList& extensions ) + { + for ( const String& extension : extensions ) + AddExtension( extension ); + } + + /*! + * Clears the file type description and the list of file extensions. + */ + void Clear(); + +private: + + String m_description; + StringList m_extensions; + + String MakeAPIFilter() const; + + friend class FileDialogPrivate; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class FileDialog + * \brief Abstract base class of PCL file dialogs + * + * ### TODO: Write a detailed description for %FileDialog. + * + * \sa GetDirectoryDialog, OpenFileDialog, SaveFileDialog, FileFilter + */ +class PCL_CLASS FileDialog +{ +public: + + /*! + * A list of file filters describing file types and their associated file + * extensions. + */ + typedef Array filter_list; + + /*! + * Constructs a %FileDialog object. + */ + FileDialog(); + + /*! + * Destroys a %FileDialog object. + */ + virtual ~FileDialog(); + + /*! + * Returns the caption of this file dialog. + */ + String Caption() const; + + /*! + * Sets a new \a caption for this file dialog. If an empty caption is + * specified, the platform will assign a default caption depending on the + * type of dialog: "Open File", "Save File As", and so on. + */ + void SetCaption( const String& caption ); + + /*! + * Returns the initial path for this file dialog. + * + * If not empty, the initial directory is selected upon dialog execution. If + * the initial path points to a file, that file is set as the initial dialog + * selection, if appropriate. + */ + String InitialPath() const; + + /*! + * Sets the initial path for this file dialog. See InitialPath() + * for a full description. + */ + void SetInitialPath( const String& path ); + + /*! + * Returns a reference to the immutable list of file filters in this file + * dialog. + */ + const filter_list& Filters() const; + + /*! + * Defines the list of file \a filters to be used by this file dialog. + */ + void SetFilters( const filter_list& filters ); + + /*! + * Defines a unique file \a filter to be used by this file dialog. + */ + void SetFilter( const FileFilter& filter ) + { + SetFilters( filter_list() << filter ); + } + + /*! + * Adds a set of file \a filters to the list of filters used by this file + * dialog. + */ + void AddFilters( const filter_list& filters ); + + /*! + * Adds a file \a filter to the list of filters used by this file dialog. + */ + void AddFilter( const FileFilter& filter ) + { + AddFilters( filter_list() << filter ); + } + + /*! + * Returns a reference to the mutable list of file filters in this file + * dialog. + * + * \deprecated This member function has been deprecated. It is kept just to + * support existing code and must not be used in newly produced code. Use + * SetFilters() instead of this function. + */ + filter_list& Filters(); + + /*! + * Returns the selected file extension in this file dialog. + * + * If not empty, a file filter containing the specified file extension will + * be selected upon dialog execution. After an accepted call to Execute(), + * this property will store the extension of the first selected file. + */ + String SelectedFileExtension() const; + + /*! + * Sets the selected file extension for this file dialog. + * See SelectedFileExtension() for a full description. + */ + void SetSelectedFileExtension( const String& ); + + /*! + * Modal dialog execution. + * + * Returns true if the dialog has been accepted; false if the dialog has + * been cancelled. + */ + virtual bool Execute() = 0; + +protected: + + AutoPointer p; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class OpenFileDialog + * \brief A modal dialog box to select one or more existing files + * + * ### TODO: Write a detailed description for %FileDialog. + * + * \sa GetDirectoryDialog, FileDialog, SaveFileDialog, FileFilter + */ +class PCL_CLASS OpenFileDialog : public FileDialog +{ +public: + + /*! + * Constructs an %OpenFileDialog object. + */ + OpenFileDialog(); + + /*! + * Destroys an %OpenFileDialog object. + */ + virtual ~OpenFileDialog(); + + /*! + * Loads a set of file filters corresponding to all installed file formats + * that are able to read image files. + * + * The set of file filters loaded by this function will depend on the file + * format modules currently installed on the PixInsight platform. Typically + * it will include formats like FITS, TIFF, JPEG, JPEG2000, and DSLR RAW. + * In the unlikely event that no file format able to read files is installed + * on the platform, the filter set will be empty. + * + * Before the set of format-specific file filters, an additional filter is + * always included that comprises the whole set of reading-capable formats, + * i.e. a first "All known formats" filter is always present. + */ + void LoadImageFilters(); + + /*! + * Returns true iff this dialog accepts multiple selections. + * + * When multiple selections are enabled, the user can select a list of one + * or more existing files. When this mode is disabled, only a single + * existing file can be selected. + * + * \sa EnableMultipleSelections(), DisableMultipleSelections() + */ + bool AllowsMultipleSelections() const; + + /*! + * Enables or disables multiple file selections for this dialog. + * + * \sa DisableMultipleSelections(), AllowsMultipleSelections() + */ + void EnableMultipleSelections( bool enable = true ); + + /*! + * Disables or enables multiple file selections for this dialog. + * + * This is a convenience member function, equivalent to + * EnableMultipleSelections( !disable ). + * + * \sa DisableMultipleSelections(), AllowsMultipleSelections() + */ + void DisableMultipleSelections( bool disable = true ) + { + EnableMultipleSelections( !disable ); + } + + /*! + */ + bool Execute() override; + + /*! + * Returns a reference to the list of selected files. + * + * Each element in the returned list is a full path to a selected file. + * + * When multiple selections are enabled, the returned list may contain one + * or more file paths. + */ + const StringList& FileNames() const; + + /*! + * Returns the first selected file path. + * + * Use this member function to access a single file name, when multiple + * selections are disabled, or to the first file name of a multiple + * selection. + */ + String FileName() const; + +private: + + AutoPointer q; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SaveFileDialog + * \brief A modal dialog box to select a single file name for output + * + * ### TODO: Write a detailed description for %SaveFileDialog. + * + * \sa GetDirectoryDialog, OpenFileDialog, FileDialog, FileFilter + */ +class PCL_CLASS SaveFileDialog : public FileDialog +{ +public: + + /*! + * Constructs a %SaveFileDialog object + */ + SaveFileDialog(); + + /*! + * Destroys a %SaveFileDialog object + */ + virtual ~SaveFileDialog(); + + /*! + * Loads a set of file filters corresponding to all installed file formats + * that are able to write image files. + * + * The set of file filters loaded by this function will depend on the file + * format modules currently installed on the PixInsight platform. Typically + * it will include formats like FITS, TIFF, JPEG, and JPEG2000. In the + * (improbable) event that no file format able to write files is installed + * on the platform, the filter set will be empty. + */ + void LoadImageFilters(); + + /*! + * Returns true iff overwrite prompts are enabled for this dialog. + * + * When overwrite prompts are enabled, the dialog will request confirmation + * if an existing file is selected. + * + * \sa EnableOverwritePrompt(), DisableOverwritePrompt() + */ + bool IsOverwritePromptEnabled() const; + + /*! + * Enables or disables overwrite prompts for this dialog. + * + * \sa DisableOverwritePrompt(), IsOverwritePromptEnabled() + */ + void EnableOverwritePrompt( bool enable = true ); + + /*! + * Disables or enables overwrite prompts for this dialog. + * + * This is a convenience member function, equivalent to + * EnableOverwritePrompt( !disable ) + * + * \sa EnableOverwritePrompt(), IsOverwritePromptEnabled() + */ + void DisableOverwritePrompt( bool disable = true ) + { + EnableOverwritePrompt( !disable ); + } + + /*! + */ + bool Execute() override; + + /*! + * Returns the selected file path. A full file path is always returned. + */ + String FileName() const; + +private: + + AutoPointer q; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GetDirectoryDialog + * \brief A modal dialog box to select an existing directory + * + * ### TODO: Write a detailed description for %GetDirectoryDialog. + * + * \sa FileDialog, OpenFileDialog, SaveFileDialog + */ +class PCL_CLASS GetDirectoryDialog : public FileDialog +{ +public: + + /*! + * Constructs a %GetDirectoryDialog object + */ + GetDirectoryDialog(); + + /*! + * Destroys a %GetDirectoryDialog object + */ + virtual ~GetDirectoryDialog(); + + /*! + */ + bool Execute() override; + + /*! + * Returns the selected directory path. A full path is always returned. + */ + String Directory() const; + +private: + + AutoPointer q; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FileDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileFormat.h b/3rdparty/include/pcl/FileFormat.h new file mode 100644 index 0000000..77c5221 --- /dev/null +++ b/3rdparty/include/pcl/FileFormat.h @@ -0,0 +1,495 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileFormat.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_FileFormat_h +#define __PCL_FileFormat_h + +/// \file pcl/FileFormat.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class FileFormatPrivate; + +/*! + * \class FileFormat + * \brief High-level interface to an installed image file format. + * + * %FileFormat instances are high-level, managed objects that represent + * installed image file formats in the PixInsight platform. A module creates an + * instance of %FileFormat to gain access to an installed file format through + * intermodule communication. + * + * %FileFormat and %MetaFileFormat + * + * %FileFormat provides a description of the functionality and properties of an + * already installed image file format. Contrarily, by subclassing the + * MetaFileFormat class a module can define and implement a new image file + * format that can be installed in the PixInsight platform. %MetaFileFormat is + * a formal description of a file format, while %FileFormat describes an + * existing (and installed) file format. + * + * As a %MetaFileFormat subclass describes how a format can be instantiated, + * %FileFormat allows a module to create new instances of a file format that + * can be used to access actual image files. %FileFormat doesn't provide any + * file handling functionality; access to image files is provided by the + * FileFormatInstance class. + * + * \sa FileFormatBase, MetaFileFormat, FileFormatInstance + */ +class PCL_CLASS FileFormat : public FileFormatBase +{ +public: + + /*! + * Constructs a %FileFormat object. + * + * \param nameExtOrMime A format name, file suffix, or MIME type. This + * parameter determines how the PixInsight core + * application looks for an installed file format to which + * this %FileFormat instance will be an interface. + * + * \param toRead When a file suffix or MIME type is specified and this + * parameter is true, a %FileFormat instance will be + * created for an installed file format able to read files + * with the specified file suffix or corresponding to the + * specified MIME type. + * + * \param toWrite When a file suffix or MIME type is specified and this + * parameter is true, a %FileFormat instance will be + * created for an installed file format able to write + * files with the specified file suffix or corresponding + * to the specified MIME type. + * + * When a format name is used as the argument of this constructor, + * %FileFormat will provide access to an installed file format with the + * specified identifier, if there exists one. If the argument is a string + * starting with a dot character, then it is interpreted as a file suffix. + * If the argument has a slash character ('/'), it is interpreted as a MIME + * type specifier. In the latter two cases, the PixInsight core application + * will search for an installed file format able to handle image files with + * the specified file suffix or for the specified MIME type. + * + * In all cases, if no installed file format fits to the specified + * argument(s), this constructor throws an Error exception with the + * corresponding error message. Your code should guarantee that these + * exceptions will be caught and handled appropriately. + * + * When \a nameExtOrMime specifies a format name, the \a toRead and + * \a toWrite parameters are ignored. + * + * Example: + * + * \code + * try + * { + * // Find a format able to read XISF files + * FileFormat xisfFormat( ".xisf", true ); + * + * // Create a format instance + * FileFormatInstance myXISFFile( xisfFormat ); + * + * // Use the instance to open an existing file + * myXISFFile.Open( "/path/to/test.xisf" ); + * + * // Read an image in 32-bit floating point format + * Image img; + * myXISFFile.ReadImage( img ); + * // ... + * } + * catch ( Exception& x ) + * { + * // Handle errors ... + * } + * \endcode + * + * \note The \a toRead and \a toWrite parameters are false by default, which + * means that no access restrictions are applied by default when creating + * %FileFormat instances. + */ + FileFormat( const String& nameExtOrMime, bool toRead = false, bool toWrite = false ); + + /*! + * Copy constructor. Constructs an \e alias %FileFormat object that refers + * to the same image file format as the specified object \a fmt. + */ + FileFormat( const FileFormat& fmt ); + + /*! + * Destroys this %FileFormat object. + * + * \note This destructor does not destroy or uninstall the actual image file + * format it refers to, which is part of the PixInsight core application. + * Only the managed alias object living in the caller module is destroyed. + */ + virtual ~FileFormat(); + + /*! + */ + IsoString Name() const override; + + /*! + */ + StringList FileExtensions() const override; + + /*! + */ + IsoStringList MimeTypes() const override; + + /*! + */ + uint32 Version() const override; + + /*! + */ + String Description() const override; + + /*! + */ + String Implementation() const override; + + /*! + */ + String Status() const override; + + /*! + */ + Bitmap Icon() const override; + + /*! + */ + Bitmap SmallIcon() const override; + + /*! + */ + bool CanRead() const override; + + /*! + */ + bool CanWrite() const override; + + /*! + */ + bool CanReadIncrementally() const override; + + /*! + */ + bool CanWriteIncrementally() const override; + + /*! + */ + bool CanStore8Bit() const override; + + /*! + */ + bool CanStore16Bit() const override; + + /*! + */ + bool CanStore32Bit() const override; + + /*! + */ + bool CanStore64Bit() const override; + + /*! + */ + bool CanStoreFloat() const override; + + /*! + */ + bool CanStoreDouble() const override; + + /*! + */ + bool CanStoreComplex() const override; + + /*! + */ + bool CanStoreDComplex() const override; + + /*! + */ + bool CanStoreGrayscale() const override; + + /*! + */ + bool CanStoreRGBColor() const override; + + /*! + */ + bool CanStoreAlphaChannels() const override; + + /*! + */ + bool CanStoreResolution() const override; + + /*! + */ + bool CanStoreKeywords() const override; + + /*! + */ + bool CanStoreICCProfiles() const override; + + /*! + */ + bool CanStoreThumbnails() const override; + + /*! + */ + bool CanStoreProperties() const override; + + /*! + */ + bool CanStoreImageProperties() const override; + + /*! + */ + bool CanStoreRGBWS() const override; + + /*! + */ + bool CanStoreDisplayFunctions() const override; + + /*! + */ + bool CanStoreColorFilterArrays() const override; + + /*! + */ + bool SupportsCompression() const override; + + /*! + */ + bool SupportsMultipleImages() const override; + + /*! + */ + bool SupportsViewProperties() const override; + + /*! + */ + bool CanEditPreferences() const override; + + /*! + */ + bool UsesFormatSpecificData() const override; + + /*! + */ + bool IsDeprecated() const override; + + /*! + */ + bool ValidateFormatSpecificData( const void* data ) const override; + + /*! + */ + void DisposeFormatSpecificData( void* data ) const override; + + /*! + */ + bool EditPreferences() const override; + + /*! + * Returns a list with all installed file formats in the PixInsight core + * application. + */ + static Array AllFormats(); + + /*! + * Returns true iff the specified file suffix corresponds to an installed + * file format. + * + * \param path A file path including a file suffix identifying an + * image format, such as ".xisf", ".jpg", etc. This + * parameter is case-insensitive. Existence of an actual + * file at the specified path is not verified. + * + * \param toRead True to identify an installed file format module able + * to read files. + * + * \param toWrite True to identify an installed file format module able + * to write files. + * + * \note The \a toRead and \a toWrite parameters are false by default, which + * means that no access restrictions are applied by default. + */ + static bool IsSupportedFileFormatBySuffix( const String& path, bool toRead = false, bool toWrite = false ); + + /*! + * Returns a list with the full file paths of all supported image files in + * a given directory of the local filesystem. + * + * \param dirPath Path to an existing directory in the local filesystem, + * where supported image files will be looked for. + * + * \param toRead True to select files supported for read operations. + * + * \param toWrite True to select files supported for write operations. + * + * \param recursive True to search for files recursively throughout the + * entire subtree rooted at \a dirPath. False to restrict + * the file search operation to existing files on + * \a dirPath. This parameter is false by default. + * + * \param followLinks True to follow symbolic links to directories and + * files, on platforms supporting symbolic links. This is + * true by default. This parameter is ignored on Windows. + * + * \note The \a toRead and \a toWrite parameters are false by default, which + * means that no access restrictions are applied by default. + */ + static StringList SupportedImageFiles( const String& dirPath, bool toRead = false, bool toWrite = false, + bool recursive = false, bool followLinks = true ); + + /*! + * Returns a list with the full file paths of all local normalization data + * files in a given directory of the local filesystem. + * + * \param dirPath Path to an existing directory in the local filesystem, + * where local normalization data files will be looked + * for. + * + * \param recursive True to search for files recursively throughout the + * entire subtree rooted at \a dirPath. False to restrict + * the file search operation to existing files on + * \a dirPath. This parameter is false by default. + * + * \param followLinks True to follow symbolic links to directories and + * files, on platforms supporting symbolic links. This is + * true by default. This parameter is ignored on Windows. + * + * Currently this function looks for files with the .xnml suffix (XML local + * normalization data format, XNML). + * + * \sa LocalNormalizationData + */ + static StringList LocalNormalizationFiles( const String& dirPath, bool recursive = false, bool followLinks = true ); + + /*! + * Returns a list with the full file paths of all drizzle data files in a + * given directory of the local filesystem. + * + * \param dirPath Path to an existing directory in the local filesystem, + * where drizzle data files will be looked for. + * + * \param recursive True to search for files recursively throughout the + * entire subtree rooted at \a dirPath. False to restrict + * the file search operation to existing files on + * \a dirPath. This parameter is false by default. + * + * \param followLinks True to follow symbolic links to directories and + * files, on platforms supporting symbolic links. This is + * true by default. This parameter is ignored on Windows. + * + * Currently this function looks for files with the .drz (compatibility text + * drizzle format) and .xdrz (XML drizzle data format, XDRZ) suffixes. + * + * \sa DrizzleData + */ + static StringList DrizzleFiles( const String& dirPath, bool recursive = false, bool followLinks = true ); + + /*! + * Returns a list with the full file paths of all ephemeris data files in a + * given directory of the local filesystem. + * + * \param dirPath Path to an existing directory in the local filesystem, + * where ephemeris data files will be looked for. + * + * \param recursive True to search for files recursively throughout the + * entire subtree rooted at \a dirPath. False to restrict + * the file search operation to existing files on + * \a dirPath. This parameter is false by default. + * + * \param followLinks True to follow symbolic links to directories and + * files, on platforms supporting symbolic links. This is + * true by default. This parameter is ignored on Windows. + * + * Currently this function looks for files with the .xeph suffix (Extensible + * Ephemeris Data format, XEPH). + * + * \sa EphemerisFile + */ + static StringList EphemerisFiles( const String& dirPath, bool recursive = false, bool followLinks = true ); + +private: + + AutoPointer m_data; + + FileFormat( const void* ); + + const void* Handle() const; + + friend class FileFormatPrivate; + friend class FileFormatInstance; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_FileFormat_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileFormat.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileFormatBase.h b/3rdparty/include/pcl/FileFormatBase.h new file mode 100644 index 0000000..f1715b2 --- /dev/null +++ b/3rdparty/include/pcl/FileFormatBase.h @@ -0,0 +1,515 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileFormatBase.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_FileFormatBase_h +#define __PCL_FileFormatBase_h + +/// \file pcl/FileFormatBase.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class FileFormatBase + * \brief Abstract base class for image file format descriptions. + * + * %FileFormatBase defines a number of descriptive properties of a file format + * in the PixInsight platform. + * + * %FileFormatBase is an abstract base class of the MetaFileFormat and + * FileFormat instantiable classes. %MetaFileFormat describes an installable + * file format, while the %FileFormat class provides direct access to an + * installed file format through intermodule communication. + * + * In more practical terms, modules defining new file formats must implement + * derived classes of %MetaFileFormat, while %FileFormat is used by modules + * requiring direct access to image files through installed file formats. + * + * Note that the %FileFormatBase, %MetaFileFormat, %FileFormat, + * FileFormatImplementation and FileFormatInstance classes are conceptually + * parallel to the ProcessBase, MetaProcess, Process, ProcessImplementation and + * ProcessInstance classes, respectively. This is just a reflection of the + * strong object orientation and modularity that characterize the PixInsight + * platform. + * + * \sa MetaFileFormat, FileFormat, FileFormatImplementation, FileFormatInstance + */ +class PCL_CLASS FileFormatBase +{ +public: + + /*! + * Constructs a %FileFormatBase object. + */ + FileFormatBase() + { + } + + /*! + * Destroys this %FileFormatBase object. + */ + virtual ~FileFormatBase() noexcept( false ) + { + } + + /*! + * Returns the identifier of this file format (also known as the + * format name). + * + * File format identifiers are unique, valid C identifiers. + * Examples: "FITS", "TIFF", "JPEG2000". + */ + virtual IsoString Name() const = 0; + + /*! + * Returns the list of file extensions associated to this file format. + * + * The returned list must be a sequence of ".xxx...x" strings in priority + * order. Examples: ".fit", ".fits", ".fts". + */ + virtual StringList FileExtensions() const = 0; + + /*! + * Returns a list of MIME types corresponding to the data supported by + * this file format. + * + * The returned list must be a sequence of "media_type/content_type" items + * approved by IANA (see http://www.iana.org/assignments/media-types/), for + * example: "image/fits", "application/fits". + * + * Providing a list of MIME types is not mandatory, but highly recommended + * for all format support modules implementing standard (i.e., recognized by + * IANA) image formats. + */ + virtual IsoStringList MimeTypes() const = 0; + + /*! + * Returns a version number for this file format, encoded as a hexadecimal + * number. + * + * For example, version 1.0.5 should be returned as 0x105, and version + * 3.11.5 as 0x3B5. The default return value is 0x100, corresponding to + * version 1.0.0. + */ + virtual uint32 Version() const = 0; + + /*! + * Returns a brief description text for this file format. + * + * This function should provide a simple, typically single-line, description + * of this image file format for quick reference. Example: "Flexible Image + * Transport System". The Implementation() member function has been designed + * to provide a more complete description of a format's functionality and + * capabilities. + */ + virtual String Description() const = 0; + + /*! + * Returns a descriptive text about this implementation of a particular + * image file format. + * + * This function must provide a brief but sufficiently informative + * description of this file format implementation. The returned description + * will appear on the Format Explorer window, and should provide information + * about how this format has been implemented in a module. Avoid too + * exhaustive descriptions that are better reserved for a technical manual. + * Avoid also describing a file format itself; the information given should + * not intend to replace an official/formal definition of an image format. + * + * Descriptions of file format implementations are always printed on + * PixInsight consoles. This means that the text output functionality of the + * Console class can be used to format the string returned by this function. + * Refer to that class and its documentation for further information. + */ + virtual String Implementation() const = 0; + + /*! + * Returns a description of the current status of this file format + * implementation. + * + * This function should return an empty string for normal file format + * implementations. Exceptions to this rule are obsolete or deprecated file + * formats (see the IsDeprecated() member function), deficient + * implementations, or other special cases where the user should be aware of + * important potential problems or limitations. + * + * The output of this function should be essentially plain text with basic + * HTML tags. No console tags should be used. + */ + virtual String Status() const = 0; + + /*! + * Returns a large icon image that identifies this format. + * + * The returned image is used to identify all instances of this format + * (e.g., images and files) in the core application's GUI. It is used on the + * Format Explorer window, on image icons of this format, and in general for + * every graphical item related to this format or to an instance of this + * format. + */ + virtual Bitmap Icon() const = 0; + + /*! + * Returns a small icon image that identifies this format. + * + * For details on format icon images, see the documentation for Icon(). + * + * Small icons are used on interface elements where screen space must be + * preserved. Two good examples are the Format Explorer window and the + * ImageContainer interface. + */ + virtual Bitmap SmallIcon() const = 0; + + /*! + * Returns true only if this file format implementation can read an entire + * image in a single operation. + */ + virtual bool CanRead() const = 0; + + /*! + * Returns true only if this file format implementation can write an entire + * image in a single operation. + */ + virtual bool CanWrite() const = 0; + + /*! + * Returns true only if this file format implementation supports + * incremental read operations on image files. + * + * Incremental read operations allow the PixInsight core application and + * other modules to load images by successive row strips. + */ + virtual bool CanReadIncrementally() const = 0; + + /*! + * Returns true only if this file format implementation supports + * incremental write operations on image files. + * + * Incremental write operations allow the PixInsight core application and + * other modules to write images by successive row strips. + */ + virtual bool CanWriteIncrementally() const = 0; + + /*! + * Returns true only if this file format implementation can read/write 8-bit + * unsigned integer images + */ + virtual bool CanStore8Bit() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 16-bit unsigned integer images + */ + virtual bool CanStore16Bit() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 32-bit unsigned integer images + */ + virtual bool CanStore32Bit() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 64-bit unsigned integer images + */ + virtual bool CanStore64Bit() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 32-bit floating point real images (IEEE 754 32-bit single + * precision format for pixel sample values). + */ + virtual bool CanStoreFloat() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 64-bit floating point real images (IEEE 754 64-bit double + * precision format for pixel sample values). + */ + virtual bool CanStoreDouble() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 32-bit complex floating point images (IEEE 754 32-bit single + * precision format for components of complex pixel sample values). + */ + virtual bool CanStoreComplex() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * 64-bit complex floating point images (IEEE 754 64-bit double + * precision format for components of complex pixel sample values). + */ + virtual bool CanStoreDComplex() const = 0; + + /*! + * Returns true only if this file format implementation can read/write + * grayscale pixel data. + */ + virtual bool CanStoreGrayscale() const = 0; + + /*! + * Returns true only if this file format implementation can read/write RGB + * color pixel data. + */ + virtual bool CanStoreRGBColor() const = 0; + + /*! + * Returns true only if this file format implementation supports alpha + * channels. + */ + virtual bool CanStoreAlphaChannels() const = 0; + + /*! + * Returns true only if this file format implementation can store/retrieve + * image resolution data. + */ + virtual bool CanStoreResolution() const = 0; + + /*! + * Returns true only if this file format implementation can embed/extract + * FITS header keyword collections. + */ + virtual bool CanStoreKeywords() const = 0; + + /*! + * Returns true only if this file format implementation can embed/extract + * ICC color profiles. + */ + virtual bool CanStoreICCProfiles() const = 0; + + /*! + * Returns true only if this file format implementation can embed/extract + * thumbnail images. + */ + virtual bool CanStoreThumbnails() const = 0; + + /*! + * Returns true only if this file format implementation can store/retrieve + * data properties associated with format instances or image files. + * + * \note Don't confuse this member function with CanStoreImageProperties(). + * This function returns true if the implementation can store properties + * associated with an entire file or format instance, while + * CanStoreImageProperties() returns true if the implementation can store + * properties associated with individual images. + * + * \sa CanStoreImageProperties(), SupportsViewProperties() + */ + virtual bool CanStoreProperties() const = 0; + + /*! + * Returns true only if this file format implementation can store/retrieve + * data properties associated with individual images. + * + * \sa CanStoreProperties(), SupportsViewProperties() + */ + virtual bool CanStoreImageProperties() const = 0; + + /*! + * Returns true only if this file format implementation can store/retrieve + * RGB working space data. + */ + virtual bool CanStoreRGBWS() const = 0; + + /*! + * Returns true only if this file format implementation can store/retrieve + * display function (aka screen transfer function, or STF) parameters. + */ + virtual bool CanStoreDisplayFunctions() const = 0; + + /*! + * Returns true only if this file format implementation can store/retrieve + * color filter array (CFA) descriptions. + */ + virtual bool CanStoreColorFilterArrays() const = 0; + + /*! + * Returns true only if this file format implementation supports compression + * of pixel data. + * + * This refers to compression of \e source pixels, not to native compression + * schemes used by some file formats. + * + * For example, the compression schemes employed in the JPEG and JPEG2000 + * formats must \e not cause this member function to return true. The + * optional ZIP and LZW compressions used in TIFF are the exact kind of + * compressions that must cause this member function to return true. + */ + virtual bool SupportsCompression() const = 0; + + /*! + * Returns true only if this file format implementation supports multiple + * images stored in a single file. + * + * For example, multiple images (e.g., taken with different filters) can be + * stored in FITS files by means of FITS image extensions, forming a + * data cube of several images with the same dimensions, or even a + * collection of independent images. + */ + virtual bool SupportsMultipleImages() const = 0; + + /*! + * Returns true only if this file format implementation supports data + * properties of different data types such as Float64, UI32Vector, String, + * Complex32, etc. + * + * If this member function returns true, a reimplementation of + * CanStoreProperties() and/or CanStoreImageProperties() (depending on + * format capabilities) must also return true, and the format must implement + * all property data types supported by View objects. For information on + * supported view property types, see the VTYPE_XXX predefined constants in + * PCL API headers. + * + * This function should return false if this format only supports storage of + * BLOB properties, represented as ByteArray objects, or a limited subset of + * view property types. + * + * \sa CanStoreProperties(), CanStoreImageProperties(), + * View::PropertyValue(), View::SetPropertyValue() + */ + virtual bool SupportsViewProperties() const = 0; + + /*! + * Returns true only if this file format implementation allows the user to + * edit specific format preferences. + * + * If this function returns true, then the EditPreferences() procedure must + * be reimplemented in a derived class of MetaFileFormat by the module that + * implements this format. + */ + virtual bool CanEditPreferences() const = 0; + + /*! + * Returns true only if this file format implementation uses + * format-specific data. + * + * Format-specific data are preserved on a per-instance (say per-file) basis + * by the PixInsight application, who actually knows nothing about them. + */ + virtual bool UsesFormatSpecificData() const = 0; + + /*! + * Returns true only if this file format has been deprecated or declared + * obsolete on the PixInsight platform. + * + * When this function returns true, the Status() member function should also + * return information about the current status of this file format, + * including an explanation of the reasons for deprecation. + */ + virtual bool IsDeprecated() const = 0; + + /*! + * Validates a format-specific data block. + * + * File formats that use format-specific data reimplement this function to + * validate format-specific data structures. If this function returns true, + * that means that the passed \a data block is a valid format-specific data + * structure for this file format implementation. + * + * This function will be called by the PixInsight core application for + * validation of the \a data block before calling + * FileFormatImplementation::SetFormatSpecificData() and + * DisposeFormatSpecificData(). + */ + virtual bool ValidateFormatSpecificData( const void* data ) const = 0; + + /*! + * Disposes a format-specific data block. + * + * File formats that use format-specific data reimplement this function to + * destroy and deallocate, as appropriate, their own format-specific data + * structures. + * + * This function will be called by the PixInsight core application with the + * \a data argument pointing to the beginning of a format-specific data + * block. This function will only be called after validation of the data + * block by ValidateFormatSpecificData(). + */ + virtual void DisposeFormatSpecificData( void* data ) const = 0; + + /*! + * Handles a request to edit format preferences. Returns true if the + * preferences were successfully edited. + * + * When implemented, this procedure should open a dialog box to let the + * user edit format-specific preferences and operating options. This + * function should only return true if the user accepts the new settings + * (e.g. by clicking the dialog's OK button). + * + * \note This member function will never be called if the + * CanEditPreferences() member function is not reimplemented to return true + * in a derived class of MetaFileFormat by the module that implements this + * file format. + */ + virtual bool EditPreferences() const = 0; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_FileFormatBase_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileFormatBase.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileFormatImplementation.h b/3rdparty/include/pcl/FileFormatImplementation.h new file mode 100644 index 0000000..5a62977 --- /dev/null +++ b/3rdparty/include/pcl/FileFormatImplementation.h @@ -0,0 +1,903 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileFormatImplementation.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_FileFormat_h +#define __PCL_FileFormat_h + +/// \file pcl/FileFormatImplementation.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +struct FileFormatImplementationPrivate; + +// ---------------------------------------------------------------------------- + +/*! + * \class FileFormatImplementation + * \brief Implementation of a PixInsight file format instance + * + * In the PixInsight/PCL framework, an image file format is formally + * defined as a descendant of the MetaFileFormat class. + * %FileFormatImplementation defines the behavior and functionality of a file + * format instance, which usually (although not necessarily) identifies an + * image file encoded in the corresponding file format. + * + * Note that %MetaFileFormat and %FileFormatImplementation describe and + * implement, respectively, an \e installable image file format in a PixInsight + * module. All installed file formats can be accessed and instantiated by means + * of the FileFormat and FileFormatInstance classes, respectively, through + * intermodule communication mechanisms. + * + * \sa MetaFileFormat, FileFormat, FileFormatInstance + */ +class PCL_CLASS FileFormatImplementation +{ +public: + + /*! + * Constructs a file format instance. + * + * \param m Pointer to a metaformat that identifies the file format class + * that this file instance belongs to. + */ + FileFormatImplementation( const MetaFileFormat* m ); + + /*! + * Destroys a file format instance. + */ + virtual ~FileFormatImplementation() noexcept( false ); + + /* + * FileFormatImplementation instances (e.g., image files) are unique. + */ + + /*! + * Copy constructor. This constructor is disabled because file format + * instances represent unique objects (e.g., files or I/O streams). + */ + FileFormatImplementation( const FileFormatImplementation& x ) = delete; + + /*! + * Copy assignment. This operator is disabled because file format instances + * represent unique objects (e.g., files or I/O streams). + */ + FileFormatImplementation& operator =( const FileFormatImplementation& ) = delete; + + /*! + * Returns a pointer to the \e metaformat of this file format instance. + * + * The metaformat defines the format class this instance belongs to. + */ + const MetaFileFormat* Meta() const + { + return meta; + } + + /*! + * Closes an image file (after Open() or Create()). + */ + virtual void Close(); + + /*! + * Returns true iff this file is currently open. + */ + virtual bool IsOpen() const; + + /*! + * Returns the current file path in this instance. If no file path has been + * set yet (by calling Open() or Create()), this member function should + * return an empty string. + */ + virtual String FilePath() const; + + // Reader functionality + + /*! + * Opens an image file for reading and/or information retrieval. + * + * \param filePath File path to a file that will be opened. The core + * PixInsight application always passes full file paths to existing + * files. However, other modules that may call this member function + * (through intermodule communication) may not behave in the same + * way. A module must be prepared to receive relative file path + * specifications, and even paths to files that don't exist, in + * this argument. + * + * \param hints A string containing a (possibly empty) list of \e hints + * intended to modify the way an image file is opened and/or the + * way image data are to be read and decoded. A format module can + * simply ignore all of these hints, or just look for one or more + * hints that it recognizes and supports, ignoring others. When two + * or more hints are specified, they must be separated by space + * characters (0x20). Most standard file formats support hints. For + * example, the standard DSLR_RAW format recognizes the "raw" hint + * to force reading pure raw data (no deBayerization, no black + * pedestal subtraction, no white balancing) irrespective of the + * current DSLR RAW format settings. + * + * This function must return a dynamic array of ImageDescription structures + * that describes the image(s) stored in the opened image file. Each + * %ImageDescription structure contains ImageInfo and ImageOptions objects + * that describe both basic image parameters (as geometry and color space) + * and format-independent image options (pixel format, embedded data, etc). + * + * In the event of error, a reimplementation of this member function should + * throw a PCL exception. Thrown exceptions will be caught and processed by + * internal PCL code. + */ + virtual ImageDescriptionArray Open( const String& filePath, const IsoString& hints ); + + /*! + * Selects the image at the specified zero-based \a index in this file. + * + * This member function will only be called for file formats that support + * multiple images stored in a single file. It will never be called if the + * MetaFileFormat::SupportsMultipleImages() member function has not been + * reimplemented to return true in the metaformat class for this instance. + */ + virtual void SelectImage( int index ); + + /*! + * Returns the current zero-based image index in this file. + * + * This member function will only be called for file formats that support + * multiple images stored in a single file. It will never be called if the + * MetaFileFormat::SupportsMultipleImages() member function has not been + * reimplemented to return true in the metaformat class for this instance. + */ + virtual int SelectedImageIndex() const; + + /*! + * Returns a format-specific data block for the current image in + * this file, or nullptr if no such data have been retrieved. + * + * See SetFormatSpecificData() for a description of format specific data + * functionality in PCL. + */ + virtual void* FormatSpecificData() const; + + /*! + * Provides a human-readable summary of format-specific properties for the + * current image in this file. + * + * The returned string should include format-specific information, \e not + * generic image information. For example, don't include image dimensions, + * color space, and other things that the PixInsight core application + * already knows. + * + * \note The default implementation returns an empty string. + */ + virtual String ImageFormatInfo() const + { + return String(); + } + + /*! + * Extraction of the ICC color profile associated with the current image in + * this file. If no ICC color profile is defined for the current image, this + * function should return a null (empty) %ICCProfile object. + * + * This member function will never be called if the underlying file format + * does not support storage of ICC color profiles. See + * FileFormat::CanStoreICCProfiles(). + */ + virtual ICCProfile ReadICCProfile(); + + /*! + * Extraction of the RGB working space associated with the current image in + * this file. If no RGBWS is defined for the current image, this function + * should return a default RGBColorSystem object (see RGBColorSystem::sRGB). + * + * This member function will never be called if the underlying file format + * does not support storage of RGB working spaces. See + * FileFormat::CanStoreRGBWS(). + */ + virtual RGBColorSystem ReadRGBWorkingSpace(); + + /*! + * Extraction of the display function associated with the current image in + * this file. If no display function is defined for the current image, this + * function should return an identity display function (see + * DisplayFunction's default constructor). + * + * This member function will never be called if the underlying file format + * does not support storage of display functions. See + * FileFormat::CanStoreDisplayFunctions(). + */ + virtual DisplayFunction ReadDisplayFunction(); + + /*! + * Extraction of the color filter array (CFA) for the current image in this + * file. If no CFA is defined for the current image, this function should + * return an empty CFA (see ColorFilterArray's default constructor). + * + * This member function will never be called if the underlying file format + * does not support storage of color filter arrays. See + * FileFormat::CanStoreColorFilterArrays(). + */ + virtual ColorFilterArray ReadColorFilterArray(); + + /*! + * Extraction of the embedded thumbnail for the current image in this file. + * If the current image does not embed a thumbnail image, this function + * should return an empty 8-bit integer image. + */ + virtual UInt8Image ReadThumbnail(); + + /*! + * Extraction of the list of embedded %FITS keywords for the current image + * in this file. If the current image embeds no %FITS keywords, this + * function should return an empty array. + */ + virtual FITSKeywordArray ReadFITSKeywords(); + + /*! + * Returns a description of all data properties associated with this file. + * For each data property, the returned array provides information on the + * unique identifier of a property and its data type. + * + * Returns an empty array if there are no properties stored for this file. + * + * This member function will never be called if the underlying file format + * does not support data properties. See FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with ImagePropertyDescriptions(). This + * function returns information on the properties of the \e whole image + * file, while %ImagePropertyDescriptions() provides the properties of the currently + * selected image. + */ + virtual PropertyDescriptionArray PropertyDescriptions(); + + /*! + * Extraction of a data property with the specified unique identifier. + * + * If no property with the specified identifier exists associated with this + * file, an invalid Variant object should be returned. + * + * This member function will never be called if the underlying file format + * does not support data properties. See FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with ReadImageProperty(). This + * function returns the value of a given property of the \e whole image + * file, while %ReadImageProperty() returns the value of a property of the + * currently selected image. + */ + virtual Variant ReadProperty( const IsoString& property ); + + /*! + * Returns a description of all data properties associated with the current + * image in this file. For each data property, the returned array provides + * information on the unique identifier of a property and its data type. + * + * Returns an empty array if there are no properties stored for the current + * image in this file. + * + * This member function will never be called if the underlying file format + * does not support data properties for individual images. See + * FileFormat::CanStoreImageProperties(). + */ + virtual PropertyDescriptionArray ImagePropertyDescriptions(); + + /*! + * Extraction of a data property of the current image with the specified + * unique identifier. + * + * If no property with the specified identifier exists associated with the + * current image in this file, an invalid Variant object should be returned. + * + * This member function will never be called if the underlying file format + * does not support data properties for individual images. See + * FileFormat::CanStoreImageProperties(). + */ + virtual Variant ReadImageProperty( const IsoString& property ); + + /*! + * Reads the current image in 32-bit floating point format. + */ + virtual void ReadImage( pcl::Image& image ); + + /*! + * Reads the current image in 64-bit floating point format. + */ + virtual void ReadImage( pcl::DImage& image ); + + /*! + * Reads the current image in 8-bit unsigned integer format. + */ + virtual void ReadImage( UInt8Image& image ); + + /*! + * Reads the current image in 16-bit unsigned integer format. + */ + virtual void ReadImage( UInt16Image& image ); + + /*! + * Reads the current image in 32-bit unsigned integer format. + */ + virtual void ReadImage( UInt32Image& image ); + + /*! + * Returns true iff this instance can perform incremental read operations. + * + * The default implementation returns true. Do not confuse this member + * function with MetaFileFormat::CanReadIncrementally(), which tells the + * PixInsight core application if a given file format has the capability of + * performing incremental file reads in general. The value returned by this + * function refers specifically to the file format instance (e.g., a + * particular file) represented by this object. + */ + virtual bool CanReadIncrementally() const + { + return true; // allow incremental reads if the format supports them + } + + /*! + * Incremental read in 32-bit floating point sample format. + * + * \param[out] buffer Address of the destination sample buffer. + * + * \param startRow First pixel row to read. + * + * \param rowCount Number of pixel rows to read. + * + * \param channel Channel index to read. + * + * Incremental read operations allow the PixInsight core application and + * other modules to load images by successive row strips. + * + * To implement incremental reading, + * MetaFileFormat::CanReadIncrementally() must be reimplemented to return + * true in the metaformat class for this file instance; otherwise this + * member function will never be called. Furthermore, the + * FileFormatImplementation::CanReadIncrementally() member function must + * return true for the format instance represented by this object. + */ + virtual void ReadSamples( pcl::Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 64-bit floating point sample format. + * + * This is an overloaded member function for the DImage type; see + * ReadSamples( Image::sample*, int, int, int, int ) for a full description. + */ + virtual void ReadSamples( pcl::DImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 8-bit unsigned integer sample format. + * + * This is an overloaded member function for the UInt8Image type; see + * ReadSamples( Image::sample*, int, int, int, int ) for a full description. + */ + virtual void ReadSamples( UInt8Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 16-bit unsigned integer sample format. + * + * This is an overloaded member function for the UInt16Image type; see + * ReadSamples( Image::sample*, int, int, int, int ) for a full description. + */ + virtual void ReadSamples( UInt16Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 32-bit unsigned integer sample format. + * + * This is an overloaded member function for the UInt32Image type; see + * ReadSamples( Image::sample*, int, int, int, int ) for a full description. + */ + virtual void ReadSamples( UInt32Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Returns true iff the last file read operation was \e inexact. + * + * The PixInsight application invokes this function just after successful + * completion of a call to ReadImage() or Read(). If a file format instance + * reads (or might read) source images inexactly, (e.g., by applying a + * rounding function to source sample values), then this function must be + * reimplemented to return true, as appropriate. + * + * \note The default implementation of this function returns false, so + * exact read operations are assumed by default. + */ + virtual bool WasInexactRead() const + { + return false; // exact read operations assumed by default + } + + // Writer functionality + + /*! + * Query image options and format-specific data before creating a new image + * file. Returns true if the file creation operation can continue; false if + * it should be aborted. + * + * \param[out] options Reference to a dynamic array of ImageOptions + * objects. On output, each of these objects must provide a general + * description of an image stored in a file instance of this file + * format. A file format module is responsible for setting the + * appropriate values in the passed structures, which will be used + * to generate a new file through a subsequent call to Create(). + * Formats that can store multiple images per file can receive more + * than one %ImageOptions structure stored in this array. Formats + * that don't support multiple images can safely ignore all + * structures but the first one in this array. + * + * \param[out] formatOptions Reference to a dynamic array of + * format-specific data blocks. Each void pointer in this + * array can be either zero or point to valid format-specific data + * for the format of this instance. This array can be empty if no + * format-specific data is being set. See the + * SetFormatSpecificData() member function for more information on + * format-specific data blocks. + * + * If the PixInsight application calls this function, it does so just before + * calling Create(). Typically, this happens as part of a File > Save + * As operation. Other modules can also invoke this function through + * intermodule communication. Format modules should open a dialog box to let + * the user modify some working options, as appropriate; then they should + * return true unless the user cancels the dialog. + * + * \note The default implementation of this function simply returns true + * without opening an options dialog. + */ + virtual bool QueryOptions( Array& options, Array& formatOptions ) + { + return true; + } + + /*! + * Creates an image file for writing. + * + * \param filePath Path to a file that will be created. If a file exists + * at the same path, it will be overwritten and its current + * contents will be lost. The PixInsight core application always + * passes full file paths to existing files. However, other modules + * that may call this member function (through intermodule + * communication) may not behave in the same way. A module must be + * prepared to receive relative file path specifications, and even + * invalid paths, in this argument. + * + * \param numberOfImages This is the number of images that will be written + * to the file after creation. It can be zero if an empty file is + * being created, and also less than zero if the number of images + * is unknown or cannot be defined at the point of creation. + * Although the PixInsight core application will always pass the + * exact number of images that will be written, other modules that + * can call this member function (through intermodule + * communication) might not behave so accurately. Therefore, format + * modules should be flexible enough as to not depend on an + * accurate count of images passed here. For a format that does not + * support empty files or multiple images stored in a single file, + * a reimplementation of this member function should throw an Error + * exception if this value is zero or not equal to one, + * respectively. + * + * \param hints A string containing a (possibly empty) list of \e hints + * intended to modify the way an image file is generated and/or the + * way image data are to be encoded and written. A format module + * can simply ignore all of these hints, or just look for one or + * more hints that it recognizes and supports, ignoring others. + * When two or more hints are specified, they must be separated by + * space characters (0x20). Many standard file formats support some + * hints. For example, the standard JPEG format recognizes the + * "quality" hint to force generation of a JPEG image with a given + * quality level in the range 1 to 100, irrespective of the current + * JPEG format settings. + * + * In the event of error, a reimplementation of this member function should + * throw a PCL exception. Thrown exceptions will be caught and processed by + * internal PCL code. + */ + virtual void Create( const String& filePath, int numberOfImages, const IsoString& hints ); + + /*! + * Specifies an identifier for the next image that will be written or + * created in this file. + * + * \note Reimplementation of this member function is optional. The default + * implementation does nothing (ignores image identifiers). + */ + virtual void SetId( const IsoString& id ) + { + } + + /*! + * Specifies a set of format-independent image \a options for the next image + * that will be written or created in this file. + * + * \note Reimplementation of this member function is optional. The default + * implementation does nothing (ignores format-independent image options). + */ + virtual void SetOptions( const ImageOptions& options ) + { + } + + /*! + * Specifies a format-specific data block for the next image that + * will be written or created in this file. + * + * Format-specific data are arbitrary data blocks; the PixInsight core + * application knows nothing about them except that it passes them among + * instances, even instances of different file formats. + * + * Format-specific data are used by file formats that need working + * parameters that must persist across different file instances. In such + * cases, derived classes should implement suitable mechanisms to identify + * and validate their own data. + * + * For example, file formats that use variable compression schemes usually + * reimplement this member function, along with FormatSpecificData(), to + * keep track of a compression ratio, along with other private data items. + * + * To implement format-specific data support, + * MetaFileFormat::UsesFormatSpecificData() must be reimplemented to return + * true in the metaformat class for this file instance; otherwise this + * member function will never be called. + * + * Before calling this function, the PixInsight core application will call + * MetaFileFormat::ValidateFormatSpecificData() for the same \a data block. + * If the validation routine returns false, this function will not be called + * for the \a data block that failed the validation test. + */ + virtual void SetFormatSpecificData( const void* data ); + + /*! + * Specifies an ICC profile to be embedded in the next image written or + * created in this file. + */ + virtual void WriteICCProfile( const ICCProfile& icc ); + + /*! + * Specifies the parameters of an RGB working space that will be embedded in + * the next image written or created in this file. + */ + virtual void WriteRGBWorkingSpace( const RGBColorSystem& rgbws ); + + /*! + * Specifies a display function that will be embedded in the next image + * written or created in this file. + */ + virtual void WriteDisplayFunction( const DisplayFunction& df ); + + /*! + * Specifies a color filter array (CFA) that will be embedded in the next + * image written or created in this file. + */ + virtual void WriteColorFilterArray( const ColorFilterArray& cfa ); + + /*! + * Specifies a thumbnail \a image to be embedded in the next image written + * or created in this file. + */ + virtual void WriteThumbnail( const pcl::UInt8Image& image ); + + /*! + * Specifies a set of %FITS \a keywords to be embedded in the next image + * written or created in this file. + */ + virtual void WriteFITSKeywords( const FITSKeywordArray& keywords ); + + /*! + * Specifies a data property to be embedded in this file. + * + * \param property Unique identifier of the data property. + * + * \param value Property value. + * + * This member function will never be called if the underlying file format + * does not support data properties. See FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with WriteImageProperty(). This + * function defines a property for the \e whole file, while + * %WriteImageProperty() defines a property of the currently selected image. + */ + virtual void WriteProperty( const IsoString& property, const Variant& value ); + + /*! + * Specifies a data property to be embedded in the next image written or + * created in this file. + * + * \param property Unique identifier of the data property. + * + * \param value Property value. + * + * This member function will never be called if the underlying file format + * does not support data properties for individual images. See + * FileFormat::CanStoreImageProperties(). + */ + virtual void WriteImageProperty( const IsoString& property, const Variant& value ); + + /*! + * Writes a 32-bit floating point image to this file. + */ + virtual void WriteImage( const pcl::Image& image ); + + /*! + * Writes a 64-bit floating point image to this file. + */ + virtual void WriteImage( const pcl::DImage& image ); + + /*! + * Writes an 8-bit unsigned integer image to this file. + */ + virtual void WriteImage( const UInt8Image& image ); + + /*! + * Writes a 16-bit unsigned integer image to this file. + */ + virtual void WriteImage( const UInt16Image& image ); + + /*! + * Writes a 32-bit unsigned integer image to this file. + */ + virtual void WriteImage( const UInt32Image& image ); + + /*! + * Creates a new image with the geometry and color space as specified by an + * ImageInfo structure. The newly created image will be written by + * subsequent incremental write operations. + * + * The sample data type and other format-independent and format-specific + * image parameters have been specified by previous calls to SetOptions() + * and SetFormatSpecificData(). + * + * \note This member function must be reimplemented by all derived classes + * supporting incremental write operations. + */ + virtual void CreateImage( const ImageInfo& info ); + + /*! + * Closes the image that has been created by a previous call to + * CreateImage(). + * + * \note This member function must be reimplemented by all derived classes + * supporting incremental write operations. + */ + virtual void CloseImage(); + + /*! + * Returns true iff this instance can perform incremental write operations. + * + * The default implementation returns true. Do not confuse this member + * function with MetaFileFormat::CanWriteIncrementally(), which tells the + * PixInsight core application if a given file format has the capability of + * performing incremental file writes in general. The value returned by this + * function refers specifically to the file format instance (e.g., a + * particular file) represented by this object. + */ + virtual bool CanWriteIncrementally() const + { + return true; // allow incremental writes if the format supports them + } + + /*! + * Incremental write of 32-bit floating point pixel samples. + * + * \param buffer Address of the source sample buffer. + * + * \param startRow First pixel row to write. + * + * \param rowCount Number of pixel rows to write. + * + * \param channel Channel index to write. + * + * Incremental write operations allow the PixInsight core application and + * other modules to generate images by successive row strips. + * + * To implement incremental writing, + * MetaFileFormat::CanWriteIncrementally() must be reimplemented to return + * true in the metaformat class for this file instance; otherwise this + * member function will never be called. Furthermore, the + * FileFormatImplementation::CanWriteIncrementally() member function must + * return true for the format instance represented by this object. + */ + virtual void WriteSamples( const pcl::Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of a 64-bit floating point image. + * + * This is an overloaded member function for the DImage type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full description. + */ + virtual void WriteSamples( const pcl::DImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of an 8-bit unsigned integer image. + * + * This is an overloaded member function for the UInt8Image type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full description. + */ + virtual void WriteSamples( const UInt8Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of a 16-bit unsigned integer image. + * + * This is an overloaded member function for the UInt16Image type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full description. + */ + virtual void WriteSamples( const UInt16Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of a 32-bit unsigned integer image. + * + * This is an overloaded member function for the UInt32Image type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full description. + */ + virtual void WriteSamples( const UInt32Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Returns true iff the last file write operation in this file was \e lossy. + * + * The PixInsight core application invokes this function just after + * successful completion of a call to WriteImage() or Write(). If a file + * format instance writes (or might write) lossy image data (e.g., by + * applying some lossy compression scheme), then this function must be + * reimplemented to return true, as appropriate. + * + * \note The default implementation of this function returns false, so + * lossless write operations are assumed by default. + */ + virtual bool WasLossyWrite() const + { + return false; // lossless write operations assumed by default + } + +protected: + + /* + * The file format to which this instance belongs. + */ + const MetaFileFormat* meta = nullptr; + +private: + + /* + * Internal stuff to automate low-level C API communication. + */ + AutoPointer m_data; + + ImageDescriptionArray m_description; // used exclusively by FileFormatDispatcher + + void BeginPrivate(); + + void BeginICCProfileExtraction(); + const ICCProfile& GetICCProfile() const; + void EndICCProfileExtraction(); + + void BeginRGBWSExtraction(); + const RGBColorSystem& GetRGBWS() const; + void EndRGBWSExtraction(); + + void BeginDisplayFunctionExtraction(); + const DisplayFunction& GetDisplayFunction() const; + void EndDisplayFunctionExtraction(); + + void BeginColorFilterArrayExtraction(); + const ColorFilterArray& GetColorFilterArray() const; + void EndColorFilterArrayExtraction(); + + void BeginThumbnailExtraction(); + const UInt8Image& GetThumbnail() const; + void EndThumbnailExtraction(); + + void BeginKeywordExtraction(); + size_type NumberOfKeywords() const; + bool GetNextKeyword( FITSHeaderKeyword& ) const; + void EndKeywordExtraction(); + + void BeginPropertyExtraction(); + const Variant& GetProperty( const IsoString& ); + void EndPropertyExtraction(); + + void BeginImagePropertyExtraction(); + const Variant& GetImageProperty( const IsoString& ); + void EndImagePropertyExtraction(); + + void BeginICCProfileEmbedding(); + void SetICCProfile( const ICCProfile& ); + void EndICCProfileEmbedding(); + + void BeginRGBWSEmbedding(); + void SetRGBWS( const RGBColorSystem& ); + void EndRGBWSEmbedding(); + + void BeginDisplayFunctionEmbedding(); + void SetDisplayFunction( const DisplayFunction& ); + void EndDisplayFunctionEmbedding(); + + void BeginColorFilterArrayEmbedding(); + void SetColorFilterArray( const ColorFilterArray& ); + void EndColorFilterArrayEmbedding(); + + void BeginThumbnailEmbedding(); + void SetThumbnail( const UInt8Image& ); + void EndThumbnailEmbedding(); + + void BeginKeywordEmbedding(); + void AddKeyword( const FITSHeaderKeyword& ); + void EndKeywordEmbedding(); + + void BeginPropertyEmbedding(); + void SetProperty( const IsoString&, const Variant& ); + void EndPropertyEmbedding(); + + void BeginImagePropertyEmbedding(); + void SetImageProperty( const IsoString&, const Variant& ); + void EndImagePropertyEmbedding(); + + friend class FileFormatDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_FileFormat_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileFormatImplementation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileFormatInstance.h b/3rdparty/include/pcl/FileFormatInstance.h new file mode 100644 index 0000000..b9a44a7 --- /dev/null +++ b/3rdparty/include/pcl/FileFormatInstance.h @@ -0,0 +1,1180 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileFormatInstance.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_FileFormatInstance_h +#define __PCL_FileFormatInstance_h + +/// \file pcl/FileFormatInstance.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS ColorFilterArray; +class PCL_CLASS DisplayFunction; +class PCL_CLASS FileFormat; +class PCL_CLASS ICCProfile; + +/*! + * \class FileFormatInstance + * \brief High-level interface to an image file format instance. + * + * %FileFormatInstance, along with %FileFormat, allows full access to any + * installed file format through intermodule communication. + * + * %FileFormatInstance represents a live instance of an installed image format; + * usually (but not necessarily) a disk file. + * + * \sa FileFormat + */ +class PCL_CLASS FileFormatInstance : public UIObject +{ +public: + + /*! + * Constructs a file format instance of the specified file format \a fmt. + */ + FileFormatInstance( const FileFormat& fmt ); + + /*! + * Move constructor. + */ + FileFormatInstance( FileFormatInstance&& x ) + : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys a file format instance. + * + * After destruction of this instance, the server-side object is also + * destroyed if it is no longer referenced by other %FileFormatInstance + * objects. When the server-side object is destroyed, any open files are + * automatically flushed and closed, as necessary. + */ + virtual ~FileFormatInstance() + { + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + FileFormatInstance& operator =( FileFormatInstance&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since file format instances are unique objects, calling this member + * function has no effect. + */ + void EnsureUnique() override + { + } + + /*! + * Returns a reference to a null format instance. A null + * %FileFormatInstance object does not correspond to an existing image file + * format instance in the PixInsight core application. + */ + static FileFormatInstance& Null(); + + /*! + * Returns a FileFormat object that represents the installed file format + * that this instance belongs to. + */ + FileFormat Format() const; + + /*! + * Closes an image file (after Open() or Create()). + * + * Returns true iff the file was successfully closed. + */ + bool Close(); + + /*! + * Returns true iff this file is currently open. + */ + bool IsOpen() const; + + /*! + * Returns the absolute file path of this file format instance. If no file + * path has been set yet (by calling Open() or Create()), this member + * function returns an empty string. + */ + String FilePath() const; + + // Reader functionality + + /*! + * Opens an image file for reading and/or information retrieval. + * + * \param images Reference to a dynamic array of ImageDescription + * structures. On successful return, this array will describe the + * image(s) stored in this image file. Each %ImageDescription + * structure will contain ImageInfo and ImageOptions objects that + * describe both basic image parameters (as geometry and color + * space) and format-independent image options (pixel format, + * embedded data, etc). Descriptive information is provided by the + * underlying format module with data retrieved from the opened + * image file. + * + * \param filePath File path to an existing file that will be opened. + * + * \param hints A string containing a (possibly empty) list of \e hints + * intended to modify the way an image file is opened and/or the + * way image data are to be read and decoded. A format module can + * simply ignore all of these hints, or just look for one or more + * hints that it recognizes and supports, ignoring others. When two + * or more hints are specified, they must be separated by space + * characters (0x20). Most standard file formats support hints. For + * example, the standard DSLR_RAW format recognizes the "raw" hint + * to force reading pure raw data (no deBayerization, no black + * pedestal subtraction, no white balancing) irrespective of the + * current DSLR RAW format settings. The default value is an empty + * string. + * + * This member function can provide an empty \a images array. If this + * happens, it means that the file is empty, that is, it contains no image. + * Although there is no standard file format module that supports empty + * image files as of writing this documentation, this is a possibility that + * must be taken into account by calling modules. + * + * Returns true if the file was successfully opened; false in the event of + * error. + */ + bool Open( ImageDescriptionArray& images, + const String& filePath, const IsoString& hints = IsoString() ); + + bool Open( ImageDescriptionArray& images, const String& filePath, const IsoString::ustring_base& hints ) + { + return Open( images, filePath, IsoString( hints ) ); + } + + /*! + * Selects the image at the specified zero-based \a index in this file. + * + * Returns true if the specified image was successfully selected; false in + * the event of error. + * + * This member function must only be called for file formats that support + * multiple images stored in a single file. It should not be called if the + * FileFormat::SupportsMultipleImages() member function returns false for + * the file format this instance belongs to. + */ + bool SelectImage( int index ); + + /*! + * Returns the current zero-based image index in this file. + * + * This member function must only be called for file formats that support + * multiple images stored in a single file. It should not be called if the + * FileFormat::SupportsMultipleImages() member function returns false for + * the file format this instance belongs to. + */ + int SelectedImageIndex() const; + + /*! + * Returns a format-specific data block for the current image in + * this file, or zero if no such data have been retrieved. + * + * See SetFormatSpecificData() for a description of format-specific data + * functionality in PCL. + * + * Format-specific data blocks do not pertain to the caller's heap, but to + * the underlying module that implements the file format. Therefore, all + * format-specific data blocks must be deallocated, when appropriate, by + * calling FileFormat::DisposeFormatSpecificData(). + */ + const void* FormatSpecificData() const; + + /*! + * Provides a human-readable summary of format-specific properties for the + * current image in this file. + * + * The returned string should include format-specific information, \e not + * generic image information. For example, it won't include image + * dimensions, color space, and other things that can be retrieved with the + * Open() member function. + */ + String ImageFormatInfo() const; + + /*! + * Extraction of the ICC color profile associated with the current image in + * this file. + * + * If the current image embeds an ICC profile, it will be assigned to the + * specified \a icc object. Otherwise, \a icc will be set to a null profile. + * + * Returns true iff the file access operation was successful, even if no + * ICC profile was extracted. Returns false in the event of error. + */ + bool ReadICCProfile( ICCProfile& icc ); + + /*! + * Extraction of the RGB working space associated with the current image in + * this file. + * + * Returns true iff the file access operation was successful, even if no + * RGBWS was extracted. Returns false in the event of error. + * + * If no RGBWS is defined for the current image, this function will assign a + * default-constructed RGBColorSystem object to \a rgbws (see + * RGBColorSystem::sRGB). + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting RGB working spaces. See + * FileFormat::CanStoreRGBWS(). + */ + bool ReadRGBWorkingSpace( RGBColorSystem& rgbws ); + + /*! + * Extraction of the display function associated with the current image in + * this file. + * + * Returns true iff the file access operation was successful, even if no + * display function was extracted. Returns false in the event of error. + * + * If no display function is defined for the current image, this function + * will assign an identity display function to \a df (see DisplayFunction's + * default constructor). + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting display functions. See + * FileFormat::CanStoreDisplayFunctions(). + */ + bool ReadDisplayFunction( DisplayFunction& df ); + + /*! + * Extraction of the color filter array (CFA) for the current image in this + * file. + * + * Returns true iff the file access operation was successful, even if no CFA + * was extracted. Returns false in the event of error. + * + * If no CFA is defined for the current image, this function will assign an + * empty CFA to \a cfa (see ColorFilterArray's default constructor). + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting color filter arrays. See + * FileFormat::CanStoreColorFilterArrays(). + */ + bool ReadColorFilterArray( ColorFilterArray& cfa ); + + /*! + * Extraction of an embedded thumbnail for the current image in this file. + * + * If the current image embeds a thumbnail image, it will be assigned to the + * specified \a thumbnail 8-bit integer image. Otherwise, a null image will + * be assigned to \a thumbnail. + * + * Returns true iff the file access operation was successful, even if no + * thumbnail image was extracted. Returns false in the event of error. + */ + bool ReadThumbnail( UInt8Image& thumbnail ); + + /*! + * Extraction of embedded keywords for the current image in this file. + * + * If the current image embeds FITS header keywords, they will be added + * to the specified \a keywords list. Otherwise the \a keywords list will be + * left empty. In any case, previous contents of the \a kwywords list will + * be destroyed. + * + * Returns true iff the file access operation was successful, even if no + * keyword was extracted. Returns false in the event of error. + */ + bool ReadFITSKeywords( FITSKeywordArray& keywords ); + + /*! + * Returns a description of all data properties associated with this file. + * For each data property, the returned array provides information on the + * unique identifier of a property and its data type. + * + * Returns an empty array if there are no properties associated with this + * file. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with ImagePropertyDescriptions(). This + * function returns information on the properties of the \e whole file, + * while %ImagePropertyDescriptions() returns information on the properties of the + * currently selected image. + */ + PropertyDescriptionArray PropertyDescriptions(); + + /*! + * Returns true iff the specified property exists associated with this file. + * Returns false if no such property exists for this file. + * + * This is a convenience member function, equivalent to the following code: + * + * \code PropertyDescriptions().Contains( property ); \endcode + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with HasImageProperty(). This + * function returns true if a given property of the \e whole file exists, + * while %HasImageProperty() returns true if a property of the currently + * selected image exists. + */ + bool HasProperty( const IsoString& property ) + { + return PropertyDescriptions().Contains( property ); + } + + bool HasProperty( const IsoString::ustring_base& property ) + { + return HasProperty( IsoString( property ) ); + } + + /*! + * Returns a description (unique identifier and data type) of the specified + * data property associated with this file. If no such property exists, the + * returned PropertyDescription object specifies an invalid data type and + * an empty identifier. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with ImagePropertyDescription(). + * This function describes a property of the \e whole file, while + * %ImagePropertyDescription() describes a property of the currently + * selected image. + */ + pcl::PropertyDescription PropertyDescription( const IsoString& property ) + { + PropertyDescriptionArray properties = PropertyDescriptions(); + PropertyDescriptionArray::const_iterator i = properties.Search( property ); + if ( i == properties.End() ) + return pcl::PropertyDescription(); + return *i; + } + + pcl::PropertyDescription PropertyDescription( const IsoString::ustring_base& property ) + { + return PropertyDescription( IsoString( property ) ); + } + + /*! + * Extraction of a data property associated with this file with the + * specified unique identifier. + * + * If no property with the specified identifier exists associated with this + * file, an invalid Variant object will be returned. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with ReadImageProperty(). This + * function returns the value of a property of the \e whole file, while + * %ReadImageProperty() returns the value of a property of the currently + * selected image. + */ + Variant ReadProperty( const IsoString& property ); + + Variant ReadProperty( const IsoString::ustring_base& property ) + { + return ReadProperty( IsoString( property ) ); + } + + /*! + * Returns an array with all data properties associated with this file. + * + * Returns an empty array if there are no properties associated with this + * file. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with ReadImageProperties(). This + * function returns the properties of the \e whole file, while + * %ReadImageProperties() returns the properties of the currently selected + * image. + */ + PropertyArray ReadProperties(); + + /*! + * Returns a description of all data properties associated with the current + * image in this file. For each data property, the returned array provides + * information on the unique identifier of a property and its data type. + * + * Returns an empty array if there are no properties stored for the current + * image in this file. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + PropertyDescriptionArray ImagePropertyDescriptions(); + + /*! + * Returns true iff the specified property exists associated with the + * current image in this file. Returns false if no such property exists. + * + * This is a convenience member function, equivalent to the following code: + * + * \code ImagePropertyDescriptions().Contains( property ); \endcode + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + bool HasImageProperty( const IsoString& property ) + { + return ImagePropertyDescriptions().Contains( property ); + } + + bool HasImageProperty( const IsoString::ustring_base& property ) + { + return HasImageProperty( IsoString( property ) ); + } + + /*! + * Returns a description (unique identifier and data type) of the specified + * data property associated with the current image. If no such property + * exists, the returned PropertyDescription object specifies an + * invalid data type and empty identifier. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + pcl::PropertyDescription ImagePropertyDescription( const IsoString& property ) + { + PropertyDescriptionArray properties = ImagePropertyDescriptions(); + PropertyDescriptionArray::const_iterator i = properties.Search( property ); + if ( i == properties.End() ) + return pcl::PropertyDescription(); + return *i; + } + + pcl::PropertyDescription ImagePropertyDescription( const IsoString::ustring_base& property ) + { + return ImagePropertyDescription( IsoString( property ) ); + } + + /*! + * Extraction of a data property of the current image with the specified + * unique identifier. + * + * If no property with the specified identifier exists associated with the + * current image in this file, an invalid Variant object will be returned. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + Variant ReadImageProperty( const IsoString& property ); + + Variant ReadImageProperty( const IsoString::ustring_base& property ) + { + return ReadImageProperty( IsoString( property ) ); + } + + /*! + * Returns an array with all data properties of the current image. + * + * If no property exists associated with the current image in this file, an + * empty array will be returned. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + PropertyArray ReadImageProperties(); + + /*! + * Reads the current image in 32-bit floating point format. Returns true iff + * the image was successfully read. + */ + bool ReadImage( FImage& image ); + + /*! + * Reads the current image in 64-bit floating point format. Returns true iff + * the image was successfully read. + */ + bool ReadImage( DImage& image ); + + /*! + * Reads the current image in 8-bit unsigned integer format. Returns true + * iff the image was successfully read. + */ + bool ReadImage( UInt8Image& image ); + + /*! + * Reads the current image in 16-bit unsigned integer format. Returns true + * iff the image was successfully read. + */ + bool ReadImage( UInt16Image& image ); + + /*! + * Reads the current image in 32-bit unsigned integer format. Returns true + * iff the image was successfully read. + */ + bool ReadImage( UInt32Image& image ); + + /*! + * Reads the current image and stores it in the image transported by the + * specified ImageVariant object, using the pixel sample format of the + * transported image. Returns true iff the ImageVariant object transports a + * valid image and the image was successfully read. + */ + bool ReadImage( ImageVariant& image ) + { + if ( image ) + if ( !image.IsComplexSample() ) + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: return ReadImage( static_cast( *image ) ); + case 64: return ReadImage( static_cast( *image ) ); + } + else + switch ( image.BitsPerSample() ) + { + case 8: return ReadImage( static_cast( *image ) ); + case 16: return ReadImage( static_cast( *image ) ); + case 32: return ReadImage( static_cast( *image ) ); + } + return false; + } + + /*! + * Returns true iff this instance can perform incremental read operations. + * + * Do not confuse this member function with + * FileFormat::CanReadIncrementally(), which tells you if a given file + * format has the capability of performing incremental file reads in + * general. The value returned by this function refers specifically to this + * format instance (e.g., a particular file). + */ + bool CanReadIncrementally() const; + + /*! + * Incremental read in 32-bit floating point sample format. + * + * \param[out] buffer Address of the destination sample buffer. + * + * \param startRow First pixel row to read. + * + * \param rowCount Number of pixel rows to read. + * + * \param channel Channel index to read. + * + * Returns true if the specified pixel row(s) were successfully read; false + * in the event of error, or if the operation was cancelled. + * + * Incremental read operations allow loading images by successive pixel row + * strips. They are useful to manage very large files, or large sets of + * image files that don't fit in the available RAM. + * + * When a file format implements incremental reading, the corresponding + * FileFormat::CanReadIncrementally() returns true. Furthermore, the + * CanReadIncrementally() member function of this class should also return + * true for this object, allowing incremental reads for this particular + * format instance. Otherwise this function must not be invoked - it will + * throw an exception if called for a format that does not support + * incremental reads, and will fail unexpectedly if called for an instance + * that does not allow them. + */ + bool ReadSamples( FImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 64-bit floating point sample format. + * + * This is an overloaded member function for the DImage type; see + * ReadSamples( FImage::sample*, int, int, int, int ) for a full + * description. + */ + bool ReadSamples( DImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 8-bit unsigned integer sample format. + * + * This is an overloaded member function for the UInt8Image type; see + * ReadSamples( FImage::sample*, int, int, int, int ) for a full + * description. + */ + bool ReadSamples( UInt8Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 16-bit unsigned integer sample format. + * + * This is an overloaded member function for the UInt16Image type; see + * ReadSamples( FImage::sample*, int, int, int, int ) for a full + * description. + */ + bool ReadSamples( UInt16Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental read in 32-bit unsigned integer sample format. + * + * This is an overloaded member function for the UInt32Image type; see + * ReadSamples( FImage::sample*, int, int, int, int ) for a full + * description. + */ + bool ReadSamples( UInt32Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Returns true iff the last file read operation was \e inexact. + * + * This function can be called just after a successful call to ReadImage() + * or Read(). If a file format instance reads source images inexactly, + * (e.g., by applying a rounding function to source sample values), then + * this function should return true. + */ + bool WasInexactRead() const; + + // Writer functionality + + /*! + * Queries image options and format-specific data before creating a new + * image file. Returns true if the file creation operation can continue; + * false if it should be aborted. + * + * \param[out] options Reference to a dynamic array of ImageOptions + * objects. Each of these objects provides a general description of + * an image stored in a file instance of this file format. The + * underlying file format module is responsible for setting the + * appropriate values in the passed structures. The returned + * options can be used to generate a new file through a subsequent + * call to Create(). Formats that support multiple images per file + * can receive more than one %ImageOptions structure stored in this + * array. Passing more than one %ImageOptions object to a format + * that doesn't support multiple images will be caught and blocked + * by the PixInsight core application. + * + * \param[out] formatOptions Reference to a dynamic array of + * format-specific data blocks. Each void pointer in this + * array can be either zero or point to valid format-specific data + * for the format of this instance. This array can be empty if no + * format-specific data is being set. See the + * SetFormatSpecificData() member function for more information on + * format-specific data blocks. + * + * A module should call this function just before calling Create(), as part + * of a File > Save As operation, or equivalent. Typically, the + * underlying format module will open a dialog box to let the user modify + * some working options. This function will return true unless the user + * cancels the format options dialog. + */ + bool QueryOptions( Array& options, Array& formatOptions ); + + /*! + * Creates an image file for writing. + * + * \param filePath Path to a file that will be created. If a file exists + * at the same path, it will be overwritten and its current + * contents will be lost. + * + * \param hints A string containing a (possibly empty) list of \e hints + * intended to modify the way an image file is generated and/or the + * way image data are to be encoded and written. A format module + * can simply ignore all of these hints, or just look for one or + * more hints that it recognizes and supports, ignoring others. + * When two or more hints are specified, they must be separated by + * space characters (0x20). Many standard file formats support some + * hints. For example, the standard JPEG format recognizes the + * "quality <n>" hint to force generation of a JPEG image + * with a given quality level <n> in the range 1 to 100, + * irrespective of the current JPEG format settings. + * + * \param numberOfImages This is the number of images that will be written + * to the file after creation. It can be zero if an empty file is + * being created, and also less than zero if the number of images + * is unknown or cannot be defined at the point of creation. This + * parameter defaults to one. + * + * Returns true iff the file was successfully created. Returns false in the + * event of error. + */ + bool Create( const String& filePath, const IsoString& hints = IsoString(), int numberOfImages = 1 ); + + bool Create( const String& filePath, const IsoString::ustring_base& hints, int numberOfImages = 1 ) + { + return Create( filePath, IsoString( hints ), numberOfImages ); + } + + /*! + * Specifies an identifier for the next image that will be written or + * created in this file. + * + * Returns true iff the identifier was successfully assigned. Returns false + * in the event of error. + * + * \note Most file format implementations don't support image identifiers + * and simply ignore a call to this function, reporting success. + */ + bool SetId( const IsoString& id ); + + bool SetId( const IsoString::ustring_base& id ) + { + return SetId( IsoString( id ) ); + } + + /*! + * Specifies a set of format-independent image \a options for the next image + * that will be written or created in this file. + * + * Returns true iff the options were successfully assigned. Returns false in + * the event of error. + * + * \note A file format implementations may ignore any format-independent + * options set with a call to this function, reporting success. + */ + bool SetOptions( const ImageOptions& options ); + + /*! + * Specifies a format-specific data block for the next image that + * will be written or created in this file. + * + * Format-specific data are arbitrary data blocks; the PixInsight core + * application knows nothing about them except that it keeps them for all + * open image files and passes them among instances, even instances of + * different file formats. The core application deallocates format-specific + * data blocks when appropriate, by invoking the corresponding module + * deallocation routines. + * + * Format-specific data are often used by image file formats to store + * working data on a per-instance basis (which usually means on a + * per-file basis), such as compression modes and ratios, file + * organization modes, and many other critical working parameters that can + * persist across different file format instances. + * + * When a file format uses (or can use) format-specific data, the + * corresponding FileFormat::UsesFormatSpecificData() member function + * returns true. + * + * Returns true iff the specified data block was accepted by this instance. + * Returns false if the data block is invalid, or in the event of error. + * + * \a note A module should verify validity of a format-specific data block + * with FileFormat::ValidateFormatSpecificData() before calling this + * function to pass the block to an instance. + */ + bool SetFormatSpecificData( const void* data ); + + /*! + * Specifies an ICC profile to be embedded in the next image written or + * created in this file. + * + * Returns true if the specified ICC profile was successfully embedded in + * the image; false in the event of error. + */ + bool WriteICCProfile( const ICCProfile& icc ); + + /*! + * Specifies the parameters of an RGB working space that will be embedded in + * the next image written or created in this file. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting RGB working spaces. See + * FileFormat::CanStoreRGBWS(). + */ + bool WriteRGBWorkingSpace( const RGBColorSystem& rgbws ); + + /*! + * Specifies a display function that will be embedded in the next image + * written or created in this file. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting display functions. See + * FileFormat::CanStoreDisplayFunctions(). + */ + bool WriteDisplayFunction( const DisplayFunction& df ); + + /*! + * Specifies a color filter array (CFA) that will be embedded in the next + * image written or created in this file. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting color filter arrays. See + * FileFormat::CanStoreColorFilterArrays(). + */ + bool WriteColorFilterArray( const ColorFilterArray& cfa ); + + /*! + * Specifies a thumbnail \a image to be embedded in the next image written + * or created in this file. + * + * Returns true if the specified thumbnail \a image was successfully + * embedded in the image; false in the event of error. + */ + bool WriteThumbnail( const UInt8Image& image ); + + /*! + * Specifies a data property to be embedded in this file. + * + * \param property Unique identifier of the data property. + * + * \param value Property value. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with WriteImageProperty(). This + * function defines a property of the \e whole file, while + * %WriteImageProperty() defines a property of the currently selected image. + */ + bool WriteProperty( const IsoString& property, const Variant& value ); + + bool WriteProperty( const IsoString::ustring_base& property, const Variant& value ) + { + return WriteProperty( IsoString( property ), value ); + } + + /*! + * Specifies a data property to be embedded in this file. + * + * Calling this member function is equivalent to: + * + * \code WriteProperty( property.Id(), property.Value() ) \endcode + */ + bool WriteProperty( const Property& property ) + { + return WriteProperty( property.Id(), property.Value() ); + } + + /*! + * Specifies a set of data \a properties to be embedded in this file. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties. See + * FileFormat::CanStoreProperties(). + * + * \note Don't confuse this member function with WriteImageProperties(). + * This function defines a set of properties for the \e whole file, while + * %WriteImageProperties() defines properties for the currently selected + * image. + */ + bool WriteProperties( const PropertyArray& properties ); + + /*! + * Specifies a data property to be embedded in the next image written or + * created in this file. + * + * \param property Unique identifier of the data property. + * + * \param value Property value. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + bool WriteImageProperty( const IsoString& property, const Variant& value ); + + bool WriteImageProperty( const IsoString::ustring_base& property, const Variant& value ) + { + return WriteImageProperty( IsoString( property ), value ); + } + + /*! + * Specifies a data property to be embedded in the next image written or + * created in this file. + * + * Calling this member function is equivalent to: + * + * \code WriteImageProperty( property.Id(), property.Value() ) \endcode + */ + bool WriteImageProperty( const Property& property ) + { + return WriteImageProperty( property.Id(), property.Value() ); + } + + /*! + * Specifies a set of data \a properties to be embedded in the next image + * written or created in this file. + * + * Returns true only if the embedding operation was successful. + * + * To prevent runtime errors, you should only call this member function for + * instances of file formats supporting data properties for individual + * images. See FileFormat::CanStoreImageProperties(). + */ + bool WriteImageProperties( const PropertyArray& properties ); + + /*! + * Specifies a set of %FITS \a keywords to be embedded in the next image + * written or created in this file. + * + * Returns true if the specified \a keywords list was successfully embedded + * in the image; false in the event of error. + */ + bool WriteFITSKeywords( const FITSKeywordArray& keywords ); + + /*! + * Writes a 32-bit floating point image to this file. Returns true iff the + * image was successfully written. + */ + bool WriteImage( const FImage& image ); + + /*! + * Writes a 64-bit floating point image to this file. Returns true iff the + * image was successfully written. + */ + bool WriteImage( const DImage& image ); + + /*! + * Writes an 8-bit unsigned integer image to this file. Returns true iff the + * image was successfully written. + */ + bool WriteImage( const UInt8Image& image ); + + /*! + * Writes a 16-bit unsigned integer image to this file. Returns true iff the + * image was successfully written. + */ + bool WriteImage( const UInt16Image& image ); + + /*! + * Writes a 32-bit unsigned integer image to this file. Returns true iff the + * image was successfully written. + */ + bool WriteImage( const UInt32Image& image ); + + /*! + * Writes image transported by the specified ImageVariant object to this + * file, using the pixel sample format of the transported image. Returns + * true iff the ImageVariant object transports a valid image and the image + * was successfully written. + */ + bool WriteImage( const ImageVariant& image ) + { + if ( image ) + if ( !image.IsComplexSample() ) + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: return WriteImage( static_cast( *image ) ); + case 64: return WriteImage( static_cast( *image ) ); + } + else + switch ( image.BitsPerSample() ) + { + case 8: return WriteImage( static_cast( *image ) ); + case 16: return WriteImage( static_cast( *image ) ); + case 32: return WriteImage( static_cast( *image ) ); + } + return false; + } + + /*! + * Returns true iff this instance can perform incremental write operations. + * + * Do not confuse this member function with + * FileFormat::CanWriteIncrementally(), which tells you if a given file + * format has the capability of performing incremental file writes in + * general. The value returned by this function refers specifically to this + * format instance (e.g., a particular file). + */ + bool CanWriteIncrementally() const; + + /*! + * Creates a new image with the geometry and color space as specified by an + * ImageInfo structure. The newly created image will be written by + * subsequent incremental write operations. + * + * The sample data type and other format-independent and format-specific + * image parameters have been specified by previous calls to SetOptions() + * and SetFormatSpecificData(). + * + * Returns true iff the image was successfully created. + * + * \note This member function should not be invoked for file formats that + * don't support incremental write operations, or for format instances that + * don't allow them. + */ + bool CreateImage( const ImageInfo& info ); + + /*! + * Closes the image that has been created by a previous call to + * CreateImage(). + * + * Returns true iff the image was successfully closed. + * + * \note This member function must be reimplemented by all derived classes + * supporting incremental write operations. + */ + bool CloseImage(); + + /*! + * Incremental write of 32-bit floating point pixel samples. + * + * \param buffer Address of the source sample buffer. + * + * \param startRow First pixel row to write. + * + * \param rowCount Number of pixel rows to write. + * + * \param channel Channel index to write. + * + * Returns true iff the specified pixel row(s) were successfully written; + * false in the event of error, or if the operation was cancelled. + * + * Incremental write operations allow the PixInsight core application and + * other modules to generate images by successive row strips. They are + * useful to generate extremely large images, or large sets of images that + * don't fit in the available RAM. + * + * When a file format implements incremental writing, the corresponding + * FileFormat::CanWriteIncrementally() returns true. Furthermore, the + * CanWriteIncrementally() member function of this class should also return + * true for this object, allowing incremental writes for this particular + * format instance. Otherwise this function must not be invoked - it will + * throw an exception if called for a format that does not support + * incremental writes, and will fail unexpectedly if called for an instance + * that does not allow them. + */ + bool WriteSamples( const FImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of a 64-bit floating point image. + * + * This is an overloaded member function for the DImage type; see + * WriteSamples( const FImage::sample*, int, int, int ) for a full + * description. + */ + bool WriteSamples( const DImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of an 8-bit unsigned integer image. + * + * This is an overloaded member function for the UInt8Image type; see + * WriteSamples( const FImage::sample*, int, int, int ) for a full + * description. + */ + bool WriteSamples( const UInt8Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of a 16-bit unsigned integer image. + * + * This is an overloaded member function for the UInt16Image type; see + * WriteSamples( const FImage::sample*, int, int, int ) for a full + * description. + */ + bool WriteSamples( const UInt16Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental write of a 32-bit unsigned integer image. + * + * This is an overloaded member function for the UInt32Image type; see + * WriteSamples( const FImage::sample*, int, int, int ) for a full + * description. + */ + bool WriteSamples( const UInt32Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Returns true iff the last file write operation in this file was \e lossy. + * + * This function can ve called just after successful completion of a call to + * WriteImage() or Write(). If a file format instance writes lossy image + * data (e.g., by applying some lossy compression scheme), then this + * function will return true. + */ + bool WasLossyWrite() const; + +private: + + FileFormatInstance( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class FileFormatInstancePrivate; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_FileFormatInstance_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileFormatInstance.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FileInfo.h b/3rdparty/include/pcl/FileInfo.h new file mode 100644 index 0000000..e977860 --- /dev/null +++ b/3rdparty/include/pcl/FileInfo.h @@ -0,0 +1,442 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FileInfo.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_FileInfo_h +#define __PCL_FileInfo_h + +/// \file pcl/FileInfo.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class FileInfo + * \brief Platform-independent information on file and directory items. + * + * ### TODO: Write a detailed description for %FileInfo. + */ +class PCL_CLASS FileInfo +{ +public: + + /*! + * Default constructor. Constructs an empty %FileInfo object without any + * information on existing file or directory items. + */ + FileInfo() + { + Clear(); + } + + /*! + * Constructs a %FileInfo object with information retrieved for the + * specified file or directory \a path. + */ + FileInfo( const String& path ) + { + Refresh( path ); + } + + /*! + * Copy constructor. + */ + FileInfo( const FileInfo& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~FileInfo() + { + } + + /*! + * Assignment operator. Returns a reference to this object. + */ + FileInfo& operator =( const FileInfo& ) = default; + + /*! + * Returns the absolute path of this file or directory. + */ + const String& Path() const + { + return m_path; + } + + /*! + * Returns the Windows drive component of the path in this object, or an + * empty string if the path does not include a Windows drive specification. + * + * This function only makes sense on Windows. On UNIX and Linux operating + * systems, this function always returns an empty string. + */ + String Drive() const + { + return File::ExtractDrive( m_path ); + } + + /*! + * Returns the parent directory component of the path in this object, or an + * empty string if the path does not include a parent directory. + * + * On Windows, the drive component of the path is \e not included. + * + * Examples: + * + * \li In '/foo.tar.gz' the directory is '/'. + * \li In '/foo/bar.tar.gz' the directory is '/foo'. + * \li In 'foo/bar.tar.gz' the directory is 'foo'. + * \li In 'C:/Foo/Bar.txt' the directory is '/Foo'. + */ + String Directory() const + { + return File::ExtractDirectory( m_path ); + } + + /*! + * Returns the file name component of the path in this object, or an empty + * string if the path does not include a name. + * + * The file extension or suffix is \e not included. + * + * Examples: + * + * \li In '/foo/bar.tar.gz' the name is 'bar'. + * \li In 'C:/Foo/Bar.txt' the name is 'Bar'. + */ + String Name() const + { + return File::ExtractName( m_path ); + } + + /*! + * Returns the file extension component of the path in this object, or an + * empty string if the path does not include an extension. + * + * The returned extension \e includes the initial dot separator. + * + * Examples: + * + * \li In '/foo/bar.tar.gz' the extension is '.gz'. + * \li In 'C:/Foo/Bar.txt' the extension is '.txt'. + */ + String Extension() const + { + return File::ExtractExtension( m_path ); + } + + /*! + * A synonym for Extension(). + */ + String Suffix() const + { + return Extension(); + } + + /*! + * Returns the complete suffix of the path in this object, or an empty + * string if the path does not include a suffix. + * + * The returned string \e includes the initial dot separator. + * + * The complete suffix is the rightmost substring of the path, starting with + * the first occurrence of a dot character. For example, in 'foo.tar.gz' the + * complete suffix is '.tar.gz'. + */ + String CompleteSuffix() const + { + return File::ExtractCompleteSuffix( m_path ); + } + + /*! + * Returns the name and extension of the path in this object. Calling this + * member function is functionally equivalent to: Name() + Extension(). + */ + String NameAndExtension() const + { + return File::ExtractNameAndExtension( m_path ); + } + + /*! + * A synonym for NameAndExtension(). + */ + String NameAndSuffix() const + { + return NameAndExtension(); + } + + /*! + * Returns true iff this object represents an existing file or directory. + */ + bool Exists() const + { + return m_exists; + } + + /*! + * Returns a constant reference to the FileAttributes flags for this file or + * directory. + */ + const FileAttributes& Attributes() const + { + return m_attributes; + } + + /*! + * Returns true iff this object represents an existing directory. + */ + bool IsDirectory() const + { + return m_attributes.IsFlagSet( FileAttribute::Directory ); + } + + /*! + * Returns true iff this object represents an existing file. + */ + bool IsFile() const + { + return m_attributes.IsFlagSet( FileAttribute::Regular ); + } + + /*! + * Returns true iff this object represents a symbolic link. + * + * This member function only makes sense on UNIX/Linux platforms. On Windows + * it always returns false. + */ + bool IsSymbolicLink() const + { + return m_attributes.IsFlagSet( FileAttribute::SymbolicLink ); + } + + /*! + * Returns the target path of this symbolic link, or an empty string if this + * object does not represent a symbolic link. + * + * This member function only makes sense on UNIX/Linux platforms. On Windows + * it always returns an empty string. + */ + String SymbolicLinkTarget() const; + + /*! + * Returns true iff this object represents a hidden file or directory. + * + * On Windows, this member function returns true if the file or directory + * represented by this object has the hidden attribute set. On UNIX and + * Linux operating systems, this function returns true when the file or + * directory name begins with a dot character. + */ + bool IsHidden() const + { + return m_attributes.IsFlagSet( FileAttribute::Hidden ); + } + + /*! + * Returns true iff the user id and group id of the caller process have read + * access permission for the item represented by this object. + */ + bool IsReadable() const + { + return m_readable; + } + + /*! + * Returns true iff the user id and group id of the caller process have write + * access permission for the item represented by this object. + */ + bool IsWritable() const + { + return m_writable; + } + + /*! + * Returns true iff the user id and group id of the caller process have + * execution access permission for the item represented by this object. + * + * This member function only makes sense on UNIX/Linux platforms. On Windows + * it always returns false. + * + * On POSIX systems, this function returns true only if the item represented + * has the S_IXUSR file mode bit set. This means that this function will + * normally return true for directories, since S_IXUSR/S_IXGRP/S_IXOTH + * represent standard search permissions for a directory. + */ + bool IsExecutable() const + { + return m_executable; + } + + /*! + * Returns the size in bytes of the file or directory item represented by + * this object. + * + * If this object represents a directory, a fixed size (usually 4096 bytes) + * is always returned on UNIX and Linux systems. On Windows, zero is always + * returned for directories. + */ + fsize_type Size() const + { + return m_size; + } + + /*! + * Returns the number of existing hard links to the file or directory item + * represented by this object. + * + * This member function only makes sense on UNIX/Linux platforms. On Windows + * it always returns zero. + */ + int NumberOfHardLinks() const + { + return m_numberOfHardLinks; + } + + /*! + * Returns the user id of the owner of the file or directory item + * represented by this object. + * + * This member function only makes sense on UNIX/Linux platforms. On Windows + * it always returns zero. + */ + int UserId() const + { + return m_userId; + } + + /*! + * Returns the group id of the owner of the file or directory item + * represented by this object. + * + * This member function only makes sense on UNIX/Linux platforms. On Windows + * it always returns zero. + */ + int GroupId() const + { + return m_groupId; + } + + /*! + * Returns a constant reference to a FileTime structure corresponding to the + * creation time of this file or directory. + */ + const FileTime& TimeCreated() const + { + return m_created; + } + + /*! + * Returns a constant reference to a FileTime structure corresponding to the + * last access time of this file or directory. + */ + const FileTime& LastAccessed() const + { + return m_lastAccessed; + } + + /*! + * Returns a constant reference to a FileTime structure corresponding to the + * last modification time of this file or directory. + */ + const FileTime& LastModified() const + { + return m_lastModified; + } + + /*! + * Retrieves up-to-date information for the item represented by this object. + */ + void Refresh(); + + /*! + * Retrieves information for the specified \a path. + */ + void Refresh( const String& path ); + + /*! + * Clears all the information in this object, leaving it in an invalid state + * corresponding to a nonexistent item. + */ + void Clear(); + +private: + + String m_path; // full file or directory path + FileAttributes m_attributes; // item attributes + fsize_type m_size; // file size in bytes + int m_numberOfHardLinks; // number of existing hard links to this file + int m_userId; // user id of the file owner + int m_groupId; // group id of the file owner + FileTime m_created; // creation time + FileTime m_lastAccessed; // time of last access + FileTime m_lastModified; // time of last change + bool m_exists; // item exists + bool m_readable; // caller has read permission + bool m_writable; // caller has write permission + bool m_executable; // caller has execute permission + + // Clears everything but *preserves* m_path + void ClearData(); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FileInfo_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FileInfo.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Flags.h b/3rdparty/include/pcl/Flags.h new file mode 100644 index 0000000..c3cbe6f --- /dev/null +++ b/3rdparty/include/pcl/Flags.h @@ -0,0 +1,409 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Flags.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_Flags_h +#define __PCL_Flags_h + +/// \file pcl/Flags.h + +#include + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ +class GlobalSettings; +} +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +template struct FlagType {}; +template <> struct FlagType { typedef unsigned type; }; +template <> struct FlagType { typedef int type; }; + +// ---------------------------------------------------------------------------- + +/*! + * \class Flags + * \brief A type-safe collection of enumerated flags + * + * ### TODO: Write a detailed description for %Flags. + */ +template +class PCL_CLASS Flags +{ +public: + + static_assert( sizeof( E ) <= sizeof( int ), + "Invalid sizeof( Flags::enum_type ): Must not be larger than sizeof( int )" ); + + /*! + * Represents the enumerated type that defines individual flags. + */ + typedef E enum_type; + + /*! + * Represents the integral type used to store flags. + */ + typedef typename FlagType::value>::type + flag_type; + + /*! + * Constructs an empty (zero) %Flags instance. + */ + Flags() = default; + + /*! + * Constructs a %Flags instance from an enumerated flag value \a e. + */ + constexpr + Flags( enum_type e ) + : m_flags( int( e ) ) + { + } + + /*! + * Constructs a %Flags instance from a mask \a m. + */ + constexpr + Flags( flag_type m ) + : m_flags( int( m ) ) + { + } + + /*! + * Copy constructor. + */ + Flags( const Flags& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Flags& operator =( const Flags& ) = default; + + /*! + * Assigns an enumerated flag value \a e to this object. Returns a reference + * to this object. + */ + Flags& operator =( enum_type e ) + { + m_flags = e; + return *this; + } + + /*! + * Performs a bitwise AND operation with other flags \a f and stores the + * resulting flags in this object. Returns a reference to this object. + */ + Flags& operator &=( Flags f ) + { + m_flags &= f.m_flags; + return *this; + } + + /*! + * Performs a bitwise AND operation with an enumerated flag value \a e and + * stores the resulting flags in this object. Returns a reference to this + * object. + */ + Flags& operator &=( enum_type e ) + { + m_flags &= unsigned( e ); + return *this; + } + + /*! + * Performs a bitwise AND operation with a mask value \a m and stores the + * resulting flags in this object. Returns a reference to this object. + */ + Flags& operator &=( unsigned m ) + { + m_flags &= m; + return *this; + } + + /*! + * Performs a bitwise inclusive OR operation with other flags \a f and + * stores the resulting flags in this object. Returns a reference to this + * object. + */ + Flags& operator |=( Flags f ) + { + m_flags |= f.m_flags; + return *this; + } + + /*! + * Performs a bitwise inclusive OR operation with an enumerated flag value + * \a e and stores the resulting flags in this object. Returns a reference + * to this object. + */ + Flags& operator |=( enum_type e ) + { + m_flags |= unsigned( e ); + return *this; + } + + /*! + * Performs a bitwise inclusive OR operation with a mask value \a m and + * stores the resulting flags in this object. Returns a reference to this + * object. + */ + Flags& operator |=( unsigned m ) + { + m_flags |= m; + return *this; + } + + /*! + * Performs a bitwise exclusive OR (XOR) operation with other flags \a f and + * stores the resulting flags in this object. Returns a reference to this + * object. + */ + Flags& operator ^=( Flags f ) + { + m_flags ^= f.m_flags; + return *this; + } + + /*! + * Performs a bitwise exclusive OR (XOR) operation with an enumerated flag + * value \a e and stores the resulting flags in this object. Returns a + * reference to this object. + */ + Flags& operator ^=( enum_type e ) + { + m_flags ^= unsigned( e ); + return *this; + } + + /*! + * Performs a bitwise exclusive OR (XOR) operation with a mask value \a m + * and stores the resulting flags in this object. Returns a reference to + * this object. + */ + Flags& operator ^=( unsigned m ) + { + m_flags ^= m; + return *this; + } + + /*! + * Returns true iff the specified flag \a e is set in this %Flags object. + */ + constexpr bool IsFlagSet( enum_type e ) const + { + return (m_flags & e) != flag_type( 0 ); + } + + /*! + * Sets or clears the specified flag \a e in this %Flags object. + */ + void SetFlag( enum_type e, bool on = true ) + { + if ( on ) + m_flags |= e; + else + m_flags &= ~e; + } + + /*! + * Clears the specified flag \a e. + * This is a convenience member function, equivalent to SetFlag( e, false ). + */ + void ClearFlag( enum_type e ) + { + SetFlag( e, false ); + } + + /*! + * Clears all flags in this object. + */ + void Clear() + { + m_flags = flag_type( 0 ); + } + + /*! + * Sets the specified flag \a e in this object. Returns a reference to this + * object. + */ + Flags& operator <<( enum_type e ) + { + SetFlag( e ); + return *this; + } + + /*! + * Returns true iff all flags in this object are zero. + */ + constexpr bool operator !() const + { + return m_flags == flag_type( 0 ); + } + + /*! + * Converts this %Flags object to an integer. + */ + constexpr operator flag_type() const + { + return m_flags; + } + + /*! + * Returns a %Flags object whose value is the bitwise negation of the flags + * stored in this object. + */ + constexpr Flags operator ~() const + { + return Flags( enum_type( ~m_flags ) ); + } + + /*! + * Bitwise AND between two %Flags objects. + */ + constexpr Flags operator &( Flags f ) const + { + return Flags( enum_type( m_flags & f.m_flags ) ); + } + + /*! + * Bitwise AND between a Flags object and an enumerated value. + */ + constexpr Flags operator &( enum_type e ) const + { + return Flags( enum_type( m_flags & flag_type( e ) ) ); + } + + /*! + * Bitwise AND between a %Flags object and a mask. + */ + constexpr Flags operator &( unsigned m ) const + { + return Flags( enum_type( m_flags & m ) ); + } + + /*! + * Bitwise OR between two %Flags objects. + */ + constexpr Flags operator |( Flags f ) const + { + return Flags( enum_type( m_flags | f.m_flags ) ); + } + + /*! + * Bitwise OR between a Flags object and an enumerated value. + */ + constexpr Flags operator |( enum_type e ) const + { + return Flags( enum_type( m_flags | flag_type( e ) ) ); + } + + /*! + * Bitwise OR between a %Flags object and a mask. + */ + constexpr Flags operator |( unsigned m ) const + { + return Flags( enum_type( m_flags | m ) ); + } + + /*! + * Bitwise XOR between two %Flags objects. + */ + constexpr Flags operator ^( Flags f ) const + { + return Flags( enum_type( m_flags ^ f.m_flags ) ); + } + + /*! + * Bitwise XOR between a Flags object and an enumerated value. + */ + constexpr Flags operator ^( enum_type e ) const + { + return Flags( enum_type( m_flags ^ flag_type( e ) ) ); + } + + /*! + * Bitwise XOR between a %Flags object and a mask. + */ + constexpr Flags operator ^( unsigned m ) const + { + return Flags( enum_type( m_flags ^ m ) ); + } + +private: + + flag_type m_flags = flag_type( 0 ); + +#ifndef __PCL_NO_FLAGS_SETTINGS_IO + friend class Settings; +#endif + +#ifndef __PCL_NO_FLAGS_FILE_IO + friend class File; +#endif + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + friend class pi::GlobalSettings; +#endif +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Flags_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Flags.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Font.h b/3rdparty/include/pcl/Font.h new file mode 100644 index 0000000..c262765 --- /dev/null +++ b/3rdparty/include/pcl/Font.h @@ -0,0 +1,547 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Font.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_Font_h +#define __PCL_Font_h + +/// \file pcl/Font.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FontFamily + * \brief Platform-independent, standard font families + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FontFamily::Default Default font
FontFamily::SansSerif Sans serif font: Helvetica, Swiss, Arial
FontFamily::Helvetica Equivalent to SansSerif
FontFamily::Swiss Equivalent to SansSerif
FontFamily::Serif Serif font: Times, Garamond
FontFamily::Times Equivalent to Serif
FontFamily::Script Handwriting font: Script, Comic
FontFamily::Monospace Fixed-pitch font: Courier, Vera Sans Mono
FontFamily::TypeWriter Equivalent to Monospace
FontFamily::Courier Equivalent to Monospace
FontFamily::Teletype Equivalent to Monospace
FontFamily::Decorative Decorative font: OldEnglish
FontFamily::OldEnglish Equivalent to Decorative
FontFamily::Symbol Math, greek, etc: Symbol
+ */ +namespace FontFamily +{ + enum value_type + { + Default, // default font + SansSerif, // sans serif font: Helvetica, Swiss, Arial + Helvetica = SansSerif, + Swiss = SansSerif, + Serif, // serif font: Times, Garamond + Times = Serif, + Script, // handwriting font: Script, Comic + Monospace, // fixed-pitch font: Courier, Vera Sans Mono + TypeWriter = Monospace, + Courier = Monospace, + Teletype = Monospace, + Decorative, // decorative font: OldEnglish, + OldEnglish = Decorative, + Symbol // math, greek, etc.: Symbol + }; + + String PCL_FUNC FamilyToFace( value_type family ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FontWeight + * \brief Standard font weights + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FontWeight::Thin 100
FontWeight::ExtraLight 200
FontWeight::UltraLight = ExtraLight
FontWeight::Light 300
FontWeight::Normal 400
FontWeight::Regular = Normal
FontWeight::Medium 500
FontWeight::SemiBold 600
FontWeight::DemiBold = SemiBold
FontWeight::Bold 700
FontWeight::ExtraBold 800
FontWeight::UltraBold = ExtraBold
FontWeight::Heavy 850
FontWeight::Black 900
+ */ +namespace FontWeight +{ + enum value_type + { + Thin = 100, + ExtraLight = 200, + UltraLight = ExtraLight, + Light = 300, + Normal = 400, + Regular = Normal, + Medium = 500, + SemiBold = 600, + DemiBold = SemiBold, + Bold = 700, + ExtraBold = 800, + UltraBold = ExtraBold, + Heavy = 850, + Black = 900 + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FontStretch + * \brief Standard font stretchs + * + * + * + * + * + * + * + * + * + * + * + *
FontStretch::UltraCondensed 50
FontStretch::ExtraCondensed 62
FontStretch::Condensed 75
FontStretch::SemiCondensed 87
FontStretch::Unstretched 100
FontStretch::SemiExpanded 112
FontStretch::Expanded 125
FontStretch::ExtraExpanded 150
FontStretch::UltraExpanded 200
+ */ +namespace FontStretch +{ + enum value_type + { + UltraCondensed = 50, + ExtraCondensed = 62, + Condensed = 75, + SemiCondensed = 87, + Unstretched = 100, + SemiExpanded = 112, + Expanded = 125, + ExtraExpanded = 150, + UltraExpanded = 200 + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class Font + * \brief Client-side interface to a PixInsight %Font object + * + * ### TODO: Write a detailed description for %Font. + */ +class PCL_CLASS Font : public UIObject +{ +public: + + /*! + * Represents a standard font family. + */ + typedef FontFamily::value_type family; + + /*! + * Represents a standard font weight. + */ + typedef FontWeight::value_type std_weight; + + /*! + * Represents a standard font stretch. + */ + typedef FontStretch::value_type std_stretch; + + /*! + * Constructs a %Font object with the specified family and \a size in + * points. + * + * ### TODO: Elaborate on font families, font matching, etc. + */ + Font( family f = FontFamily::Default, double size = 12.0 ); + + /*! + * Constructs a %Font object with the specified font \a face and \a size + * in points. + * + * ### TODO: Elaborate on font faces, font matching, etc. + */ + Font( const String& face, double size = 12.0 ); + + /*! + * Copy constructor. This object will reference the same server-side font + * as the specified instance \a f. + */ + Font( const Font& f ) : UIObject( f ) + { + } + + /*! + * Move constructor. + */ + Font( Font&& x ) : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys a %Font object. If this object references an existing font in + * the PixInsight core application, its reference count is decremented. If + * it becomes unreferenced, it will be garbage-collected. + */ + virtual ~Font() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side font as the specified + * instance \a f. If the previous font becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + Font& operator =( const Font& f ) + { + SetHandle( f.handle ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Font& operator =( Font&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null font. A null %Font object does not + * correspond to an existing font object in the PixInsight core application. + */ + static Font& Null(); + + /*! # + */ + String Face() const; + + /*! # + */ + void SetFace( const String& ); + + /*! # + */ + bool IsExactMatch() const; + + /*! # + */ + StringList AvailableWritingSystems() const + { + return AvailableFontWritingSystems( Face() ); + } + + /*! # + */ + StringList AvailableStyles() const + { + return AvailableFontStyles( Face() ); + } + + /*! # + */ + bool IsScalable( const String& style = String() ) const + { + return IsScalableFont( Face(), style ); + } + + /*! # + */ + Array OptimalPointSizes( const String& style = String() ) const + { + return OptimalFontPointSizes( Face(), style ); + } + + /*! # + */ + int PixelSize() const; + + /*! # + */ + void SetPixelSize ( int ); + + /*! # + */ + double PointSize() const; + + /*! # + */ + void SetPointSize( double ); + + /*! # + */ + bool IsFixedPitch() const; + + /*! # + */ + bool IsFixedPitch( const String& style ) const + { + return IsFixedPitchFont( Face(), style ); + } + + /*! # + */ + void SetFixedPitch( bool = true ); + + /*! # + */ + bool IsKerningEnabled() const; + + /*! # + */ + void EnableKerning( bool = true ); + + /*! # + */ + void DisableKerning( bool = true ); + + /*! # + */ + int StretchFactor() const; + + /*! # + */ + void SetStretchFactor( int ); + + /*! # + */ + int Weight() const; + + /*! # + */ + int Weight( const String& style ) const + { + return FontWeight( Face(), style ); + } + + /*! # + */ + void SetWeight( int ); + + /*! # + */ + bool IsBold() const + { + return Weight() >= FontWeight::Bold; + } + + /*! # + */ + void SetBold( bool b = true ) + { + SetWeight( b ? FontWeight::Bold : FontWeight::Normal ); + } + + /*! # + */ + bool IsItalic() const; + + /*! # + */ + bool IsItalic( const String& style ) const + { + return IsItalicFont( Face(), style ); + } + + /*! # + */ + void SetItalic( bool = true ); + + /*! # + */ + bool IsUnderline() const; + + /*! # + */ + void SetUnderline( bool = true ); + + /*! # + */ + bool IsOverline() const; + + /*! # + */ + void SetOverline( bool = true ); + + /*! # + */ + bool IsStrikeOut() const; + + /*! # + */ + void SetStrikeOut( bool = true ); + + /*! # + */ + int Ascent() const; + + /*! # + */ + int Descent() const; + + /*! # + */ + int Height() const; + + /*! # + */ + int LineSpacing() const; + + /*! # + */ + bool IsCharDefined( int ) const; + + /*! # + */ + int MaxWidth() const; + + /*! # + */ + int Width( const String& ) const; + + /*! # + */ + int Width( int ch ) const; + + /*! # + */ + Rect BoundingRect( const String& ) const; + + /*! # + */ + Rect TightBoundingRect( const String& ) const; + + /*! # + */ + static StringList AvailableFonts( const String& writingSystem = String() ); + + /*! # + */ + static StringList AvailableFontWritingSystems( const String& font ); + + /*! # + */ + static StringList AvailableFontStyles( const String& font ); + + /*! # + */ + static Array OptimalFontPointSizes( const String& font, const String& style = String() ); + + /*! # + */ + static bool IsScalableFont( const String& font, const String& style = String() ); + + /*! # + */ + static bool IsFixedPitchFont( const String& font, const String& style = String() ); + + /*! # + */ + static bool IsItalicFont( const String& font, const String& style = String() ); + + /*! # + */ + static int FontWeight( const String& font, const String& style = String() ); + +private: + + Font( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class InternalFontEnumerator; + friend class GraphicsContextBase; + friend class Control; + friend class TreeBox; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Font_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Font.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FontComboBox.h b/3rdparty/include/pcl/FontComboBox.h new file mode 100644 index 0000000..533df9a --- /dev/null +++ b/3rdparty/include/pcl/FontComboBox.h @@ -0,0 +1,393 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FontComboBox.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_FontComboBox_h +#define __PCL_FontComboBox_h + +/// \file pcl/FontComboBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class FontComboBox + * \brief A %ComboBox descendant class to select font faces. + * + * %FontComboBox is a utility class that provides a simple list with all the + * installed fonts on the system, plus the set of standard font + * families - see the FontFamily namespace for the supported set of + * standard font families in the PixInsight/PCL platform. + * + * Optionally, %FontComboBox can restrict the list of font items to include + * only scalable, bitmapped or fixed-pitch fonts. The fonts list can also be + * restricted as a function of the available writing systems (Latin, Greek, + * Cyrillic, and so on). + * + * \sa Font, ComboBox, FontFamily + */ +class PCL_CLASS FontComboBox : public ComboBox +{ +public: + + /*! + * Constructs a %FontComboBox as a child control of \a parent. + * + * A default set of %ComboBox items is created for the full set of fonts + * currently installed on the system. + */ + FontComboBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %FontComboBox control. + */ + virtual ~FontComboBox() + { + } + + /*! + * Returns the face name of the font that corresponds to the currently + * selected %ComboBox item, or an empty string if no item is currently + * selected. + * + * \sa CurrentFont(), SetCurrentFont( const String& ), + * SetCurrentFont( const Font& ) + */ + String CurrentFontFace() const; + + /*! + * Returns a Font object that corresponds to the currently selected + * %ComboBox item, or a null font object (Font::Null()) if no item is + * currently selected. + * + * \param size The size in points of the returned font. + * + * This is a convenience member function, equivalent to: + * Font( CurrentFontFace(), size ). + * + * \sa CurrentFontFace(), SetCurrentFont( const String& ), + * SetCurrentFont( const Font& ) + */ + pcl::Font CurrentFont( double size = 12.0 ) const + { + return pcl::Font( CurrentFontFace(), size ); + } + + /*! + * Selects the %ComboBox item corresponding to the specified font \a face. + * + * If the specified \a face doesn't correspond to an installed or standard + * font family, or if an empty string is specified, this member function + * leaves the %ComboBox control with no selection, i.e. with its selected + * index equal to -1. + * + * \sa SetCurrentFont( const Font& ), CurrentFont(), CurrentFontFace() + */ + void SetCurrentFont( const String& face ); + + /*! + * Selects the %ComboBox item corresponding to the specified \a font. + * + * If the specified \a font doesn't correspond to an installed or standard + * font family, or if \a font is Font::Null(), this member function leaves + * the %ComboBox control with no selection, i.e. with its selected index + * equal to -1. + * + * This is a convenience member function, equivalent to: + * SetCurrentFont( font.Face() ). + * + * \sa SetCurrentFont( const String& ), CurrentFont(), CurrentFontFace() + */ + void SetCurrentFont( const pcl::Font& font ) + { + SetCurrentFont( font.Face() ); + } + + /*! + * Resets this %FontComboBox control to its default state: Replaces the + * current list of %ComboBox items with a new set corresponding to the + * standard font families available on the PixInsight/PCL platform, plus all + * installed fonts on the system. + * + * \sa AddStandardFontFamilies(), AddScalableFonts(), AddFixedPitchFonts(), + * AddItalicFonts(), AddWritingSystem() + */ + void ResetFonts(); + + /*! + * Adds a list of %ComboBox items corresponding to the standard font + * families available on the PixInsight/PCL platform. This includes the + * following fonts: Default, SansSerif, Serif, Script, Monospace, + * Decorative, and Symbol. + * + * \note The list of standard font families is always prepended at the + * beginning of the existing set of items. + * + * \sa RemoveStandardFontFamilies() + */ + void AddStandardFontFamilies(); + + /*! + * Removes all existing %ComboBox items that correspond to standard font + * families available on the PixInsight/PCL platform. See + * AddStandardFontFamilies() for more information. + * + * \sa AddStandardFontFamilies() + */ + void RemoveStandardFontFamilies(); + + /*! + * Adds a list of %ComboBox items corresponding to all scalable fonts + * currently installed on the system. + * + * \sa RemoveScalableFonts() + */ + void AddScalableFonts(); + + /*! + * Removes all existing %ComboBox items that correspond to scalable fonts. + * + * \sa AddScalableFonts() + */ + void RemoveScalableFonts(); + + /*! + * Adds a list of %ComboBox items corresponding to all fixed-pitch fonts + * currently installed on the system. + * + * \sa RemoveFixedPitchFonts() + */ + void AddFixedPitchFonts(); + + /*! + * Removes all existing %ComboBox items that correspond to fixed-pitch + * fonts. + * + * \sa AddFixedPitchFonts() + */ + void RemoveFixedPitchFonts(); + + /*! + * Adds a list of %ComboBox items corresponding to all italic fonts + * currently installed on the system. + * + * \sa RemoveItalicFonts() + */ + void AddItalicFonts(); + + /*! + * Removes all existing %ComboBox items that correspond to italic fonts. + * + * \sa AddItalicFonts() + */ + void RemoveItalicFonts(); + + /*! + * Adds a list of %ComboBox items corresponding to all installed fonts that + * support the specified writing system. + * + * \sa RemoveWritingSystem() + */ + void AddWritingSystem( const String& writingSystem ); + + /*! + * Removes all existing %ComboBox items that correspond to installed fonts + * supporting the specified writing system. + * + * \sa AddWritingSystem() + */ + void RemoveWritingSystem( const String& writingSystem ); + + /*! + * Adds items for all installed fonts that support the Latin writing system. + * + * This is a convenience member function, equivalent to: + * AddWritingSystem( "Latin" ). + * + * \sa RemoveLatinFonts(), AddGreekFonts() + */ + void AddLatinFonts() + { + AddWritingSystem( "Latin" ); + } + + /*! + * Removes all existing %ComboBox items that correspond to installed fonts + * supporting the Latin writing system. + * + * \sa AddLatinFonts(), RemoveGreekFonts() + */ + void RemoveLatinFonts() + { + RemoveWritingSystem( "Latin" ); + } + + /*! + * Adds items for all installed fonts that support the Greek writing system. + * + * This is a convenience member function, equivalent to: + * AddWritingSystem( "Greek" ). + * + * \sa RemoveGreekFonts(), AddLatinFonts() + */ + void AddGreekFonts() + { + AddWritingSystem( "Greek" ); + } + + /*! + * Removes all existing %ComboBox items that correspond to installed fonts + * supporting the Greek writing system. + * + * \sa AddGreekFonts(), RemoveLatinFonts() + */ + void RemoveGreekFonts() + { + RemoveWritingSystem( "Greek" ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnFontSelected( FontComboBox& sender, const String& font ); + // void OnFontHighlighted( FontComboBox& sender, const String& font ); + + /*! + * \defgroup fontcombobox_event_handlers FontComboBox Event Handlers + */ + + /*! + * Defines the prototype of a font combo box event handler. + * + * A font combo box event is generated when an item is selected or + * highlighted in a font combo box. + * + * \param sender The %FontComboBox control that sends a font combo box + * event. + * + * \param font The face name of the font that has been selected or + * highlighted in the \a sender font combo box. + * + * \ingroup fontcombobox_event_handlers + */ + typedef void (Control::*font_event_handler)( FontComboBox& sender, const String& font ); + + /*! + * Sets the font selected event handler for this font combo box. + * + * \param handler The font combo box event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever a font is selected in this + * font combo box control. + * + * \param receiver The control that will receive font selected + * events from this font combo box. + * + * \ingroup fontcombobox_event_handlers + */ + void OnFontSelected( font_event_handler handler, Control& receiver ); + + /*! + * Sets the font highlighted event handler for this font combo + * box control. + * + * \param handler The font combo box event handler. Must be a member + * function of the receiver object's class. This handler + * will be called whenever a font is highlighted in this + * font combo box control. + * + * \param receiver The control that will receive font + * highlighted events from this font combo box. + * + * \ingroup fontcombobox_event_handlers + */ + void OnFontHighlighted( font_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + font_event_handler onFontSelected = nullptr; + Control* onFontSelectedReceiver = nullptr; + + font_event_handler onFontHighlighted = nullptr; + Control* onFontHighlightedReceiver = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + void ItemSelected( ComboBox&, int ); + void ItemHighlighted( ComboBox&, int ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_FontComboBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FontComboBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/FourierTransform.h b/3rdparty/include/pcl/FourierTransform.h new file mode 100644 index 0000000..0e902e7 --- /dev/null +++ b/3rdparty/include/pcl/FourierTransform.h @@ -0,0 +1,386 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/FourierTransform.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_FourierTransform_h +#define __PCL_FourierTransform_h + +/// \file pcl/FourierTransform.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FFTDirection + * \brief Defines directions and types of fast Fourier transforms. + * + * + * + * + *
FFTDirection::Forward Fourier transform
FFTDirection::Backward Inverse Fourier transform
+ */ +namespace FFTDirection +{ + enum value_type + { + Forward, + Backward + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class InPlaceFourierTransform + * \brief In-place discrete Fourier transform of two-dimensional complex images. + * + * %InPlaceFourierTransform performs in-place, discrete Fourier transforms of + * complex-sampled two-dimensional images using fast Fourier transform + * algorithms. + * + * %InPlaceFourierTransform can only be applied to 32-bit and 64-bit floating + * point complex images: either ComplexImage or DComplexImage. + * + * \note \b Important - For performance reasons, %InPlaceFourierTransform can + * change the dimensions of a transformed image (width and/or height in pixels) + * to their nearest optimized %FFT lengths. This may involve reallocation of + * pixel data. If the transformed image already has optimized dimensions, no + * size change or reallocation occurs. See the GenericFFT::GenericFFT( int ) + * constructor for details on optimized %FFT lengths. + * + * \sa FourierTransform + */ +class PCL_CLASS InPlaceFourierTransform : public ImageTransformation, public ParallelProcess +{ +public: + + /*! + * Represents a %FFT direction and type. + */ + typedef FFTDirection::value_type transform_type; + + /*! + * Constructs an %InPlaceFourierTransform instance. + * + * \param type Transform direction and type. This parameter can have one of + * the following values:\n + * \n + * + * + * + * + * + *
FFTDirection::ForwardFourier transform. This is the default value.
FFTDirection::BackwardInverse Fourier transform
+ */ + InPlaceFourierTransform( transform_type type = FFTDirection::Forward ) + : m_type( type ) + { + } + + /*! + * Copy constructor. + */ + InPlaceFourierTransform( const InPlaceFourierTransform& ) = default; + + /*! + * Destroys this %InPlaceFourierTransform object. + */ + virtual ~InPlaceFourierTransform() + { + } + + /*! + * Returns the type and direction of this Fourier transform. See the + * FFTDirection namespace for possible values. + */ + transform_type Type() const + { + return m_type; + } + +protected: + + transform_type m_type; + + // In-place FFT of complex images. + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class InPlaceInverseFourierTransform + * \brief In-place discrete inverse Fourier transform of two-dimensional complex images. + * + * %InPlaceInverseFourierTransform performs in-place, inverse discrete Fourier + * transforms of complex-sampled two-dimensional images using fast Fourier + * transform algorithms. + * + * This is a convenience class derived from InPlaceFourierTransform. It + * implements exactly the same functions as its parent class, but performs + * inverse Fourier transforms by default. + * + * \sa InPlaceFourierTransform + */ +class PCL_CLASS InPlaceInverseFourierTransform : public InPlaceFourierTransform +{ +public: + + /*! + * Constructs an %InPlaceInverseFourierTransform instance. + */ + InPlaceInverseFourierTransform() + : InPlaceFourierTransform( FFTDirection::Backward ) + { + } + + /*! + * Copy constructor. + */ + InPlaceInverseFourierTransform( const InPlaceInverseFourierTransform& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~InPlaceInverseFourierTransform() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class FourierTransform + * \brief Out-of-place discrete Fourier transform of two-dimensional images. + * + * %FourierTransform performs out-of-place, discrete Fourier transforms of + * complex and real two-dimensional images, using fast Fourier transform + * algorithms. + * + * %FourierTransform stores a Fourier transform as either a ComplexImage + * (32-bit floating point) or a DComplexImage (64-bit floating point). The + * transform image is transported by an ImageVariant object. 64-bit transforms + * are created for 64-bit floating point (both real and complex) and 32-bit + * integer (real) images. For the rest of images a 32-bit transform is used. + * + * \sa InPlaceFourierTransform + */ +class PCL_CLASS FourierTransform : public BidirectionalImageTransformation, public ParallelProcess +{ +public: + + /*! + * Default constructor. + * + * Creates a %FourierTransform object with an empty Fourier transform. + */ + FourierTransform() = default; + + /*! + * Copy constructor. + * + * This constructor copies the Fourier transform in the specified source + * object. The Fourier transform is an ImageVariant object. This constructor + * creates an %ImageVariant that references the same image as the source + * object. + */ + FourierTransform( const FourierTransform& ) = default; + + /*! + * Move constructor. + */ + FourierTransform( FourierTransform&& ) = default; + + /*! + * Destroys this %FourierTransform object. + * + * The current Fourier transform, if it exists, is automatically released. + * The Fourier transform is implemented as an ImageVariant object. If there + * are no external references to the image transported by the %ImageVariant, + * then it is also destroyed and deallocated. + */ + virtual ~FourierTransform() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * This operator copies the Fourier transform in the source object. The + * Fourier transform is an ImageVariant object. This operator causes the + * %ImageVariant in this object to reference the same image as the source + * object. If this object already stores a Fourier transform, it is released + * before assignment. + */ + FourierTransform& operator =( const FourierTransform& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + FourierTransform& operator =( FourierTransform&& ) = default; + + /*! + * Returns a constant reference to the Fourier transform in this + * %FourierTransform object. + * + * The Fourier transform is an ImageVariant object. It can transport either + * a 32-bit (float) or 64-bit (double) complex image, that is, either a + * ComplexImage or a DComplexImage, depending on the sample type of the + * transformed image. + */ + const ImageVariant& DFT() const + { + return m_dft; + } + + /*! + * Returns a reference to the Fourier transform in this %FourierTransform + * object. + * + * The Fourier transform is an ImageVariant object. It can transport either + * a 32-bit (float) or 64-bit (double) complex image, that is, either a + * ComplexImage or a DComplexImage, depending on the sample type of the + * transformed image. + */ + ImageVariant& DFT() + { + return m_dft; + } + + /*! + * A synonym for DFT() const. + */ + const ImageVariant& operator *() const + { + return DFT(); + } + + /*! + * A synonym for DFT(). + */ + ImageVariant& operator *() + { + return DFT(); + } + + /*! + * Transfers ownership of the current Fourier transform to the caller. + * + * Returns a copy of the ImageVariant object that transports the current + * Fourier transform in this object. Then the internal ImageVariant of this + * object is released. The transform itself, which is either a ComplexImage + * or a DComplexImage, will not be destroyed, as the newly created + * %ImageVariant will transport and reference it. + * + * If this object stores no Fourier transform, the returned %ImageVariant + * will be empty (no image transported). + */ + ImageVariant ReleaseTransform() + { + ImageVariant r; + m_dft.ReleaseTo( r ); + return r; + } + + /*! + * Releases the current Fourier transform, if exists. + * + * If there are no external references to the image transported by the + * internal ImageVariant object, then the transform matrix, which is either + * a ComplexImage or a DComplexImage object, is destroyed. + */ + void Clear() + { + m_dft.Free(); + } + +protected: + + // Discrete 2-D Fourier Transform + ImageVariant m_dft; + + // Transform + void Transform( const pcl::Image& ) override; + void Transform( const pcl::DImage& ) override; + void Transform( const pcl::ComplexImage& ) override; + void Transform( const pcl::DComplexImage& ) override; + void Transform( const pcl::UInt8Image& ) override; + void Transform( const pcl::UInt16Image& ) override; + void Transform( const pcl::UInt32Image& ) override; + + // Inverse transform + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_FourierTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/FourierTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Frame.h b/3rdparty/include/pcl/Frame.h new file mode 100644 index 0000000..aa51538 --- /dev/null +++ b/3rdparty/include/pcl/Frame.h @@ -0,0 +1,195 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Frame.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_Frame_h +#define __PCL_Frame_h + +/// \file pcl/Frame.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FrameStyle + * \brief Frame styles + * + * + * + * + * + * + * + *
FrameStyle::Flat No frame is drawn
FrameStyle::Box Simple rectangular frame
FrameStyle::Raised Raised 3-D panel
FrameStyle::Sunken Sunken (lowered) 3-D panel
FrameStyle::Styled The appearance depends on the current platform and GUI style
+ */ +namespace FrameStyle +{ + enum value_type + { + Flat, // No frame is drawn + Box, // Simple rectangular frame + Raised, // Raised 3-D panel + Sunken, // Sunken (lowered) 3-D panel + Styled // The appearance depends on the current platform and GUI style + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class Frame + * \brief Client-side interface to a PixInsight %Frame control + * + * ### TODO: Write a detailed description for %Frame. + */ +class PCL_CLASS Frame : public Control +{ +public: + + /*! + * Represents a frame style. + */ + typedef FrameStyle::value_type style; + + /*! + * Constructs a %Frame as a child control of \a parent. + */ + Frame( Control& parent = Control::Null() ); + + /*! + * Destroys a %Frame object. + */ + virtual ~Frame() + { + } + + /*! + * Returns the current frame style. + */ + style Style() const; + + /*! + * Sets the frame style. + */ + void SetStyle( style ); + + /*! + * Returns the current frame's line width in pixels. + */ + int LineWidth() const; + + /*! + * Sets the frame's line width in pixels. + */ + void SetLineWidth( int ); + + /*! + * Returns the border width of this frame. + * + * The border width is the distance in pixels from the outer frame rectangle + * to the inner client rectangle. + */ + int BorderWidth() const; + + /*! # + */ + int ScaledLineWidth() const + { + return PhysicalPixelsToLogical( LineWidth() ); + } + + /*! # + */ + void SetScaledLineWidth( int width ) + { + SetLineWidth( LogicalPixelsToPhysical( width ) ); + } + + /*! # + */ + int ScaledBorderWidth() const + { + return PhysicalPixelsToLogical( BorderWidth() ); + } + +protected: + + /*! + * \internal + */ + Frame( void* h ) : Control( h ) + { + } +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Frame_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Frame.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GaiaDatabaseFile.h b/3rdparty/include/pcl/GaiaDatabaseFile.h new file mode 100644 index 0000000..532686e --- /dev/null +++ b/3rdparty/include/pcl/GaiaDatabaseFile.h @@ -0,0 +1,483 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GaiaDatabaseFile.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_GaiaDatabaseFile_h +#define __PCL_GaiaDatabaseFile_h + +/// \file pcl/GaiaDatabaseFile.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::GaiaStarFlag + * \brief Data availability and quality flags for Gaia star data. + * + * + * + * + * + * + + * + * + * + * + * + * + + * + * + * + * + * + * + + * + * + * + * + * + * + + * + * + * + * + + * + * + * + * + + * + * + * + * + + * + * + + *
GaiaStarFlag::NoPM No proper motions and parallax available.
GaiaStarFlag::NoGBPMag No G-BP magnitude available.
GaiaStarFlag::NoGRPMag No G-RP magnitude available.
GaiaStarFlag::LackingData Equivalent to NoPM|NoGBPMag|NoGRPMag.
GaiaStarFlag::GoldRA Standard error of right ascension < 0.13 mas.
GaiaStarFlag::GoldDec Standard error of declination < 0.12 mas.
GaiaStarFlag::GoldParx Standard error of parallax < 0.13 mas.
GaiaStarFlag::GoldPMRA Standard error of proper motion in right ascension < 0.14 mas/year.
GaiaStarFlag::GoldPMDec Standard error of proper motion in declination < 0.12 mas/year.
GaiaStarFlag::GoldAstrometry Equivalent to GoldRA|GoldDec|GoldParx|GoldPMRA|GoldPMDec.
GaiaStarFlag::SilverRA Standard error of right ascension in the range [0.13,1.43) mas.
GaiaStarFlag::SilverDec Standard error of declination in the range [0.12,1.28) mas.
GaiaStarFlag::SilverParx Standard error of parallax in the range [0.13,0.86) mas.
GaiaStarFlag::SilverPMRA Standard error of proper motion in right ascension in the range [0.14,0.97) mas/year.
GaiaStarFlag::SilverPMDec Standard error of proper motion in declination in the range [0.12,0.85) mas/year.
GaiaStarFlag::SilverAstrometry Equivalent to SilverRA|SilverDec|SilverParx|SilverPMRA|SilverPMDec.
GaiaStarFlag::BronzeRA Standard error of right ascension in the range [1.43,2.49) mas.
GaiaStarFlag::BronzeDec Standard error of declination in the range [1.28,2.22) mas.
GaiaStarFlag::BronzeParx Standard error of parallax in the range [0.86,1.38) mas.
GaiaStarFlag::BronzePMRA Standard error of proper motion in right ascension in the range [0.97,1.58) mas/year.
GaiaStarFlag::BronzePMDec Standard error of proper motion in declination in the range [0.85,1.38) mas/year.
GaiaStarFlag::BronzeAstrometry Equivalent to BronzeRA|BronzeDec|BronzeParx|BronzePMRA|BronzePMDec.
GaiaStarFlag::GoldGMag Error on G-band mean flux < 0.84 e-/s.
GaiaStarFlag::GoldGBPMag Error on the integrated BP mean flux < 4.94 e-/s.
GaiaStarFlag::GoldGRPMag Error on the integrated RP mean flux < 5.89 e-/s.
GaiaStarFlag::GoldPhotometry Equivalent to GoldGMag|GoldGBPMag|GoldGRPMag.
GaiaStarFlag::SilverGMag Error on G-band mean flux in the range [0.84,2.13) e-/s.
GaiaStarFlag::SilverGBPMag Error on the integrated BP mean flux in the range [4.94,12.61) e-/s.
GaiaStarFlag::SilverGRPMag Error on the integrated RP mean flux in the range [5.89,15.40) e-/s.
GaiaStarFlag::SilverPhotometry Equivalent to SilverGMag|SilverGBPMag|SilverGRPMag.
GaiaStarFlag::BronzeGMag Error on G-band mean flux in the range [2.13,3.08) e-/s.
GaiaStarFlag::BronzeGBPMag Error on the integrated BP mean flux in the range [12.61,18.04) e-/s.
GaiaStarFlag::BronzeGRPMag Error on the integrated RP mean flux in the range [15.40,22.35) e-/s.
GaiaStarFlag::BronzePhotometry Equivalent to BronzeGMag|BronzeGBPMag|BronzeGRPMag.
GaiaStarFlag::BPRPExcess BP-RP excess factor ≥ 2.0
GaiaStarFlag::BPRPExcessHigh BP-RP excess factor ≥ 5.0 (Gaia EDR3 only)
+ * + * The above data quality ranges correspond to the Gaia EDR3 XPSD database + * version 1.0.0, released December 4, 2020. + * + * \ingroup point_source_databases + */ +namespace GaiaStarFlag +{ + enum mask_type + { + NoPM = 0x00000001, + NoGBPMag = 0x00000002, + NoGRPMag = 0x00000004, + LackingData = 0x00000007, + + GoldRA = 0x00000010, + GoldDec = 0x00000020, + GoldPMRA = 0x00000040, + GoldPMDec = 0x00000080, + + SilverRA = 0x00000100, + SilverDec = 0x00000200, + SilverPMRA = 0x00000400, + SilverPMDec = 0x00000800, + + BronzeRA = 0x00001000, + BronzeDec = 0x00002000, + BronzePMRA = 0x00004000, + BronzePMDec = 0x00008000, + + GoldGMag = 0x00010000, + GoldGBPMag = 0x00020000, + GoldGRPMag = 0x00040000, + GoldParx = 0x00080000, + + SilverGMag = 0x00100000, + SilverGBPMag = 0x00200000, + SilverGRPMag = 0x00400000, + SilverParx = 0x00800000, + + BronzeGMag = 0x01000000, + BronzeGBPMag = 0x02000000, + BronzeGRPMag = 0x04000000, + BronzeParx = 0x08000000, + + BPRPExcess = 0x10000008, + BPRPExcessHigh = 0x20000000, + + GoldAstrometry = 0x000800F0, + SilverAstrometry = 0x00800F00, + BronzeAstrometry = 0x0800F000, + + GoldPhotometry = 0x00070000, + SilverPhotometry = 0x00700000, + BronzePhotometry = 0x07000000 + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \struct GaiaStarData + * \brief Star data structure for Gaia catalog search operations. + * + * \ingroup point_source_databases + */ +struct PCL_CLASS GaiaStarData +{ + double ra = 0; //!< Right ascension in degrees, in the range [0,360). + double dec = 0; //!< Declination in degrees, in the range [-90,+90]. + float parx = 0; //!< Parallax in mas. + float pmra = 0; //!< Proper motion in right ascension * cos(dec), in mas/year. + float pmdec = 0; //!< Proper motion in declination, in mas/year. + float magG = 0; //!< Mean G magnitude. + float magBP = 0; //!< Mean G_BP magnitude. + float magRP = 0; //!< Mean G_RP magnitude. + uint32 flags = 0u; //!< Data availability and quality flags. See the GaiaStarFlag namespace. +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct pcl::GaiaSearchData + * \brief Data items and parameters for Gaia catalog search operations. + * + * \ingroup point_source_databases + */ +typedef XPSD::SearchData GaiaSearchData; + +// ---------------------------------------------------------------------------- + +/*! + * \class GaiaDatabaseFile + * \brief Gaia catalog star database file (XPSD format). + * + * This class implements an interface to XPSD files serializing encoded Gaia + * star data. As of writing this documentation (December 2020), Gaia DR2 and + * EDR3 are supported and have been implemented. + * + * The most important functionality of this class is performing fast indexed + * search operations to retrieve point source data for Gaia stars matching a + * set of user-defined criteria. See the GaiaDatabaseFile::Search() member + * function and the GaiaSearchData structure for detailed information. + * + * This implementation provides the following data for the complete Gaia DR2 + * and EDR3 catalogs: + * + * \li Source positions. + * \li Parallaxes. + * \li Proper motions. + * \li Mean magnitudes on the G, GBP and GRP bands. + * \li Data availability and quality flags. + * + * \b References + * + * \li Gaia Data Release 2 - online resources: + * https://www.cosmos.esa.int/web/gaia/data-release-2 + * + * \li Gaia Data Release 2. Summary of the contents and survey + * properties. Gaia Collaboration, Brown, A.G.A., et al.: + * https://arxiv.org/abs/1804.09365v2 + * + * \li Gaia Data Release 2. Documentation release 1.2: + * https://gea.esac.esa.int/archive/documentation/GDR2/index.html + * + * \li Gaia Early Data Release 3 - online resources: + * https://www.cosmos.esa.int/web/gaia/early-data-release-3 + * + * \li Gaia Early Data Release 3. Summary of the contents and survey + * properties. Gaia Collaboration, A.G.A. Brown, A. Vallenari, T. Prusti, + * J.H.J. de Bruijne, et al.: + * https://www.aanda.org/articles/aa/pdf/forth/aa39657-20.pdf + * + * \li Gaia Early Data Release 3. Documentation release 1.0: + * https://gea.esac.esa.int/archive/documentation/GEDR3/index.html + * + * \b Credits + * + * This work has made use of data from the European Space Agency (ESA) mission + * Gaia (https://www.cosmos.esa.int/gaia), processed by the Gaia Data + * Processing and Analysis Consortium (DPAC, + * https://www.cosmos.esa.int/web/gaia/dpac/consortium). Funding for the DPAC + * has been provided by national institutions, in particular the institutions + * participating in the Gaia Multilateral Agreement. + * + * \sa StarDatabaseFile, APASSDatabaseFile + * \ingroup point_source_databases + */ +class PCL_CLASS GaiaDatabaseFile : public StarDatabaseFile +{ +public: + + /*! + * Default constructor. + * + * Constructs an invalid instance that cannot be used until initialized by + * calling the Open() member function. + */ + GaiaDatabaseFile() = default; + + /*! + * Constructs a &GaiaDatabaseFile instance initialized from the specified + * point source database file in XPSD format. As of writing this + * documentation (December 2020), The Gaia DR2 and EDR3 catalogs are + * available. + * + * In the event of errors or invalid data, this constructor will throw the + * appropriate Error exception. + */ + GaiaDatabaseFile( const String& filePath ) + : StarDatabaseFile( filePath ) + { + static_assert( sizeof( EncodedStarData ) == 32, "Invalid sizeof( GaiaDatabaseFile::EncodedStarData )" ); + if ( Metadata().databaseIdentifier == "GaiaEDR3" ) + m_dr = "EDR3"; + else if ( Metadata().databaseIdentifier == "GaiaDR2" ) + { + m_dr = "DR2"; + StringList tokens; + Metadata().databaseVersion.Break( tokens, '.' ); + // Make sure we reject an unsupported DR2 version older than 1.0.2 + if ( tokens.Length() < 3 || tokens[0].ToInt() < 1 || tokens[1].ToInt() < 0 || tokens[2].ToInt() < 2 ) + throw Error( "Unsupported Gaia DR2 database version '" + + Metadata().databaseVersion + "': " + filePath ); + } + else + throw Error( "Invalid or unsupported Gaia database file with unknown identifier '" + + Metadata().databaseIdentifier + "': " + filePath ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GaiaDatabaseFile& operator =( GaiaDatabaseFile&& ) = default; + + /*! + * Deleted copy constructor. %GaiaDatabaseFile instances are unique, + * hence cannot be copied. + */ + GaiaDatabaseFile( const GaiaDatabaseFile& ) = delete; + + /*! + * Deleted copy assignment operator. %GaiaDatabaseFile instances are + * unique, hence cannot be copied. + */ + GaiaDatabaseFile& operator =( const GaiaDatabaseFile& ) = delete; + + /*! + * Performs a search operation for point sources matching the specified + * criteria. + * + * This member function performs a fast indexed search for point sources in + * this database file matching the criteria defined in the specified \a data + * structure. See the GaiaSearchData structure for detailed information on + * search parameters and output data. + * + * Summarily, search criteria include: + * + * \li The region of the sky where point sources will be searched for. This + * region is defined by the equatorial coordinates of a field center and a + * field radius. + * + * \li An optional range of magnitudes. + * + * \li Optional inclusion/exclusion flags. + * + * \li An optional limit for the number of sources included in the search + * result. + * + * The result of the search operation is also returned in the specified + * \a data structure, including, among others, the following items: + * + * \li The list of point sources found. + * + * \li Instrumentation items for performance analysis, including: total + * search time, time used for I/O operations, total I/O operations, time + * used for data decoding, and time used for data decompression. + */ + void Search( GaiaSearchData& data ) const + { + ElapsedTime T; + for ( const XPSD::IndexTree& tree : m_index ) + tree.Search( data.centerRA, data.centerDec, data.radius, &data ); + data.timeTotal += T(); + } + + /*! + * Returns the name of the Gaia data release corresponding to the data + * available in this database file. As of writing this documentation + * (December 2020), this member function can return either "DR2" or "EDR3". + */ + const IsoString& DataRelease() const + { + return m_dr; + } + +private: + + IsoString m_dr; // data release, one of "DR2", "EDR3" + +#pragma pack(push, 1) + /* + * Encoded star record (32 bytes uncompressed). + */ + struct EncodedStarData + { + // Projected coordinates relative to the origin of the parent quadtree + // node, in 0.002 mas units. + uint32 dx; + uint32 dy; + // Parallax in mas units. + float parx; + // Proper motions, mas/yr. + float pmra; + float pmdec; + // Mean magnitudes in 0.001 mag units, encoded as (mag + 1.5)*1000. + uint16 magG; + uint16 magBP; + uint16 magRP; + // Right ascension correction for high declinations, in 0.01 mas units. + int16 dra; + // Data availability and quality flags. + uint32 flags; + }; +#pragma pack(pop) + + void LoadData( void* block, uint64 offset, uint32 size, void* searchData ) const override + { + ElapsedTime T; + StarDatabaseFile::LoadData( block, offset, size, searchData ); + reinterpret_cast( searchData )->timeIO += T(); + ++reinterpret_cast( searchData )->countIO; + } + + void Uncompress( ByteArray& block, uint32 uncompressedSize, void* searchData ) const override + { + ElapsedTime T; + StarDatabaseFile::Uncompress( block, uncompressedSize, searchData ); + reinterpret_cast( searchData )->timeUncompress += T(); + } + + void GetEncodedData( const ByteArray& data, const XPSD::IndexTree& tree, const XPSD::IndexNode& node, void* searchData ) const override + { + ElapsedTime T; + GaiaSearchData* search = reinterpret_cast( searchData ); + double r = Rad( search->radius ); + const EncodedStarData* S = reinterpret_cast( data.Begin() ); + int count = int( data.Size() / sizeof( EncodedStarData ) ); + int matched = 0; + for ( int i = 0; i < count; ++i, ++S ) + if ( search->requiredFlags == 0 || (S->flags & search->requiredFlags) == search->requiredFlags ) + if ( search->inclusionFlags == 0 || (S->flags & search->inclusionFlags) != 0 ) + if ( search->exclusionFlags == 0 || (S->flags & search->exclusionFlags) == 0 ) + { + float magG = 0.001*S->magG - 1.5; + if ( magG >= search->magnitudeLow ) + if ( magG <= search->magnitudeHigh ) + { + GaiaStarData star; + double x = node.x0 + double( S->dx )/3600/1000/500; + double y = node.y0 + double( S->dy )/3600/1000/500; + tree.Unproject( star.ra, star.dec, x, y ); + if ( unlikely( S->dra != 0 ) ) + { + star.ra += double( S->dra )/3600/1000/100; + if ( star.ra < 0 ) + star.ra += 360; + else if ( star.ra >= 360 ) + star.ra -= 360; + } + if ( Distance( search->centerRA, search->centerDec, star.ra, star.dec ) < r ) + { + if ( search->stars.Length() < size_type( search->sourceLimit ) ) + { + star.parx = S->parx; + star.pmra = S->pmra; + star.pmdec = S->pmdec; + star.magG = magG; + star.magBP = 0.001*S->magBP - 1.5; + star.magRP = 0.001*S->magRP - 1.5; + star.flags = S->flags; + search->stars << star; + } + else + ++search->excessCount; + ++matched; + } + } + } + + search->rejectCount += count - matched; + search->timeDecode += T(); + } + + friend class GaiaDR2DatabaseFileGenerator; + friend class GaiaEDR3DatabaseFileGenerator; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_GaiaDatabaseFile_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GaiaDatabaseFile.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GaussianFilter.h b/3rdparty/include/pcl/GaussianFilter.h new file mode 100644 index 0000000..5c58620 --- /dev/null +++ b/3rdparty/include/pcl/GaussianFilter.h @@ -0,0 +1,498 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GaussianFilter.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_GaussianFilter_h +#define __PCL_GaussianFilter_h + +/// \file pcl/GaussianFilter.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GaussianFilter + * \brief A kernel filter implementing a discrete Gaussian distribution in two + * dimensions. + * + * A %GaussianFilter object is a specialized KernelFilter whose elements are + * calculated as a discrete representation of an elliptical Gaussian function + * centered at the origin: + * + * G(x,y) = Exp( -( x^2/(2*sx^2) + y^2/(2*sy^2) ) ) + * + * where sx and sy are the standard deviations of the Gaussian distribution on + * the horizontal and vertical axes, respectively. + * + * %GaussianFilter also supports arbitrary rotation around the origin. When the + * filter is rotated, the coordinates x, y in the equation above are replaced + * by their rotated counterparts. + * + * A %GaussianFilter instance is formally defined by the following parameters: + * + * + * + * + * + * + *
\e sigma Standard deviation of the filter distribution on the X axis (sigma > 0).
\e rho The ratio sy/sx (see equation above) of the generated filter distribution (0 <= rho <= 1).
\e theta Rotation angle of the horizontal axis in radians (0 <= theta < PI). This parameter only makes sense when rho < 1.
\e epsilon Maximum truncation error of the computed filter coefficients (eps > 0).
+ * + * \sa KernelFilter, VariableShapeFilter, MoffatFilter, LinearFilter, + * MeanFilter + */ +class PCL_CLASS GaussianFilter : public KernelFilter +{ +public: + + /*! + * Constructs an empty %GaussianFilter object with default functional + * parameters: sigma=2, epsilon=0.01, rho=1, theta=0. + */ + GaussianFilter() = default; + + /*! + * Constructs a %GaussianFilter object given the standard deviation + * \a sigma > 0 and truncation error \a epsilon > 0. Assigns an optional + * \a name to the new filter object. + */ + GaussianFilter( float sigma, float epsilon = 0.01, const String& name = String() ) + { + Initialize( sigma, epsilon, 1, 0 ); + Rename( name ); + } + + /*! + * Constructs a %GaussianFilter object given the standard deviation + * \a sigma > 0, truncation error \a epsilon > 0, aspect ratio + * 0 <= \a rho <= 1, and rotation angle 0 <= \a theta <= PI in radians. + * Assigns an optional \a name to the new filter object. + */ + GaussianFilter( float sigma, float epsilon, float rho, float theta = 0, const String& name = String() ) + { + Initialize( sigma, epsilon, rho, theta ); + Rename( name ); + } + + /*! + * Constructs a %GaussianFilter object given the odd kernel size \a n >= 3 + * and truncation error \a epsilon > 0. Assigns an optional \a name to the + * new filter object. + */ + GaussianFilter( int n, float epsilon = 0.01, const String& name = String() ) + { + Initialize( n, epsilon, 1, 0 ); + Rename( name ); + } + + /*! + * Constructs a %GaussianFilter object given the odd kernel size \a n >= 3, + * truncation error \a epsilon > 0, aspect ratio 0 <= \a rho <= 1, and + * rotation angle 0 <= \a theta <= PI in radians. Assigns an optional + * \a name to the new filter object. + */ + GaussianFilter( int n, float epsilon, float rho, float theta = 0, const String& name = String() ) + { + Initialize( n, epsilon, rho, theta ); + Rename( name ); + } + + /*! + * Copy constructor. + */ + GaussianFilter( const GaussianFilter& ) = default; + + /*! + * Move constructor. + */ + GaussianFilter( GaussianFilter&& ) = default; + + /*! + */ + KernelFilter* Clone() const override + { + return new GaussianFilter( *this ); + } + + /*! + * Returns a separable filter equivalent to this Gaussian kernel filter. + * + * A Gaussian filter is the only circularly symmetric, two-dimensional + * separable filter. This reimplementation returns a separable filter only + * if this object represents an undistorted/unrotated Gaussian function, + * that is, when its aspect ratio is 1. Otherwise an empty SeparableFilter + * object is returned since the filter matrix is not separable. + */ + SeparableFilter AsSeparableFilter( float tolerance = __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE ) const override + { + if ( m_rho == 1 ) + { + FVector v = coefficients.RowVector( Size()>>1 ); + return SeparableFilter( v, v ); + } + return SeparableFilter(); + } + + /*! + * Returns true iff this filter is separable, + * + * A Gaussian filter is separable. As reimplemented in %GaussianFilter, this + * member function returns true for undistorted/unrotated Gaussian filters, + * that is, when this object's aspect ratio is 1. + */ + bool IsSeparable() const override + { + return m_rho == 1; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + GaussianFilter& operator =( const GaussianFilter& x ) + { + (void)KernelFilter::operator =( x ); + m_sigma = x.m_sigma; + m_epsilon = x.m_epsilon; + m_rho = x.m_rho; + m_theta = x.m_theta; + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GaussianFilter& operator =( GaussianFilter&& x ) + { + (void)KernelFilter::operator =( std::move( x ) ); + m_sigma = x.m_sigma; + m_epsilon = x.m_epsilon; + m_rho = x.m_rho; + m_theta = x.m_theta; + return *this; + } + + /*! + * Returns the standard deviation of the filter distribution on the X + * (horizontal) axis. + */ + float SigmaX() const + { + return m_sigma; + } + + /*! + * Returns the standard deviation of the filter distribution on the Y + * (vertical) axis. + */ + float SigmaY() const + { + return m_rho*m_sigma; + } + + /*! + * Returns the standard deviation of the filter distribution on the X + * (horizontal) axis. + * + * This function is an alias to SigmaX(). + */ + float Sigma() const + { + return SigmaX(); + } + + /*! + * Returns the maximum truncation error of the filter coefficients. + */ + float Truncation() const + { + return m_epsilon; + } + + /*! + * Returns the aspect ratio of the filter distribution. This is the ratio + * vertical:horizontal between filter axes in the range [0,1]. + */ + float AspectRatio() const + { + return m_rho; + } + + /*! + * Returns the rotation angle of the filter distribution. This is the + * rotation angle in radians with respect to the central pixel, in the + * range [0,+PI]. + */ + float RotationAngle() const + { + return m_theta; + } + + /*! + * Returns the full width at half maximum (FWHM), in sigma units, for the + * horizontal axis of the elliptical Gaussian filter distribution. + */ + double FWHMx() const + { + return 2.3548200450309493 * m_sigma; + + } + + /*! + * Returns the full width at half maximum (FWHM), in sigma units, for the + * vertical axis of the elliptical Gaussian filter distribution. + */ + double FWHMy() const + { + return m_rho * FWHMx(); + + } + + /*! + * Returns the full width at half maximum, in sigma units, for the + * horizontal axis of the elliptical Gaussian filter distribution. + * + * This function is an alias to FWHMx(). + */ + double FWHM() const + { + return FWHMx(); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0, + * truncation error \a epsilon > 0, aspect ratio 0 <= \a rho <= 1, and + * rotation angle 0 <= \a theta <= PI in radians. + */ + void Set( float sigma, float epsilon, float rho, float theta ) + { + Initialize( sigma, epsilon, rho, theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0, + * truncation error \a epsilon > 0, and aspect ratio 0 <= \a rho <= 1. Does + * not change the current rotation angle. + */ + void Set( float sigma, float epsilon, float rho ) + { + Initialize( sigma, epsilon, rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0 and + * truncation error \a epsilon > 0. Does not change the current aspect ratio + * and rotation angle. + */ + void Set( float sigma, float epsilon ) + { + Initialize( sigma, epsilon, m_rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0. + * The current coefficient truncation error, aspect ratio and rotation angle + * are not changed. + */ + void Set( float sigma ) + { + Initialize( sigma, m_epsilon, m_rho, m_theta ); + } + + /*! + * This is a convenience member function, equivalent to Set( sigma ). + */ + void SetSigma( float sigma ) + { + Set( sigma ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), epsilon ). + */ + void SetTruncation( float epsilon ) + { + Set( m_sigma, epsilon ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Truncation(), rho ). + */ + void SetAspectRatio( float rho ) + { + Set( m_sigma, m_epsilon, rho ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Truncation(), AspectRatio(), theta ). + */ + void SetRotationAngle( float theta ) + { + Set( m_sigma, m_epsilon, m_rho, theta ); + } + + /*! + * Recalculates filter coefficients for the given odd kernel size \a n >= 3. + * This routine computes the required standard deviation to sample the + * Gaussian function on a matrix of the specified size, preserving the + * current coefficient truncation, aspect ratio and rotation angle. + */ + void Resize( int n ) override + { + Initialize( n, m_epsilon, m_rho, m_theta ); + } + + /*! + * Exchanges two Gaussian filters \a x1 and \a x2. + */ + friend void Swap( GaussianFilter& x1, GaussianFilter& x2 ) + { + pcl::Swap( static_cast( x1 ), static_cast( x2 ) ); + pcl::Swap( x1.m_sigma, x2.m_sigma ); + pcl::Swap( x1.m_rho, x2.m_rho ); + pcl::Swap( x1.m_theta, x2.m_theta ); + pcl::Swap( x1.m_epsilon, x2.m_epsilon ); + } + +private: + + float m_sigma = 2; // standard deviation, horizontal axis + float m_rho = 1; // vertical:horizontal axes ratio + float m_theta = 0; // rotation angle in radians, [0,+pi] + float m_epsilon = 0.01F; // maximum truncation error in sigma units + + void Initialize( float s, float e, float r, float a ) + { + PCL_PRECONDITION( s > 0 ) + PCL_PRECONDITION( e > 0 ) + PCL_PRECONDITION( r >= 0 && r <= 1 ) + PCL_PRECONDITION( a >= 0 && a <= Const::pi() ) + m_sigma = Abs( s ); + m_epsilon = Abs( e ); + m_rho = Range( r, 0.0F, 1.0F ); + m_theta = Range( a, 0.0F, Const::pi() ); + KernelFilter::Resize( 1 + (Max( 1, RoundInt( m_sigma * Sqrt( -2*Ln( m_epsilon ) ) ) ) << 1) ); + Rebuild(); + } + + void Initialize( int n, float e, float r, float a ) + { + PCL_PRECONDITION( n == 0 || n >= 3 && (n & 1) != 0 ) + PCL_PRECONDITION( e > 0 ) + PCL_PRECONDITION( r >= 0 && r <= 1 ) + PCL_PRECONDITION( a >= 0 && a <= Const::pi() ) + KernelFilter::Resize( n ); + m_epsilon = Abs( e ); + m_sigma = (Size() >> 1)/Sqrt( -2*Ln( m_epsilon ) ); + m_rho = Range( r, 0.0F, 1.0F ); + m_theta = Range( a, 0.0F, Const::pi() ); + Rebuild(); + } + + void Rebuild() + { + int size = Size(); + if ( size == 0 ) + return; + + float* __restrict__ h = *coefficients; + double sx = m_sigma; + double sy = m_rho * sx; + + if ( m_theta == 0 || m_rho == 1 ) + { + double twosx2 = 2*sx*sx; + double twosy2 = 2*sy*sy; + for ( int n2 = size >> 1, dy = -n2; dy <= n2; ++dy ) + if ( dy > 0 ) + for ( int dx = 0; dx < size; ++dx, ++h ) + *h = *(h - ((dy+dy)*size)); + else + for ( int dx = -n2; dx <= n2; ++dx, ++h ) + *h = (dx > 0) ? *(h - (dx+dx)) : float( Exp( -(dx*dx/twosx2 + dy*dy/twosy2) ) ); + } + else + { + double st, ct; SinCos( double( m_theta ), st, ct ); + double sct = st*ct; + double st2 = st*st; + double ct2 = ct*ct; + double twosx2 = 2*sx*sx; + double twosy2 = 2*sy*sy; + double p1 = ct2/twosx2 + st2/twosy2; + double p2 = sct/twosy2 - sct/twosx2; + double p3 = st2/twosx2 + ct2/twosy2; + for ( int n2 = size >> 1, dy = -n2; dy <= n2; ++dy ) + { + double twop2dy = 2*p2*dy; + double p3dy2 = p3*dy*dy; + for ( int dx = -n2; dx <= n2; ++dx, ++h ) + *h = float( Exp( -(p1*dx*dx + twop2dy*dx + p3dy2) ) ); + } + } + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_GaussianFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GaussianFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GeometricTransformation.h b/3rdparty/include/pcl/GeometricTransformation.h new file mode 100644 index 0000000..2cc0b77 --- /dev/null +++ b/3rdparty/include/pcl/GeometricTransformation.h @@ -0,0 +1,277 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GeometricTransformation.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_GeometricTransformation_h +#define __PCL_GeometricTransformation_h + +/// \file pcl/GeometricTransformation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GeometricTransformation + * \brief Abstract base class of all PCL geometric image transformations. + * + * %GeometricTransformation represents a geometrical transformation that can be + * applied to any image type defined in PCL. + * + * \sa InterpolatingGeometricTransformation, ImageTransformation + */ +class PCL_CLASS GeometricTransformation : public virtual ImageTransformation +{ +public: + + /*! + * Constructs a %GeometricTransformation object. + */ + GeometricTransformation() = default; + + /*! + * Copy constructor. + */ + GeometricTransformation( const GeometricTransformation& ) = default; + + /*! + * Destroys a %GeometricTransformation object. + */ + virtual ~GeometricTransformation() + { + } + + /*! + * Predicts transformed image dimensions. + * + * \param[in,out] width Reference to a variable whose value is a horizontal + * dimension in pixels (width). On output, it will receive the + * predicted horizontal dimension after the transformation. + * + * \param[in,out] height Reference to a variable whose value is a vertical + * dimension in pixels (height). On output, it will receive the + * predicted vertical dimension after the transformation. + * + * \note This is a pure virtual member function that must be reimplemented + * in every derived class. + */ + virtual void GetNewSizes( int& width, int& height ) const = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class InterpolatingGeometricTransformation + * \brief Abstract base class of all PCL interpolating geometric image + * transformations. + * + * %InterpolatingGeometricTransformation represents a geometrical + * transformation that uses a pixel interpolating algorithm to yield + * transformed pixel sample values. Transformations implemented as derived + * classes of %InterpolatingGeometricTransformation can be applied to all + * standard image types defined in PCL. + * + * \sa GeometricTransformation, PixelInterpolation, ImageTransformation + */ +class PCL_CLASS InterpolatingGeometricTransformation : public GeometricTransformation +{ +public: + + /*! + * Constructs a %InterpolatingGeometricTransformation object that will use + * the specified pixel interpolation \a p. + * + * The specified PixelInterpolation object must remain valid and accessible + * as long as this object exists, or until this object is associated with a + * different pixel interpolation. + */ + InterpolatingGeometricTransformation( PixelInterpolation& p ) + : m_interpolation( &p ) + { + PCL_CHECK( m_interpolation != nullptr ) + } + + /*! + * Copy constructor. The constructed object will use the same pixel + * interpolation as the specified source object. + * + * The PixelInterpolation object used by both this object and the source + * object must remain valid and accessible as long as at least one of both + * objects is associated with it. + */ + InterpolatingGeometricTransformation( const InterpolatingGeometricTransformation& ) = default; + + /*! + * Move constructor. + */ + InterpolatingGeometricTransformation( InterpolatingGeometricTransformation&& x ) + : GeometricTransformation( x ) + , m_interpolation( x.m_interpolation ) + , m_unclipped( x.m_unclipped ) + { + x.m_interpolation = nullptr; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * After assignment, this object will use the same pixel interpolation as + * the specified source object. The previously used pixel interpolation is + * simply forgotten by this object, which will no longer depend on it. + * + * The PixelInterpolation object used by both this object and the source + * object must remain valid and accessible as long as at least one of both + * objects is associated with it. + */ + InterpolatingGeometricTransformation& operator =( const InterpolatingGeometricTransformation& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + InterpolatingGeometricTransformation& operator =( InterpolatingGeometricTransformation&& x ) + { + m_interpolation = x.m_interpolation; + x.m_interpolation = nullptr; + m_unclipped = x.m_unclipped; + return *this; + } + + /*! + * Returns a reference to the unmodifiable PixelInterpolation object that + * this transformation is currently using. + */ + const PixelInterpolation& Interpolation() const + { + PCL_CHECK( m_interpolation != nullptr ) + return *m_interpolation; + } + + /*! + * Returns a reference to the PixelInterpolation object that this + * transformation is currently using. + */ + PixelInterpolation& Interpolation() + { + PCL_CHECK( m_interpolation != nullptr ) + return *m_interpolation; + } + + /*! + * Causes this transformation to use the specified pixel interpolation \a p. + * + * The new pixel interpolation will be used to generate transformed pixel + * values after calling this function. The previously used pixel + * interpolation is simply forgotten by this object, which will no longer + * depend on it. + * + * The specified PixelInterpolation object must remain valid and accessible + * as long as this object exists, or until this object is associated with a + * different pixel interpolation. + */ + void SetInterpolation( PixelInterpolation& p ) + { + m_interpolation = &p; + PCL_CHECK( m_interpolation != nullptr ) + } + + /*! + * Returns true if this image transformation applies unclipped pixel + * interpolations. Unclipped interpolations don't constrain interpolated + * pixel sample values to the native range of the pixel data type of the + * transformed image. This allows to apply interpolating transformations to + * images that exceed their representable ranges; for example, when images + * are used to store and manipulate arbitrary matrices for convenience. + * + * Unclipped transformations are always disabled by default. + */ + bool UsingUnclippedInterpolation() const + { + return m_unclipped; + } + + /*! + * Enables the use of unclipped pixel interpolations. See + * UsingUnclippedInterpolation() for more information. + */ + void EnableUnclippedInterpolation( bool enable = true ) + { + m_unclipped = enable; + } + + /*! + * Disables the use of unclipped pixel interpolations. See + * UsingUnclippedInterpolation() for more information. + */ + void DisableUnclippedInterpolation( bool disable = true ) + { + EnableUnclippedInterpolation( !disable ); + } + +protected: + + PixelInterpolation* m_interpolation = nullptr; + bool m_unclipped = false; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_GeometricTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GeometricTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GlobalSettings.h b/3rdparty/include/pcl/GlobalSettings.h new file mode 100644 index 0000000..f565f3f --- /dev/null +++ b/3rdparty/include/pcl/GlobalSettings.h @@ -0,0 +1,522 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GlobalSettings.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_GlobalSettings_h +#define __PCL_GlobalSettings_h + +/// \file pcl/GlobalSettings.h + +#include +#include + +#include +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION +#include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::GlobalVariableType + * \brief Data types for global platform variables + * + * + * + * + * + * + * + * + * + * + *
GlobalVariableType::Undefined Indicates that the requested global variable does not exist.
GlobalVariableType::Flag Boolean value.
GlobalVariableType::Integer Signed integer.
GlobalVariableType::Unsigned Unsigned integer.
GlobalVariableType::Real Floating point real (IEEE 64-bit floating point).
GlobalVariableType::Color RGBA color (uint32).
GlobalVariableType::Font A font face (a string).
GlobalVariableType::String A UTF-16 string.
+ */ +namespace GlobalVariableType +{ + enum value_type + { + Undefined, // The requested global variable doesn't exist + Flag, // bool + Integer, // int + Unsigned, // unsigned + Real, // double + Color, // RGBA (= uint32) + Font, // Font + String // String + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class PixInsightSettings + * \brief Retrieves global settings from the PixInsight core application + * + * PixInsight global settings, also known as global variables, are + * identifier/value pairs available from the core application to all installed + * modules. Settings can be of six types: flags (or Boolean), integer (signed + * and unsigned), real (floating point), color, font, and string. See the + * pcl::GlobalVariableType namespace for more details. + * + * Below is a complete list of all global settings available in current + * versions of the PixInsight platform (updated as of core version 1.8.8-13). + * + *

PixInsight Public Global Variables

+ * + *

Global %Flags

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Application/AutoUIScaling
Application/HealRegistryInformationOnUpdates
ColorManagement/DefaultEmbedProfilesInGrayscaleImages
ColorManagement/DefaultEmbedProfilesInRGBImages
ColorManagement/DefaultGamutCheckEnabled
ColorManagement/DefaultProofingEnabled
ColorManagement/IsEnabled
ColorManagement/IsValidRead-only.
ColorManagement/UseLowResolutionCLUTs
ColorManagement/UseProofingBPC
ImageWindow/BackupFiles
ImageWindow/CreatePreviewsFromCoreProperties
ImageWindow/Default24BitScreenLUT
ImageWindow/DefaultEmbedProperties
ImageWindow/DefaultEmbedThumbnails
ImageWindow/DefaultMasksShown
ImageWindow/DefaultMetricResolution
ImageWindow/FastScreenRenditions
ImageWindow/FileFormatWarnings
ImageWindow/FollowDownloadLocations
ImageWindow/HighDPIRenditions
ImageWindow/LoadAstrometricSolutions
ImageWindow/LoadInitialProcessingFromCoreProperties
ImageWindow/MeasureScreenRenderingPerformance
ImageWindow/NativeFileDialogs
ImageWindow/ProjectVerifyIncrementalChecksums
ImageWindow/RememberFileOpenType
ImageWindow/RememberFileSaveType
ImageWindow/ShowActiveSTFIndicators
ImageWindow/ShowCaptionCurrentChannels
ImageWindow/ShowCaptionFullPaths
ImageWindow/ShowCaptionIdentifiers
ImageWindow/ShowCaptionZoomRatios
ImageWindow/ShowViewSelectorImageThumbnails
ImageWindow/StrictFileSaveMode
ImageWindow/SwapCompression
ImageWindow/TouchEvents
ImageWindow/UseFileNamesAsImageIdentifiers
ImageWindow/VerboseNetworkOperationsNot available on Windows.
ImageWindow/ZoomAtCursor
MainWindow/AcceptDroppedFiles
MainWindow/AnimateCombo
MainWindow/AnimateMenu
MainWindow/AnimateToolBox
MainWindow/AnimateToolTip
MainWindow/AnimateWindows
MainWindow/CapitalizedMenuBars
MainWindow/CheckForUpdatesAtStartup
MainWindow/ConfirmProgramTermination
MainWindow/DesktopSettingsAware
MainWindow/DoubleClickLaunchesOpenDialog
MainWindow/ExpandFavoritesAtStartup
MainWindow/ExpandMostUsedAtStartup
MainWindow/ExpandRecentlyUsedAtStartup
MainWindow/ExplodeIcons
MainWindow/FadeAutoHideWindows
MainWindow/FadeMenu
MainWindow/FadeToolTip
MainWindow/FadeWindows
MainWindow/FadeWorkspaces
MainWindow/FullScreenAtStartup
MainWindow/HighQualityWallpapers
MainWindow/HoverableAutoHideWindows
MainWindow/ImplodeIcons
MainWindow/MaximizeAtStartup
MainWindow/NativeMenuBar
MainWindow/OpenURLsWithInternalBrowser
MainWindow/OpenResourcesOnNewWebBrowserWindows
MainWindow/PrivateWebBrowsingMode
MainWindow/ShowFavorites
MainWindow/ShowMostUsed
MainWindow/ShowRecentlyUsed
MainWindow/ShowSplashAtStartup
MainWindow/ShowViewListImageThumbnails
MainWindow/ShowWorkspaceThumbnails
MainWindow/TranslucentAutoHideWindows
MainWindow/TranslucentChildWindows
MainWindow/TranslucentWindows
MainWindow/UseWallpapers
MainWindow/WindowButtonsOnTheLeft
Process/AlertOnProcessCompleted
Process/BackupFiles
Process/EnableCUDAAcceleration
Process/EnableExecutionStatistics
Process/EnableLaunchStatistics
Process/EnableParallelCoreColorManagement
Process/EnableParallelCoreRendering
Process/EnableParallelModuleProcessing
Process/EnableParallelProcessing
Process/EnableThreadCPUAffinity
Process/GenerateScriptComments
Process/InitCUDARuntimeAtStartup
Process/VerifyScriptChecksums
+ * + *

Global Integers

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Application/FontResolutionIn dots per inch.
ColorManagement/DefaultRenderingIntentSee the pcl::ICCRenderingIntent namespace.
ColorManagement/OnMissingProfileCore application policies. See the documentation for ColorManagementSetup.
ColorManagement/OnProfileMismatchCore application policies. See the documentation for ColorManagementSetup.
ColorManagement/ProofingIntentSee the pcl::ICCRenderingIntent namespace.
ImageWindow/CursorToleranceIn device pixels.
ImageWindow/DefaultMaskModeSee the pcl::MaskMode namespace.
ImageWindow/DefaultTransparencyModeSee the pcl::TransparencyMode namespace.
ImageWindow/FastScreenRenditionThresholdIn MiB.
ImageWindow/ImageThumbnailSizeIn image pixels.
ImageWindow/ProjectThumbnailSizeIn image pixels.
ImageWindow/WheelStepAngleIn degrees, unsigned.
ImageWindow/WheelDirectionWhen >= 0, rotating forward zooms out. When < 0, rotating forward zooms in.
MainWindow/MaxRecentFilesMaximum length of recent file menu lists.
Process/AutoSavePSMPeriodIn seconds.
Process/ConsoleDelayIn milliseconds.
Process/MaxConsoleLinesMaximum number of stored text lines on %Process %Console.
Process/MaxModuleThreadPriorityFrom 0=idle to 7=real-time.
Process/MaxProcessorsMaximum number of processor cores allowed for installed modules.
Process/MaxFileReadThreadsMaximum number of concurrent file reading threads.
Process/MaxFileWriteThreadsMaximum number of concurrent file writing threads.
Process/MaxUsageListLengthMaximum length of the Recently Used and Most Used lists on %Process %Explorer.
System/NumberOfProcessorsTotal number of processor cores available. Read-only.
TransparencyBrush/BrushSee the pcl::BackgroundBrush namespace.
Workspace/PrimaryScreenCenterXRead-only. In physical device pixels.
Workspace/PrimaryScreenCenterYRead-only. In physical device pixels.
Workspace/IconGridSpacingGrid distance for aligned icon positions on all workspaces. In logical device pixels.
+ * + *

Global Reals

+ * + * + * + * + * + * + * + * + * + * + * + * + * + *
Application/StartJDStarting time of the core application instance as a Julian day number. Read-only.
Application/UIScalingFactorGlobal interface scaling factor of the core application. In the range [1.0,4.0].
ImageWindow/DefaultHorizontalResolutionIn device pixels per resolution unit. See the ImageWindow/DefaultMetricResolution global variable.
ImageWindow/DefaultVerticalResolutionIn device pixels per resolution unit. See the ImageWindow/DefaultMetricResolution global variable.
ImageWindow/PinchSensitivityFor touch events. In device pixels.
MainWindow/ActiveWindowOpacityWindow opacity in the [0,1] range.
MainWindow/AutoHideWindowOpacityWindow opacity in the [0,1] range.
MainWindow/InactiveChildWindowOpacityWindow opacity in the [0,1] range.
MainWindow/InactiveWindowOpacityWindow opacity in the [0,1] range.
MainWindow/MovingChildWindowOpacityWindow opacity in the [0,1] range.
MainWindow/MovingWindowOpacityWindow opacity in the [0,1] range.
+ * + *

Global Colors

+ * + * Since PixInsight core version 1.8.0, most UI colors and fonts are defined in + * cascading style sheet files loaded automatically on startup. Only the + * following four color variables remain because they are purely functional + * (i.e., not related to the appearance of GUI controls). + * + * + * + * + * + * + *
ColorManagement/GamutWarningColorFor signaling out-of-gamut pixels in color proofing image renditions.
TransparencyBrush/BackgroundColorBackground brush color for renditions of translucent image pixels.
TransparencyBrush/DefaultColorOpaque color for renditions of translucent image pixels.
TransparencyBrush/ForegroundColorForeground brush color for renditions of translucent image pixels.
+ * + *

Global Fonts

+ * + * Currently there are no global font variables. Since PixInsight core version + * 1.8.0, all UI fonts are defined through cascading style sheet files loaded + * automatically on startup. + * + *

Global Strings

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Application/AppDirectoryFull path to the distribution's core application bundle. Read-only. macOS only,
Application/AsteroidEphemeridesFileFile name or path of the distribution's asteroid ephemerides file (XEPH format).
Application/AsteroidEphemeridesFilePathFull path to the current distribution's asteroid ephemerides file (XEPH format). Read-only.
Application/BaseDirectoryBase directory of the core distribution. Read-only.
Application/BinDirectoryFull path to the distribution's bin directory. Read-only.
Application/CIP_ITRSDataFileFile name or path of the distribution's data file of CIP coordinates in the ITRS (plain text).
Application/CIP_ITRSDataFilePathFull path to the current distribution's data file of CIP coordinates in the ITRS (plain text). Read-only
Application/CoreDirectoryFull directory of the core executable file. Read-only.
Application/CoreFilePathFull file path of the core executable. Read-only.
Application/DeltaATDataFileFile name or path of the distribution's Delta AT (TAI-UTC) data file (plain text).
Application/DeltaATDataFilePathFull path to the current distribution's Delta AT (TAI-UTC) data file (plain text). Read-only
Application/DeltaTDataFileFile name or path of the distribution's Delta T (TT-UT1) data file (plain text).
Application/DeltaTDataFilePathFull path to the current distribution's Delta T (TT-UT1) data file (plain text). Read-only
Application/DocDirectoryFull path to the distribution's doc directory. Read-only.
Application/EtcDirectoryFull path to the distribution's etc directory. Read-only.
Application/FundamentalEphemeridesFileFile name or path of the distribution's fundamental ephemerides file (XEPH format).
Application/FundamentalEphemeridesFilePathFull path to the current distribution's fundamental ephemerides file (XEPH format). Read-only.
Application/HighResFont%Font family for automatic style sheet replacement on high-dpi displays.
Application/HighResMonoFontMonospaced font family for automatic style sheet replacement on high-dpi displays.
Application/IncludeDirectoryFull path to the distribution's include directory. Read-only.
Application/LibDirectoryFull path to the distribution's lib directory. Read-only.
Application/LibraryDirectoryFull path to the distribution's library directory. Read-only.
Application/LowResFont%Font family for automatic style sheet replacement on low-dpi displays.
Application/LowResMonoFontMonospaced font family for automatic style sheet replacement on low-dpi displays.
Application/NutationModelFileFile name or path of the distribution's nutation model file (XEPH format).
Application/NutationModelFilePathFull path to the current distribution's nutation model file (XEPH format). Read-only.
Application/ResourceFile01Core resource file #1.
Application/ResourceFile02Core resource file #2.
Application/ResourceFile03Core resource file #3.
Application/ResourceFile04Core resource file #4.
Application/ResourceFile05Core resource file #5.
Application/ResourceFile06Core resource file #6.
Application/ResourceFile07Core resource file #7.
Application/ResourceFile08Core resource file #8.
Application/ResourceFile09Core resource file #9.
Application/ResourceFile10Core resource file #10.
Application/RscDirectoryFull path to the distribution's rsc directory. Read-only.
Application/ShortTermAsteroidEphemeridesFileFile name or path of the distribution's asteroid ephemerides file (XEPH format) - short-term version (reduced time span).
Application/ShortTermAsteroidEphemeridesFilePathFull path to the current distribution's asteroid ephemerides file (XEPH format) - short-term version (reduced time span). Read-only.
Application/ShortTermFundamentalEphemeridesFileFile name or path of the distribution's fundamental ephemerides file (XEPH format) - short-term version (reduced time span).
Application/ShortTermFundamentalEphemeridesFilePathFull path to the current distribution's fundamental ephemerides file (XEPH format) - short-term version (reduced time span). Read-only.
Application/ShortTermNutationModelFileFile name or path of the distribution's nutation model file (XEPH format) - short-term version (reduced time span).
Application/ShortTermNutationModelFilePathFull path to the current distribution's nutation model file (XEPH format) - short-term version (reduced time span). Read-only.
Application/SrcDirectoryFull path to the distribution's src directory. Read-only.
Application/StartTimeStarting time of the core application in ISO 8601 extended format. Read-only.
Application/StyleSheetFileMain core stile sheet file.
ColorManagement/DefaultGrayscaleProfilePathFull path to the default ICC color profile for grayscale monochrome images.
ColorManagement/DefaultRGBProfilePathFull path to the default ICC color profile for RGB color images.
ColorManagement/MonitorProfilePathFull path to the ICC color profile associated with the primary monitor. Read-only.
ColorManagement/ProofingProfilePathFull path to the ICC color profile for the color proofing target device.
ColorManagement/UpdateMonitorProfileFull path to the scheduled new ICC color profile for the primary monitor. Write-only. See the documentation for ColorManagementSetup.
FileFormat/ReadFiltersA list of file filters for file formats capable of image read operations, suitable for file dialogs. Read-only. Updated dynamically on-demand.
FileFormat/WriteFiltersA list of file filters for file formats capable of image write operations, suitable for file dialogs. Read-only. Updated dynamically on-demand.
ImageContainerIcon/PrefixPrefix for automatically generated image container identifiers.
ImageWindow/ClonePostfixPostfix appended to image duplicates
ImageWindow/DefaultFileExtensionThe default file suffix used to save newly created images.
ImageWindow/DownloadsDirectoryFull path to the core downloads directory.
ImageWindow/NewImageCaptionWindow title token for signaling newly created images.
ImageWindow/PrefixPrefix used for automatically generated image identifiers.
ImageWindow/ProxyURLThe proxy that will be used for core network operations.
MainWindow/WallpaperFile01Core workspace wallpaper file #1.
MainWindow/WallpaperFile02Core workspace wallpaper file #2.
MainWindow/WallpaperFile03Core workspace wallpaper file #3.
MainWindow/WallpaperFile04Core workspace wallpaper file #4.
MainWindow/WallpaperFile05Core workspace wallpaper file #5.
MainWindow/WallpaperFile06Core workspace wallpaper file #6.
MainWindow/WallpaperFile07Core workspace wallpaper file #7.
MainWindow/WallpaperFile08Core workspace wallpaper file #8.
MainWindow/WallpaperFile09Core workspace wallpaper file #9.
MainWindow/WallpaperFile10Core workspace wallpaper file #10.
Preview/PrefixPrefix used for automatically generated preview identifiers.
ProcessIcon/PrefixPrefix used for automatically generated process icon identifiers.
View/BrokenLinkTextText fragment used to signal broken image and/or process relations, such as missing masks.
ViewList/NoPreviewSelectedTextText fragment used when there are no previews selected.
ViewList/NoPreviewsAvailableTextText fragment used when there are no previews available.
ViewList/NoViewSelectedTextText fragment used when there are no views selected.
ViewList/NoViewsAvailableTextText fragment used when there are no views available.
Workspace/PrefixPrefix used for automatically generated workspace identifiers.
+ */ +class PCL_CLASS PixInsightSettings +{ +public: + + /*! + * Represents the data type of a global variable. + */ + typedef GlobalVariableType::value_type variable_type; + + /*! + * Default constructor. This constructor is disabled because + * %PixInsightSettings is not an instantiable class. + */ + PixInsightSettings() = delete; + + /*! + * Copy constructor. This constructor is disabled because + * %PixInsightSettings is not an instantiable class. + */ + PixInsightSettings( const PixInsightSettings& ) = delete; + + /*! + * Copy assignment. This operator is disabled because + * %PixInsightSettings is not an instantiable class. + */ + PixInsightSettings& operator =( const PixInsightSettings& ) = delete; + + /*! + * Virtual destructor. This destructor is disabled because + * %PixInsightSettings is not an instantiable class. + */ + virtual ~PixInsightSettings() = delete; + + /*! + * Retrieves the type of a global variable \a globalId. + */ + static variable_type GlobalVariableType( const IsoString& globalId ); + + /*! + * Returns true iff the specified global variable \a globalId is defined in + * the current PixInsight platform. + */ + static bool IsGlobalVariableDefined( const IsoString& globalId ) + { + return GlobalVariableType( globalId ) != GlobalVariableType::Undefined; + } + + /*! + * Returns the value of a global boolean variable. + */ + static bool GlobalFlag( const IsoString& globalId ); + + /*! + * Returns the value of a global signed integer variable. + */ + static int GlobalInteger( const IsoString& globalId ); + + /*! + * Returns the value of a global unsigned integer variable. + */ + static unsigned GlobalUnsigned( const IsoString& globalId ); + + /*! + * Returns the value of a global floating point real variable. + */ + static double GlobalReal( const IsoString& globalId ); + + /*! + * Returns the value of a global RGBA color variable. + */ + static RGBA GlobalColor( const IsoString& globalId ); + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + /*! + * Returns the value of a global font face variable. + */ + static Font GlobalFont( const IsoString& globalId ); +#endif + + /*! + * Returns the value of a global string variable. + */ + static String GlobalString( const IsoString& globalId ); + + /*! + * Begins a global variable update operation. + * + * \sa EndUpdate(), CalcelUpdate() + */ + static void BeginUpdate(); + + /*! + * Terminates a global variable update operation. + * + * \sa BeginUpdate(), CancelUpdate() + */ + static void EndUpdate(); + + /*! + * Aborts an ongoing global variable update operation. + * + * Use this function if you catch an exception during the sequence of + * SetGlobalXXX() calls. After cancelling an update operation, you + * shouldn't call EndUpdate(). + * + * \sa BeginUpdate(), EndUpdate() + */ + static void CancelUpdate(); + + /*! + * Sets the value of a global boolean variable. + */ + static void SetGlobalFlag( const IsoString& globalId, bool ); + + /*! + * Sets the value of a global signed integer variable. + */ + static void SetGlobalInteger( const IsoString& globalId, int ); + + /*! + * Sets the value of a global unsigned integer variable. + */ + static void SetGlobalUnsigned( const IsoString& globalId, unsigned ); + + /*! + * Sets the value of a global floating point real variable. + */ + static void SetGlobalReal( const IsoString& globalId, double ); + + /*! + * Sets the value of a global RGBA color variable. + */ + static void SetGlobalColor( const IsoString& globalId, RGBA ); + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + /*! + * Sets the value of a global font face variable. + */ + static void SetGlobalFont( const IsoString& globalId, const Font& ); +#endif + + /*! + * Sets the value of a global string variable. + */ + static void SetGlobalString( const IsoString& globalId, const String& ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_GlobalSettings_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GlobalSettings.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GnomonicProjection.h b/3rdparty/include/pcl/GnomonicProjection.h new file mode 100644 index 0000000..696298f --- /dev/null +++ b/3rdparty/include/pcl/GnomonicProjection.h @@ -0,0 +1,178 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GnomonicProjection.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_GnomonicProjection_h +#define __PCL_GnomonicProjection_h + +/// \file pcl/GnomonicProjection.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GnomonicProjection + * \brief Gnomonic projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS GnomonicProjection : public ProjectionBase +{ +public: + + /*! + * Constructs a default %GnomonicProjection object with the specified + * origin equatorial coordinates \a ra0 and \a dec0 in degrees. + */ + GnomonicProjection( double ra0, double dec0 ) + { + m_ra0 = Rad( ra0 ); + m_dec0 = Rad( dec0 ); + SinCos( m_dec0, m_sinDec0, m_cosDec0 ); + } + + /*! + * Constructs a %GnomonicProjection object with the specified \a scale + * factor and origin equatorial coordinates \a ra0 and \a dec0 in degrees. + */ + GnomonicProjection( double scale, double ra0, double dec0 ) + : m_scale( scale ) + { + m_ra0 = Rad( ra0 ); + m_dec0 = Rad( dec0 ); + SinCos( m_dec0, m_sinDec0, m_cosDec0 ); + } + + /*! + * Copy constructor. + */ + GnomonicProjection( const GnomonicProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new GnomonicProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "TAN"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Gnomonic"; + } + + /*! + * Transforms from celestial coordinates to world coordinates. + */ + bool Direct( DPoint& pW, const DPoint& pRD ) const noexcept override; + + /*! + * Transforms from world coordinates to celestial coordinates. + */ + bool Inverse( DPoint& pRD, const DPoint& pW ) const noexcept override; + + /*! + * + */ + bool CheckBrokenLine( const DPoint& cp1, const DPoint& cp2 ) const noexcept override + { + DPoint gp1, gp2; + return Direct( gp1, cp1 ) && Direct( gp2, cp2 ) && + (gp1.x - gp2.x)*(gp1.x - gp2.x) + (gp1.y - gp2.y)*(gp1.y - gp2.y) < 45*45; + } + +protected: + + bool Project( DPoint& pW, const DPoint& pN ) const noexcept override + { + return false; + } + + bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept override + { + return false; + } + +private: + + double m_scale = Const::deg(); + double m_sinDec0; + double m_cosDec0; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_GnomonicProjection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GnomonicProjection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Graphics.h b/3rdparty/include/pcl/Graphics.h new file mode 100644 index 0000000..af561f8 --- /dev/null +++ b/3rdparty/include/pcl/Graphics.h @@ -0,0 +1,2329 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Graphics.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_Graphics_h +#define __PCL_Graphics_h + +/// \file pcl/Graphics.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __PCL_GRAPHICS_DONT_REMOVE_PREVIOUS_DECLARATIONS + +// Remove conflicting identifiers from Win32 SDK headers. +// If more conflicts arise, fix *all* of them *here only*. +#ifdef DrawText +#undef DrawText +#endif + +#endif // !__PCL_GRAPHICS_DONT_REMOVE_PREVIOUS_DECLARATIONS + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::CompositionOp + * \brief Image composition operators. + * + * The following are the Porter-Duff alpha composition operators, + * supported by all versions of PixInsight: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
CompositionOp::Clear Clear
CompositionOp::Source A
CompositionOp::Destination B
CompositionOp::SourceOver A over B
CompositionOp::DestinationOver B over A
CompositionOp::SourceIn A in B
CompositionOp::DestinationIn B in A
CompositionOp::SourceOut A out B
CompositionOp::DestinationOut B out A
CompositionOp::SourceAtop A atop B
CompositionOp::DestinationAtop B atop A
CompositionOp::Xor A xor B
+ * + * See T. Porter & T. Duff, Compositing Digital Images, Computer + * Graphics Vol. 18, Num. 3, July 1984, pp 253-259. + * + * In addition, the following operators are also supported starting from + * PixInsight core version 1.7.0.702: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
CompositionOp::Min Min( A, B )
CompositionOp::Max Max( A, B )
CompositionOp::Add A + B
CompositionOp::Multiply A * B
CompositionOp::Screen ~A * ~B
CompositionOp::Overlay (A > 0.5) ? ~(~(2*(A - 0.5)) * ~B) : 2*A*B
CompositionOp::ColorDodge A/~B
CompositionOp::ColorBurn ~(~A/B)
CompositionOp::HardLight (B > 0.5) ? ~(~A * ~(2*(B - 0.5))) : A*2*B
CompositionOp::SoftLight (B > 0.5) ? ~(~A * ~(B - 0.5)) : A*(B + 0.5)
CompositionOp::Difference Abs( A - B )
CompositionOp::Exclusion 0.5 - 2*(A - 0.5)*(B - 0.5)
+ * + * In the tables above, A represents a target pixel and B represents a source + * pixel. For example, if a Graphics object is being used to paint on a Bitmap + * object, bitmap pixels are target pixels, and any graphical elements drawn + * using the %Graphics object are considered as source pixels. + */ +namespace CompositionOp +{ + enum value_type + { + Clear, // 0 + Source, // A + Destination, // B + SourceOver, // A over B + DestinationOver, // B over A + SourceIn, // A in B + DestinationIn, // B in A + SourceOut, // A out B + DestinationOut, // B out A + SourceAtop, // A atop B + DestinationAtop, // B atop A + Xor, // A xor B + Min, // Min( A, B ) + Max, // Max( A, B ) + Add, // A + B + Multiply, // A * B + Screen, // ~A * ~B + Overlay, // (A > 0.5) ? ~(~(2*(A - 0.5)) * ~B) : 2*A*B + ColorDodge, // A/~B + ColorBurn, // ~(~A/B) + HardLight, // (B > 0.5) ? ~(~A * ~(2*(B - 0.5))) : A*2*B + SoftLight, // (B > 0.5) ? ~(~A * ~(B - 0.5)) : A*(B + 0.5) + Difference, // Abs( A - B ) + Exclusion, // 0.5 - 2*(A - 0.5)*(B - 0.5) + + NumberOfCompositionOps + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::FillRule + * \brief Polygon fill rules + * + * + * + * + *
FillRule::OddEven Odd-even (or parity, alternate) polygon fill rule
FillRule::Winding Nonzero winding polygon fill rule
+ */ +namespace FillRule +{ + enum value_type + { + OddEven, // Odd-even (or parity, alternate) polygon fill rule + Winding, // Nonzero winding polygon fill rule + + NumberOfFillRules + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class Control; +class Bitmap; +class SVG; + +// ---------------------------------------------------------------------------- + +/*! + * \brief Base class of client-side interface classes to PixInsight graphics contexts + * + * ### TODO: Write a detailed description for %GraphicsContextBase. + * + * ### TODO: Include a number of examples for drawing primitives, composition + * operators, rendering performance, transformations, etc. + */ +class PCL_CLASS GraphicsContextBase : public UIObject +{ +public: + + /*! + * Represents a Porter-Duff alpha composition operator. + */ + typedef CompositionOp::value_type composition_op; + + /*! + * Represents a polygon fill rule. + */ + typedef FillRule::value_type fill_rule; + + /*! + * Constructs an inactive graphics context. + */ + GraphicsContextBase(); + + /*! + * Constructs an active graphics context, ready to draw on the specified + * \a control. + * + * \warning Invoking this constructor outside a Control::OnPaint() event + * handler is illegal on all supported platforms. If called without an + * active OnPaint() event, this constructor throws an Error exception. + */ + GraphicsContextBase( Control& control ); + + /*! + * Constructs an active graphics context, ready to draw on the specified + * \a bitmap. + */ + GraphicsContextBase( Bitmap& bitmap ); + + /*! + * Constructs an active graphics context, ready to draw on the specified + * \a svg object. + */ + GraphicsContextBase( SVG& svg ); + + /*! + * Move constructor. + */ + GraphicsContextBase( GraphicsContextBase&& x ) + : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys a %GraphicsContextBase object. If this graphics context is + * active, it is terminated upon destruction. + */ + virtual ~GraphicsContextBase() + { + if ( !IsNull() ) + if ( IsPainting() ) + EndPaint(); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GraphicsContextBase& operator =( GraphicsContextBase&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since graphics contexts are unique objects, calling this member function + * has no effect. + */ + void EnsureUnique() override + { + } + + /*! + * Activates this graphics context to draw on the specified \a control. + * + * \warning Calling this function outside a Control::OnPaint() event handler + * is illegal on all supported platforms. + */ + bool BeginPaint( Control& control ); + + /*! + * Activates this graphics context to draw on the specified \a bitmap. + */ + bool BeginPaint( Bitmap& bitmap ); + + /*! + * Activates this graphics context to draw on the specified \a svg object. + */ + bool BeginPaint( SVG& svg ); + + /*! + * Returns true iff this graphics context is currently active. + */ + bool IsPainting() const; + + /*! + * Terminates a graphics context drawing operation. + */ + void EndPaint(); + + /*! # + */ + bool IsTransformationEnabled() const; + + /*! # + */ + void EnableTransformation( bool = true ); + + /*! # + */ + void DisableTransformation( bool disable = true ) + { + EnableTransformation( !disable ); + } + + /*! # + */ + Matrix TransformationMatrix() const; + + /*! # + */ + void SetTransformationMatrix( const Matrix& M ); + + /*! # + */ + void SetTransformationMatrix( double m11, double m12, double m13, + double m21, double m22, double m23, + double m31, double m32, double m33 ) + { + SetTransformationMatrix( Matrix( m11, m12, m13, m21, m22, m23, m31, m32, m33 ) ); + } + + /*! # + */ + void MultiplyTransformationMatrix( const Matrix& M ); + + /*! # + */ + void MultiplyTransformationMatrix( double m11, double m12, double m13, + double m21, double m22, double m23, + double m31, double m32, double m33 ) + { + MultiplyTransformationMatrix( Matrix( m11, m12, m13, m21, m22, m23, m31, m32, m33 ) ); + } + + /*! # + */ + void RotateTransformation( double angleRadians ); + + /*! # + */ + void ScaleTransformation( double xScale, double yScale ); + + /*! # + */ + void ScaleTransformation( double scale ) + { + ScaleTransformation( scale, scale ); + } + + /*! # + */ + void TranslateTransformation( double dx, double dy ); + + /*! # + */ + void TranslateTransformation( double d ) + { + TranslateTransformation( d, d ); + } + + /*! # + */ + void ShearTransformation( double sx, double sy ); + + /*! # + */ + void ShearTransformation( double s ) + { + ShearTransformation( s, s ); + } + + /*! # + */ + void ResetTransformation(); + + /*! # + */ + void Transform( double& x, double& y ) const; + + /*! # + */ + void Transform( DPoint* p, size_type n ) const; + + /*! # + */ + void Transform( Array& a ) const + { + Transform( a.Begin(), a.Length() ); + } + + /*! # + */ + DPoint Transformed( const DPoint& p ) const + { + DPoint p1( p ); + Transform( p1.x, p1.y ); + return p1; + } + + /*! # + */ + DRect Transformed( const DRect& r ) const + { + DRect r1( r ); + Transform( r1.x0, r1.y0 ); + Transform( r1.x1, r1.y1 ); + return r1; + } + + /*! # + */ + Array Transformed( const Array& a ) const + { + Array a1( a ); + Transform( a1 ); + return a1; + } + + /*! # + */ + bool IsClippingEnabled() const; + + /*! # + */ + void EnableClipping( bool = true ); + + /*! # + */ + void DisableClipping( bool disable = true ) + { + EnableClipping( !disable ); + } + + /*! # + */ + bool IsAntialiasingEnabled() const; + + /*! # + */ + void EnableAntialiasing( bool = true ); + + /*! # + */ + void DisableAntialiasing( bool disable = true ) + { + EnableAntialiasing( !disable ); + } + + /*! # + */ + bool IsTextAntialiasingEnabled() const; + + /*! # + */ + void EnableTextAntialiasing( bool = true ); + + /*! # + */ + void DisableTextAntialiasing( bool disable = true ) + { + EnableTextAntialiasing( !disable ); + } + + /*! # + */ + bool IsSmoothInterpolationEnabled() const; + + /*! # + */ + void EnableSmoothInterpolation( bool = true ); + + /*! # + */ + void DisableSmoothInterpolation( bool disable = true ) + { + EnableSmoothInterpolation( !disable ); + } + + /*! # + */ + composition_op CompositionOperator() const; + + /*! # + */ + void SetCompositionOperator( composition_op ); + + /*! # + */ + void ResetCompositionOperator() + { + SetCompositionOperator( CompositionOp::SourceOver ); + } + + /*! # + */ + double Opacity() const; + + /*! # + */ + void SetOpacity( double op ); + + /*! # + */ + pcl::Brush BackgroundBrush() const; + + /*! # + */ + void SetBackgroundBrush( const pcl::Brush& ); + + /*! # + */ + bool IsTransparentBackground() const; + + /*! # + */ + bool IsOpaqueBackground() const + { + return !IsTransparentBackground(); + } + + /*! # + */ + void SetTransparentBackground( bool = true ); + + /*! # + */ + void SetOpaqueBackground( bool opaque = true ) + { + SetTransparentBackground( !opaque ); + } + + /*! # + */ + pcl::Pen Pen() const; + + /*! + * \deprecated Use Graphics::Pen() in newly produced code. + */ + pcl::Pen GetPen() const + { + return this->Pen(); + } + + /*! # + */ + void SetPen( const pcl::Pen& ); + + /*! # + */ + void SetPen( RGBA color, float width ) + { + SetPen( pcl::Pen( color, width ) ); + } + + /*! # + */ + pcl::Brush Brush() const; + + /*! + * \deprecated Use Graphics::Brush() in newly produced code. + */ + pcl::Brush GetBrush() const + { + return this->Brush(); + } + + /*! # + */ + void SetBrush( const pcl::Brush& ); + + /*! # + */ + pcl::Font Font() const; + + /*! + * \deprecated Use Graphics::Font() in newly produced code. + */ + pcl::Font GetFont() const + { + return this->Font(); + } + + /*! # + */ + void SetFont( const pcl::Font& ); + + /*! # + */ + void PushState(); + + /*! # + */ + void PopState(); + +protected: + + /*! + * \internal + */ + GraphicsContextBase( void* h ) : UIObject( h ) + { + } + +private: + + void* CloneHandle() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Graphics + * \brief Client-side interface to a PixInsight graphics context object + * + * ### TODO: Write a detailed description for %Graphics. + * + * ### TODO: Include a number of examples for drawing primitives, composition + * operators, rendering performance, transformations, etc. + */ +class PCL_CLASS Graphics : public GraphicsContextBase +{ +public: + + /*! + * Represents a Porter-Duff alpha composition operator. + */ + typedef GraphicsContextBase::composition_op composition_op; + + /*! + * Represents a polygon fill rule. + */ + typedef GraphicsContextBase::fill_rule fill_rule; + + /*! + * Constructs an inactive graphics context. + */ + Graphics() = default; + + /*! + * Constructs an active graphics context, ready to draw on the specified + * \a control. + * + * \warning Invoking this constructor outside a Control::OnPaint() event + * handler is illegal on all supported platforms. If called without an + * active OnPaint() event, this constructor throws an Error exception. + */ + Graphics( Control& control ) + : GraphicsContextBase( control ) + { + } + + /*! + * Constructs an active graphics context, ready to draw on the specified + * \a bitmap. + */ + Graphics( Bitmap& bitmap ) + : GraphicsContextBase( bitmap ) + { + } + + /*! + * Constructs an active graphics context, ready to draw on the specified + * \a svg object. + */ + Graphics( SVG& svg ) + : GraphicsContextBase( svg ) + { + } + + /*! + * Move constructor. + */ + Graphics( Graphics&& x ) + : GraphicsContextBase( std::move( x ) ) + { + } + + /*! + * Destroys a %Graphics object. If this graphics context is active, it is + * terminated upon destruction. + */ + virtual ~Graphics() + { + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Graphics& operator =( Graphics&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null %Graphics instance. A null %Graphics does + * not correspond to an existing graphics context in the PixInsight core + * application. + */ + static Graphics& Null(); + + /*! # + */ + pcl::Rect ClipRect() const; + + /*! # + */ + void SetClipRect( const pcl::Rect& r ) + { + SetClipRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void SetClipRect( int x0, int y0, int x1, int y1 ); + + /*! # + */ + void IntersectClipRect( const pcl::Rect& r ) + { + SetClipRect( ClipRect().Intersection( r ) ); + } + + /*! # + */ + void IntersectClipRect( int x0, int y0, int x1, int y1 ) + { + IntersectClipRect( pcl::Rect( x0, y0, x1, y1 ) ); + } + + /*! # + */ + void UniteClipRect( const pcl::Rect& r ) + { + SetClipRect( ClipRect().Union( r ) ); + } + + /*! # + */ + void UniteClipRect( int x0, int y0, int x1, int y1 ) + { + UniteClipRect( pcl::Rect( x0, y0, x1, y1 ) ); + } + + /*! # + */ + pcl::Point BrushOrigin() const; + + /*! # + */ + void SetBrushOrigin( const pcl::Point& p ) + { + SetBrushOrigin( p.x, p.y ); + } + + /*! # + */ + void SetBrushOrigin( int x, int y ); + + /*! # + */ + void DrawPoint( const pcl::Point& p ) + { + DrawPoint( p.x, p.y ); + } + + /*! # + */ + void DrawPoint( int x, int y ); + + /*! # + */ + void DrawLine( const pcl::Point& p0, const pcl::Point& p1 ) + { + DrawLine( p0.x, p0.y, p1.x, p1.y ); + } + + /*! # + */ + void DrawLine( int x0, int y0, int x1, int y1 ); + + /*! # + */ + void DrawRect( int x0, int y0, int x1, int y1 ); + + /*! # + */ + void DrawRect( const pcl::Rect& r ) + { + DrawRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void StrokeRect( int x0, int y0, int x1, int y1, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + void StrokeRect( const pcl::Rect& r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRect( r.x0, r.y0, r.x1, r.y1, pen ); + } + + /*! # + */ + void FillRect( int x0, int y0, int x1, int y1, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + void FillRect( const pcl::Rect& r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRect( r.x0, r.y0, r.x1, r.y1, brush ); + } + + /*! # + */ + void EraseRect( int x0, int y0, int x1, int y1 ) + { + FillRect( x0, y0, x1, y1, BackgroundBrush() ); + } + + /*! # + */ + void EraseRect( const pcl::Rect& r ) + { + EraseRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void DrawRoundedRect( int x0, int y0, int x1, int y1, double rx, double ry ); + + /*! # + */ + void DrawRoundedRect( int x0, int y0, int x1, int y1, double rxy = 25 ) + { + DrawRoundedRect( x0, y0, x1, y1, rxy, rxy ); + } + + /*! # + */ + void DrawRoundedRect( const pcl::Rect& r, double rx, double ry ) + { + DrawRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry ); + } + + /*! # + */ + void DrawRoundedRect( const pcl::Rect& r, double rxy = 25 ) + { + DrawRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy ); + } + + /*! # + */ + void StrokeRoundedRect( int x0, int y0, int x1, int y1, double rx, double ry, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + void StrokeRoundedRect( int x0, int y0, int x1, int y1, double rxy = 25, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRoundedRect( x0, y0, x1, y1, rxy, rxy, pen ); + } + + /*! # + */ + void StrokeRoundedRect( const pcl::Rect& r, double rx, double ry, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry, pen ); + } + + /*! # + */ + void StrokeRoundedRect( const pcl::Rect& r, double rxy = 25, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy, pen ); + } + + /*! # + */ + void FillRoundedRect( int x0, int y0, int x1, int y1, double rx, double ry, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + void FillRoundedRect( int x0, int y0, int x1, int y1, double rxy = 25, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRoundedRect( x0, y0, x1, y1, rxy, rxy, brush ); + } + + /*! # + */ + void FillRoundedRect( const pcl::Rect& r, double rx, double ry, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry, brush ); + } + + /*! # + */ + void FillRoundedRect( const pcl::Rect& r, double rxy = 25, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy, brush ); + } + + /*! # + */ + void EraseRoundedRect( int x0, int y0, int x1, int y1, double rx, double ry ) + { + FillRoundedRect( x0, y0, x1, y1, rx, ry, BackgroundBrush() ); + } + + /*! # + */ + void EraseRoundedRect( int x0, int y0, int x1, int y1, double rxy = 25 ) + { + EraseRoundedRect( x0, y0, x1, y1, rxy, rxy ); + } + + /*! # + */ + void EraseRoundedRect( const pcl::Rect& r, double rx, double ry ) + { + EraseRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry ); + } + + /*! # + */ + void EraseRoundedRect( const pcl::Rect& r, double rxy = 25 ) + { + EraseRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy ); + } + + /*! # + */ + void DrawEllipse( int x0, int y0, int x1, int y1 ); + + /*! # + */ + void DrawEllipse( const pcl::Rect& r ) + { + DrawEllipse( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void StrokeEllipse( int x0, int y0, int x1, int y1, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + void StrokeEllipse( const pcl::Rect& r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipse( r.x0, r.y0, r.x1, r.y1, pen ); + } + + /*! # + */ + void FillEllipse( int x0, int y0, int x1, int y1, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + void FillEllipse( const pcl::Rect& r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipse( r.x0, r.y0, r.x1, r.y1, brush ); + } + + /*! # + */ + void EraseEllipse( int x0, int y0, int x1, int y1 ) + { + FillEllipse( x0, y0, x1, y1, BackgroundBrush() ); + } + + /*! # + */ + void EraseEllipse( const pcl::Rect& r ) + { + EraseEllipse( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void DrawCircle( int xc, int yc, int r ) + { + DrawEllipse( xc-r, yc-r, xc+r+1, yc+r+1 ); + } + + /*! # + */ + void DrawCircle( const pcl::Point& c, int r ) + { + DrawCircle( c.x, c.y, r ); + } + + /*! # + */ + void StrokeCircle( int xc, int yc, int r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipse( xc-r, yc-r, xc+r+1, yc+r+1, pen ); + } + + /*! # + */ + void StrokeCircle( const pcl::Point& c, int r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeCircle( c.x, c.y, r, pen ); + } + + /*! # + */ + void FillCircle( int xc, int yc, int r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipse( xc-r, yc-r, xc+r+1, yc+r+1, brush ); + } + + /*! # + */ + void FillCircle( const pcl::Point& c, int r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillCircle( c.x, c.y, r, brush ); + } + + /*! # + */ + void EraseCircle( int xc, int yc, int r ) + { + FillCircle( xc, yc, r, BackgroundBrush() ); + } + + /*! # + */ + void EraseCircle( const pcl::Point& c, int r ) + { + EraseCircle( c.x, c.y, r ); + } + + /*! # + */ + void DrawPolygon( const pcl::Point* p, size_type n, fill_rule rule = FillRule::OddEven ); + + /*! # + */ + template + void DrawPolygon( const C& c, fill_rule rule = FillRule::OddEven ) + { + DrawPolygon( c.Begin(), c.Length(), rule ); + } + + /*! # + */ + void StrokePolygon( const pcl::Point* p, size_type n, const pcl::Pen& pen = pcl::Pen::Null(), fill_rule rule = FillRule::OddEven ); + + /*! # + */ + template + void StrokePolygon( const C& c, const pcl::Pen& pen = pcl::Pen::Null(), fill_rule rule = FillRule::OddEven ) + { + StrokePolygon( c.Begin(), c.Length(), pen, rule ); + } + + /*! # + */ + void FillPolygon( const pcl::Point* p, size_type n, const pcl::Brush& brush = pcl::Brush::Null(), fill_rule rule = FillRule::OddEven ); + + /*! # + */ + template + void FillPolygon( const C& c, const pcl::Brush& brush = pcl::Brush::Null(), fill_rule rule = FillRule::OddEven ) + { + FillPolygon( c.Begin(), c.Length(), brush, rule ); + } + + /*! # + */ + void ErasePolygon( const pcl::Point* p, size_type n, fill_rule rule = FillRule::OddEven ) + { + FillPolygon( p, n, BackgroundBrush(), rule ); + } + + /*! # + */ + template + void ErasePolygon( const C& c, fill_rule rule = FillRule::OddEven ) + { + ErasePolygon( c.Begin(), c.Length(), rule ); + } + + /*! # + */ + void DrawPolyline( const pcl::Point*, size_type n ); + + /*! # + */ + template + void DrawPolyline( const C& c ) + { + DrawPolyline( c.Begin(), c.Length() ); + } + + /*! # + */ + void DrawEllipticArc( int x0, int y0, int x1, int y1, double start, double span ); + + /*! # + */ + void DrawEllipticArc( const pcl::Rect& r, double start, double span ) + { + DrawEllipticArc( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void DrawArc( int xc, int yc, int r, double start, double span ) + { + DrawEllipticArc( xc-r, yc-r, xc+r+1, yc+r+1, start, span ); + } + + /*! # + */ + void DrawArc( const pcl::Point& c, int r, double start, double span ) + { + DrawArc( c.x, c.y, r, start, span ); + } + + /*! # + */ + void DrawEllipticChord( int x0, int y0, int x1, int y1, double start, double span ); + + /*! # + */ + void DrawEllipticChord( const pcl::Rect& r, double start, double span ) + { + DrawEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void StrokeEllipticChord( int x0, int y0, int x1, int y1, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + void StrokeEllipticChord( const pcl::Rect& r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span, pen ); + } + + /*! # + */ + void FillEllipticChord( int x0, int y0, int x1, int y1, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + void FillEllipticChord( const pcl::Rect& r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span, brush ); + } + + /*! # + */ + void EraseEllipticChord( int x0, int y0, int x1, int y1, double start, double span ) + { + FillEllipticChord( x0, y0, x1, y1, start, span, BackgroundBrush() ); + } + + /*! # + */ + void EraseEllipticChord( const pcl::Rect& r, double start, double span ) + { + EraseEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void DrawChord( int xc, int yc, int r, double start, double span ) + { + DrawEllipticChord( xc-r, yc-r, xc+r+1, yc+r+1, start, span ); + } + + /*! # + */ + void DrawChord( const pcl::Point& c, int r, double start, double span ) + { + DrawChord( c.x, c.y, r, start, span ); + } + + /*! # + */ + void StrokeChord( int xc, int yc, int r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticChord( xc-r, yc-r, xc+r+1, yc+r+1, start, span, pen ); + } + + /*! # + */ + void StrokeChord( const pcl::Point& c, int r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeChord( c.x, c.y, r, start, span, pen ); + } + + /*! # + */ + void FillChord( int xc, int yc, int r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticChord( xc-r, yc-r, xc+r+1, yc+r+1, start, span, brush ); + } + + /*! # + */ + void FillChord( const pcl::Point& c, int r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillChord( c.x, c.y, r, start, span, brush ); + } + + /*! # + */ + void EraseChord( int xc, int yc, int r, double start, double span ) + { + FillChord( xc, yc, r, start, span, BackgroundBrush() ); + } + + /*! # + */ + void EraseChord( const pcl::Point& c, int r, double start, double span ) + { + EraseChord( c.x, c.y, r, start, span ); + } + + /*! # + */ + void DrawEllipticPie( int x0, int y0, int x1, int y1, double start, double span ); + + /*! # + */ + void DrawEllipticPie( const pcl::Rect& r, double start, double span ) + { + DrawEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void StrokeEllipticPie( int x0, int y0, int x1, int y1, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + void StrokeEllipticPie( const pcl::Rect& r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span, pen ); + } + + /*! # + */ + void FillEllipticPie( int x0, int y0, int x1, int y1, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + void FillEllipticPie( const pcl::Rect& r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span, brush ); + } + + /*! # + */ + void EraseEllipticPie( int x0, int y0, int x1, int y1, double start, double span ) + { + FillEllipticPie( x0, y0, x1, y1, start, span, BackgroundBrush() ); + } + + /*! # + */ + void EraseEllipticPie( const pcl::Rect& r, double start, double span ) + { + EraseEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void DrawPie( int xc, int yc, int r, double start, double span ) + { + DrawEllipticPie( xc-r, yc-r, xc+r+1, yc+r+1, start, span ); + } + + /*! # + */ + void DrawPie( const pcl::Point& c, int r, double start, double span ) + { + DrawPie( c.x, c.y, r, start, span ); + } + + /*! # + */ + void StrokePie( int xc, int yc, int r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticPie( xc-r, yc-r, xc+r+1, yc+r+1, start, span, pen ); + } + + /*! # + */ + void StrokePie( const pcl::Point& c, int r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokePie( c.x, c.y, r, start, span, pen ); + } + + /*! # + */ + void FillPie( int xc, int yc, int r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticPie( xc-r, yc-r, xc+r+1, yc+r+1, start, span, brush ); + } + + /*! # + */ + void FillPie( const pcl::Point& c, int r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillPie( c.x, c.y, r, start, span, brush ); + } + + /*! # + */ + void ErasePie( int xc, int yc, int r, double start, double span ) + { + FillPie( xc, yc, r, start, span, BackgroundBrush() ); + } + + /*! # + */ + void ErasePie( const pcl::Point& c, int r, double start, double span ) + { + ErasePie( c.x, c.y, r, start, span ); + } + + /*! # + */ + void DrawBitmap( int x, int y, const Bitmap& ); + + /*! # + */ + void DrawBitmap( const pcl::Point& p, const Bitmap& bm ) + { + DrawBitmap( p.x, p.y, bm ); + } + + /*! # + */ + void DrawBitmapRect( int x, int y, const Bitmap&, int x0, int y0, int x1, int y1 ); + + /*! # + */ + void DrawBitmapRect( const pcl::Point& p, const Bitmap& bm, const pcl::Rect& r ) + { + DrawBitmapRect( p.x, p.y, bm, r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void DrawScaledBitmap( int x0, int y0, int x1, int y1, const Bitmap& ); + + /*! # + */ + void DrawScaledBitmap( const pcl::Rect& r, const Bitmap& bm ) + { + DrawScaledBitmap( r.x0, r.y0, r.x1, r.y1, bm ); + } + + /*! # + */ + void DrawScaledBitmapRect( int dx0, int dy0, int dx1, int dy1, const Bitmap&, int sx0, int sy0, int sx1, int sy1 ); + + /*! # + */ + void DrawScaledBitmapRect( const pcl::Rect& dst, const Bitmap& bm, const pcl::Rect& src ) + { + DrawScaledBitmapRect( dst.x0, dst.y0, dst.x1, dst.y1, bm, src.x0, src.y0, src.x1, src.y1 ); + } + + /*! # + */ + void DrawTiledBitmap( int x0, int y0, int x1, int y1, const Bitmap&, int xOffset = 0, int yOffset = 0 ); + + /*! # + */ + void DrawTiledBitmap( const pcl::Rect& r, const Bitmap& bm, const pcl::Point& offset = pcl::Point( 0 ) ) + { + DrawTiledBitmap( r.x0, r.y0, r.x1, r.y1, bm, offset.x, offset.y ); + } + + /*! # + */ + void DrawText( int x, int y, const String& ); + + /*! # + */ + void DrawText( const pcl::Point& p, const String& s ) + { + DrawText( p.x, p.y, s ); + } + + /*! # + */ + void DrawTextRect( int x0, int y0, int x1, int y1, const String&, TextAlignmentFlags = TextAlign::Default ); + + /*! # + */ + void DrawTextRect( const pcl::Rect r, const String& s, TextAlignmentFlags a = TextAlign::Default ) + { + DrawTextRect( r.x0, r.y0, r.x1, r.y1, s, a ); + } + + /*! # + */ + pcl::Rect TextRect( int x0, int y0, int x1, int y1, const String&, TextAlignmentFlags = TextAlign::Default ) const; + + /*! # + */ + pcl::Rect TextRect( const pcl::Rect r, const String& s, TextAlignmentFlags a = TextAlign::Default ) + { + return TextRect( r.x0, r.y0, r.x1, r.y1, s, a ); + } + +private: + + Graphics( void* h ) : GraphicsContextBase( h ) + { + } + + friend class InterfaceDispatcher; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class VectorGraphics + * \brief Client-side interface to a PixInsight vector graphics context. + * + * ### TODO: Write a detailed description for %VectorGraphics. + * + * ### TODO: Include a number of examples for drawing primitives, composition + * operators, rendering performance, transformations, etc. + */ +class PCL_CLASS VectorGraphics : public GraphicsContextBase +{ +public: + + /*! + * Represents a Porter-Duff alpha composition operator. + */ + typedef GraphicsContextBase::composition_op composition_op; + + /*! + * Represents a polygon fill rule. + */ + typedef GraphicsContextBase::fill_rule fill_rule; + + /*! + * Constructs an inactive vector graphics context. + */ + VectorGraphics() = default; + + /*! + * Constructs an active vector graphics context, ready to draw on the + * specified \a control. + * + * \warning Invoking this constructor outside a Control::OnPaint() event + * handler is illegal on all supported platforms. If called without an + * active OnPaint() event, this constructor throws an Error exception. + */ + VectorGraphics( Control& control ) + : GraphicsContextBase( control ) + { + } + + /*! + * Constructs an active vector graphics context, ready to draw on the + * specified \a bitmap. + */ + VectorGraphics( Bitmap& bitmap ) + : GraphicsContextBase( bitmap ) + { + } + + /*! + * Constructs an active vector graphics context, ready to draw on the + * specified \a svg object. + */ + VectorGraphics( SVG& svg ) + : GraphicsContextBase( svg ) + { + } + + /*! + * Move constructor. + */ + VectorGraphics( VectorGraphics&& x ) + : GraphicsContextBase( std::move( x ) ) + { + } + + /*! + * Destroys a %VectorGraphics object. If this graphics context is active, it + * is terminated upon destruction. + */ + virtual ~VectorGraphics() + { + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + VectorGraphics& operator =( VectorGraphics&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null %VectorGraphics instance. A null + * %VectorGraphics does not correspond to an existing vector graphics + * context in the PixInsight core application. + */ + static VectorGraphics& Null(); + + /*! # + */ + pcl::DRect ClipRect() const; + + /*! # + */ + template + void SetClipRect( const R& r ) + { + SetClipRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void SetClipRect( double x0, double y0, double x1, double y1 ); + + /*! # + */ + template + void IntersectClipRect( const R& r ) + { + SetClipRect( ClipRect().Intersection( r ) ); + } + + /*! # + */ + void IntersectClipRect( double x0, double y0, double x1, double y1 ) + { + IntersectClipRect( pcl::DRect( x0, y0, x1, y1 ) ); + } + + /*! # + */ + template + void UniteClipRect( const R& r ) + { + SetClipRect( ClipRect().Union( r ) ); + } + + /*! # + */ + void UniteClipRect( double x0, double y0, double x1, double y1 ) + { + UniteClipRect( pcl::DRect( x0, y0, x1, y1 ) ); + } + + /*! # + */ + pcl::DPoint BrushOrigin() const; + + /*! # + */ + template + void SetBrushOrigin( const P& p ) + { + SetBrushOrigin( p.x, p.y ); + } + + /*! # + */ + void SetBrushOrigin( double x, double y ); + + /*! # + */ + template + void DrawPoint( const P& p ) + { + DrawPoint( p.x, p.y ); + } + + /*! # + */ + void DrawPoint( double x, double y ); + + /*! # + */ + template + void DrawLine( const P0& p0, const P1& p1 ) + { + DrawLine( p0.x, p0.y, p1.x, p1.y ); + } + + /*! # + */ + void DrawLine( double x0, double y0, double x1, double y1 ); + + /*! # + */ + void DrawRect( double x0, double y0, double x1, double y1 ); + + /*! # + */ + template + void DrawRect( const R& r ) + { + DrawRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void StrokeRect( double x0, double y0, double x1, double y1, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + template + void StrokeRect( const R& r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRect( r.x0, r.y0, r.x1, r.y1, pen ); + } + + /*! # + */ + void FillRect( double x0, double y0, double x1, double y1, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + template + void FillRect( const R& r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRect( r.x0, r.y0, r.x1, r.y1, brush ); + } + + /*! # + */ + void EraseRect( double x0, double y0, double x1, double y1 ) + { + FillRect( x0, y0, x1, y1, BackgroundBrush() ); + } + + /*! # + */ + template + void EraseRect( const R& r ) + { + EraseRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void DrawRoundedRect( double x0, double y0, double x1, double y1, double rx, double ry ); + + /*! # + */ + void DrawRoundedRect( double x0, double y0, double x1, double y1, double rxy = 25 ) + { + DrawRoundedRect( x0, y0, x1, y1, rxy, rxy ); + } + + /*! # + */ + template + void DrawRoundedRect( const R& r, double rx, double ry ) + { + DrawRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry ); + } + + /*! # + */ + template + void DrawRoundedRect( const R& r, double rxy = 25 ) + { + DrawRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy ); + } + + /*! # + */ + void StrokeRoundedRect( double x0, double y0, double x1, double y1, double rx, double ry, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + void StrokeRoundedRect( double x0, double y0, double x1, double y1, double rxy = 25, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRoundedRect( x0, y0, x1, y1, rxy, rxy, pen ); + } + + /*! # + */ + template + void StrokeRoundedRect( const R& r, double rx, double ry, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry, pen ); + } + + /*! # + */ + template + void StrokeRoundedRect( const R& r, double rxy = 25, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy, pen ); + } + + /*! # + */ + void FillRoundedRect( double x0, double y0, double x1, double y1, double rx, double ry, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + void FillRoundedRect( double x0, double y0, double x1, double y1, double rxy = 25, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRoundedRect( x0, y0, x1, y1, rxy, rxy, brush ); + } + + /*! # + */ + template + void FillRoundedRect( const R& r, double rx, double ry, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry, brush ); + } + + /*! # + */ + template + void FillRoundedRect( const R& r, double rxy = 25, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy, brush ); + } + + /*! # + */ + void EraseRoundedRect( double x0, double y0, double x1, double y1, double rx, double ry ) + { + FillRoundedRect( x0, y0, x1, y1, rx, ry, BackgroundBrush() ); + } + + /*! # + */ + void EraseRoundedRect( double x0, double y0, double x1, double y1, double rxy = 25 ) + { + EraseRoundedRect( x0, y0, x1, y1, rxy, rxy ); + } + + /*! # + */ + template + void EraseRoundedRect( const R& r, double rx, double ry ) + { + EraseRoundedRect( r.x0, r.y0, r.x1, r.y1, rx, ry ); + } + + /*! # + */ + template + void EraseRoundedRect( const R& r, double rxy = 25 ) + { + EraseRoundedRect( r.x0, r.y0, r.x1, r.y1, rxy, rxy ); + } + + /*! # + */ + void DrawEllipse( double x0, double y0, double x1, double y1 ); + + /*! # + */ + template + void DrawEllipse( const R& r ) + { + DrawEllipse( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void StrokeEllipse( double x0, double y0, double x1, double y1, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + template + void StrokeEllipse( const R& r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipse( r.x0, r.y0, r.x1, r.y1, pen ); + } + + /*! # + */ + void FillEllipse( double x0, double y0, double x1, double y1, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + template + void FillEllipse( const R& r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipse( r.x0, r.y0, r.x1, r.y1, brush ); + } + + /*! # + */ + void EraseEllipse( double x0, double y0, double x1, double y1 ) + { + FillEllipse( x0, y0, x1, y1, BackgroundBrush() ); + } + + /*! # + */ + template + void EraseEllipse( const R& r ) + { + EraseEllipse( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void DrawCircle( double xc, double yc, double r ) + { + DrawEllipse( xc-r, yc-r, xc+r, yc+r ); + } + + /*! # + */ + template + void DrawCircle( const P& c, double r ) + { + DrawCircle( c.x, c.y, r ); + } + + /*! # + */ + void StrokeCircle( double xc, double yc, double r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipse( xc-r, yc-r, xc+r, yc+r, pen ); + } + + /*! # + */ + template + void StrokeCircle( const P& c, double r, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeCircle( c.x, c.y, r, pen ); + } + + /*! # + */ + void FillCircle( double xc, double yc, double r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipse( xc-r, yc-r, xc+r, yc+r, brush ); + } + + /*! # + */ + template + void FillCircle( const P& c, double r, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillCircle( c.x, c.y, r, brush ); + } + + /*! # + */ + void EraseCircle( double xc, double yc, double r ) + { + FillCircle( xc, yc, r, BackgroundBrush() ); + } + + /*! # + */ + template + void EraseCircle( const P& c, double r ) + { + EraseCircle( c.x, c.y, r ); + } + + /*! # + */ + void DrawPolygon( const pcl::DPoint* p, size_type n, fill_rule rule = FillRule::OddEven ); + + /*! # + */ + template + void DrawPolygon( const C& c, fill_rule rule = FillRule::OddEven ) + { + DrawPolygon( c.Begin(), c.Length(), rule ); + } + + /*! # + */ + void StrokePolygon( const pcl::DPoint* p, size_type n, const pcl::Pen& pen = pcl::Pen::Null(), fill_rule rule = FillRule::OddEven ); + + /*! # + */ + template + void StrokePolygon( const C& c, const pcl::Pen& pen = pcl::Pen::Null(), fill_rule rule = FillRule::OddEven ) + { + StrokePolygon( c.Begin(), c.Length(), pen, rule ); + } + + /*! # + */ + void FillPolygon( const pcl::DPoint* p, size_type n, const pcl::Brush& brush = pcl::Brush::Null(), fill_rule rule = FillRule::OddEven ); + + /*! # + */ + template + void FillPolygon( const C& c, const pcl::Brush& brush = pcl::Brush::Null(), fill_rule rule = FillRule::OddEven ) + { + FillPolygon( c.Begin(), c.Length(), brush, rule ); + } + + /*! # + */ + void ErasePolygon( const pcl::DPoint* p, size_type n, fill_rule rule = FillRule::OddEven ) + { + FillPolygon( p, n, BackgroundBrush(), rule ); + } + + /*! # + */ + template + void ErasePolygon( const C& c, fill_rule rule = FillRule::OddEven ) + { + ErasePolygon( c.Begin(), c.Length(), rule ); + } + + /*! # + */ + void DrawPolyline( const pcl::DPoint*, size_type n ); + + /*! # + */ + template + void DrawPolyline( const C& c ) + { + DrawPolyline( c.Begin(), c.Length() ); + } + + /*! # + */ + void DrawEllipticArc( double x0, double y0, double x1, double y1, double start, double span ); + + /*! # + */ + template + void DrawEllipticArc( const R& r, double start, double span ) + { + DrawEllipticArc( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void DrawArc( double xc, double yc, double r, double start, double span ) + { + DrawEllipticArc( xc-r, yc-r, xc+r, yc+r, start, span ); + } + + /*! # + */ + template + void DrawArc( const P& c, double r, double start, double span ) + { + DrawArc( c.x, c.y, r, start, span ); + } + + /*! # + */ + void DrawEllipticChord( double x0, double y0, double x1, double y1, double start, double span ); + + /*! # + */ + template + void DrawEllipticChord( const R& r, double start, double span ) + { + DrawEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void StrokeEllipticChord( double x0, double y0, double x1, double y1, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + template + void StrokeEllipticChord( const R& r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span, pen ); + } + + /*! # + */ + void FillEllipticChord( double x0, double y0, double x1, double y1, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + template + void FillEllipticChord( const R& r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span, brush ); + } + + /*! # + */ + void EraseEllipticChord( double x0, double y0, double x1, double y1, double start, double span ) + { + FillEllipticChord( x0, y0, x1, y1, start, span, BackgroundBrush() ); + } + + /*! # + */ + template + void EraseEllipticChord( const R& r, double start, double span ) + { + EraseEllipticChord( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void DrawChord( double xc, double yc, double r, double start, double span ) + { + DrawEllipticChord( xc-r, yc-r, xc+r, yc+r, start, span ); + } + + /*! # + */ + template + void DrawChord( const P& c, double r, double start, double span ) + { + DrawChord( c.x, c.y, r, start, span ); + } + + /*! # + */ + void StrokeChord( double xc, double yc, double r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticChord( xc-r, yc-r, xc+r, yc+r, start, span, pen ); + } + + /*! # + */ + template + void StrokeChord( const P& c, double r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeChord( c.x, c.y, r, start, span, pen ); + } + + /*! # + */ + void FillChord( double xc, double yc, double r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticChord( xc-r, yc-r, xc+r, yc+r, start, span, brush ); + } + + /*! # + */ + template + void FillChord( const P& c, double r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillChord( c.x, c.y, r, start, span, brush ); + } + + /*! # + */ + void EraseChord( double xc, double yc, double r, double start, double span ) + { + FillChord( xc, yc, r, start, span, BackgroundBrush() ); + } + + /*! # + */ + template + void EraseChord( const P& c, double r, double start, double span ) + { + EraseChord( c.x, c.y, r, start, span ); + } + + /*! # + */ + void DrawEllipticPie( double x0, double y0, double x1, double y1, double start, double span ); + + /*! # + */ + template + void DrawEllipticPie( const R& r, double start, double span ) + { + DrawEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void StrokeEllipticPie( double x0, double y0, double x1, double y1, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ); + + /*! # + */ + template + void StrokeEllipticPie( const R& r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span, pen ); + } + + /*! # + */ + void FillEllipticPie( double x0, double y0, double x1, double y1, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ); + + /*! # + */ + template + void FillEllipticPie( const R& r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span, brush ); + } + + /*! # + */ + void EraseEllipticPie( double x0, double y0, double x1, double y1, double start, double span ) + { + FillEllipticPie( x0, y0, x1, y1, start, span, BackgroundBrush() ); + } + + /*! # + */ + template + void EraseEllipticPie( const R& r, double start, double span ) + { + EraseEllipticPie( r.x0, r.y0, r.x1, r.y1, start, span ); + } + + /*! # + */ + void DrawPie( double xc, double yc, double r, double start, double span ) + { + DrawEllipticPie( xc-r, yc-r, xc+r, yc+r, start, span ); + } + + /*! # + */ + template + void DrawPie( const P& c, double r, double start, double span ) + { + DrawPie( c.x, c.y, r, start, span ); + } + + /*! # + */ + void StrokePie( double xc, double yc, double r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokeEllipticPie( xc-r, yc-r, xc+r, yc+r, start, span, pen ); + } + + /*! # + */ + template + void StrokePie( const P& c, double r, double start, double span, const pcl::Pen& pen = pcl::Pen::Null() ) + { + StrokePie( c.x, c.y, r, start, span, pen ); + } + + /*! # + */ + void FillPie( double xc, double yc, double r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillEllipticPie( xc-r, yc-r, xc+r, yc+r, start, span, brush ); + } + + /*! # + */ + template + void FillPie( const P& c, double r, double start, double span, const pcl::Brush& brush = pcl::Brush::Null() ) + { + FillPie( c.x, c.y, r, start, span, brush ); + } + + /*! # + */ + void ErasePie( double xc, double yc, double r, double start, double span ) + { + FillPie( xc, yc, r, start, span, BackgroundBrush() ); + } + + /*! # + */ + template + void ErasePie( const P& c, double r, double start, double span ) + { + ErasePie( c.x, c.y, r, start, span ); + } + + /*! # + */ + void DrawBitmap( double x, double y, const Bitmap& ); + + /*! # + */ + template + void DrawBitmap( const P& p, const Bitmap& bm ) + { + DrawBitmap( p.x, p.y, bm ); + } + + /*! # + */ + void DrawBitmapRect( double x, double y, const Bitmap&, double x0, double y0, double x1, double y1 ); + + /*! # + */ + template + void DrawBitmapRect( const P& p, const Bitmap& bm, const R& r ) + { + DrawBitmapRect( p.x, p.y, bm, r.x0, r.y0, r.x1, r.y1 ); + } + + /*! # + */ + void DrawScaledBitmap( double x0, double y0, double x1, double y1, const Bitmap& ); + + /*! # + */ + template + void DrawScaledBitmap( const R& r, const Bitmap& bm ) + { + DrawScaledBitmap( r.x0, r.y0, r.x1, r.y1, bm ); + } + + /*! # + */ + void DrawScaledBitmapRect( double dx0, double dy0, double dx1, double dy1, const Bitmap&, double sx0, double sy0, double sx1, double sy1 ); + + /*! # + */ + template + void DrawScaledBitmapRect( const R1& dst, const Bitmap& bm, const R2& src ) + { + DrawScaledBitmapRect( dst.x0, dst.y0, dst.x1, dst.y1, bm, src.x0, src.y0, src.x1, src.y1 ); + } + + /*! # + */ + void DrawTiledBitmap( double x0, double y0, double x1, double y1, const Bitmap&, double xOffset = 0, double yOffset = 0 ); + + /*! # + */ + template + void DrawTiledBitmap( const R& r, const Bitmap& bm, const P& offset = P() ) + { + DrawTiledBitmap( r.x0, r.y0, r.x1, r.y1, bm, offset.x, offset.y ); + } + + /*! # + */ + void DrawText( double x, double y, const String& ); + + /*! # + */ + template + void DrawText( const P& p, const String& s ) + { + DrawText( p.x, p.y, s ); + } + + /*! # + */ + void DrawTextRect( double x0, double y0, double x1, double y1, const String&, TextAlignmentFlags = TextAlign::Default ); + + /*! # + */ + template + void DrawTextRect( const R& r, const String& s, TextAlignmentFlags a = TextAlign::Default ) + { + DrawTextRect( r.x0, r.y0, r.x1, r.y1, s, a ); + } + + /*! # + */ + pcl::DRect TextRect( double x0, double y0, double x1, double y1, const String&, TextAlignmentFlags = TextAlign::Default ) const; + + /*! # + */ + template + pcl::DRect TextRect( const R& r, const String& s, TextAlignmentFlags a = TextAlign::Default ) + { + return TextRect( r.x0, r.y0, r.x1, r.y1, s, a ); + } + +private: + + VectorGraphics( void* h ) : GraphicsContextBase( h ) + { + } + + friend class InterfaceDispatcher; +}; + +// ---------------------------------------------------------------------------- + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Graphics_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Graphics.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GridInterpolation.h b/3rdparty/include/pcl/GridInterpolation.h new file mode 100644 index 0000000..b3a7b49 --- /dev/null +++ b/3rdparty/include/pcl/GridInterpolation.h @@ -0,0 +1,987 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GridInterpolation.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_GridInterpolation_h +#define __PCL_GridInterpolation_h + +/// \file pcl/GridInterpolation.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION +# include +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GridInterpolation + * \brief Discretized scalar surface interpolation/approximation in two + * dimensions. + * + * This class performs the same tasks as a surface interpolation device, such + * as SurfaceSpline or ShepardInterpolation, but allows for much faster + * interpolation with negligible accuracy loss in most applications. + * + * Interpolation from discrete grids can be orders of magnitude faster than + * direct evaluation of surface interpolation/approximation devices, depending + * on the number of input data points. + */ +class PCL_CLASS GridInterpolation : public ParallelProcess +{ +public: + + /*! + * Default constructor. Yields an empty instance that cannot be used without + * initialization. + */ + GridInterpolation() = default; + + /*! + * Copy constructor. + */ + GridInterpolation( const GridInterpolation& ) = default; + + /*! + * Move constructor. + */ + GridInterpolation( GridInterpolation&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + GridInterpolation& operator =( const GridInterpolation& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GridInterpolation& operator =( GridInterpolation&& ) = default; + + /*! + * Initializes this %GridInterpolation object for the specified input data + * and interpolation parameters. + * + * \param rect Reference rectangle. Interpolation will be initialized + * within the boundaries of this rectangle at discrete + * \a delta coordinate intervals. + * + * \param delta Grid distance for calculation of discrete function values. + * Must be > 0. + * + * \param S Reference to a surface interpolation/approximation object + * that will be used to evaluate function values at discrete + * coordinate intervals. This object must have been + * previously initialized and must be valid. + * + * \param verbose If true, this function will write information to the + * standard PixInsight console to provide some feedback to + * the user during the (potentially long) initialization + * process. If false, no feedback will be provided. + * + * The template parameter SI must provide a member function of the form: + * + * double SI::operator ()( int x, int y ) const + * + * or an equivalent operator member function whose return value can be + * statically casted to double, with two by-value parameters that can be + * statically casted from the int type. This function will be called + * multiple times to evaluate the approximated surface at discrete grid + * coordinate pairs {x,y}. The implementation of this member function must + * be thread-safe if parallel processing has been enabled and allowed for + * this object. + * + * If parallel processing is allowed, this function executes the + * initialization process using multiple concurrent threads. See + * EnableParallelProcessing() for additional information. + */ + template + void Initialize( const Rect& rect, int delta, const SI& S, bool verbose = true ) + { + PCL_PRECONDITION( rect.IsRect() ) + PCL_PRECONDITION( delta > 0 ) + + m_rect = rect.Ordered(); + if ( !m_rect.IsRect() ) + throw Error( "GridInterpolation::Initialize(): Empty interpolation space." ); + + m_delta = Abs( delta ); + if ( m_delta == 0 ) + throw Error( "GridInterpolation::Initialize(): Zero grid distance." ); + + int w = rect.Width(); + int h = rect.Height(); + int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); + int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); + + m_G = DMatrix( rows, cols ); + + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( "Building surface interpolation grid", rows ); + } +#endif + + Array L = Thread::OptimalThreadLoads( rows, + 1/*overheadLimit*/, + m_parallel ? m_maxProcessors : 1 ); + AbstractImage::ThreadData data( monitor, rows ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new GridInitializationThread( data, *this, S, n, n + int( L[i] ) ) ); + AbstractImage::RunThreads( threads, data ); + threads.Destroy(); + + m_I.Initialize( m_G.Begin(), cols, rows ); + } + + /*! + * Initializes this %GridInterpolation object with a prescribed discrete + * interpolation matrix. + * + * \param rect Reference rectangle. Interpolation will be initialized + * within the boundaries of this rectangle at discrete + * \a delta coordinate intervals. + * + * \param delta Grid distance for calculation of discrete function values. + * Must be > 0. + * + * \param G interpolation matrix. + * + * The specified \a G matrix must have \a n rows and \a m columns, which are + * given by: + * + * n = 1 + Ceil( rect.Height()/delta )\n + * m = 1 + Ceil( rect.Width()/delta ) + * + * If the dimensions of the specified matrix are different from the values + * defined above, this function will throw an Error exception. + * + * Matrix elements must be function values computed at discrete \a delta + * intervals within \a rect boundaries. For a given matrix row \a r and + * matrix column \a c, the corresponding matrix element must be a function + * value computed at coordinates {\a x,\a y} given by: + * + * x = rect.x0 + c*delta\n + * y = rect.y0 + r*delta + */ + void Initialize( const Rect& rect, int delta, const DMatrix& G ) + { + PCL_PRECONDITION( rect.IsRect() ) + PCL_PRECONDITION( delta > 0 ) + + m_rect = rect.Ordered(); + if ( !m_rect.IsRect() ) + throw Error( "GridInterpolation::Initialize(): Empty interpolation space." ); + + m_delta = Abs( delta ); + if ( m_delta == 0 ) + throw Error( "GridInterpolation::Initialize(): Zero grid distance." ); + + int w = rect.Width(); + int h = rect.Height(); + int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); + int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); + if ( G.Rows() != rows || G.Cols() != cols ) + throw Error( "GridInterpolation::Initialize(): Invalid matrix dimensions." ); + + m_G = G; + m_I.Initialize( m_G.Begin(), cols, rows ); + } + + /*! + * Returns true iff this is a valid, initialized object ready for + * interpolation. + */ + bool IsValid() const + { + return !m_G.IsEmpty(); + } + + /*! + * Deallocates internal structures, yielding an empty object that cannot be + * used before a new call to Initialize(). + */ + void Clear() + { + m_I.Clear(); + m_G.Clear(); + } + + /*! + * Returns the current interpolation reference rectangle. See Initialize() + * for more information. + */ + const Rect& ReferenceRect() const + { + return m_rect; + } + + /*! + * Returns the current grid distance for calculation of discrete function + * values. See Initialize() for more information. + */ + int Delta() const + { + return m_delta; + } + + /*! + * Returns a reference to the discrete matrix used for interpolation of + * function values. + * + * If this object has not been initialized, this member function returns a + * reference to an empty matrix. + */ + const DMatrix& InterpolationMatrix() const + { + return m_G; + } + + /*! + * Returns an interpolated function value at the specified coordinates. + */ + template + double operator ()( T x, T y ) const + { + double fx = (double( x ) - m_rect.x0)/m_delta; + double fy = (double( y ) - m_rect.y0)/m_delta; + return m_I( fx, fy ); + } + + /*! + * Returns an interpolated function value at \a p.x and \a p.y coordinates. + */ + template + double operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + +private: + + /*! + * N.B.: Here we need a smooth interpolation function without negative + * lobes, in order to prevent small-scale oscillations. Other options are + * BilinearInterpolation and CubicBSplineFilter. + */ + typedef BicubicBSplineInterpolation grid_interpolation; + + Rect m_rect; + int m_delta; + DMatrix m_G; + grid_interpolation m_I; + + template + class GridInitializationThread : public Thread + { + public: + + GridInitializationThread( const AbstractImage::ThreadData& data, + GridInterpolation& grid, const SI& surface, int startRow, int endRow ) + : m_data( data ) + , m_grid( grid ) + , m_surface( surface ) + , m_startRow( startRow ) + , m_endRow( endRow ) + { + } + + PCL_HOT_FUNCTION void Run() override + { + INIT_THREAD_MONITOR() + + for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) + { + for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_G.Cols(); ++j, x += m_grid.m_delta ) + m_grid.m_G[i][j] = m_surface( x, y ); + + UPDATE_THREAD_MONITOR( 32 ) + } + } + + private: + + const AbstractImage::ThreadData& m_data; + GridInterpolation& m_grid; + const SI& m_surface; + int m_startRow, m_endRow; + }; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PointGridInterpolation + * \brief Discretized vector surface interpolation/approximation in two + * dimensions. + * + * This class performs the same tasks as a point surface interpolation device, + * such as PointSurfaceSpline or PointShepardInterpolation, but allows for much + * faster interpolation with negligible accuracy loss in most applications. + * + * Interpolation from discrete grids can be orders of magnitude faster than + * direct evaluation of surface interpolation/approximation devices, depending + * on the number of input data points. + */ +class PCL_CLASS PointGridInterpolation : public ParallelProcess +{ +public: + + /*! + * Default constructor. Yields an empty instance that cannot be used without + * initialization. + */ + PointGridInterpolation() = default; + + /*! + * Copy constructor. + */ + PointGridInterpolation( const PointGridInterpolation& ) = default; + + /*! + * Move constructor. + */ + PointGridInterpolation( PointGridInterpolation&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PointGridInterpolation& operator =( const PointGridInterpolation& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PointGridInterpolation& operator =( PointGridInterpolation&& ) = default; + + /*! + * Initializes a %PointGridInterpolation object with a point surface + * interpolation/approximation. + * + * \param rect Reference rectangle. Interpolation will be initialized + * within the boundaries of this rectangle at discrete + * \a delta coordinate intervals. + * + * \param delta Grid distance for calculation of discrete function values. + * Must be > 0. + * + * \param PS Reference to a point surface interpolation/approximation + * object that will be used to evaluate function values at + * discrete coordinate intervals. This object must have been + * previously initialized and must be valid. + * + * \param verbose If true, this function will write information to the + * standard PixInsight console to provide some feedback to + * the user during the (potentially long) initialization + * process. If false, no feedback will be provided. + * + * The template parameter PSI must provide a member function of the form: + * + * DPoint PSI::operator ()( int x, int y ) const + * + * or an equivalent operator member function whose return value can be + * statically casted to DPoint, with two by-value parameters that can be + * statically casted from the int type. This function will be called + * multiple times to evaluate the approximated surface at discrete grid + * coordinate pairs {x,y}. The implementation of this member function must + * be thread-safe if parallel processing has been enabled and allowed for + * this object. + * + * If parallel processing is allowed, this function executes the + * initialization process using multiple concurrent threads. See + * EnableParallelProcessing() for additional information. + */ + template + void Initialize( const Rect& rect, int delta, const PSI& PS, bool verbose = true ) + { + PCL_PRECONDITION( rect.IsRect() ) + PCL_PRECONDITION( delta > 0 ) + + m_rect = rect.Ordered(); + if ( !m_rect.IsRect() ) + throw Error( "PointGridInterpolation::Initialize(): Empty interpolation space." ); + + m_delta = Abs( delta ); + if ( m_delta == 0 ) + throw Error( "PointGridInterpolation::Initialize(): Zero grid distance." ); + + int w = rect.Width(); + int h = rect.Height(); + int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); + int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); + + m_Gx = DMatrix( rows, cols ); + m_Gy = DMatrix( rows, cols ); + + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( "Building surface interpolation grid", rows ); + } +#endif + + Array L = Thread::OptimalThreadLoads( rows, + 1/*overheadLimit*/, + m_parallel ? m_maxProcessors : 1 ); + AbstractImage::ThreadData data( monitor, rows ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new GridInitializationThread( data, *this, PS, n, n + int( L[i] ) ) ); + AbstractImage::RunThreads( threads, data ); + threads.Destroy(); + + m_Ix.Initialize( m_Gx.Begin(), cols, rows ); + m_Iy.Initialize( m_Gy.Begin(), cols, rows ); + } + + /*! + * Initializes a %PointGridInterpolation object with separate surface + * interpolations/approximations for the X and Y directions. + * + * \param rect Reference rectangle. Interpolation will be initialized + * within the boundaries of this rectangle at discrete + * \a delta coordinate intervals. + * + * \param delta Grid distance for calculation of discrete function values. + * Must be > 0. + * + * \param Sx Reference to a surface interpolation/approximation object + * that will be used to evaluate function values at discrete + * coordinate intervals on the X axis. This object must have + * been previously initialized and must be valid. + * + * \param Sy Reference to a surface interpolation/approximation object + * that will be used to evaluate function values at discrete + * coordinate intervals on the Y axis. This object must have + * been previously initialized and must be valid. + * + * \param verbose If true, this function will write information to the + * standard PixInsight console to provide some feedback to + * the user during the (potentially long) initialization + * process. If false, no feedback will be provided. + * + * The template parameter SI must provide a member function of the form: + * + * double SI::operator ()( int x, int y ) const + * + * or an equivalent operator member function whose return value can be + * statically casted to double, with two by-value parameters that can be + * statically casted from the int type. This function will be called + * multiple times for the \a Sx and \a Sy objects to evaluate the + * approximated surface at discrete grid coordinate pairs {x,y}, + * respectively on the X and Y plane directions. The implementation of this + * member function must be thread-safe if parallel processing has been + * enabled and allowed for this object. + * + * If parallel processing is allowed, this function executes the + * initialization process using multiple concurrent threads. See + * EnableParallelProcessing() for additional information. + */ + template + void Initialize( const Rect& rect, int delta, const SI& Sx, const SI& Sy, bool verbose = true ) + { + PCL_PRECONDITION( rect.IsRect() ) + PCL_PRECONDITION( delta > 0 ) + + m_rect = rect.Ordered(); + if ( !m_rect.IsRect() ) + throw Error( "PointGridInterpolation::Initialize(): Empty interpolation space." ); + + m_delta = Abs( delta ); + if ( m_delta == 0 ) + throw Error( "PointGridInterpolation::Initialize(): Zero grid distance." ); + + int w = rect.Width(); + int h = rect.Height(); + int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); + int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); + + m_Gx = DMatrix( rows, cols ); + m_Gy = DMatrix( rows, cols ); + + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( "Building surface interpolation grid", rows ); + } +#endif + + Array L = Thread::OptimalThreadLoads( rows, + 1/*overheadLimit*/, + m_parallel ? m_maxProcessors : 1 ); + AbstractImage::ThreadData data( monitor, rows ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new GridInitializationXYThread( data, *this, Sx, Sy, n, n + int( L[i] ) ) ); + AbstractImage::RunThreads( threads, data ); + threads.Destroy(); + + m_Ix.Initialize( m_Gx.Begin(), cols, rows ); + m_Iy.Initialize( m_Gy.Begin(), cols, rows ); + } + + /*! + * Initializes this %PointGridInterpolation object with prescribed + * interpolation matrices. + * + * \param rect Reference rectangle. Interpolation will be initialized + * within the boundaries of this rectangle at discrete + * \a delta coordinate intervals. + * + * \param delta Grid distance for calculation of discrete function values. + * Must be > 0. + * + * \param Gx interpolation matrix in the X direction. + * + * \param Gy Interpolation matrix in the Y direction. + * + * Both \a Gx and \a Gy matrices must have \a n rows and \a m columns, which + * are given by: + * + * n = 1 + Ceil( rect.Height()/delta )\n + * m = 1 + Ceil( rect.Width()/delta ) + * + * If one or both matrices have different dimensions, this function will + * throw an Error exception. + * + * Matrix elements must be function values computed at discrete \a delta + * intervals within \a rect boundaries. For a given matrix row \a r and + * matrix column \a c, the corresponding matrix element must be a function + * value computed at coordinates {\a x,\a y} given by: + * + * x = rect.x0 + c*delta\n + * y = rect.y0 + r*delta + */ + void Initialize( const Rect& rect, int delta, const DMatrix& Gx, const DMatrix& Gy ) + { + PCL_PRECONDITION( rect.IsRect() ) + PCL_PRECONDITION( delta > 0 ) + + m_rect = rect.Ordered(); + if ( !m_rect.IsRect() ) + throw Error( "PointGridInterpolation::Initialize(): Empty interpolation space." ); + + m_delta = Abs( delta ); + if ( m_delta == 0 ) + throw Error( "PointGridInterpolation::Initialize(): Zero grid distance." ); + + int w = rect.Width(); + int h = rect.Height(); + int rows = 1 + h/m_delta + ((h%m_delta) ? 1 : 0); + int cols = 1 + w/m_delta + ((w%m_delta) ? 1 : 0); + if ( Gx.Rows() != rows || Gx.Cols() != cols || Gy.Rows() != rows || Gy.Cols() != cols ) + throw Error( "PointGridInterpolation::Initialize(): Invalid matrix dimensions." ); + + m_Gx = Gx; + m_Gy = Gy; + m_Ix.Initialize( m_Gx.Begin(), cols, rows ); + m_Iy.Initialize( m_Gy.Begin(), cols, rows ); + } + + /*! + * + */ + template + void ApplyLocalModel( const PSI& PS, + const String& message = "Applying local interpolation model", + bool verbose = true ) + { + PCL_PRECONDITION( IsValid() ) + if ( !IsValid() ) + throw Error( "PointGridInterpolation::ApplyLocalModel(): Uninitialized interpolation." ); + + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( message, m_Gx.Rows() ); + } +#endif + + Array L = Thread::OptimalThreadLoads( m_Gx.Rows(), + 1/*overheadLimit*/, + m_parallel ? m_maxProcessors : 1 ); + AbstractImage::ThreadData data( monitor, m_Gx.Rows() ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new LocalModelThread( data, *this, PS, n, n + int( L[i] ) ) ); + AbstractImage::RunThreads( threads, data ); + threads.Destroy(); + } + + /*! + * + */ + template + void ApplyLocalModel( const SI& Sx, const SI& Sy, + const String& message = "Applying local interpolation model", + bool verbose = true ) + { + PCL_PRECONDITION( IsValid() ) + if ( !IsValid() ) + throw Error( "PointGridInterpolation::ApplyLocalModel(): Uninitialized interpolation." ); + + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( message, m_Gx.Rows() ); + } +#endif + + Array L = Thread::OptimalThreadLoads( m_Gx.Rows(), + 1/*overheadLimit*/, + m_parallel ? m_maxProcessors : 1 ); + AbstractImage::ThreadData data( monitor, m_Gx.Rows() ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new LocalModelThread2( data, *this, Sx, Sy, n, n + int( L[i] ) ) ); + AbstractImage::RunThreads( threads, data ); + threads.Destroy(); + } + + /*! + * Returns true iff this is a valid, initialized object ready for + * interpolation. + */ + bool IsValid() const + { + return !m_Gx.IsEmpty() && !m_Gy.IsEmpty(); + } + + /*! + * Deallocates internal structures, yielding an empty object that cannot be + * used before a new call to Initialize(). + */ + void Clear() + { + m_Ix.Clear(); + m_Iy.Clear(); + m_Gx.Clear(); + m_Gy.Clear(); + } + + /*! + * Returns the current interpolation reference rectangle. See Initialize() + * for more information. + * + * The returned rectangle is ordered (see pcl::IsOrderedRect()). + */ + const Rect& ReferenceRect() const + { + return m_rect; + } + + /*! + * Returns the current grid distance for calculation of discrete function + * values. See Initialize() for more information. + */ + int Delta() const + { + return m_delta; + } + + /*! + * Returns a reference to the discrete matrix used for interpolation of + * function values in the X direction. + * + * If this object has not been initialized, this member function returns a + * reference to an empty matrix. + */ + const DMatrix& XInterpolationMatrix() const + { + return m_Gx; + } + + /*! + * Returns a reference to the discrete matrix used for interpolation of + * function values in the Y direction. + * + * If this object has not been initialized, this member function returns a + * reference to an empty matrix. + */ + const DMatrix& YInterpolationMatrix() const + { + return m_Gy; + } + + /*! + * Returns an interpolated point at the specified coordinates. + */ + template + DPoint operator ()( T x, T y ) const + { + PCL_PRECONDITION( IsValid() ) + double fx = (double( x ) - m_rect.x0)/m_delta; + double fy = (double( y ) - m_rect.y0)/m_delta; + return DPoint( m_Ix( fx, fy ), m_Iy( fx, fy ) ); + } + + /*! + * Returns an interpolated point at the given \a p.x and \a p.y coordinates. + */ + template + DPoint operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + +private: + + /*! + * N.B.: Here we need a smooth interpolation function without negative + * lobes, in order to prevent small-scale oscillations. Other options are + * BilinearInterpolation and CubicBSplineFilter. + */ + typedef BicubicBSplineInterpolation grid_interpolation; + + Rect m_rect; + int m_delta; + DMatrix m_Gx, m_Gy; + grid_interpolation m_Ix, m_Iy; + + template + class GridInitializationThread : public Thread + { + public: + + GridInitializationThread( const AbstractImage::ThreadData& data, + PointGridInterpolation& grid, const PSI& surface, int startRow, int endRow ) + : m_data( data ) + , m_grid( grid ) + , m_surface( surface ) + , m_startRow( startRow ) + , m_endRow( endRow ) + { + } + + PCL_HOT_FUNCTION void Run() override + { + INIT_THREAD_MONITOR() + + for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) + { + for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) + { + DPoint p = m_surface( x, y ); + m_grid.m_Gx[i][j] = p.x; + m_grid.m_Gy[i][j] = p.y; + } + + UPDATE_THREAD_MONITOR( 32 ) + } + } + + private: + + const AbstractImage::ThreadData& m_data; + PointGridInterpolation& m_grid; + const PSI& m_surface; + int m_startRow, m_endRow; + }; + + template + class GridInitializationXYThread : public Thread + { + public: + + GridInitializationXYThread( const AbstractImage::ThreadData& data, + PointGridInterpolation& grid, + const SI& surfaceX, const SI& surfaceY, int startRow, int endRow ) + : m_data( data ) + , m_grid( grid ) + , m_surfaceX( surfaceX ) + , m_surfaceY( surfaceY ) + , m_startRow( startRow ) + , m_endRow( endRow ) + { + } + + PCL_HOT_FUNCTION void Run() override + { + INIT_THREAD_MONITOR() + + for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) + { + for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) + { + m_grid.m_Gx[i][j] = m_surfaceX( x, y ); + m_grid.m_Gy[i][j] = m_surfaceY( x, y ); + } + + UPDATE_THREAD_MONITOR( 32 ) + } + } + + private: + + const AbstractImage::ThreadData& m_data; + PointGridInterpolation& m_grid; + const SI& m_surfaceX; + const SI& m_surfaceY; + int m_startRow, m_endRow; + }; + + template + class LocalModelThread : public Thread + { + public: + + LocalModelThread( const AbstractImage::ThreadData& data, + PointGridInterpolation& grid, const PSI& model, int startRow, int endRow ) + : m_data( data ) + , m_grid( grid ) + , m_model( model ) + , m_startRow( startRow ) + , m_endRow( endRow ) + { + } + + PCL_HOT_FUNCTION void Run() override + { + INIT_THREAD_MONITOR() + + for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) + { + for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) + { + DPoint d = m_model( x, y ); + m_grid.m_Gx[i][j] += d.x; + m_grid.m_Gy[i][j] += d.y; + } + + UPDATE_THREAD_MONITOR( 32 ) + } + } + + private: + + const AbstractImage::ThreadData& m_data; + PointGridInterpolation& m_grid; + const PSI& m_model; + int m_startRow, m_endRow; + }; + + template + class LocalModelThread2 : public Thread + { + public: + + LocalModelThread2( const AbstractImage::ThreadData& data, + PointGridInterpolation& grid, const SI& modelX, const SI& modelY, int startRow, int endRow ) + : m_data( data ) + , m_grid( grid ) + , m_modelX( modelX ) + , m_modelY( modelY ) + , m_startRow( startRow ) + , m_endRow( endRow ) + { + } + + PCL_HOT_FUNCTION void Run() override + { + INIT_THREAD_MONITOR() + + for ( int i = m_startRow, y = m_grid.m_rect.y0 + i*m_grid.m_delta; i < m_endRow; ++i, y += m_grid.m_delta ) + { + for ( int j = 0, x = m_grid.m_rect.x0; j < m_grid.m_Gx.Cols(); ++j, x += m_grid.m_delta ) + { + m_grid.m_Gx[i][j] += m_modelX( x, y ); + m_grid.m_Gy[i][j] += m_modelY( x, y ); + } + + UPDATE_THREAD_MONITOR( 32 ) + } + } + + private: + + const AbstractImage::ThreadData& m_data; + PointGridInterpolation& m_grid; + const SI& m_modelX, m_modelY; + int m_startRow, m_endRow; + }; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_GridInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GridInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/GroupBox.h b/3rdparty/include/pcl/GroupBox.h new file mode 100644 index 0000000..4d4f8a7 --- /dev/null +++ b/3rdparty/include/pcl/GroupBox.h @@ -0,0 +1,175 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/GroupBox.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_GroupBox_h +#define __PCL_GroupBox_h + +/// \file pcl/GroupBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GroupBox + * \brief Client-side interface to a PixInsight %GroupBox control + * + * ### TODO: Write a detailed description for %GroupBox. + */ +class PCL_CLASS GroupBox : public Control +{ +public: + + /*! + * Constructs a %GroupBox object with the specified \a title, as a child + * control of \a parent. + */ + GroupBox( const String& title = String(), Control& parent = Control::Null() ); + + /*! + * Destroys a %GroupBox object. + */ + virtual ~GroupBox() + { + } + + /*! # + */ + String Title() const; + + /*! # + */ + void SetTitle( const String& ); + + /*! # + */ + bool HasTitleCheckBox() const; + + /*! # + */ + void EnableTitleCheckBox( bool = true ); + + /*! # + */ + void DisableTitleCheckBox( bool disable = true ) + { + EnableTitleCheckBox( !disable ); + } + + /*! # + */ + bool IsChecked() const; + + /*! # + */ + void SetChecked( bool = true ); + + /*! # + */ + void Check() + { + SetChecked( true ); + } + + /*! # + */ + void Uncheck() + { + SetChecked( false ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnCheck( GroupBox& sender, bool checked ); + + /*! # + */ + typedef void (Control::*check_event_handler)( GroupBox& sender, bool checked ); + + /*! # + */ + void OnCheck( check_event_handler, Control& ); + +private: + + struct EventHandlers + { + check_event_handler onCheck = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class GroupBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_GroupBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/GroupBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/HammerAitoffProjection.h b/3rdparty/include/pcl/HammerAitoffProjection.h new file mode 100644 index 0000000..ac98477 --- /dev/null +++ b/3rdparty/include/pcl/HammerAitoffProjection.h @@ -0,0 +1,132 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/HammerAitoffProjection.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_HammerAitoffProjection_h +#define __PCL_HammerAitoffProjection_h + +/// \file pcl/HammerAitoffProjection.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class HammerAitoffProjection + * \brief Hammer-Aitoff projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS HammerAitoffProjection : public ProjectionBase +{ +public: + + /*! + * Default constructor. + */ + HammerAitoffProjection() = default; + + /*! + * Copy constructor. + */ + HammerAitoffProjection( const HammerAitoffProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new HammerAitoffProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "AIT"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Hammer-Aitoff"; + } + +protected: + + bool Project( DPoint& pW, const DPoint& pN ) const noexcept override; + + bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept override; + +private: + + double m_Zmin = Const::_1_sqrt2(); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_HammerAitoffProjection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/HammerAitoffProjection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Histogram.h b/3rdparty/include/pcl/Histogram.h new file mode 100644 index 0000000..69112d8 --- /dev/null +++ b/3rdparty/include/pcl/Histogram.h @@ -0,0 +1,660 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Histogram.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_Histogram_h +#define __PCL_Histogram_h + +/// \file pcl/Histogram.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Histogram + * \brief Discrete image histogram function + * + * ### TODO: Write a detailed description for %Histogram. + */ +class PCL_CLASS Histogram : public ParallelProcess +{ +public: + + /*! + * Represents a histogram bin count, or the value of the discrete histogram + * function at a specific abscissa or range of abscissae. + */ + typedef uint64 count_type; + + /*! + * A vector of histogram bin counts, which is the type used internally to + * store the values of the discrete histogram function. + */ + typedef UI64Vector histogram_type; + + /*! + * Constructs an empty %Histogram object with the specified \a resolution. + * + * The resolution of a histogram function is the number of discrete + * intervals (or \e bins) used to analyze image data. The minimum possible + * resolution is 2. In PCL, the default resolution is 2^16 = 65536 intervals + * (also known as a 16-bit histogram). + */ + Histogram( int resolution = 0x10000L ) + : m_resolution( pcl::Max( 2, resolution ) ) + { + PCL_PRECONDITION( resolution > 1 ) + } + + /*! + * Constructs a %Histogram object by importing a copy of the specified + * \a data vector as its internal vector of histogram function values. + * Automatically sets the histogram resolution equal to the length of the + * \a data vector, and calculates the peak level of the newly constructed + * histogram. + * + * If the specified \a data vector has less than two components, this + * constructor will yield an empty histogram with the default 16-bit + * resolution. + */ + Histogram( const histogram_type& data ) + { + SetHistogramData( data ); + } + + /*! + * Copy constructor. + */ + Histogram( const Histogram& ) = default; + + /*! + * Move constructor. + */ + Histogram( Histogram&& ) = default; + + /*! + * Destroys a %Histogram object. + */ + virtual ~Histogram() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Histogram& operator =( const Histogram& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Histogram& operator =( Histogram&& ) = default; + + /*! + * Assigns another %Histogram object \a x to this object. + */ + void Assign( const Histogram& x ) + { + (void)operator =( x ); + } + + /*! + * Deallocates the internal vector of histogram values, yielding an empty + * %Histogram object. + */ + void Clear() + { + m_histogram.Clear(); + m_peakLevel = 0; + } + + /*! + * Returns true iff this %Histogram object is empty. An empty histogram has + * no computed histogram values. + */ + bool IsEmpty() const + { + return m_histogram.IsEmpty(); + } + + /*! + * Returns the current resolution of this %Histogram object. + * + * The resolution of a histogram function is the number of discrete + * intervals (or \e bins) used to analyze image data. The minimum possible + * resolution is 2. In PCL, the default resolution is 2^16 = 65536 intervals + * (also known as a 16-bit histogram). + */ + int Resolution() const + { + return m_resolution; + } + + /*! + * Returns the highest valid discrete histogram level, or Resolution()-1. + */ + int LastLevel() const + { + return m_resolution-1; + } + + /*! + * Sets the resolution of this %Histogram object. + * + * The resolution of a histogram function is the number of discrete + * intervals (or \e bins) used to analyze image data. The minimum possible + * resolution is 2. In PCL, the default resolution is 2^16 = 65536 intervals + * (also known as a 16-bit histogram). + * + * After calling this member function, the histogram will be empty and the + * internal vector of histogram function values will be deallocated. + */ + void SetResolution( int resolution ) + { + PCL_PRECONDITION( resolution > 1 ) + Clear(); + m_resolution = pcl::Max( 2, resolution ); + } + + /*! + * If this histogram object is empty, this member function allocates the + * internal vector of histogram function values. Newly allocated vectors are + * not initialized, so the histogram will contain unpredictable values after + * calling this function. + * + * If the histogram is not empty, calling this function has no effect. + */ + void Allocate() + { + if ( m_histogram.IsEmpty() ) + m_histogram = histogram_type( m_resolution ); + } + + /*! + * Returns the current peak level of the histogram. If this histogram is + * empty, the peak level is zero conventionally. + * + * The peak level is simply the index (or integer abscissa) of the histogram + * bin with the largest count, or the position on the X axis of the maximum + * of the histogram function, in the discrete range [0,LastLevel()]. + */ + int PeakLevel() const + { + return m_histogram.IsEmpty() ? 0 : m_peakLevel; + } + + /*! + * Returns the histogram peak level as a floating point number normalized to + * the [0,1] range. See PeakLevel(). + */ + double NormalizedPeakLevel() const + { + return NormalizedLevel( PeakLevel() ); + } + + /*! + * Recalculates the histogram peak level from current histogram function + * values. If the histogram is empty, the peak level is reset to zero + * conventionally. + * + * Returns the newly calculated histogram peak level. + */ + int UpdatePeakLevel() + { + return m_peakLevel = m_histogram.IsEmpty() ? 0 : + int( pcl::MaxItem( m_histogram.Begin(), m_histogram.End() ) - m_histogram.Begin() ); + } + + /*! + * Returns the index of the discrete level in this %Histogram object + * corresponding to the specified normalized level \a x in the [0,1] range. + */ + int HistogramLevel( double x ) const + { + PCL_PRECONDITION( x >= 0 && x <= 1 ) + return RoundInt( pcl::Range( x, 0.0, 1.0 )*(m_resolution - 1) ); + } + + /*! + * Returns the normalized histogram level in the [0,1] range corresponding + * to the specified discrete level \a i in this %Histogram object. + */ + double NormalizedLevel( int i ) const + { + PCL_PRECONDITION( i >= 0 && i < m_resolution ) + return double( pcl::Range( i, 0, m_resolution-1 ) )/(m_resolution - 1); + } + + /*! + * Converts the specified normalized levels \a a, \a b in the [0,1] range to + * discrete histogram levels \a i, \a j, respectively. + */ + void GetHistogramRange( int& i, int& j, double a, double b ) const + { + i = HistogramLevel( a ); + j = HistogramLevel( b ); + if ( j < i ) + pcl::Swap( i, j ); + } + + /*! + * Converts the specified discrete histogram levels \a i, \a j to normalized + * levels \a a, \a b, respectively, in the [0,1] range. + */ + void GetNormalizedRange( double& a, double& b, int i, int j ) const + { + if ( j < i ) + pcl::Swap( i, j ); + a = NormalizedLevel( i ); + b = NormalizedLevel( j ); + } + + /*! + * Returns the total sum of the counts in all histogram intervals, or the + * sum of all discrete histogram function values. If this %Histogram object + * is empty, this function returns zero. + */ + count_type Count() const + { + return m_histogram.Sum(); + } + + /*! + * Returns the histogram count, or the value of the histogram function, at + * the specified discrete level \a i. + */ + count_type Count( int i ) const + { + PCL_PRECONDITION( i >= 0 && i < m_histogram.Length() ) + if ( i < 0 || i >= m_histogram.Length() ) + return 0; + return m_histogram[i]; + } + + /*! + * Subscript operator. Equivalent to Count( int ). + */ + count_type operator []( int i ) const + { + return Count( i ); + } + + /*! + * Returns the sum of counts in the specified interval of discrete histogram + * levels \a i, \a j. + */ + count_type Count( int i, int j ) const + { + PCL_PRECONDITION( i >= 0 && i < m_histogram.Length() ) + PCL_PRECONDITION( j >= 0 && j < m_histogram.Length() ) + if ( m_histogram.IsEmpty() ) + return 0; + i = pcl::Range( i, 0, m_histogram.Length()-1 ); + j = pcl::Range( j, 0, m_histogram.Length()-1 ); + if ( j < i ) + pcl::Swap( i, j ); + return pcl::Sum( m_histogram.At( i ), m_histogram.At( j+1 ) ); + } + + /*! + * Returns the histogram function value for the bin at the current peak + * level. Typically, the peak count is used to normalize the histogram to + * a prescribed range. For example, by dividing all histogram function + * values by the peak count the entire histogram will be normalized to the + * [0,1] range. + */ + count_type PeakCount() const + { + return Count( m_peakLevel ); + } + + /*! + * Returns the peak count, or the maximum histogram function value, within + * the specified range [i,j] of discrete histogram intervals. + */ + count_type PeakCount( int i, int j ) const + { + PCL_PRECONDITION( i >= 0 && i < m_histogram.Length() ) + PCL_PRECONDITION( j >= 0 && j < m_histogram.Length() ) + if ( m_histogram.IsEmpty() ) + return 0; + i = pcl::Range( i, 0, m_histogram.Length()-1 ); + j = pcl::Range( j, 0, m_histogram.Length()-1 ); + if ( j < i ) + pcl::Swap( i, j ); + return *pcl::MaxItem( m_histogram.At( i ), m_histogram.At( j+1 ) ); + } + + /*! + * Returns the discrete histogram level where the sum of counts for its + * preceding levels is greater than or equal to the specified amount \a n. + * + * This function is useful to compute an automatic histogram shadows + * clipping point. The returned index is the position of the shadows + * clipping point that clips (sets to black) the specified amount of image + * pixel samples + */ + int ClipLow( count_type n ) const + { + int i = 0; + for ( count_type s = 0; i < m_histogram.Length()-1 && (s += m_histogram[i]) <= n; ++i ) {} + return i; + } + + /*! + * Returns the normalized histogram level (in the [0,1] range) where the sum + * of counts for its preceding levels is greater than or equal to the + * specified amount \a n. + */ + double NormalizedClipLow( count_type n ) const + { + return NormalizedLevel( ClipLow( n ) ); + } + + /*! + * Returns the discrete histogram level where the sum of counts for its + * succeding levels is greater than or equal to the specified amount \a n. + * + * This function is useful to compute an automatic histogram highlights + * clipping point. The returned index is the position of the highlights + * clipping point that clips (sets to white) the specified amount of image + * pixel samples + */ + int ClipHigh( count_type n ) const + { + int i = m_histogram.Length(); + for ( count_type s = 0; --i > 0 && (s += m_histogram[i]) <= n; ) {} + return i; + } + + /*! + * Returns the normalized histogram level (in the [0,1] range) where the sum + * of counts for its succeding levels is greater than or equal to the + * specified amount \a n. + */ + double NormalizedClipHigh( count_type n ) const + { + return NormalizedLevel( ClipHigh( n ) ); + } + + /*! + * Returns a reference to the immutable internal vector of histogram + * function values. + */ + const histogram_type& HistogramData() const + { + return m_histogram; + } + + /*! + * Causes this %Histogram object to import a copy of the specified \a data + * vector as its internal vector of histogram function values. Automatically + * sets the histogram resolution equal to the length of the \a data vector, + * and recalculates the peak level of the new histogram. + * + * If the specified \a data vector has less than two components, this member + * function will yield an empty histogram without changing the current + * histogram resolution. + */ + void SetHistogramData( const histogram_type& data ) + { + if ( data.Length() < 2 ) + Clear(); + else + { + m_histogram = data; + m_resolution = m_histogram.Length(); + UpdatePeakLevel(); + } + } + + /*! + * \deprecated This member function has been deprecated. It is kept as part + * of PCL for compatibility with existing modules; do not use it in newly + * produced code. + */ + void GetData( count_type* where, int fromLevel = 0, int toLevel = -1 ) const + { + PCL_PRECONDITION( where != nullptr ) + PCL_PRECONDITION( fromLevel >= 0 ) + if ( where != nullptr ) + if ( !m_histogram.IsEmpty() ) + { + fromLevel = pcl::Range( fromLevel, 0, m_histogram.Length()-1 ); + toLevel = (toLevel < 0) ? m_histogram.Length()-1 : pcl::Range( toLevel, 0, m_histogram.Length()-1 ); + if ( toLevel < fromLevel ) + pcl::Swap( fromLevel, toLevel ); + ::memcpy( where, m_histogram.At( fromLevel ), (1+toLevel-fromLevel)*sizeof( count_type ) ); + } + } + + /*! + * Remaps the histogram function to fit the resolution of a target + * histogram \a h. + * + * If the target histogram has the same resolution as this object, this + * member function is equivalent to a plain assignment. If the resolutions + * differ, if this histogram is empty then the target histogram is + * deallocated and cleared, otherwise the target histogram is recomputed as + * a resampled version of this histogram. + * + * This member function is useful to generate reduced versions of a + * histogram. It can also be used to generate bootstrap samples from an + * existing histogram function. + */ + void Resample( Histogram& h ) const + { + if ( h.m_resolution == m_resolution ) + h = *this; + else + { + if ( m_histogram.IsEmpty() ) + h.Clear(); + else + { + h.Allocate(); + h.m_histogram = 0; + double k = double( h.m_histogram.Length() - 1 )/(m_histogram.Length() - 1); + for ( int i = 0; i < m_histogram.Length(); ++i ) + h.m_histogram[pcl::RoundInt( i*k )] += m_histogram[i]; + h.m_peakLevel = int( pcl::MaxItem( h.m_histogram.Begin(), h.m_histogram.End() ) - h.m_histogram.Begin() ); + } + } + } + + /*! + * Computes the discrete entropy of this histogram. + * + * The returned value is normalized to the total weight of the histogram, + * that is, it is independent on the total number of counts stored in the + * histogram data vector. + */ + double Entropy() const + { + double H = 0; + count_type n = Count(); + if ( n > 0 ) + for ( int i = 0; i < m_histogram.Length(); ++i ) + if ( m_histogram[i] > 0 ) + { + double f = double( m_histogram[i] )/n; + H -= f*Log( f ); + } + return H; + } + + /*! + * Computes the histogram function of a 32-bit floating point real image. + */ + const Image& operator <<( const Image& ); + + /*! + * Computes the histogram function of a 64-bit floating point real image. + */ + const DImage& operator <<( const DImage& ); + + /*! + * Computes the histogram function of an 8-bit unsigned integer image. + */ + const UInt8Image& operator <<( const UInt8Image& ); + + /*! + * Computes the histogram function of a 16-bit unsigned integer image. + */ + const UInt16Image& operator <<( const UInt16Image& ); + + /*! + * Computes the histogram function of a 32-bit unsigned integer image. + */ + const UInt32Image& operator <<( const UInt32Image& ); + + /*! + * Computes the histogram function of the image transported by an + * ImageVariant object. + */ + const ImageVariant& operator <<( const ImageVariant& ); + + /*! + * Returns the current rectangular selection in this %Histogram object. + * + * By default, the rectangular selection is an empy rectangle, meaning that + * the rectangular selection in the target image will be used. + */ + const Rect& SelectedRectangle() const + { + return m_rect; + } + + /*! + * Sets a new rectangular selection for this %Histogram object. + * + * When a non-empty rectangular selection is specified, it is used as the + * region of interest (ROI) for calculation of histograms. If an empty or + * invalid rectangle is specified, the current selection in the target image + * will be used. + */ + void SelectRectangle( const Rect& r ) + { + m_rect = r; + } + + /*! + * Clears the rectangular selection in this %Histogram object. + * + * After calling this function, histograms will be calculated for the + * current rectangular selection of the target image. + */ + void ClearRectangle() + { + m_rect = Rect( 0 ); + } + + /*! + * Returns the current channel index selected in this %Histogram object. + * + * By default, the selected channel index is -1, meaning that the channel + * selected in the target image will be used. + */ + int SelectedChannel() const + { + return m_channel; + } + + /*! + * Selects a channel index for this %Histogram object. + * + * When a positive (>= 0) channel index is specified, it is used for + * calculation of histograms. If a negative channel index is specified, the + * current selected channel in the target image will be used. + */ + void SelectChannel( int channel ) + { + m_channel = pcl::Max( -1, channel ); + } + + /*! + * Clears the channel index selection in this %Histogram object. + * + * After calling this function, histograms will be calculated for the + * current selected channel of the target image. + */ + void ClearSelectedChannel() + { + m_channel = -1; + } + +protected: + + histogram_type m_histogram; // Discrete histogram levels + int m_resolution = 0x10000L; // Number of histogram levels + int m_peakLevel = 0; // Maximum level (index of maximum count) + Rect m_rect = 0; // ROI, Rect( 0 ) to use target image's selection + int m_channel = -1; // < 0 to use target image's selection + + friend class View; + friend class HistogramTransformation; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Histogram_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Histogram.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/HistogramTransformation.h b/3rdparty/include/pcl/HistogramTransformation.h new file mode 100644 index 0000000..f395347 --- /dev/null +++ b/3rdparty/include/pcl/HistogramTransformation.h @@ -0,0 +1,530 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/HistogramTransformation.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_HistogramTransformation_h +#define __PCL_HistogramTransformation_h + +/// \file pcl/HistogramTransformation.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS Histogram; + +/*! + * \class HistogramTransformation + * \brief Multiple histogram transformation. + * + * ### TODO: Write a detailed description for %HistogramTransformation. + */ +class PCL_CLASS HistogramTransformation : public ImageTransformation, public ParallelProcess +{ +public: + + /*! + * Represents a set of chained histogram transformations. + */ + typedef Array transformation_list; + + /*! + * Constructs a %HistogramTransformation object with the specified + * parameters. + * + * \param mb Midtones balance in the range [0,1]. + * + * \param sc Shadows clipping point in the range [0,1]. + * + * \param hc Highlights clipping point in the range [0,1]. + * + * \param lr Low dynamic range expansion bound, \a lr ≤ 0. + * + * \param hr High dynamic range expansion bound, \a hr ≥ 1. + * + * The default parameter values define an identity transformation: + * + * \a mb = 0.5, \a sc = 0, \a hc = 1, \a lr = 0, \a hr = 1. + */ + HistogramTransformation( double mb = 0.5, + double sc = 0, double hc = 1, + double lr = 0, double hr = 1 ) + { + PCL_PRECONDITION( mb >= 0 && mb <= 1 ) + PCL_PRECONDITION( sc >= 0 && sc <= 1 ) + PCL_PRECONDITION( hc >= 0 && hc <= 1 ) + PCL_PRECONDITION( lr <= 0 ) + PCL_PRECONDITION( hr >= 1 ) + m_midtonesBalance = pcl::Range( mb, 0.0, 1.0 ); + m_clipLow = pcl::Range( sc, 0.0, 1.0 ); + m_clipHigh = pcl::Range( hc, 0.0, 1.0 ); + if ( m_clipHigh < m_clipLow ) + pcl::Swap( m_clipLow, m_clipHigh ); + m_expandLow = Min( lr, 0.0 ); + m_expandHigh = Max( 1.0, hr ); + UpdateFlags(); + } + + /*! + * Copy constructor. + */ + HistogramTransformation( const HistogramTransformation& ) = default; + + /*! + * Move constructor. + */ + HistogramTransformation( HistogramTransformation&& ) = default; + + /*! + * Destroys a %HistogramTransformation object. + */ + virtual ~HistogramTransformation() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + HistogramTransformation& operator =( const HistogramTransformation& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + HistogramTransformation& operator =( HistogramTransformation&& ) = default; + + /*! + * Returns the number of histogram transforms in the transformation chain. + */ + size_type Length() const + { + return 1 + m_transformChain.Length(); + } + + /*! + * Returns a reference to the (immutable) transformation at the specified + * \a index in the current transformation chain. + */ + const HistogramTransformation& operator []( size_type index ) const + { + return (index == 0) ? *this : m_transformChain[index-1]; + } + + /*! + * Returns a reference to the (mutable) transformation at the specified + * \a index in this transformation chain. + */ + HistogramTransformation& operator []( size_type index ) + { + return (index == 0) ? *this : m_transformChain[index-1]; + } + + /*! + * Returns a reference to the (immutable) first histogram transformation in + * the current chain. The returned value is always a reference to this + * object. + */ + const HistogramTransformation& operator *() const + { + return *this; + } + + /*! + * Returns a reference to the (mutable) first histogram transformation in + * the current chain. The returned value is always a reference to this + * object. + */ + HistogramTransformation& operator *() + { + return *this; + } + + /*! + * Adds a histogram transformation to the transformation chain of this + * %HistogramTransformation object. + */ + void Add( const HistogramTransformation& H ) + { + m_transformChain.Add( H ); + } + + /*! # + */ + double MidtonesBalance() const + { + return m_midtonesBalance; + } + + /*! # + */ + double ShadowsClipping() const + { + return m_clipLow; + } + + /*! # + */ + double HighlightsClipping() const + { + return m_clipHigh; + } + + /*! # + */ + double LowRange() const + { + return m_expandLow; + } + + /*! # + */ + double HighRange() const + { + return m_expandHigh; + } + + /*! # + */ + bool IsIdentityTransformation() const + { + return m_midtonesBalance == 0.5 + && m_clipLow == 0 && m_clipHigh == 1 + && m_expandLow == 0 && m_expandHigh == 1; + } + + /*! # + */ + bool IsIdentityTransformationSet() const; + + /*! # + */ + void SetMidtonesBalance( double b ) + { + PCL_PRECONDITION( b >= 0 && b <= 1 ) + m_midtonesBalance = pcl::Range( b, 0.0, 1.0 ); + UpdateFlags(); + } + + /*! # + */ + void SetShadowsClipping( double c ) + { + PCL_PRECONDITION( c >= 0 && c <= 1 ) + m_clipLow = pcl::Range( c, 0.0, 1.0 ); + if ( m_clipHigh < m_clipLow ) + pcl::Swap( m_clipLow, m_clipHigh ); + UpdateFlags(); + } + + /*! # + */ + void SetHighlightsClipping( double c ) + { + PCL_PRECONDITION( c >= 0 && c <= 1 ) + m_clipHigh = pcl::Range( c, 0.0, 1.0 ); + if ( m_clipHigh < m_clipLow ) + pcl::Swap( m_clipLow, m_clipHigh ); + UpdateFlags(); + } + + /*! # + */ + void SetClipping( double sc, double hc ) + { + PCL_PRECONDITION( sc >= 0 && sc <= 1 ) + PCL_PRECONDITION( hc >= 0 && hc <= 1 ) + m_clipLow = pcl::Range( sc, 0.0, 1.0 ); + m_clipHigh = pcl::Range( hc, 0.0, 1.0 ); + if ( m_clipHigh < m_clipLow ) + pcl::Swap( m_clipLow, m_clipHigh ); + UpdateFlags(); + } + + /*! # + */ + void SetLowRange( double r ) + { + PCL_PRECONDITION( r <= 0 ) + m_expandLow = Min( 0.0, r ); + UpdateFlags(); + } + + /*! # + */ + void SetHighRange( double r ) + { + PCL_PRECONDITION( r >= 1 ) + m_expandHigh = Max( 1.0, r ); + UpdateFlags(); + } + + /*! # + */ + void SetRange( double lr, double hr ) + { + PCL_PRECONDITION( lr <= 0 ) + PCL_PRECONDITION( hr >= 1 ) + m_expandLow = Min( 0.0, lr ); + m_expandHigh = Max( 1.0, hr ); + UpdateFlags(); + } + + /*! + * Resets all transformation parameters to yield an identity histogram + * transformation. + */ + void Reset() + { + m_midtonesBalance = 0.5; + m_clipLow = 0; + m_clipHigh = 1; + m_expandLow = 0; + m_expandHigh = 1; + m_transformChain.Clear(); + UpdateFlags(); + } + + // Avoid "hides virtual function in base" warnings by clang + using ImageTransformation::Apply; + + /*! # + */ + void Apply( double*, size_type, double x0 = 0, double x1 = 1 ) const; + + /*! # + */ + void Apply( float*, size_type, float x0 = 0, float x1 = 1 ) const; + + /*! # + */ + void Apply( Histogram& dstH, const Histogram& srcH ) const; + + /*! # + */ + void Make8BitLUT( uint8* ) const; + + /*! # + */ + void Make16BitLUT( uint8* ) const; + + /*! # + */ + void Make16BitLUT( uint16* ) const; + + /*! # + */ + void Make20BitLUT( uint8* ) const; + + /*! # + */ + void Make20BitLUT( uint16* ) const; + + /*! # + */ + void Make24BitLUT( uint8* ) const; + + /*! # + */ + void Make24BitLUT( uint16* ) const; + + /*! + * Returns the value of the midtones transfer function (MTF) for a + * given midtones balance \a m and a sample point \a x. Both \a m and \a x + * must be in the range [0,1]. + */ + static double MidtonesTransferFunction( double m, double x ) + { + /* + * Bulirsch-Stoer algorithm for a diagonal rational interpolation + * function with three fixed data points: (0,0) (m,1/2) (1,1). + * + * This is the MTF function after direct substitution in the B-S + * equations: + * + * double r = 1 + 0.5/((x - m)/(x - 1)/2 - 1); + * return r + r/(x/(x - 1) * (1 - r/(r - 0.5)) - 1); + * + * We can simplify: + * + * double r = (m - 1)/(x + m - 2); + * + * and then we can further simplify to: + * + * return (m - 1)*x/((2*m - 1)*x - m); + * + * Finally, precalculating (m - 1) we can save a multiplication. + */ + if ( x > 0 ) // guard us against degenerate cases + { + if ( x < 1 ) + { + double m1 = m - 1; + return m1*x/((m + m1)*x - m); + } + return 1; + } + return 0; + } + + /*! + * A convenience synonym for MidtonesTransferFunction( m, x ). + */ + static double MTF( double m, double x ) + { + return MidtonesTransferFunction( m, x ); + } + + /*! + * Transforms a real \a value in the normalized [0,1] range. + */ + void Transform( double& value ) const + { + if ( m_flags.hasClipping ) + value = m_flags.hasDelta ? ((value <= m_clipLow) ? 0.0 : ((value >= m_clipHigh) ? 1.0 : (value - m_clipLow)/m_flags.d)) : m_clipLow; + if ( m_flags.hasMTF ) + value = HistogramTransformation::MTF( m_midtonesBalance, value ); + if ( m_flags.hasRange ) + value = (value - m_expandLow)/m_flags.dr; + } + + /*! + * \struct pcl::HistogramTransformation::Flags + * \brief Characterizes a histogram transformation pertaining to a + * histogram transformation chain. + */ + struct Flags + { + double d = 1.0; //!< Total width of the stretched dynamic range + double dr = 1.0; //!< Total width of the expanded dynamic range + bool hasClipping = false; //!< The transformation defines clipping parameters + bool hasMTF = false; //!< The transformation defines a midtones transfer function + bool hasRange = false; //!< The transformation defines dynamic range expansion parameters + bool hasDelta = false; //!< The transformation defines a nonzero stretched range of sample values + + /*! + * Default constructor. + */ + Flags() = default; + + /*! + * Copy constructor. + */ + Flags( const Flags& ) = default; + + /*! + * Constructs a new %Flags object initialized for the parameters of the + * specified HistogramTransformation \a H. + */ + Flags( const HistogramTransformation& H ) + { + hasClipping = H.m_clipLow != 0 || H.m_clipHigh != 1; + hasMTF = H.m_midtonesBalance != 0.5; + hasRange = H.m_expandLow != 0 || H.m_expandHigh != 1; + hasDelta = false; + if ( hasClipping ) + { + d = H.m_clipHigh - H.m_clipLow; + hasDelta = 1 + d != 1; + } + if ( hasRange ) + dr = H.m_expandHigh - H.m_expandLow; + } + }; + + /*! + * Returns the set of flags characterizing this histogram transformation. + */ + Flags TransformationFlags() const + { + return m_flags; + } + +private: + + double m_midtonesBalance = 0.5; // midtones balance + double m_clipLow = 0; // shadows clipping point + double m_clipHigh = 1; // highlights clipping point + double m_expandLow = 0; // shadows dynamic range expansion + double m_expandHigh = 1; // highlights dynamic range expansion + Flags m_flags; // transformation flags + transformation_list m_transformChain; // more transformations + + /*! + * \internal + */ + void UpdateFlags() + { + m_flags = Flags( *this ); + } + + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; + + friend class LUT2408Thread; + friend class LUT2416Thread; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_HistogramTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/HistogramTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Homography.h b/3rdparty/include/pcl/Homography.h new file mode 100644 index 0000000..c210df3 --- /dev/null +++ b/3rdparty/include/pcl/Homography.h @@ -0,0 +1,406 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Homography.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_Homography_h +#define __PCL_Homography_h + +/// \file pcl/Homography.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Homography + * \brief Homography geometric transformation. + * + * A two-dimensional projective transformation, or \e homography, is a + * line-preserving geometric transformation between two sets of points in the + * plane. More formally, if P represents the set of points in the plane, a + * homography is an invertible mapping H from P^2 to itself such that three + * points p1, p2, p3 are collinear if and only if H(p1), H(p2), H(p3) do. + * + * Homographies have important practical applications in the field of computer + * vision. On the PixInsight platform, this class is an essential component of + * image registration and astrometry processes. + */ +template +class PCL_CLASS Homography +{ +public: + + /*! + * Represents a reference point in two dimensions. + */ + typedef P point; + + /*! + * Represents a list of two-dimensional reference points involved in a + * homography transformation. + */ + typedef Array point_list; + + /*! + * Default constructor. Constructs a no-op transformation with a unit matrix + * transformation matrix. + */ + Homography() + : m_H( Matrix::UnitMatrix( 3 ) ) + { + } + + /*! + * Constructor from a given homography matrix. + */ + Homography( const Matrix& H ) + : m_H( H ) + { + } + + /*! + * Constructor from two 2D point lists. + * + * Computes a homography transformation to generate a list \a P2 of + * transformed points from a list \a P1 of original points. In other words, + * the computed homography H works as follows: + * + * P2 = H( P1 ) + * + * The transformation matrix is calculated by the Direct Linear + * Transformation (DLT) method. Both point lists must contain at least four + * points. + * + * If one of the specified point lists contains less than four points, or if + * no homography can be estimated from the specified point lists (which + * leads to a singular transformation matrix), this constructor throws an + * appropriate Error exception. + * + * \b References + * + * R. Hartley, In defense of the eight-point algorithm. IEEE + * Transactions on Pattern Analysis and Machine Intelligence, vol. 19, pp. + * 580–593, June 1997. + */ + Homography( const point_list& P1, const point_list& P2 ) + : m_H( DLT( P1, P2 ) ) + { + } + + /*! + * Copy constructor. + */ + Homography( const Homography& ) = default; + + /*! + * Copy assignment operator. + */ + Homography& operator =( const Homography& ) = default; + + /*! + * Move constructor. + */ + Homography( Homography&& ) = default; + + /*! + * Move assignment operator. + */ + Homography& operator =( Homography&& ) = default; + + /*! + * Coordinate transformation operator. Applies the homography matrix to the + * specified \a x and \a y coordinates. Returns the transformed point as a + * two-dimensional point with real coordinates. + */ + template + DPoint operator ()( T x, T y ) const + { + double w = m_H[2][0]*x + m_H[2][1]*y + m_H[2][2]; + PCL_CHECK( 1 + w != 1 ) + return DPoint( (m_H[0][0]*x + m_H[0][1]*y + m_H[0][2])/w, + (m_H[1][0]*x + m_H[1][1]*y + m_H[1][2])/w ); + } + + /*! + * Point transformation operator. Applies the homography matrix to the + * coordinates of the specified point \a p. Returns the transformed point as + * a two-dimensional point with real coordinates. + */ + template + DPoint operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + + /*! + * Returns the inverse of this homography transformation. + * + * If this transformation has been computed from two point lists \a P1 and + * \a P2: + * + * P2 = H( P1 ) + * + * then this function returns a transformation H1 such that: + * + * P1 = H1( P2 ) + */ + Homography Inverse() const + { + return Homography( m_H.Inverse() ); + } + + /*! + * Returns the homography transformation matrix. + */ + operator const Matrix&() const + { + return m_H; + } + + /*! + * Returns true iff this transformation has been initialized and is valid. + */ + bool IsValid() const + { + return !m_H.IsEmpty(); + } + + /*! + * Returns true iff this is an affine homography transformation. + * + * An affine homography is a special type of a general homography where the + * last row of the 3x3 transformation matrix is equal to (0, 0, 1). This + * function verifies that this property holds for the current transformation + * matrix (if it is valid) up to the machine epsilon for the \c double + * numeric type. + */ + bool IsAffine() const + { + return IsValid() + && Abs( m_H[2][0] ) <= std::numeric_limits::epsilon() + && Abs( m_H[2][1] ) <= std::numeric_limits::epsilon() + && 1 - Abs( m_H[2][2] ) <= std::numeric_limits::epsilon(); + } + + /*! + * Ensures that the transformation uniquely references its internal matrix + * data. + */ + void EnsureUnique() + { + m_H.EnsureUnique(); + } + +private: + + Matrix m_H; + + /* + * Normalization of reference points. + */ + struct NormalizedPoints + { + Array N; // the normalized points + Matrix T; // 3x3 normalization matrix + + NormalizedPoints( const point_list& points ) + { + /* + * Calculate the centroid of the input set of points. + */ + DPoint centroid( 0 ); + for ( const auto& p : points ) + centroid += p; + centroid /= points.Length(); + + /* + * Calculate mean centroid distance and move origin to the centroid. + */ + double d0 = 0; + for ( const auto& p : points ) + { + double x = p.x - centroid.x; + double y = p.y - centroid.y; + N << DPoint( x, y ); + d0 += Sqrt( x*x + y*y ); + } + d0 /= points.Length(); + + /* + * Scale point coordinates. + */ + double scale = Const::sqrt2()/d0; + for ( auto& p : N ) + p *= scale; + + /* + * Form the normalization matrix. + */ + T = Matrix( scale, 0.0, -scale*centroid.x, + 0.0, scale, -scale*centroid.y, + 0.0, 0.0, 1.0 ); + } + }; + + /* + * Implementation of the Direct Linear Transformation (DLT) method to + * compute a normalized homography matrix. + */ + static Matrix DLT( const point_list& P1, const point_list& P2 ) + { + int n = Min( P1.Length(), P2.Length() ); + if ( n < 4 ) + throw Error( "Homography::DLT(): Less than four points specified." ); + + /* + * Normalize all points. + */ + NormalizedPoints p1( P1 ); + NormalizedPoints p2( P2 ); + + /* + * Setup cross product matrix A. + */ + Matrix A( 2*n, 9 ); + for ( int i = 0; i < n; ++i ) + { + double x1 = p1.N[i].x; + double y1 = p1.N[i].y; + double x2 = p2.N[i].x; + double y2 = p2.N[i].y; + double* A0 = A[2*i]; + double* A1 = A[2*i + 1]; + //double* A2 = A[3*i + 2]; <-- linearly dependent eqn. + + A0[0] = A0[1] = A0[2] = 0; + A0[3] = -x1; + A0[4] = -y1; + A0[5] = -1; + A0[6] = y2*x1; + A0[7] = y2*y1; + A0[8] = y2; + + A1[0] = x1; + A1[1] = y1; + A1[2] = 1; + A1[3] = A1[4] = A1[5] = 0; + A1[6] = -x2*x1; + A1[7] = -x2*y1; + A1[8] = -x2; + + /* <-- linearly dependent eqn. + A2[0] = -y2*x1; + A2[1] = -y2*y1; + A2[2] = -y2; + A2[3] = x2*x1; + A2[4] = x2*y1; + A2[5] = x2; + A2[6] = A2[7] = A2[8] = 0; + */ + } + + /* + * SVD of cross product matrix. + */ + InPlaceSVD svd( A ); + + /* + * For sanity, set to zero all insignificant singular values. + */ + for ( int i = 0; i < svd.W.Length(); ++i ) + if ( Abs( svd.W[i] ) <= std::numeric_limits::epsilon() ) + svd.W[i] = 0; + + /* + * Locate the smallest nonzero singular value. + */ + int i = svd.IndexOfSmallestSingularValue(); + + /* + * The components of the homography matrix are those of the smallest + * eigenvector, i.e. the column vector of V corresponding to the smallest + * singular value. + */ + Matrix H( svd.V[0][i], svd.V[1][i], svd.V[2][i], + svd.V[3][i], svd.V[4][i], svd.V[5][i], + svd.V[6][i], svd.V[7][i], svd.V[8][i] ); + + if ( Abs( H[2][2] ) <= std::numeric_limits::epsilon() ) + throw Error( "Homography::DLT(): Singular matrix." ); + + /* + * Denormalize matrix components. + */ + H = p2.T.Inverse() * H * p1.T; + + /* + * Normalize matrix so that H[2][2] = 1. + */ + return H *= 1/H[2][2]; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Homography_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Homography.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ICCProfile.h b/3rdparty/include/pcl/ICCProfile.h new file mode 100644 index 0000000..76c1572 --- /dev/null +++ b/3rdparty/include/pcl/ICCProfile.h @@ -0,0 +1,905 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ICCProfile.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_ICCProfile_h +#define __PCL_ICCProfile_h + +/// \file pcl/ICCProfile.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup color_management Color Management Classes + */ + +/*! + * \namespace pcl::ICCProfileClass + * \brief Representation of ICC color profile classes + * \ingroup color_management + * + * + * + * + * + * + * + * + * + * + * + *
ICCProfileClass::Unknown Unknown or unsupported ICC profile class
ICCProfileClass::Any Any ICC profile class
ICCProfileClass::InputDevice Input device (scanner) profile
ICCProfileClass::DisplayDevice Display device (monitor) profile
ICCProfileClass::OutputDevice Output device (printer) profile
ICCProfileClass::DeviceLink Device link profile
ICCProfileClass::ColorSpaceConversion Color space conversion profile
ICCProfileClass::AbstractProfile Abstract profile
ICCProfileClass::NamedColorProfile Named color profile
+ */ +namespace ICCProfileClass +{ + enum mask_type + { + Unknown = 0x80000000, + Any = 0x00000000, + InputDevice = 0x00000001, + DisplayDevice = 0x00000002, + OutputDevice = 0x00000004, + DeviceLink = 0x00000008, + ColorSpaceConversion = 0x00000010, + AbstractProfile = 0x00000020, + NamedColorProfile = 0x00000040 + }; +} + +/*! + * \class pcl::ICCProfileClasses + * \brief A combination of ICCProfileClass values. + * \ingroup color_management + */ +typedef Flags ICCProfileClasses; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ICCColorSpace + * \brief Representation of data and connection color spaces in ICC color profiles. + * \ingroup color_management + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ICCColorSpace::Unknown Unknown or unsupported color space
ICCColorSpace::Any Any color space in an ICC profile
ICCColorSpace::XYZ CIE XYZ color space
ICCColorSpace::Lab CIE L*a*b* color space
ICCColorSpace::Luv CIE L*u*v* color space
ICCColorSpace::YCbCr YCbCr color space
ICCColorSpace::Yxy Yxy (luminance and chromaticity coordinates)
ICCColorSpace::RGB RGB color space
ICCColorSpace::Gray Grayscale color space
ICCColorSpace::HSV HSV color ordering system
ICCColorSpace::HLS HLS color ordering system
ICCColorSpace::CMYK CMYK color space
ICCColorSpace::CMY CMY color space
ICCColorSpace::LuvK LuvK color space
+ * + * Other color spaces supported by the ICC profile specification, as for + * example 2-color and 15-color spaces, are unknown to this implementation. + */ +namespace ICCColorSpace +{ + enum mask_type + { + Unknown = 0x80000000, + Any = 0x00000000, + XYZ = 0x00000001, + Lab = 0x00000002, + Luv = 0x00000004, + YCbCr = 0x00000008, + Yxy = 0x00000010, + RGB = 0x00000020, + Gray = 0x00000040, + HSV = 0x00000080, + HLS = 0x00000100, + CMYK = 0x00000200, + CMY = 0x00000400, + LuvK = 0x00000800 + }; +} + +/*! + * \class pcl::ICCColorSpaces + * \brief A combination of ICCColorSpace values. + * \ingroup color_management + */ +typedef Flags ICCColorSpaces; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ICCRenderingIntent + * \brief ICC rendering intents + * \ingroup color_management + * + * + * + * + * + * + *
ICCRenderingIntent::Perceptual Perceptual rendering intent (photographic images)
ICCRenderingIntent::Saturation Saturation rendering intent (graphics)
ICCRenderingIntent::RelativeColorimetric Relative colorimetric rendering intent (match white points)
ICCRenderingIntent::AbsoluteColorimetric Absolute colorimetric rendering intent (proofing)
+ */ +namespace ICCRenderingIntent +{ + enum value_type + { + Perceptual, + Saturation, + RelativeColorimetric, + AbsoluteColorimetric + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ICCRenderingDirection + * \brief ICC transform rendering direction + * \ingroup color_management + * + * + * + * + * + *
ICCRenderingDirection::Input Denotes a rendering intent applied to input pixel values.
ICCRenderingDirection::Output Denotes a rendering intent applied to output pixel values.
ICCRenderingDirection::Proofing Denotes a rendering intent applied by a proofing transform.
+ */ +namespace ICCRenderingDirection +{ + enum value_type + { + Input, + Output, + Proofing + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class ICCProfile + * \brief A high-level interface to ICC color profiles + * + * %ICCProfile is a high-level interface to the ICC profile handling + * functionality implemented in the PixInsight core application. An instance of + * %ICCProfile transports an ICC profile structure that can be embedded in + * image files or used to build color management transformations with the + * ICCProfileTransformation class. + * + * %ICCProfile implements a set of utility functions for profile validation, + * profile information retrieval, profile disk I/O and profile directory + * search, among other tasks. + * + * \ingroup color_management + * \sa ICCProfileTransformation + */ +class PCL_CLASS ICCProfile +{ +public: + + /*! + * Represents an opaque handle to an internal ICC profile. + */ + typedef void* handle; + + /*! + * Represents an ICC profile device class. + */ + typedef ICCProfileClass::mask_type profile_class; + + /*! + * Represents an ICC profile color space. + */ + typedef ICCColorSpace::mask_type color_space; + + /*! + * Represents an ICC rendering intent. + */ + typedef ICCRenderingIntent::value_type rendering_intent; + + /*! + * Represents an ICC transform rendering direction. + */ + typedef ICCRenderingDirection::value_type rendering_direction; + + /*! + * Constructs an empty %ICCProfile object. An empty %ICCProfile doesn't + * store an ICC profile structure. + */ + ICCProfile() = default; + + /*! + * Copy constructor. + */ + ICCProfile( const ICCProfile& ) = default; + + /*! + * Move constructor. + */ + ICCProfile( ICCProfile&& ) = default; + + /*! + * Constructs an %ICCProfile object and loads an ICC profile from a file at + * the specified \a profilePath. + * + * If the specified file does not exist, is not readable, or does not + * contain a valid ICC profile structure, this constructor throws an Error + * exception. + */ + ICCProfile( const String& profilePath ) + { + Load( profilePath ); + } + + /*! + * Constructs an %ICCProfile object to store a copy of the raw ICC profile + * structure available in the specified container. This constructor simply + * calls Set( rawData ). + */ + ICCProfile( const ByteArray& rawData ) + { + Set( rawData ); + } + + /*! + * Constructs an %ICCProfile object to store a copy of the raw ICC profile + * structure at the specified location. This constructor simply calls + * Set( rawData ). + */ + ICCProfile( const void* rawData ) + { + Set( rawData ); + } + + /*! + * Destroys an %ICCProfile object. If this object stores an ICC profile + * structure, it is deallocated upon destruction. + */ + virtual ~ICCProfile() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ICCProfile& operator =( const ICCProfile& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ICCProfile& operator =( ICCProfile&& ) = default; + + /*! + * Returns true iff this object stores an ICC color profile structure. + */ + bool IsProfile() const + { + return !m_data.IsEmpty(); + } + + /*! + * A convenience synonym for IsProfile(). + */ + operator bool() const + { + return IsProfile(); + } + + /*! + * Returns true if this profile has been read from a disk file. Otherwise + * this object either does not transport an ICC profile, or the profile has + * been generated or assigned directly from a memory buffer. + */ + bool IsDiskProfile() const + { + return !m_path.IsEmpty(); + } + + /*! + * Returns true iff the ICC profile stored in this object is identical to the + * profile stored in \a other %ICCProfile object. + * + * If necessary, this function performs a byte-to-byte comparison between + * both ICC profile structures (when both have the same size in bytes). + */ + bool IsSameProfile( const ICCProfile& other ) const; + + /*! + * Returns a reference to the immutable container that stores an ICC profile + * in this %ICCProfile object. The returned ByteArray is empty if this + * object does not transport an ICC color profile. + */ + const ByteArray& ProfileData() const + { + return m_data; + } + + /*! + * Returns the length of the stored ICC profile structure in bytes. Returns + * zero if this %ICCProfile object doesn't store an ICC color profile. + */ + size_type ProfileSize() const; + + /*! + * Returns the full file path of the stored ICC profile, if this object + * transports an ICC profile structure that has been loaded from a file, or + * an empty string otherwise. + */ + String FilePath() const + { + return m_path; + } + + /*! + * Returns the localized profile description of the stored ICC profile. + * + * \param language Optional language code (ISO 639/2) of the requested + * profile description. The default value is "en" for + * English. + * + * \param country Optional country code (ISO 3166) of the requested + * profile description. The default value is "US" for + * United States. + * + * If this object does not transport an ICC profile, this routine returns an + * empty string. Otherwise this routine will always return a valid profile + * description, even if no localized version exists for the requested + * language and country. The returned description will be as close as + * possible to the requested localization. + */ + String Description( const char* language = "en", const char* country = "US" ) const; + + /*! + * Returns the localized manufacturer information of the stored ICC profile. + * + * See Description( const char*, const char* ) const for detailed + * information on function parameters and behavior. + */ + String Manufacturer( const char* language = "en", const char* country = "US" ) const; + + /*! + * Returns the localized device model information of the stored ICC profile. + * + * See Description( const char*, const char* ) const for detailed + * information on function parameters and behavior. + */ + String Model( const char* language = "en", const char* country = "US" ) const; + + /*! + * Returns the localized copyright information of the stored ICC profile. + * + * See Description( const char*, const char* ) const for detailed + * information on function parameters and behavior. + */ + String Copyright( const char* language = "en", const char* country = "US" ) const; + + /*! + * Retrieves localized description, manufacturer, device model and copyright + * information from the stored ICC profile. + * + * If this object does not transport an ICC profile, this routine clears the + * \a description, \a manufacturer, \a model and \a copyright strings. If a + * valid ICC profile is stored in this object, the passed strings will be + * assigned with the corresponding information, as close as possible to the + * requested localization. See Description( const char*, const char* ) const + * for detailed information on localization parameters. + */ + void GetInformation( String& description, String& manufacturer, String& model, String& copyright, + const char* language = "en", const char* country = "US" ) const; + + /*! + * Returns the ICC profile class of the stored profile. See the + * ICCProfileClass namespace for supported profile classes. + * + * If this object doesn't transport an ICC profile, this function returns + * ICCProfileClass::Unknown. + */ + profile_class Class() const; + + /*! + * Returns the ICC color space of the stored profile. See the ICCColorSpace + * namespace for supported color spaces. + * + * If this object doesn't transport an ICC profile, this function returns + * ICCColorSpace::Unknown. + */ + color_space ColorSpace() const; + + /*! + * Returns true iff this object stores an RGB ICC profile. + */ + bool IsRGB() const + { + return ColorSpace() == ICCColorSpace::RGB; + } + + /*! + * Returns true iff this object stores a grayscale ICC profile. + */ + bool IsGrayscale() const + { + return ColorSpace() == ICCColorSpace::Gray; + } + + /*! + * Returns true iff this object stores an ICC profile that supports the + * specified \a intent in the specified transform \a direction. See the + * ICCRenderingIntent and ICCRenderingDirection namespaces, respectively, + * for supported rendering intents and directions. + */ + bool SupportsRenderingIntent( rendering_intent intent, rendering_direction direction ) const; + + /*! + * Returns true iff this object stores an embedded ICC profile. + * + * An embedded ICC profile must have the Embedded Profile bit field + * (bit #0 of header byte #44) set. + */ + bool IsEmbedded() const; + + /*! + * Sets or clears the Embedded Profile header bit field (bit #0 of + * header byte #44) of the stored ICC profile. + * + * \note If this %ICCProfile object is being used to embed an ICC profile in + * an image file, the Embedded Profile flag must be set before + * embedding. + */ + void SetEmbeddedFlag( bool on = true ); + + /*! + * Clears or sets the Embedded Profile header bit field (bit #0 of + * header byte #44) of the stored ICC profile. + * + * This is a convenience member function, equivalent to + * SetEmbeddedFlag( false ) + */ + void ClearEmbeddedFlag() + { + SetEmbeddedFlag( false ); + } + + /*! + * Loads an ICC profile from a disk file at \a profilePath and stores it in + * this %ICCProfile object. + * + * If this object stores an ICC profile before calling this function, it is + * deallocated upon successful load of the specified ICC profile. + * + * If the specified file does not exist or is not readable, or if the file + * contains data that cannot be identified as a valid ICC profile, this + * function throws an Error exception. + */ + void Load( const String& profilePath ); + + /*! + * Forces this %ICCProfile object to store a copy of the ICC profile stored + * in the specified ByteArray container. Previously existing ICC profile + * data will be deallocated. + * + * If the specified container is empty, calling this function is equivalent + * to Clear(). If the container is not empty, it must store a valid ICC + * profile structure; otherwise this function will throw an Error exception. + */ + void Set( const ByteArray& profile ); + + /*! + * Forces this %ICCProfile object to store a copy of the raw ICC profile + * data at the specified location. Previously existing ICC profile data will + * be deallocated. + * + * The specified pointer must be the starting address of a valid ICC profile + * structure; otherwise this function will throw an Error exception. + */ + void Set( const void* rawData ); + + /*! + * Deallocates the stored ICC profile structure and all auxiliary data. + * + * If the profile has been opened before calling this function, any existing + * handle to it will not be closed or invalidated. + */ + void Clear() + { + m_data.Clear(); + m_path.Clear(); + } + + /*! + * Opens the ICC profile stored in this %ICCProfile object. Returns a handle + * to the opened ICC profile. + * + * If this object does not transport a valid ICC profile structure, this + * function throws an Error exception. + * + * Color management transformations are defined through handles to open ICC + * profiles. The caller is responsible for closing ICC profile handles when + * they are no longer needed. + */ + handle Open() const + { + return Open( m_data ); + } + + /*! + * Exchanges two ICC profiles \a x1 and \a x2. + */ + friend void Swap( ICCProfile& x1, ICCProfile& x2 ) + { + pcl::Swap( x1.m_data, x2.m_data ); + pcl::Swap( x1.m_path, x2.m_path ); + } + + /*! + * Opens an ICC profile disk file at \a profilePath. Returns a handle to the + * opened ICC profile. + * + * If the specified file does not exist or is not readable, or if it does + * not contain a valid ICC profile structure, this function throws an Error + * exception. + */ + static handle Open( const String& profilePath ); + + /*! + * Opens an ICC profile from raw ICC profile data stored at the specified + * location. Returns a handle to the opened ICC profile. + * + * If the argument does not point to a valid ICC profile structure, this + * function throws an Error exception. + */ + static handle Open( const void* rawData ); + + /*! + * Opens an ICC profile stored in the specified ByteArray container \a icc. + * Returns a handle to the opened ICC profile. + * + * If the specified container is empty or does not contain a valid ICC + * profile structure, this function throws an Error exception. + */ + static handle Open( const ByteArray& icc ) + { + return Open( icc.Begin() ); + } + + /*! + * Closes an open ICC profile handle. + */ + static void Close( handle h ); + + /*! + * Validates an ICC profile handle. Returns true iff the specified handle is + * a valid handle to an open ICC profile. + */ + static bool IsValidHandle( handle h ); + + /*! + * Validates an ICC profile structure stored in a file at \a profilePath. + * Returns true iff the specified file exists and contains a valid ICC + * profile. + */ + static bool IsValidFile( const String& profilePath ); + + /*! + * Validates an ICC profile from raw ICC profile data stored at the + * specified location. Returns true iff the argument points to a valid ICC + * profile structure. + */ + static bool IsValid( const void* rawdata ); + + /*! + * Validates an ICC profile structure stored in the specified ByteArray + * container \a icc. Returns true iff the container stores a valid ICC + * profile. + */ + static bool IsValid( const ByteArray& icc ) + { + return IsValid( icc.Begin() ); + } + + /*! + * Returns the localized profile description of an open ICC profile. + * + * \param h Handle to an open ICC profile, from which the requested + * profile description will be obtained. + * + * \param language Optional language code (ISO 639/2) of the requested + * profile description. The default value is "en" for + * English. + * + * \param country Optional country code (ISO 3166) of the requested + * profile description. The default value is "US" for the + * United States. + * + * This routine will always return a valid profile description, even if no + * localized version is available for the requested language and country. + * The returned description will be as close as possible to the requested + * localization. + */ + static String Description( handle h, const char* language = "en", const char* country = "US" ); + + /*! + * Returns the localized manufacturer information of an open ICC profile. + * + * See Description( handle, const char*, const char* ) for detailed + * information on function parameters and behavior. + */ + static String Manufacturer( handle h, const char* language = "en", const char* country = "US" ); + + /*! + * Returns the localized device model information of an open ICC profile. + * + * See Description( handle, const char*, const char* ) for detailed + * information on function parameters and behavior. + */ + static String Model( handle h, const char* language = "en", const char* country = "US" ); + + /*! + * Returns the localized copyright information of an open ICC profile. + * + * See Description( handle, const char*, const char* ) for detailed + * information on function parameters and behavior. + */ + static String Copyright( handle h, const char* language = "en", const char* country = "US" ); + + /*! + * Returns the ICC profile class of an open profile. See the ICCProfileClass + * namespace for supported profile classes. + */ + static profile_class Class( handle h ); + + /*! + * Returns the ICC color space of an open profile. See the ICCColorSpace + * namespace for supported color spaces. + */ + static color_space ColorSpace( handle h ); + + /*! + * Returns true iff an open profile supports the specified \a intent in the + * specified transform \a direction. See the ICCRenderingIntent and + * ICCRenderingDirection namespaces, respectively, for supported rendering + * intents and directions. + */ + static bool SupportsRenderingIntent( handle h, rendering_intent intent, rendering_direction direction ); + + /*! + * Returns the list of profile directories. + * + * The profile directories contain the ICC profiles currently installed in + * the system. The specific directories provided by this function are + * platform-dependent. + * + * On X11 Linux and FreeBSD, there is no universally standardized color + * management system. By default, the returned list will include a single + * directory that can be one of the following: + * + * /usr/share/color/icc + * ~/.color/icc + * + * for system-wide or user-local profiles, respectively. If none of the + * above directories exists (and is readable) on the local filesystem, the + * routine will return a fallback directory within the installation + * directory tree of the PixInsight core application. + * + * On OS X, the returned list may contain one or more from the following + * directories: + * + * ~/Library/ColorSync/Profiles + * /Library/ColorSync/Profiles + * /Network/Library/ColorSync/Profiles + * + * Finally, on Windows this function returns the current COLOR directory, + * as reported by the GetColorDirectory() Win32 API function. + */ + static StringList ProfileDirectories(); + + /*! + * Gets a list of full paths for every ICC profile on a given directory. + * + * \param dirPath Optional path to a search directory. If no directory is + * specified, or if an empty string is passed, the whole + * list of system profile directories, as returned by the + * ProfileDirectories() member function, will be searched + * recursively. + * + * This routine performs a recursive directory search on the specified + * directory, or on each system profiles directory if no directory is + * specified. Profiles are quickly identified by opening them and validating + * their profile headers. The search is not limited to any particular file + * suffix such as ".icc" or ".icm". + * + * Returns a list of full paths to the ICC profile files found on the + * search directory. + */ + static StringList FindProfiles( const String& dirPath = String() ); + + /*! + * Finds the file path to an installed ICC profile, given its profile + * description. + * + * \param description Description of the profile to search for. + * + * \param exactMatch If true, this routine will search for a profile that + * matches the specified \a description exactly, including + * character case. If false, the routine will report any + * profile whose description contains the specified + * description performing case-insensitive comparisons. + * The default value is true, so profile descriptions must + * be matched exactly by default. + * + * This function searches the system color directories, as reported by the + * ProfileDirectories() member function, until it finds an ICC profile with + * the specified \a description. This routine performs a recursive directory + * search on each profiles directory. + * + * Returns the full path to the ICC profile, or an empty string if no + * profile was found matching the specified \a description. + */ + static String FindInstalledProfile( const String& description, bool exactMatch = true ); + + /*! + * Extracts a subset of profile paths and their descriptions from a + * previously retrieved list of full paths to ICC profiles. + * + * \param[out] selectedDescriptionsList The list of profile descriptions + * for selected profiles. + * + * \param[out] selectedPathsList The list of paths to selected profiles. + * + * \param pathList The input list of paths to ICC profiles. + * + * \param spaces A combination of ICC color spaces for selected ICC + * profiles. + * + * \param classes A combination of ICC device classes for selected ICC + * profiles. + */ + static void ExtractProfileList( StringList& selectedDescriptionsList, + StringList& selectedPathsList, + const StringList& pathList, + ICCColorSpaces spaces = ICCColorSpace::Any, + ICCProfileClasses classes = ICCProfileClass::Any ); + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::ICCProfile::Info + * \brief A structure to hold descriptive data about ICC profiles. + * \ingroup color_management + * + * The %ICCProfile::Info structure is designed to be used with the + * ICCProfile::FindProfilesByColorSpace() utility function. + */ + struct Info + { + String description; //!< Description of an ICC profile + String path; //!< Full path to an ICC profile disk file + + /*! + * Constructs an %ICCProfile::Info structure. + */ + Info( const String& a_description, const String& a_path = String() ) + : description( a_description ) + , path( a_path ) + { + } + + /*! + * Equality operator. Two %ICCProfile::Info objects are equal if their + * profile descriptions are equal. + */ + bool operator ==( const Info& x ) const + { + return description == x.description; + } + + /*! + * Less than relational operator. %ICCProfile::Info objects are sorted by + * their profile descriptions + */ + bool operator <( const Info& x ) const + { + return description < x.description; + } + }; + + /*! + * Represents a sorted list of ICC profile information items. + */ + typedef SortedArray profile_list; + + /*! + * Returns a sorted list of profile information items (full file paths and + * profile description strings) for the existing ICC profiles of the + * specified ICC profile color spaces. + * + * \param spaces A combination of ICC profile color spaces to search for. + * + * The search operation is restricted to the system color directories, as + * reported by the ProfileDirectories() member function. This routine + * performs a recursive directory search on each profiles directory. + * + * Duplicate profiles are not included in the output \a info list. If the + * same profile is present in two or more directories, or if the same + * profile is present on the same directory with different file names, only + * the first instance seen will be included. Profiles are compared by their + * profile descriptions. + */ + static profile_list FindProfilesByColorSpace( ICCColorSpaces spaces ); + + /*! + * \internal + */ + static void ThrowErrorWithCMSInfo( const String& message ); + +private: + + ByteArray m_data; // ICC profile data + String m_path; // empty if this is an embedded or newly created profile +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ICCProfile_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ICCProfile.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ICCProfileTransformation.h b/3rdparty/include/pcl/ICCProfileTransformation.h new file mode 100644 index 0000000..7e93dd0 --- /dev/null +++ b/3rdparty/include/pcl/ICCProfileTransformation.h @@ -0,0 +1,691 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ICCProfileTransformation.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_ICCProfileTransformation_h +#define __PCL_ICCProfileTransformation_h + +/// \file pcl/ICCProfileTransformation.h + +#include + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ + class ImageWindow; +} // pi +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ICCProfileTransformation + * \brief Conversion of pixel values between ICC profile color spaces + * + * %ICCProfileTransformation is a portable color transformation based on ICC + * color profiles. This class is a high-level interface to the color management + * functionality implemented in the PixInsight core application. + * + * %ICCProfileTransformation implements simple profile-to-profile color + * transformations, multiprofile transformations, and device proofing + * transformations with out-of-gamut checks. + * + * \ingroup color_management + * \sa ICCProfile, ImageTransformation + */ +class PCL_CLASS ICCProfileTransformation : public ImageTransformation, public ParallelProcess +{ +public: + + /*! + * Represents an ICC rendering intent. + */ + typedef ICCRenderingIntent::value_type rendering_intent; + + /*! + * Represents an opaque handle to a server-side ICC transformation. + */ + typedef void* transformation_handle; + + /*! + * Represents a list of handles to open ICC profiles. + */ + typedef Array profile_list; + + /*! + * Constructs an empty %ICCPRofileTransformation object. + */ + ICCProfileTransformation() = default; + + /*! + * Move constructor. + */ + ICCProfileTransformation( ICCProfileTransformation&& x ) + : ImageTransformation( x ) + , ParallelProcess( x ) + , m_transformation( x.m_transformation ) + , m_profiles( std::move( x.m_profiles ) ) + , m_intent( x.m_intent ) + , m_proofingIntent( x.m_proofingIntent ) + , m_blackPointCompensation( x.m_blackPointCompensation ) + , m_forceFloatingPoint( x.m_forceFloatingPoint ) + , m_highResolutionCLUT( x.m_highResolutionCLUT ) + , m_lowResolutionCLUT( x.m_lowResolutionCLUT ) + , m_proofingTransformation( x.m_proofingTransformation ) + , m_gamutCheck( x.m_gamutCheck ) + , m_srcRGB( x.m_srcRGB ) + , m_dstRGB( x.m_dstRGB ) + , m_floatingPoint( x.m_floatingPoint ) + { + x.m_transformation = nullptr; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ICCProfileTransformation& operator =( ICCProfileTransformation&& x ) + { + (void)ImageTransformation::operator =( x ); + (void)ParallelProcess::operator =( x ); + m_transformation = x.m_transformation; + m_profiles = std::move( x.m_profiles ); + m_intent = x.m_intent; + m_proofingIntent = x.m_proofingIntent; + m_blackPointCompensation = x.m_blackPointCompensation; + m_forceFloatingPoint = x.m_forceFloatingPoint; + m_highResolutionCLUT = x.m_highResolutionCLUT; + m_lowResolutionCLUT = x.m_lowResolutionCLUT; + m_proofingTransformation = x.m_proofingTransformation; + m_gamutCheck = x.m_gamutCheck; + m_srcRGB = x.m_srcRGB; + m_dstRGB = x.m_dstRGB; + m_floatingPoint = x.m_floatingPoint; + x.m_transformation = nullptr; + return *this; + } + + /*! + * Copy constructor. This constructor is disabled because ICC color profile + * transformations are unique objects. + */ + ICCProfileTransformation( const ICCProfileTransformation& ) = delete; + + /*! + * Copy assignment. This operator is disabled because ICC color profile + * transformations are unique objects. + */ + ICCProfileTransformation& operator =( const ICCProfileTransformation& ) = delete; + + /*! + * Destroys an %ICCPRofileTransformation object. + */ + virtual ~ICCProfileTransformation() + { + Clear(); + } + + /*! + * Loads an ICC profile from a file at \a profilePath and adds it to this + * ICC profile transformation. + */ + void Add( const String& profilePath ); + + /*! + * Adds the specified ICC \a profile to this ICC profile transformation. + */ + void Add( const ICCProfile& profile ); + + /*! + * Adds an already open ICC profile \a profileHandle to this ICC profile + * transformation. + */ + void Add( const ICCProfile::handle profileHandle ); + + /*! + * Returns true iff this object represents a valid color space transformation + * based on ICC color profiles. + * + * For this member function to return true, the underlying low-level + * transformation should have been created, either implicitly by using + * this object to apply a color transformation, or explicitly by calling + * Create(). + */ + bool IsValid() const + { + return m_transformation != nullptr; + } + + /*! + * Returns a reference to the immutable list of ICC profiles in this ICC + * profile transformation. + */ + const profile_list& Profiles() const + { + return m_profiles; + } + + /*! + * Returns the ICC rendering intent for this ICC profile transformation. + */ + rendering_intent RenderingIntent() const + { + return m_intent; + } + + /*! + * Sets the ICC rendering intent for this ICC profile transformation. + * + * When no intent is set explicitly with this function, the default + * rendering intent is ICCRenderingIntent::Perceptual. + */ + void SetRenderingIntent( rendering_intent i ) + { + CloseTransformation(); + m_intent = i; + } + + /*! + * Returns true iff this ICC profile transformation applies a black point + * compensation algorithm. + */ + bool UsingBlackPointCompensation() const + { + return m_blackPointCompensation; + } + + /*! + * Enables or disables black point compensation for this ICC + * profile transformation. + * + * When not enabled explicitly with this function, no black point + * compensation is applied by default. + */ + void EnableBlackPointCompensation( bool enable = true ) + { + CloseTransformation(); + m_blackPointCompensation = enable; + } + + /*! + * Disables or enables black point compensation for this ICC + * profile transformation. + * + * This is a convenience member function, equivalent to + * EnableBlackPointCompensation( !disable ) + */ + void DisableBlackPointCompensation( bool disable = true ) + { + EnableBlackPointCompensation( !disable ); + } + + /*! + * Returns true iff this ICC profile transformation forces the use of + * floating point operations for computation of transformed pixel samples of + * all numerical data types. + * + * When this option is disabled (which is its default state), 16-bit integer + * arithmetics will be used for 8-bit and 16-bit integer images. Floating + * point will always be used for the rest of images, irrespective of the + * state of this option, in order to preserve numerical accuracy. + */ + bool ForcesFloatingPointTransformation() const + { + return m_forceFloatingPoint; + } + + /*! + * Enables or disables enforcement of floating point computations for this + * ICC profile transformation. + */ + void ForceFloatingPointTransformation( bool force = true ) + { + CloseTransformation(); + m_forceFloatingPoint = force; + } + + /*! + * Disables or enables enforcement of floating point computations for this + * ICC profile transformation. + * + * This is a convenience member function, equivalent to + * ForceFloatingPointTransformation( !relax ) + */ + void RelaxFloatingPointTransformation( bool relax = true ) + { + ForceFloatingPointTransformation( !relax ); + } + + /*! + * Returns true iff this ICC profile transformation uses high-resolution + * color lookup tables (CLUTs) for precalculation of device link functions. + * + * Disabling high-resolution CLUTs may provide a (usually small) speed + * improvement. + * + * By default, %ICCProfileTransformation uses high-resolution CLUTs. + */ + bool UsingHighResolutionCLUT() const + { + return m_highResolutionCLUT; + } + + /*! + * Enables or disables usage of high-resolution CLUT tables for this ICC + * profile transformation. + */ + void EnableHighResolutionCLUT( bool enable = true ) + { + CloseTransformation(); + if ( (m_highResolutionCLUT = enable) == true ) + m_lowResolutionCLUT = false; + } + + /*! + * Disables or enables usage of high-resolution CLUT tables for this ICC + * profile transformation. + * + * This is a convenience member function, equivalent to + * EnableHighResolutionCLUT( !disable ) + */ + void DisableHighResolutionCLUT( bool disable = true ) + { + EnableHighResolutionCLUT( !disable ); + } + + /*! + * Returns true iff this ICC profile transformation uses low-resolution color + * lookup tables (CLUTs) for precalculation of device link functions. + * + * Enabling low-resolution CLUTs may provide a (usually small) speed + * improvement. + * + * By default, %ICCProfileTransformation uses high-resolution CLUTs. + */ + bool UsingLowResolutionCLUT() const + { + return m_lowResolutionCLUT; + } + + /*! + * Enables or disables usage of low-resolution color lookup tables (CLUTs) + * in this ICC color transformation. + */ + void EnableLowResolutionCLUT( bool enable = true ) + { + CloseTransformation(); + if ( (m_lowResolutionCLUT = enable) == true ) + m_highResolutionCLUT = false; + } + + /*! + * Disables or enables usage of low-resolution color lookup tables (CLUTs) + * in this ICC color transformation. + * + * This is a convenience member function, equivalent to + * EnableLowResolutionCLUT( !disable ) + */ + void DisableLowResolutionCLUT( bool disable = true ) + { + EnableLowResolutionCLUT( !disable ); + } + + /*! + * Returns true iff this object represents a device proofing transformation. + */ + bool IsProofingTransformation() const + { + return m_proofingTransformation; + } + + /*! + * Forces the immediate creation (or re-creation) of the underlying + * low-level transformation. + * + * You normally shouldn't need to call this member function, since + * %ICCProfileTransformation automatically creates the necessary low-level + * transformations at the points they are required. + */ + void Create() + { + CreateTransformation( m_forceFloatingPoint ); + } + + /*! + * \internal + * Returns the low-level handle that this %ICCProfileTransformation object + * serves as a high-level interface to. + * + * This function is intended for private use of the PixInsight core + * application; you normally shouldn't need to call it. + */ + transformation_handle Handle() const + { + return m_transformation; + } + + /*! + * Resets this %ICCProfileTransformation object to a default state. + * + * The list of ICC profiles is cleared and the underlying transformation and + * all associated data structures are destroyed. + */ + void Clear(); + + /*! + * Returns true iff the starting ICC profile in this transformation is a RGB + * profile. + */ + bool IsSourceRGBProfile() const + { + return m_srcRGB; + } + + /*! + * Returns true iff the target (last) ICC profile in this transformation is a + * RGB profile. + */ + bool IsTargetRGBProfile() const + { + return m_dstRGB; + } + +protected: + + /* + * Opaque handle to the profile transformation. + */ + mutable transformation_handle m_transformation = nullptr; + + /* + * The ICC profiles, rendering intents and operating parameters that define + * this color transformation. + */ + profile_list m_profiles; + rendering_intent m_intent = ICCRenderingIntent::Perceptual; + rendering_intent m_proofingIntent = ICCRenderingIntent::AbsoluteColorimetric; + bool m_blackPointCompensation = false; + bool m_forceFloatingPoint = false; + bool m_highResolutionCLUT = true; + bool m_lowResolutionCLUT = false; + bool m_proofingTransformation = false; + bool m_gamutCheck = false; + + /* + * Flags indicating source and destination color spaces. + * ### NB: These refer to the color spaces of the source and target pixel + * buffers, *not* to the color spaces of the profiles involved in the + * transformation. + */ + mutable bool m_srcRGB = false; + mutable bool m_dstRGB = false; + + /* + * Flag indicating whether the current transformation (if any) has been + * created forcing floating point arithmetics. + */ + mutable bool m_floatingPoint = false; + + void AddAt( size_type, const String& ); + void AddAt( size_type, const ICCProfile& ); + void AddAt( size_type, const ICCProfile::handle ); + void AddOrReplaceAt( size_type i, const ICCProfile::handle ); + + void CreateTransformation( bool ) const; + void CloseTransformation() const; + + // Inherited from ImageTransformation + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ICCProofingTransformation + * \brief A soft proofing ICC profile transformation + * + * %ICCProofingTransformation implements a device proofing + * transformation. This kind of color transformation allows previewing of + * the final results that would be obtained on a specific proofing + * device without actually performing any rendition on physical media. + * + * A device proofing transformation uses three ICC profiles: a source + * profile, a proofing profile, and a target profile. In + * a typical scenario, the proofing device is a printer and we want to proof it + * on a display monitor. In this common case we have: + * + * Source profile = The ICC profile describing the color space to which source + * pixel values are referred. + * + * Proofing profile = The ICC profile describing the device where the final + * result will be obtained (usually a printer). + * + * Target profile = The ICC profile describing the display device where we'll + * preview the result (usually a monitor). + * + * \ingroup color_management + * \sa ICCProfileTransformation, ICCProfile + */ +class PCL_CLASS ICCProofingTransformation : public ICCProfileTransformation +{ +public: + + /*! + * Constructs a default %ICCProofingTransformation object. + */ + ICCProofingTransformation() + { + m_proofingTransformation = true; + m_profiles.Add( static_cast( nullptr ), 3 ); + } + + /*! + * Move constructor. + */ + ICCProofingTransformation( ICCProofingTransformation&& ) = default; + + /*! + * Destroys an %ICCProofingTransformation object. + */ + virtual ~ICCProofingTransformation() + { + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ICCProofingTransformation& operator =( ICCProofingTransformation&& ) = default; + + /*! + * Loads an ICC profile from a file at \a profilePath and selects it as the + * profile describing the source color space in this transformation. + */ + void SetSourceProfile( const String& profilePath ); + + /*! + * Selects the specified ICC \a profile as the profile describing the source + * color space in this transformation. + */ + void SetSourceProfile( const ICCProfile& profile ); + + /*! + * Selects an already open ICC profile \a profileHandle as the profile + * describing the source color space in this transformation. + */ + void SetSourceProfile( const ICCProfile::handle profileHandle ); + + /*! + * Loads an ICC profile from a file at \a profilePath and selects it as the + * profile describing the proofing device in this transformation. + */ + void SetProofingProfile( const String& profilePath ); + + /*! + * Selects the specified ICC \a profile as the profile describing the + * proofing device in this transformation. + */ + void SetProofingProfile( const ICCProfile& profile ); + + /*! + * Selects an already open ICC profile \a profileHandle as the profile + * describing the proofing device in this transformation. + */ + void SetProofingProfile( const ICCProfile::handle profileHandle ); + + /*! + * Loads an ICC profile from a file at \a profilePath and selects it as the + * profile describing the target (output) color space in this + * transformation. + */ + void SetTargetProfile( const String& profilePath ); + + /*! + * Selects the specified ICC \a profile as the profile describing the target + * (output) color space in this transformation. + */ + void SetTargetProfile( const ICCProfile& profile ); + + /*! + * Selects an already open ICC profile \a profileHandle as the profile + * describing the target (output) color space in this transformation. + */ + void SetTargetProfile( const ICCProfile::handle profileHandle ); + + /*! + * Returns the proofing rendering intent for this ICC proofing + * transformation. + */ + rendering_intent ProofingIntent() const + { + return m_intent; + } + + /*! + * Sets the proofing rendering intent for this ICC proofing transformation. + * + * The default proofing intent is ICCRenderingIntent::AbsoluteColorimetric. + */ + void SetProofingIntent( rendering_intent i ) + { + CloseTransformation(); + m_proofingIntent = i; + } + + /*! + * Returns true iff gamut checking has been enabled for this color + * transformation. When gamut check is enabled, out-of-gamut colors in the + * final rendition are automatically replaced by the current gamut + * warning color (see the SetGamutWarningColor() member function). + */ + bool IsGamutCheckEnabled() const + { + return m_gamutCheck; + } + + /*! + * Enables or disables gamut check for this color transformation. + */ + void EnableGamutCheck( bool enable = true ) + { + CloseTransformation(); + m_gamutCheck = enable; + } + + /*! + * Disables or enables gamut check for this color transformation. + */ + void DisableGamutCheck( bool disable = true ) + { + EnableGamutCheck( !disable ); + } + + /*! + * Returns the current gamut warning color used to represent + * out-of-gamut pixel values in final proofing renditions. The returned + * value is a 32-bit RGBA pixel value. + */ + static RGBA GamutWarningColor(); + + /*! + * Specifies the special RGB color used to represent out-of-gamut pixel + * values in final proofing renditions. Only used for proofing + * transformations with gamut check enabled. + * + * \param color Gamut warning color encoded as a 32-bit RGBA pixel value. + * + * Note that since this is a static member function, the current gamut + * warning color is a global setting that affects all proofing + * transformations performed by the calling module. + */ + static void SetGamutWarningColor( RGBA color ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ICCProfileTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ICCProfileTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Image.h b/3rdparty/include/pcl/Image.h new file mode 100644 index 0000000..4875882 --- /dev/null +++ b/3rdparty/include/pcl/Image.h @@ -0,0 +1,17817 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Image.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_Image_h +#define __PCL_Image_h + +/// \file pcl/Image.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __PCL_IMAGE_NO_BITMAP +# ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +# ifndef __PI_Bitmap_h +# include // using server-side bitmaps +# endif +using namespace pi; +# else +# ifndef __PCL_Bitmap_h +# include // using client-side bitmaps +# endif +# endif +# ifndef __PCL_Color_h +# include // for RGBA +# endif +#endif + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ + class SharedImage; +} +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ImageOp + * \brief Arithmetic, bitwise logical and pixel composition operations. + * + * Supported operations: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ImageOp::Nop No operation
ImageOp::Mov Copy pixels
ImageOp::Add Add
ImageOp::Sub Subtract
ImageOp::Mul Multiply
ImageOp::Div Divide
ImageOp::Pow Raise
ImageOp::Dif Absolute difference
ImageOp::Min Minimum value
ImageOp::Max Maximum value
ImageOp::Or Bitwise OR (inclusive OR)
ImageOp::And Bitwise AND
ImageOp::Xor Bitwise XOR (exclusive OR)
ImageOp::Not Bitwise NOT
ImageOp::Nor Bitwise NOR (inclusive NOR)
ImageOp::Nand Bitwise NAND
ImageOp::Xnor Bitwise XNOR (exclusive NOR)
ImageOp::ColorBurn Color burn pixel composition operator
ImageOp::LinearBurn Linear burn pixel composition operator
ImageOp::Screen Screen pixel composition operator
ImageOp::ColorDodge Color dodge pixel composition operator
ImageOp::Overlay Overlay pixel composition operator
ImageOp::SoftLight Soft light pixel composition operator
ImageOp::HardLight Hard light pixel composition operator
ImageOp::VividLight Vivid light pixel composition operator
ImageOp::LinearLight Linear light pixel composition operator
ImageOp::PinLight Pin light pixel composition operator
ImageOp::Exclusion Exclusion pixel composition operator
+ */ +namespace ImageOp +{ + enum value_type + { + Nop, // No operation + Mov, // a = b + Add, // a + b + Sub, // a - b + Mul, // a * b + Div, // a / b + Pow, // Pow( a, b ) + Dif, // |a - b| + Min, // Min( a, b ) + Max, // Max( a, b ) + Or, // a | b + And, // a & b + Xor, // a ^ b + Not, // ~a + Nor, // ~(a | b) + Nand, // ~(a & b) + Xnor, // ~(a ^ b) + ColorBurn, // 1 - Min( (1 - a)/b, 1 ) + LinearBurn, // a + b - 1 + Screen, // 1 - (1 - a)*(1 - b) + ColorDodge, // Min( a/(1 - b), 1 ) + Overlay, // (a > 0.5) ? 1 - ((1 - 2*(a - 0.5)) * (1 - b)) : 2*a*b + SoftLight, // (b > 0.5) ? 1 - (1 - a)*(1 - b - 0.5) : a*(b + 0.5) + HardLight, // (b > 0.5) ? 1 - (1 - a)*(1 - 2*(b - 0.5)) : 2*a*b + VividLight, // (b > 0.5) ? 1 - Max( (1 - a)/(b - 0.5)/2, 1.0 ) : Min( a/(1 - 2*b ), 1.0 ) + LinearLight, // (b > 0.5) ? Max( a + 2*(b - 0.5), 1.0 ) : Max( a + 2*b - 1, 1.0 ) + PinLight, // (b > 0.5) ? Max( a, 2*(b - 0.5) ) : Min( a, 2*b ) + Exclusion, // 0.5 - 2*(a - 0.5)*(b - 0.5) + NumberOfOperators + }; + + /*! + * Returns true iff the specified operator \a op is an arithmetic operator. + */ + inline bool IsArithmeticOperator( int op ) noexcept + { + return op >= Add && op <= Dif; + } + + /*! + * Returns true iff the specified operator \a op is a bitwise logical + * operator. + */ + inline bool IsBitwiseLogicalOperator( int op ) noexcept + { + return op >= Or && op <= Xnor; + } + + /*! + * Returns true iff the specified operator \a op is a move or replace + * operator. + */ + inline bool IsMoveOperator( int op ) noexcept + { + return op == Mov || op == Min || op == Max; + } + + /*! + * Returns true iff the specified operator \a op is a pixel composition + * operator. + */ + inline bool IsPixelCompositionOperator( int op ) noexcept + { + return op >= ColorBurn && op <= Exclusion; + } + + /*! + * Returns a string with the name of a pixel \a operation. + */ + String Id( value_type operation ); +} + +// ---------------------------------------------------------------------------- + +#define m_pixelData m_data->data +#define m_channelData( c ) reinterpret_cast( PCL_ASSUME_ALIGNED_32( m_pixelData[c] ) ) +#define m_allocator m_data->allocator + +#define m_width m_geometry->width +#define m_height m_geometry->height +#define m_numberOfChannels m_geometry->numberOfChannels + +#define m_colorSpace m_color->colorSpace +#define m_RGBWS m_color->RGBWS + +#define m_channel m_selected.channel +#define m_lastChannel m_selected.lastChannel +#define m_point m_selected.point +#define m_rectangle m_selected.rectangle +#define m_clipLow m_selected.clipLow +#define m_clipHigh m_selected.clipHigh +#define m_clippedLow m_selected.clippedLow +#define m_clippedHigh m_selected.clippedHigh + +// ---------------------------------------------------------------------------- + +class PCL_CLASS ImageVariant; +class PCL_CLASS ImageTransformation; +class PCL_CLASS BidirectionalImageTransformation; + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericImage + * \brief Implements a generic, two-dimensional, shared or local image. + * + * Template class %GenericImage implements a two-dimensional image in PCL. It + * inherits all public properties and functionality from its base classes: + * ImageGeometry, ImageColor, and AbstractImage, and adds a rich set of + * processing primitives through a versatile and easily adaptable interface. + * + * Template instantiations of %GenericImage and GenericPixelTraits provide + * instantiable image classes adapted to particular pixel sample types. Seven + * image types are already predefined in this way by PCL, corresponding to all + * supported real, integer and complex two-dimensional images in the current + * versions of the PixInsight platform: + * + * + * + * + * + * + * + * + * + *
pcl::Image 32-bit floating point real image
pcl::DImage 64-bit floating point real image
pcl::ComplexImage 32-bit floating point complex image
pcl::DComplexImage 64-bit floating point complex image
pcl::UInt8Image 8-bit unsigned integer image
pcl::UInt16Image 16-bit unsigned integer image
pcl::UInt32Image 32-bit unsigned integer image
+ * + * Developers can define new image types easily by writing suitable + * instantiations of GenericPixelTraits and the corresponding instantiations of + * %GenericImage. This system allows for the implementation of new image types + * tightly adapted to particular requirements. + * + * \sa \ref image_types_2d "2-D Image Types", + * \ref image_iterators "Image Iterators", ImageGeometry, ImageColor, + * AbstractImage, ImageVariant, GenericPixelTraits + */ +template +class PCL_CLASS GenericImage : public AbstractImage +{ +public: + + /*! + * Represents the GenericPixelTraits instantiation used in this template + * instantiation of %GenericImage. + * + * The \c pixel_traits type identifies a class implementing basic storage + * and functional primitives adapted to a particular sample data type. + */ + typedef P pixel_traits; + + /*! + * Represents a class responsible for allocation and deallocation of pixel + * data in this template instantiation of %GenericImage. \c pixel_allocator + * must be able to handle shared and local pixel data allocation and + * deallocation in a transparent way. + * + * By default, %GenericImage uses an instantiation of the PixelAllocator + * template class for \c pixel_traits. + */ + typedef PixelAllocator

pixel_allocator; + + /*! + * Represents the data type used to store pixel sample values in this + * template instantiation of %GenericImage. + */ + typedef typename pixel_traits::sample sample; + + /*! + * An enumerated type that represents the set of supported color spaces. + * Valid constants for this enumeration are defined in the ColorSpace + * namespace. + */ + typedef AbstractImage::color_space color_space; + + /*! + * The type of a container class used to store rectangular and channel range + * selections. + */ + typedef AbstractImage::selection_stack selection_stack; + + /*! + * An enumerated type that represents the set of supported arithmetic and + * bitwise pixel operations. Valid constants for this enumeration are + * defined in the ImageOp namespace. + */ + typedef ImageOp::value_type image_op; + + /*! + * A vector of pixel sample values. + */ + typedef GenericVector sample_vector; + + /*! + * A dynamic array of pixel sample values. + */ + typedef Array sample_array; + + // ------------------------------------------------------------------------- + + /*! + * \defgroup image_iterators Image Iterator Classes + */ + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::sample_iterator + * \brief Mutable pixel sample iterator. + * + * A mutable pixel sample iterator provides read/write, random access to + * pixel samples in a single channel of an image. + * + * \ingroup image_iterators + */ + class sample_iterator + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + sample_iterator() = default; + + /*! + * Constructs a mutable pixel sample iterator for one channel of an + * image. + * + * \param image The image to iterate. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + sample_iterator( image_type& image, int channel = -1 ) + : m_image( &image ) + { + m_image->EnsureUnique(); + if ( m_image->ParseChannel( channel ) ) + { + m_iterator = (*m_image)[channel]; + m_end = m_iterator + m_image->NumberOfPixels(); + } + } + + /*! + * Constructs a mutable pixel sample iterator for a range of contiguous + * pixel samples of an image. + * + * \param image The image to iterate. + * + * \param i Pointer to the first pixel sample in the iteration + * range. The iterator will be initialized to access this + * pixel sample just after construction. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to pixel + * samples in the \e same channel of the specified \a image. + */ + sample_iterator( image_type& image, sample* i, sample* j ) + : m_image( &image ) + , m_iterator( i ) + , m_end( j ) + { + } + + /*! + * Copy constructor. + */ + sample_iterator( const sample_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + sample_iterator& operator =( const sample_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return m_image != nullptr && m_iterator != nullptr; + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *m_image; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator. + */ + sample* Position() const noexcept + { + return m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel sample iterator is active if it has not reached (or + * surpassed) its iteration limit: either the end of the iterated image + * channel, or the end of the iteration range, depending on how the + * iterator has been constructed. + */ + operator bool() const noexcept + { + return m_iterator < m_end; + } + + /*! + * Indirection operator. Returns a reference to the pixel sample pointed + * to by this iterator. + */ + sample& operator *() const noexcept + { + return *m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated image channel. Returns a reference to + * this iterator. + */ + sample_iterator& operator ++() noexcept + { + ++m_iterator; + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated image channel. Returns a copy of the + * iterator as it was before incrementing it. + */ + sample_iterator operator ++( int ) noexcept + { + return sample_iterator( *m_image, m_iterator++, m_end ); + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated image channel, then returns a reference + * to this iterator. + */ + sample_iterator& operator --() noexcept + { + --m_iterator; + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated image channel. Returns a copy of the + * iterator as it was before decrementing it. + */ + sample_iterator operator --( int ) noexcept + { + return sample_iterator( *m_image, m_iterator--, m_end ); + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixel samples. Negative + * increments move this iterator backward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + sample_iterator& operator +=( distance_type delta ) noexcept + { + m_iterator += delta; + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixel samples. Negative + * increments move this iterator forward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + sample_iterator& operator -=( distance_type delta ) noexcept + { + m_iterator -= delta; + return *this; + } + + /*! + * Moves this iterator on the iterated image channel by the specified + * horizontal and vertical increments in pixels, \a dx and \a dy + * respectively, relative to its current position. Positive (negative) + * \a dx increments move the iterator rightwards (leftwards). Positive + * (negative) \a dy increments move the iterator downwards (upwards). + */ + sample_iterator& MoveBy( int dx, int dy ) noexcept + { + m_iterator += distance_type( dy )*m_image->Width() + distance_type( dx ); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend sample_iterator operator +( const sample_iterator& i, distance_type delta ) noexcept + { + return sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend sample_iterator operator +( distance_type delta, const sample_iterator& i ) noexcept + { + return sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend sample_iterator operator -( const sample_iterator& i, distance_type delta ) noexcept + { + return sample_iterator( *i.m_image, i.m_iterator - delta, i.m_end ); + } + + /*! + * Iterator subtraction operator. Returns the distance in pixels between + * the specified iterators \a i and \a j. + */ + friend distance_type operator -( const sample_iterator& i, const sample_iterator& j ) noexcept + { + return i.m_iterator - j.m_iterator; + } + + /*! + * Returns the distance in pixels between an iterator \a i and a sample + * pointer \a j. + */ + friend distance_type operator -( const sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator - j; + } + + /*! + * Returns the distance in pixels between a sample pointer \a i and an + * iterator \a j. + */ + friend distance_type operator -( const sample* i, const sample_iterator& j ) noexcept + { + return i - j.m_iterator; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const sample_iterator& i, const sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const sample_iterator& i, const sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + + protected: + + image_type* m_image = nullptr; + sample* __restrict__ m_iterator = nullptr; + const sample* __restrict__ m_end = nullptr; + + friend class const_sample_iterator; + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_sample_iterator + * \brief Immutable pixel sample iterator. + * + * An immutable pixel sample iterator provides read-only, random access to + * pixel samples in a single channel of an image. + * + * \ingroup image_iterators + */ + class const_sample_iterator + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_sample_iterator() = default; + + /*! + * Constructs an immutable pixel sample iterator for one channel of an + * image. + * + * \param image The constant image to iterate. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + const_sample_iterator( const image_type& image, int channel = -1 ) + : m_image( &image ) + { + if ( m_image->ParseChannel( channel ) ) + { + m_iterator = (*m_image)[channel]; + m_end = m_iterator + m_image->NumberOfPixels(); + } + } + + /*! + * Constructs an immutable pixel sample iterator for a range of + * contiguous pixel samples of an image. + * + * \param image The constant image to iterate. + * + * \param i Pointer to the first constant pixel sample in the + * iteration range. The iterator will be initialized to + * access this pixel sample just after construction. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to constant + * pixel samples in the \e same channel of the specified \a image. + */ + const_sample_iterator( const image_type& image, const sample* i, const sample* j ) + : m_image( &image ) + , m_iterator( i ) + , m_end( j ) + { + } + + /*! + * Constructs an immutable iterator from a mutable iterator. + * + * \note Don't confuse this constructor with the copy constructor for the + * const_sample_iterator class. Note that the argument to this function + * is a reference to an object of a different class. + */ + const_sample_iterator( const sample_iterator& i ) + : m_image( i.m_image ) + , m_iterator( i.m_iterator ) + , m_end( i.m_end ) + { + } + + /*! + * Copy constructor. + */ + const_sample_iterator( const const_sample_iterator& ) = default; + + /*! + * Assigns a mutable iterator to this object. Returns a reference to this + * iterator. + */ + const_sample_iterator& operator =( const sample_iterator& i ) noexcept + { + m_image = i.m_image; + m_iterator = i.m_iterator; + m_end = i.m_end; + return *this; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + const_sample_iterator& operator =( const const_sample_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return m_image != nullptr && m_iterator != nullptr; + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *m_image; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator. + */ + const sample* Position() const noexcept + { + return m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel sample iterator is active if it has not reached (or + * surpassed) its iteration limit: either the end of the iterated image + * channel, or the end of the iteration range, depending on how the + * iterator has been constructed. + */ + operator bool() const noexcept + { + return m_iterator < m_end; + } + + /*! + * Indirection operator. Returns a reference to the constant pixel sample + * pointed to by this iterator. + */ + const sample& operator *() const noexcept + { + return *m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated image channel, then returns a reference + * to this iterator. + */ + const_sample_iterator& operator ++() noexcept + { + ++m_iterator; + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated image channel. Returns a copy of the + * iterator as it was before incrementing it. + */ + const_sample_iterator operator ++( int ) noexcept + { + return const_sample_iterator( *m_image, m_iterator++, m_end ); + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated image channel, then returns a reference + * to this iterator. + */ + const_sample_iterator& operator --() noexcept + { + --m_iterator; + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated image channel. Returns a copy of the + * iterator as it was before decrementing it. + */ + const_sample_iterator operator --( int ) noexcept + { + return const_sample_iterator( *m_image, m_iterator--, m_end ); + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixel samples. Negative + * increments move this iterator backward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + const_sample_iterator& operator +=( distance_type delta ) noexcept + { + m_iterator += delta; + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixel samples. Negative + * increments move this iterator forward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + const_sample_iterator& operator -=( distance_type delta ) noexcept + { + m_iterator -= delta; + return *this; + } + + /*! + * Moves this iterator on the iterated image channel by the specified + * horizontal and vertical increments in pixels, \a dx and \a dy + * respectively, relative to its current position. Positive (negative) + * \a dx increments move the iterator rightwards (leftwards). Positive + * (negative) \a dy increments move the iterator downwards (upwards). + */ + const_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + m_iterator += distance_type( dy )*m_image->Width() + distance_type( dx ); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_sample_iterator operator +( const const_sample_iterator& i, distance_type delta ) noexcept + { + return const_sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_sample_iterator operator +( distance_type delta, const const_sample_iterator& i ) noexcept + { + return const_sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_sample_iterator operator -( const const_sample_iterator& i, distance_type delta ) noexcept + { + return const_sample_iterator( *i.m_image, i.m_iterator - delta, i.m_end ); + } + + /*! + * Iterator subtraction operator. Returns the distance in pixels between + * the specified iterators \a i and \a j. + */ + friend distance_type operator -( const const_sample_iterator& i, const const_sample_iterator& j ) noexcept + { + return i.m_iterator - j.m_iterator; + } + + /*! + * Returns the distance in pixels between an iterator \a i and a sample + * pointer \a j. + */ + friend distance_type operator -( const const_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator - j; + } + + /*! + * Returns the distance in pixels between a sample pointer \a i and an + * iterator \a j. + */ + friend distance_type operator -( const sample* i, const const_sample_iterator& j ) noexcept + { + return i - j.m_iterator; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const const_sample_iterator& i, const const_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const const_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const const_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_sample_iterator& i, const const_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const const_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const const_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + + protected: + + const image_type* m_image = nullptr; + const sample* __restrict__ m_iterator = nullptr; + const sample* __restrict__ m_end = nullptr; + }; + + // ------------------------------------------------------------------------- + + template + class roi_sample_iterator_base + { + protected: + + image_type* m_image = nullptr; + sample_pointer m_iterator = nullptr; + sample_pointer m_rowBegin = nullptr; + sample_pointer m_rowEnd = nullptr; + sample_pointer m_end = nullptr; + + roi_sample_iterator_base() = default; + + roi_sample_iterator_base( image_type& image, const Rect& rect, int channel ) + : m_image( &image ) + { + Rect r = rect; + if ( m_image->ParseRect( r ) ) + { + if ( m_image->ParseChannel( channel ) ) + { + m_iterator = m_rowBegin = m_image->PixelAddress( r.x0, r.y0, channel ); + m_rowEnd = m_rowBegin + r.Width(); + m_end = m_rowEnd + ((r.Height() - 1)*m_image->Width()); + } + } + } + + roi_sample_iterator_base( image_type& image, sample_pointer i, sample_pointer j ) + : m_image( &image ) + { + if ( j < i ) + pcl::Swap( i, j ); + m_iterator = m_rowBegin = i; + m_rowEnd = m_rowBegin + (j - i)%m_image->Width(); + m_end = j; + } + + roi_sample_iterator_base( const roi_sample_iterator_base& i ) = default; + + roi_sample_iterator_base& operator =( const roi_sample_iterator_base& ) = default; + + void Increment() noexcept + { + if ( ++m_iterator == m_rowEnd ) + { + m_rowBegin += m_image->Width(); + m_rowEnd += m_image->Width(); + m_iterator = m_rowBegin; + } + } + + void Decrement() noexcept + { + if ( m_iterator == m_rowBegin ) + { + m_rowBegin -= m_image->Width(); + m_rowEnd -= m_image->Width(); + m_iterator = m_rowEnd; + } + --m_iterator; + } + + void MoveBy( int cols, int rows ) noexcept + { + cols += m_iterator - m_rowBegin; + if ( cols != 0 ) + { + int w = m_rowEnd - m_rowBegin; + if ( pcl::Abs( cols ) >= w ) + { + rows += cols/w; + cols %= w; + } + } + int dy = rows * m_image->Width(); + m_rowBegin += dy; + m_rowEnd += dy; + m_iterator = m_rowBegin + cols; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::roi_sample_iterator + * \brief Mutable region-of-interest pixel sample iterator. + * + * A mutable, region-of-interest (ROI) pixel sample iterator provides + * read/write, random access to pixel samples within a rectangular subset of + * a single channel of an image. + * + * \ingroup image_iterators + */ + class roi_sample_iterator : private roi_sample_iterator_base, sample*> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + typedef roi_sample_iterator_base, sample*> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + roi_sample_iterator() = default; + + /*! + * Constructs a mutable, region-of-interest (ROI) pixel sample iterator + * for one channel of an image. + * + * \param image The image to iterate. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + roi_sample_iterator( image_type& image, const Rect& rect = Rect( 0 ), int channel = -1 ) + : iterator_base( image.EnsureUnique(), rect, channel ) + { + } + + /*! + * Constructs a mutable, region-of-interest (ROI) pixel sample iterator + * for a range of pixel samples of an image. + * + * \param image The image to iterate. + * + * \param i Pointer to the first pixel sample in the iteration + * range. The iterator will be initialized to access this + * pixel sample just after construction. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to pixel + * samples in the \e same channel of the specified \a image. + */ + roi_sample_iterator( image_type& image, sample* i, sample* j ) + : iterator_base( image, i, j ) + { + } + + /*! + * Copy constructor. + */ + roi_sample_iterator( const roi_sample_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + roi_sample_iterator& operator =( const roi_sample_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && this->m_iterator != nullptr; + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator. + */ + sample* Position() const noexcept + { + return this->m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel sample iterator is active if it has not reached + * (or surpassed) its iteration limit, i.e. the bottom right corner of + * its iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator < this->m_end; + } + + /*! + * Indirection operator. Returns a reference to the pixel sample pointed + * to by this iterator. + */ + sample& operator *() const noexcept + { + return *this->m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated region of interest, then returns a + * reference to this iterator. + */ + roi_sample_iterator& operator ++() noexcept + { + this->Increment(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated region of interest. Returns a copy of the + * iterator as it was before incrementing it. + */ + roi_sample_iterator operator ++( int ) noexcept + { + roi_sample_iterator i0( *this ); + this->Increment(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated region of interest, then returns a + * reference to this iterator. + */ + roi_sample_iterator& operator --() noexcept + { + this->Decrement(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated region of interest. Returns a copy of the + * iterator as it was before decrementing it. + */ + roi_sample_iterator operator --( int ) noexcept + { + roi_sample_iterator i0( *this ); + this->Decrement(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_sample_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( delta%w, delta/w ); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_sample_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( -delta%w, -delta/w ); + return *this; + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + roi_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + iterator_base::MoveBy( dx, dy ); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend roi_sample_iterator operator +( const roi_sample_iterator& i, distance_type delta ) noexcept + { + roi_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend roi_sample_iterator operator +( distance_type delta, const roi_sample_iterator& i ) noexcept + { + roi_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend roi_sample_iterator operator -( const roi_sample_iterator& i, distance_type delta ) noexcept + { + roi_sample_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const roi_sample_iterator& i, const roi_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const roi_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const roi_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const roi_sample_iterator& i, const roi_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const roi_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const roi_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + + friend class const_roi_pixel_iterator; + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_roi_sample_iterator + * \brief Immutable region-of-interest pixel sample iterator. + * + * An immutable, region-of-interest pixel sample iterator provides + * read-only, random access to pixel samples within a rectangular subset of + * a single channel of an image. + * + * \ingroup image_iterators + */ + class const_roi_sample_iterator : private roi_sample_iterator_base, const sample*> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + typedef roi_sample_iterator_base, const sample*> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_roi_sample_iterator() = default; + + /*! + * Constructs an immutable, region-of-interest (ROI) pixel sample + * iterator for one channel of an image. + * + * \param image The constant image to iterate. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + const_roi_sample_iterator( const image_type& image, const Rect& rect = Rect( 0 ), int channel = -1 ) + : iterator_base( image, rect, channel ) + { + } + + /*! + * Constructs an immutable, region-of-interest (ROI) pixel sample + * iterator for a range of pixel samples of an image. + * + * \param image The constant image to iterate. + * + * \param i Pointer to the first constant pixel sample in the + * iteration range. The iterator will be initialized to + * access this pixel sample just after construction. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to constant + * pixel samples in the \e same channel of the specified \a image. + */ + const_roi_sample_iterator( const image_type& image, const sample* i, const sample* j ) + : iterator_base( image, i, j ) + { + } + + /*! + * Constructs an immutable ROI pixel sample iterator from a mutable ROI + * pixel sample iterator. + * + * \note Don't confuse this constructor with the copy constructor for the + * const_roi_sample_iterator class. Note that the argument to this + * function is a reference to an object of a different class. + */ + const_roi_sample_iterator( const roi_sample_iterator& i ) + : iterator_base( i.m_image, i.m_rowBegin, i.m_end ) + { + } + + /*! + * Copy constructor. + */ + const_roi_sample_iterator( const const_roi_sample_iterator& ) = default; + + /*! + * Assigns a mutable iterator to this object. Returns a reference to this + * iterator. + */ + const_roi_sample_iterator& operator =( const roi_sample_iterator& i ) noexcept + { + this->m_image = i.m_image; + this->m_iterator = i.m_iterator; + this->m_rowBegin = i.m_rowBegin; + this->m_rowEnd = i.m_rowEnd; + this->m_end = i.m_end; + return *this; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + const_roi_sample_iterator& operator =( const const_roi_sample_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && this->m_iterator != nullptr; + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator. + */ + const sample* Position() const noexcept + { + return this->m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel sample iterator is active if it has not reached + * (or surpassed) its iteration limit, i.e. the bottom right corner of + * its iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator < this->m_end; + } + + /*! + * Indirection operator. Returns a reference to the constant pixel sample + * pointed to by this iterator. + */ + const sample& operator *() const noexcept + { + return *this->m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated region of interest, then returns a + * reference to this iterator. + */ + const_roi_sample_iterator& operator ++() noexcept + { + this->Increment(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel sample in the iterated region of interest. Returns a copy of the + * iterator as it was before incrementing it. + */ + const_roi_sample_iterator operator ++( int ) noexcept + { + const_roi_sample_iterator i0( *this ); + this->Increment(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated region of interest, then returns a + * reference to this iterator. + */ + const_roi_sample_iterator& operator --() noexcept + { + this->Decrement(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel sample in the iterated region of interest. Returns a copy of the + * iterator as it was before decrementing it. + */ + const_roi_sample_iterator operator --( int ) noexcept + { + const_roi_sample_iterator i0( *this ); + this->Decrement(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_sample_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( delta%w, delta/w ); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_sample_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( -delta%w, -delta/w ); + return *this; + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + const_roi_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + iterator_base::MoveBy( dx, dy ); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_roi_sample_iterator operator +( const const_roi_sample_iterator& i, distance_type delta ) noexcept + { + const_roi_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_roi_sample_iterator operator +( distance_type delta, const const_roi_sample_iterator& i ) noexcept + { + const_roi_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_roi_sample_iterator operator -( const const_roi_sample_iterator& i, distance_type delta ) noexcept + { + const_roi_sample_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const const_roi_sample_iterator& i, const const_roi_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const const_roi_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const const_roi_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_roi_sample_iterator& i, const const_roi_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const const_roi_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const const_roi_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + }; + + // ------------------------------------------------------------------------- + + template + class filter_sample_iterator_base : public iterator_base + { + protected: + + filter_type m_filter; + sample_pointer m_begin = nullptr; + + filter_sample_iterator_base() = default; + + filter_sample_iterator_base( image_type& image, const filter_type& filter, int channel ) + : iterator_base( image, channel ) + , m_filter( filter ) + , m_begin( iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + filter_sample_iterator_base( image_type& image, const filter_type& filter, sample_pointer i, sample_pointer j ) + : iterator_base( image, i, j ) + , m_filter( filter ) + , m_begin( iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + filter_sample_iterator_base( const iterator_base& i, const filter_type& filter ) + : iterator_base( i ) + , m_filter( filter ) + , m_begin( iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + filter_sample_iterator_base( const filter_sample_iterator_base& ) = default; + + filter_sample_iterator_base& operator =( const filter_sample_iterator_base& ) = default; + + filter_sample_iterator_base& operator =( const iterator_base& i ) noexcept + { + (void)iterator_base::operator =( i ); + JumpToNextValidSample(); + return *this; + } + + void JumpToNextValidSample() noexcept + { + while ( this->m_iterator < this->m_end && !this->m_filter( *this->m_iterator ) ) + ++this->m_iterator; + } + + void JumpToPrevValidSample() noexcept + { + while ( this->m_iterator > this->m_begin && !this->m_filter( *this->m_iterator ) ) + --this->m_iterator; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::filter_sample_iterator + * \brief Mutable filter pixel sample iterator. + * + * A mutable pixel sample iterator provides read/write, random access to + * pixel samples in a single channel of an image. A filter iterator uses a + * predicate object to filter pixel samples within its iteration range. + * + * Filter Predicates + * + * For a mutable filter sample iterator, the class template argument F must + * provide a function call operator of the form: + * + * \code bool F::operator()( sample& v ) const \endcode + * + * which returns true if the passed pixel sample value \a v is valid in the + * context of the filter iterator. The filter iterator stores a private + * instance of F to validate pixel samples, so the F class must provide also + * copy constructor semantics, either explicitly or implicitly. + * + * Filter Iterators + * + * Each time a filter iterator is constructed, incremented, decremented, or + * moved forward or backward, the filter predicate is called to validate the + * pixel or pixel sample pointed to by the iterator. If the pointed item is + * not valid, the iterator is incremented or decremented (depending on the + * operation performed initially) until it finds a valid one, or until it + * reaches the end of the iteration range, whichever happens first. In this + * way a filter iterator gives access only to valid items in a completely + * automatic and transparent fashion. + * + * \ingroup image_iterators + */ + template + class filter_sample_iterator : + public filter_sample_iterator_base, sample_iterator, sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef filter_sample_iterator_base, sample_iterator, sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + filter_sample_iterator() = default; + + /*! + * Constructs a mutable filter pixel sample iterator for one channel of + * an image. + * + * \param image The image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + filter_sample_iterator( image_type& image, const F& filter, int channel = -1 ) + : iterator_base( image.EnsureUnique(), filter, channel ) + { + } + + /*! + * Constructs a mutable filter pixel sample iterator for a range of + * contiguous pixel samples of an image. + * + * \param image The image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param i Pointer to the first pixel sample in the iteration + * range. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to pixel + * samples in the \e same channel of the specified \a image. + */ + filter_sample_iterator( image_type& image, const F& filter, sample* i, sample* j ) + : iterator_base( image, filter, i, j ) + { + } + + /*! + * Constructs a mutable filter pixel sample iterator from a sample + * iterator and the specified \a filter. + */ + filter_sample_iterator( const sample_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + filter_sample_iterator( const filter_sample_iterator& i ) = default; + + /*! + * Copy assignment operator. Returns a reference to this iterator. + */ + filter_sample_iterator& operator =( const filter_sample_iterator& ) = default; + + /*! + * Assigns a pixel sample iterator to this object. Returns a reference to + * this iterator. + */ + filter_sample_iterator& operator =( const sample_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && this->m_iterator != nullptr; + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator. + */ + sample* Position() const noexcept + { + return this->m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel sample iterator is active if it has not reached (or + * surpassed) its iteration limit: either the end of the iterated image + * channel, or the end of the iteration range, depending on how the + * iterator has been constructed. + */ + operator bool() const noexcept + { + return this->m_iterator < this->m_end; + } + + /*! + * Indirection operator. Returns a reference to the pixel sample pointed + * to by this iterator. + */ + sample& operator *() const noexcept + { + return *this->m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated image channel. Returns a reference + * to this iterator. + */ + filter_sample_iterator& operator ++() noexcept + { + ++this->m_iterator; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated image channel. Returns a copy of + * the iterator as it was before incrementing it. + */ + filter_sample_iterator operator ++( int ) noexcept + { + sample* __restrict__ i0 = this->m_iterator++; + this->JumpToNextValidSample(); + return filter_sample_iterator( *this->m_image, this->m_filter, i0, this->m_end ); + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated image channel, then returns a + * reference to this iterator. + */ + filter_sample_iterator& operator --() noexcept + { + --this->m_iterator; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated image channel. Returns a copy of + * the iterator as it was before decrementing it. + */ + filter_sample_iterator operator --( int ) noexcept + { + sample* __restrict__ i0 = this->m_iterator--; + this->JumpToPrevValidSample(); + return filter_sample_iterator( *this->m_image, this->m_filter, i0, this->m_end ); + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixel samples. Negative + * increments move this iterator backward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + filter_sample_iterator& operator +=( distance_type delta ) noexcept + { + this->m_iterator += delta; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixel samples. Negative + * increments move this iterator forward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + filter_sample_iterator& operator -=( distance_type delta ) noexcept + { + this->m_iterator -= delta; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Moves this iterator on the iterated image channel by the specified + * horizontal and vertical increments in pixels, \a dx and \a dy + * respectively, relative to its current position. Positive (negative) + * \a dx increments move the iterator rightwards (leftwards). Positive + * (negative) \a dy increments move the iterator downwards (upwards). + */ + filter_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + distance_type d = distance_type( dy )*this->m_image->Width() + distance_type( dx ); + this->m_iterator += d; + if ( d >= 0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend filter_sample_iterator operator +( const filter_sample_iterator& i, distance_type delta ) noexcept + { + return filter_sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend filter_sample_iterator operator +( distance_type delta, const filter_sample_iterator& i ) noexcept + { + return filter_sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend filter_sample_iterator operator -( const filter_sample_iterator& i, distance_type delta ) noexcept + { + return filter_sample_iterator( *i.m_image, i.m_iterator - delta, i.m_end ); + } + + /*! + * Iterator subtraction operator. Returns the distance in pixels between + * the specified iterators \a i and \a j. + */ + friend distance_type operator -( const filter_sample_iterator& i, const filter_sample_iterator& j ) noexcept + { + return i.m_iterator - j.m_iterator; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const filter_sample_iterator& i, const filter_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const filter_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const filter_sample_iterator& i, const filter_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const filter_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_filter_sample_iterator + * \brief Immutable filter pixel sample iterator. + * + * An immutable pixel sample iterator provides read-only, random access to + * pixel samples in a single channel of an image. A filter iterator uses a + * predicate object to filter pixel samples within its iteration range. + * + * Filter Predicates + * + * For an immutable filter sample iterator, the class template argument F + * must provide a function call operator of the form: + * + * \code bool F::operator()( const sample& v ) const \endcode + * + * which returns true if the passed pixel sample value \a v is valid in the + * context of the filter iterator. The filter iterator stores a private + * instance of F to validate pixel samples, so the F class must provide also + * copy constructor semantics, either explicitly or implicitly. + * + * Filter Iterators + * + * Each time a filter iterator is constructed, incremented, decremented, or + * moved forward or backward, the filter predicate is called to validate the + * pixel or pixel sample pointed to by the iterator. If the pointed item is + * not valid, the iterator is incremented or decremented (depending on the + * operation performed initially) until it finds a valid one, or until it + * reaches the end of the iteration range, whichever happens first. In this + * way a filter iterator gives access only to valid items in a completely + * automatic and transparent fashion. + * + * \ingroup image_iterators + */ + template + class const_filter_sample_iterator : + public filter_sample_iterator_base, const_sample_iterator, const sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef filter_sample_iterator_base, const_sample_iterator, const sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_filter_sample_iterator() = default; + + /*! + * Constructs an immutable filter pixel sample iterator for one channel + * of an image. + * + * \param image The constant image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + const_filter_sample_iterator( const image_type& image, const F& filter, int channel = -1 ) + : iterator_base( image, filter, channel ) + { + } + + /*! + * Constructs an immutable filter pixel sample iterator for a range of + * contiguous pixel samples of an image. + * + * \param image The constant image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param i Pointer to the first constant pixel sample in the + * iteration range. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to constant + * pixel samples in the \e same channel of the specified \a image. + */ + const_filter_sample_iterator( const image_type& image, const F& filter, const sample* i, const sample* j ) + : iterator_base( image, filter, i, j ) + { + } + + /*! + * Constructs an immutable filter pixel sample iterator from a mutable + * sample iterator and the specified \a filter. + */ + const_filter_sample_iterator( const sample_iterator& i, const F& filter ) + : iterator_base( i.m_image, filter, i.m_iterator, i.m_end ) + { + } + + /*! + * Constructs an immutable filter pixel sample iterator from an immutable + * sample iterator and the specified \a filter. + */ + const_filter_sample_iterator( const const_sample_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Constructs an immutable filter pixel sample iterator from a mutable + * filter pixel sample iterator. + */ + const_filter_sample_iterator( const filter_sample_iterator& i ) + : iterator_base( i ) + { + } + + /*! + * Copy constructor. + */ + const_filter_sample_iterator( const const_filter_sample_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this iterator. + */ + const_filter_sample_iterator& operator =( const const_filter_sample_iterator& ) = default; + + /*! + * Assigns a mutable pixel sample iterator to this object. Returns a + * reference to this iterator. + */ + const_filter_sample_iterator& operator =( const sample_iterator& i ) noexcept + { + (void)const_sample_iterator::operator =( i ); + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Assigns an immutable pixel sample iterator to this object. Returns a + * reference to this iterator. + */ + const_filter_sample_iterator& operator =( const const_sample_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && this->m_iterator != nullptr; + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator. + */ + const sample* Position() const noexcept + { + return this->m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel sample iterator is active if it has not reached (or + * surpassed) its iteration limit: either the end of the iterated image + * channel, or the end of the iteration range, depending on how the + * iterator has been constructed. + */ + operator bool() const noexcept + { + return this->m_iterator < this->m_end; + } + + /*! + * Indirection operator. Returns a reference to the constant pixel sample + * pointed to by this iterator. + */ + const sample& operator *() const noexcept + { + return *this->m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated image channel. Returns a reference + * to this iterator. + */ + const_filter_sample_iterator& operator ++() noexcept + { + ++this->m_iterator; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated image channel. Returns a copy of + * the iterator as it was before incrementing it. + */ + const_filter_sample_iterator operator ++( int ) noexcept + { + sample* __restrict__ i0 = this->m_iterator++; + this->JumpToNextValidSample(); + return const_filter_sample_iterator( *this->m_image, this->m_filter, i0, this->m_end ); + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated image channel, then returns a + * reference to this iterator. + */ + const_filter_sample_iterator& operator --() noexcept + { + --this->m_iterator; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated image channel. Returns a copy of + * the iterator as it was before decrementing it. + */ + const_filter_sample_iterator operator --( int ) noexcept + { + sample* __restrict__ i0 = this->m_iterator--; + this->JumpToPrevValidSample(); + return const_filter_sample_iterator( *this->m_image, this->m_filter, i0, this->m_end ); + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixel samples. Negative + * increments move this iterator backward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + const_filter_sample_iterator& operator +=( distance_type delta ) noexcept + { + this->m_iterator += delta; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixel samples. Negative + * increments move this iterator forward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + const_filter_sample_iterator& operator -=( distance_type delta ) noexcept + { + this->m_iterator -= delta; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Moves this iterator on the iterated image channel by the specified + * horizontal and vertical increments in pixels, \a dx and \a dy + * respectively, relative to its current position. Positive (negative) + * \a dx increments move the iterator rightwards (leftwards). Positive + * (negative) \a dy increments move the iterator downwards (upwards). + */ + const_filter_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + distance_type d = distance_type( dy )*this->m_image->Width() + distance_type( dx ); + this->m_iterator += d; + if ( d >= 0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_filter_sample_iterator operator +( const const_filter_sample_iterator& i, distance_type delta ) noexcept + { + return const_filter_sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_filter_sample_iterator operator +( distance_type delta, const const_filter_sample_iterator& i ) noexcept + { + return const_filter_sample_iterator( *i.m_image, i.m_iterator + delta, i.m_end ); + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_filter_sample_iterator operator -( const const_filter_sample_iterator& i, distance_type delta ) noexcept + { + return const_filter_sample_iterator( *i.m_image, i.m_iterator - delta, i.m_end ); + } + + /*! + * Iterator subtraction operator. Returns the distance in pixels between + * the specified iterators \a i and \a j. + */ + friend distance_type operator -( const const_filter_sample_iterator& i, const const_filter_sample_iterator& j ) noexcept + { + return i.m_iterator - j.m_iterator; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const const_filter_sample_iterator& i, const const_filter_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const const_filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const const_filter_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_filter_sample_iterator& i, const const_filter_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const const_filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const const_filter_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + }; + + // ------------------------------------------------------------------------- + + template + class roi_filter_sample_iterator_base : public roi_sample_iterator_base + { + protected: + + typedef roi_sample_iterator_base + roi_iterator_base; + + filter_type m_filter; + sample_pointer m_begin = nullptr; + + roi_filter_sample_iterator_base() = default; + + roi_filter_sample_iterator_base( image_type& image, const filter_type& filter, const Rect& rect, int channel ) + : roi_iterator_base( image, rect, channel ) + , m_filter( filter ) + , m_begin( roi_iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + roi_filter_sample_iterator_base( image_type& image, const filter_type& filter, sample_pointer i, sample_pointer j ) + : roi_iterator_base( image, i, j ) + , m_filter( filter ) + , m_begin( roi_iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + roi_filter_sample_iterator_base( const roi_iterator_base& i, const filter_type& filter ) + : roi_iterator_base( i ) + , m_filter( filter ) + , m_begin( roi_iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + roi_filter_sample_iterator_base( const roi_filter_sample_iterator_base& ) = default; + + roi_filter_sample_iterator_base& operator =( const roi_filter_sample_iterator_base& i ) = default; + + roi_filter_sample_iterator_base& operator =( const roi_iterator_base& i ) noexcept + { + (void)roi_iterator_base::operator =( i ); + JumpToNextValidSample(); + return *this; + } + + void JumpToNextValidSample() noexcept + { + while ( this->m_iterator < this->m_end && !this->m_filter( *this->m_iterator ) ) + roi_iterator_base::Increment(); + } + + void JumpToPrevValidSample() noexcept + { + while ( this->m_iterator > this->m_begin && !this->m_filter( *this->m_iterator ) ) + roi_iterator_base::Decrement(); + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::roi_filter_sample_iterator + * \brief Mutable region-of-interest, filter pixel sample iterator. + * + * A mutable, region-of-interest (ROI), filter pixel sample iterator + * combines the capabilities of roi_sample_iterator and + * filter_sample_iterator in a single iterator class. + * + * \ingroup image_iterators + */ + template + class roi_filter_sample_iterator : public roi_filter_sample_iterator_base, sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef roi_filter_sample_iterator_base, sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + roi_filter_sample_iterator() = default; + + /*! + * Constructs a mutable, region-of-interest (ROI), filter pixel sample + * iterator for one channel of an image. + * + * \param image The image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + roi_filter_sample_iterator( image_type& image, const F& filter, const Rect& rect = Rect( 0 ), int channel = -1 ) + : iterator_base( image.EnsureUnique(), filter, rect, channel ) + { + } + + /*! + * Constructs a mutable, region-of-interest (ROI), filter pixel sample + * iterator for a range of pixel samples of an image. + * + * \param image The image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param i Pointer to the first pixel sample in the iteration + * range. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to pixel + * samples in the \e same channel of the specified \a image. + */ + roi_filter_sample_iterator( image_type& image, const F& filter, sample* i, sample* j ) + : iterator_base( image, filter, i, j ) + { + } + + /*! + * Constructs a mutable, region-of-interest (ROI), filter pixel sample + * iterator from the specified ROI iterator \a i and \a filter. + */ + roi_filter_sample_iterator( const roi_sample_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + roi_filter_sample_iterator( const roi_filter_sample_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + roi_filter_sample_iterator& operator =( const roi_filter_sample_iterator& ) = default; + + /*! + * Assigns a ROI pixel sample iterator. Returns a reference to this + * object. + */ + roi_filter_sample_iterator& operator =( const roi_sample_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && this->m_iterator != nullptr; + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator. + */ + sample* Position() const noexcept + { + return this->m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel sample iterator is active if it has not reached + * (or surpassed) its iteration limit, i.e. the bottom right corner of + * its iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator < this->m_end; + } + + /*! + * Indirection operator. Returns a reference to the pixel sample pointed + * to by this iterator. + */ + sample& operator *() const noexcept + { + return *this->m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated region of interest. Returns a + * reference to this iterator. + */ + roi_filter_sample_iterator& operator ++() noexcept + { + this->Increment(); + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated region of interest. Returns a copy + * of the iterator as it was before incrementing it. + */ + roi_filter_sample_iterator operator ++( int ) noexcept + { + roi_filter_sample_iterator i0( *this ); + this->Increment(); + this->JumpToNextValidSample(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated region of interest, then returns a + * reference to this iterator. + */ + roi_filter_sample_iterator& operator --() noexcept + { + this->Decrement(); + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated region of interest. Returns a copy + * of the iterator as it was before decrementing it. + */ + roi_filter_sample_iterator operator --( int ) noexcept + { + roi_filter_sample_iterator i0( *this ); + this->Decrement(); + this->JumpToPrevValidSample(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_filter_sample_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( delta%w, delta/w ); + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_filter_sample_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( -delta%w, -delta/w ); + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + roi_filter_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + sample* __restrict__ i0 = this->m_iterator; + iterator_base::MoveBy( dx, dy ); + if ( this->m_iterator >= i0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend roi_filter_sample_iterator operator +( const roi_filter_sample_iterator& i, distance_type delta ) noexcept + { + roi_filter_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend roi_filter_sample_iterator operator +( distance_type delta, const roi_filter_sample_iterator& i ) noexcept + { + roi_filter_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend roi_filter_sample_iterator operator -( const roi_filter_sample_iterator& i, distance_type delta ) noexcept + { + roi_filter_sample_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const roi_filter_sample_iterator& i, const roi_filter_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const roi_filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const roi_filter_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const roi_filter_sample_iterator& i, const roi_filter_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const roi_filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const roi_filter_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_roi_filter_sample_iterator + * \brief Immutable region-of-interest, filter pixel sample iterator. + * + * An immutable, region-of-interest (ROI), filter pixel sample iterator + * combines the capabilities of const_roi_sample_iterator and + * const_filter_sample_iterator in a single iterator class. + * + * \ingroup image_iterators + */ + template + class const_roi_filter_sample_iterator : public roi_filter_sample_iterator_base, const sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef roi_filter_sample_iterator_base, const sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_roi_filter_sample_iterator() = default; + + /*! + * Constructs an immutable, region-of-interest (ROI), filter pixel sample + * iterator for one channel of an image. + * + * \param image The constant image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + * + * \param channel Channel index. If this parameter is a negative integer, + * then this object will be initialized to iterate on the + * currently selected channel of the \a image. If an + * invalid (i.e., nonexistent) channel index is specified, + * then the resulting iterator will also be invalid, with + * an empty iteration range. The default value is -1. + */ + const_roi_filter_sample_iterator( const image_type& image, const F& filter, const Rect& rect = Rect( 0 ), int channel = -1 ) + : iterator_base( image, filter, rect, channel ) + { + } + + /*! + * Constructs an immutable, region-of-interest (ROI), filter pixel sample + * iterator for a range of pixel samples of an image. + * + * \param image The constant image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param i Pointer to the first constant pixel sample in the + * iteration range. + * + * \param j End of the iteration range. The iterator will be + * invalid when it reaches (or surpasses) this point. + * + * \note Both iteration limits \a i and \a j must be pointers to pixel + * samples in the \e same channel of the specified \a image. + */ + const_roi_filter_sample_iterator( const image_type& image, const F& filter, const sample* i, const sample* j ) + : iterator_base( image, filter, i, j ) + { + } + + /*! + * Constructs an immutable, region-of-interest (ROI), filter pixel sample + * iterator from the specified immutable ROI iterator \a i and \a filter. + */ + const_roi_filter_sample_iterator( const const_roi_sample_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + const_roi_filter_sample_iterator( const const_roi_filter_sample_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + const_roi_filter_sample_iterator& operator =( const const_roi_filter_sample_iterator& ) = default; + + /*! + * Assigns an immutable ROI pixel sample iterator. Returns a reference to + * this object. + */ + const_roi_filter_sample_iterator& operator =( const const_roi_sample_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && this->m_iterator != nullptr; + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator. + */ + const sample* Position() const noexcept + { + return this->m_iterator; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel sample iterator is active if it has not reached + * (or surpassed) its iteration limit, i.e. the bottom right corner of + * its iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator < this->m_end; + } + + /*! + * Indirection operator. Returns a reference to the constant pixel sample + * pointed to by this iterator. + */ + const sample& operator *() const noexcept + { + return *this->m_iterator; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated region of interest. Returns a + * reference to this iterator. + */ + const_roi_filter_sample_iterator& operator ++() noexcept + { + this->Increment(); + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel sample in the iterated region of interest. Returns a copy + * of the iterator as it was before incrementing it. + */ + const_roi_filter_sample_iterator operator ++( int ) noexcept + { + const_roi_filter_sample_iterator i0( *this ); + this->Increment(); + this->JumpToNextValidSample(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated region of interest, then returns a + * reference to this iterator. + */ + const_roi_filter_sample_iterator& operator --() noexcept + { + this->Decrement(); + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel sample in the iterated region of interest. Returns a copy + * of the iterator as it was before decrementing it. + */ + const_roi_filter_sample_iterator operator --( int ) noexcept + { + const_roi_filter_sample_iterator i0( *this ); + this->Decrement(); + this->JumpToPrevValidSample(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_filter_sample_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( delta%w, delta/w ); + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_filter_sample_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( -delta%w, -delta/w ); + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + const_roi_filter_sample_iterator& MoveBy( int dx, int dy ) noexcept + { + const sample* __restrict__ i0 = this->m_iterator; + iterator_base::MoveBy( dx, dy ); + if ( this->m_iterator >= i0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_roi_filter_sample_iterator operator +( const const_roi_filter_sample_iterator& i, distance_type delta ) noexcept + { + const_roi_filter_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_roi_filter_sample_iterator operator +( distance_type delta, const const_roi_filter_sample_iterator& i ) noexcept + { + const_roi_filter_sample_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_roi_filter_sample_iterator operator -( const const_roi_filter_sample_iterator& i, distance_type delta ) noexcept + { + const_roi_filter_sample_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel sample. + */ + friend bool operator ==( const const_roi_filter_sample_iterator& i, const const_roi_filter_sample_iterator& j ) noexcept + { + return i.m_iterator == j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i and a sample pointer \a j point to + * the same pixel sample. + */ + friend bool operator ==( const const_roi_filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator == j; + } + + /*! + * Returns true iff a sample pointer \a i and an iterator \a j point to + * the same pixel sample. + */ + friend bool operator ==( const sample* i, const const_roi_filter_sample_iterator& j ) noexcept + { + return i == j.m_iterator; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_roi_filter_sample_iterator& i, const const_roi_filter_sample_iterator& j ) noexcept + { + return i.m_iterator < j.m_iterator; + } + + /*! + * Returns true iff an iterator \a i precedes a sample pointer \a j. + */ + friend bool operator <( const const_roi_filter_sample_iterator& i, const sample* j ) noexcept + { + return i.m_iterator < j; + } + + /*! + * Returns true iff a sample pointer \a i precedes an iterator \a j. + */ + friend bool operator <( const sample* i, const const_roi_filter_sample_iterator& j ) noexcept + { + return i < j.m_iterator; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::pixel_iterator + * \brief Mutable pixel iterator. + * + * A mutable pixel iterator provides read/write, random access to all pixels + * of an image. + * + * \ingroup image_iterators + */ + class pixel_iterator + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + typedef GenericVector iterator_type; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + pixel_iterator() = default; + + /*! + * Constructs a mutable pixel iterator for the specified \a image. + */ + pixel_iterator( image_type& image ) + : m_image( &image ) + { + m_image->EnsureUnique(); + if ( !m_image->IsEmpty() ) + { + m_iterator = iterator_type( m_image->NumberOfChannels() ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] = (*m_image)[i]; + m_end = m_iterator[0] + m_image->NumberOfPixels(); + } + } + + /*! + * Copy constructor. + */ + pixel_iterator( const pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this iterator. + */ + pixel_iterator& operator =( const pixel_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return m_image != nullptr && !m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *m_image; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator in + * the specified \a channel. + */ + sample* Position( int channel ) const noexcept + { + return m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel iterator is active if it has not reached (or + * surpassed) its iteration limit. + */ + operator bool() const noexcept + { + return m_iterator[0] < m_end; + } + + /*! + * Array subscript operator. Returns a reference to the pixel sample + * pointed to by this iterator in the specified \a channel. + */ + sample& operator []( int channel ) const noexcept + { + return *m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel in the iterated image. Returns a reference to this iterator. + */ + pixel_iterator& operator ++() noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + ++m_iterator[i]; + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel in the iterated image. Returns a copy of the iterator as it was + * before incrementing it. + */ + pixel_iterator operator ++( int ) noexcept + { + pixel_iterator i0( *this ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + ++m_iterator[i]; + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated image. Returns a reference to this iterator. + */ + pixel_iterator& operator --() noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + --m_iterator[i]; + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated image. Returns a copy of the iterator as it was + * before decrementing it. + */ + pixel_iterator operator --( int ) noexcept + { + pixel_iterator i0( *this ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + --m_iterator[i]; + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixels. Negative increments + * move this iterator backward by \a delta pixels. Returns a reference to + * this iterator. + */ + pixel_iterator& operator +=( distance_type delta ) noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] += delta; + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixels. Negative increments + * move this iterator forward by \a delta pixels. Returns a reference to + * this iterator. + */ + pixel_iterator& operator -=( distance_type delta ) noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] -= delta; + return *this; + } + + /*! + * Moves this iterator on the iterated image by the specified horizontal + * and vertical increments in pixels, \a dx and \a dy respectively, + * relative to its current position. Positive (negative) \a dx increments + * move the iterator rightwards (leftwards). Positive (negative) \a dy + * increments move the iterator downwards (upwards). + */ + pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + return operator +=( distance_type( dy )*m_image->Width() + distance_type( dx ) ); + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend pixel_iterator operator +( const pixel_iterator& i, distance_type delta ) noexcept + { + pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend pixel_iterator operator +( distance_type delta, const pixel_iterator& i ) noexcept + { + pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend pixel_iterator operator -( const pixel_iterator& i, distance_type delta ) noexcept + { + pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Iterator subtraction operator. Returns the distance in pixels between + * the specified iterators \a i and \a j. + */ + friend distance_type operator -( const pixel_iterator& i, const pixel_iterator& j ) noexcept + { + return i.m_iterator[0] - j.m_iterator[0]; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const pixel_iterator& i, const pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const pixel_iterator& i, const pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + + protected: + + image_type* m_image = nullptr; + iterator_type m_iterator; + const sample* __restrict__ m_end = nullptr; + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_pixel_iterator + * \brief Immutable pixel iterator. + * + * An immutable pixel iterator provides read-only, random access to all + * pixels of an image. + * + * \ingroup image_iterators + */ + class const_pixel_iterator + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + typedef GenericVector iterator_type; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_pixel_iterator() = default; + + /*! + * Constructs an immutable pixel iterator for the specified \a image. + */ + const_pixel_iterator( const image_type& image ) + : m_image( &image ) + { + if ( !m_image->IsEmpty() ) + { + m_iterator = iterator_type( m_image->NumberOfChannels() ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] = (*m_image)[i]; + m_end = m_iterator[0] + m_image->NumberOfPixels(); + } + } + + /*! + * Copy constructor. + */ + const_pixel_iterator( const const_pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this iterator. + */ + const_pixel_iterator& operator =( const const_pixel_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return m_image != nullptr && !m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *m_image; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator in the specified \a channel. + */ + const sample* Position( int channel ) const noexcept + { + return m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel iterator is active if it has not reached (or + * surpassed) its iteration limit. + */ + operator bool() const noexcept + { + return m_iterator[0] < m_end; + } + + /*! + * Array subscript operator. Returns a reference to the constant pixel + * sample pointed to by this iterator in the specified \a channel. + */ + const sample& operator []( int channel ) const noexcept + { + return *m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel in the iterated image. Returns a reference to this iterator. + */ + const_pixel_iterator& operator ++() noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + ++m_iterator[i]; + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel in the iterated image. Returns a copy of the iterator as it was + * before incrementing it. + */ + const_pixel_iterator operator ++( int ) noexcept + { + const_pixel_iterator i0( *this ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + ++m_iterator[i]; + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated image. Returns a reference to this iterator. + */ + const_pixel_iterator& operator --() noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + --m_iterator[i]; + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated image. Returns a copy of the iterator as it was + * before decrementing it. + */ + const_pixel_iterator operator --( int ) noexcept + { + const_pixel_iterator i0( *this ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + --m_iterator[i]; + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixels. Negative increments + * move this iterator backward by \a delta pixels. Returns a reference to + * this iterator. + */ + const_pixel_iterator& operator +=( distance_type delta ) noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] += delta; + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixels. Negative increments + * move this iterator forward by \a delta pixels. Returns a reference to + * this iterator. + */ + const_pixel_iterator& operator -=( distance_type delta ) noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] -= delta; + return *this; + } + + /*! + * Moves this iterator on the iterated image by the specified horizontal + * and vertical increments in pixels, \a dx and \a dy respectively, + * relative to its current position. Positive (negative) \a dx increments + * move the iterator rightwards (leftwards). Positive (negative) \a dy + * increments move the iterator downwards (upwards). + */ + const_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + return operator +=( distance_type( dy )*m_image->Width() + distance_type( dx ) ); + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_pixel_iterator operator +( const const_pixel_iterator& i, distance_type delta ) noexcept + { + const_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_pixel_iterator operator +( distance_type delta, const const_pixel_iterator& i ) noexcept + { + const_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_pixel_iterator operator -( const const_pixel_iterator& i, distance_type delta ) noexcept + { + const_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Iterator subtraction operator. Returns the distance in pixels between + * the specified iterators \a i and \a j. + */ + friend distance_type operator -( const const_pixel_iterator& i, const const_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] - j.m_iterator[0]; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const const_pixel_iterator& i, const const_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_pixel_iterator& i, const const_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + + protected: + + const image_type* m_image = nullptr; + iterator_type m_iterator; + const sample* __restrict__ m_end = nullptr; + }; + + // ------------------------------------------------------------------------- + + template + class roi_pixel_iterator_base + { + protected: + + typedef GenericVector iterator_type; + + image_type* m_image = nullptr; + iterator_type m_iterator; + sample_pointer m_rowBegin = nullptr; + sample_pointer m_rowEnd = nullptr; + sample_pointer m_end = nullptr; + + roi_pixel_iterator_base() = default; + + roi_pixel_iterator_base( image_type& image, const Rect& rect ) + : m_image( &image ) + { + Rect r = rect; + if ( m_image->ParseRect( r ) ) + { + m_iterator = iterator_type( m_image->NumberOfChannels() ); + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] = m_image->PixelAddress( r.x0, r.y0, i ); + m_rowBegin = m_iterator[0]; + m_rowEnd = m_rowBegin + r.Width(); + m_end = m_rowEnd + ((r.Height() - 1)*m_image->Width()); + } + } + + roi_pixel_iterator_base( const roi_pixel_iterator_base& ) = default; + + roi_pixel_iterator_base& operator =( const roi_pixel_iterator_base& ) = default; + + void Increment() noexcept + { + for ( int i = 0; i < m_iterator.Length(); ++i ) + ++m_iterator[i]; + if ( m_iterator[0] == m_rowEnd ) + { + int w = m_rowEnd - m_rowBegin; + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] += m_image->Width() - w; + m_rowBegin += m_image->Width(); + m_rowEnd += m_image->Width(); + } + } + + void Decrement() noexcept + { + if ( m_iterator[0] == m_rowBegin ) + { + int w = m_rowEnd - m_rowBegin; + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] -= m_image->Width() - w; + m_rowBegin -= m_image->Width(); + m_rowEnd -= m_image->Width(); + } + for ( int i = 0; i < m_iterator.Length(); ++i ) + --m_iterator[i]; + } + + void MoveBy( int cols, int rows ) noexcept + { + int dx = m_iterator[0] - m_rowBegin; + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] -= dx; + cols += dx; + if ( cols != 0 ) + { + int w = m_rowEnd - m_rowBegin; + if ( pcl::Abs( cols ) >= w ) + { + rows += cols/w; + cols %= w; + } + } + int dy = rows * m_image->Width(); + for ( int i = 0; i < m_iterator.Length(); ++i ) + m_iterator[i] += dy + cols; + m_rowBegin += dy; + m_rowEnd += dy; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::roi_pixel_iterator + * \brief Mutable region-of-interest pixel iterator. + * + * A mutable, region-of-interest (ROI) pixel iterator provides read/write, + * random access to pixels within a rectangular subset of an image. + * + * \ingroup image_iterators + */ + class roi_pixel_iterator : private roi_pixel_iterator_base, sample*> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + typedef roi_pixel_iterator_base, sample*> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + roi_pixel_iterator() = default; + + /*! + * Constructs a mutable, region-of-interest (ROI) pixel iterator. + * + * \param image The image to iterate. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + */ + roi_pixel_iterator( image_type& image, const Rect& rect = Rect( 0 ) ) + : iterator_base( image.EnsureUnique(), rect ) + { + } + + /*! + * Copy constructor. + */ + roi_pixel_iterator( const roi_pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + roi_pixel_iterator& operator =( const roi_pixel_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && !this->m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator in + * the specified \a channel. + */ + sample* Position( int channel ) const noexcept + { + return this->m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel iterator is active if it has not reached (or + * surpassed) its iteration limit, i.e. the bottom right corner of its + * iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator[0] < this->m_end; + } + + /*! + * Array subscript operator. Returns a reference to the pixel sample + * pointed to by this iterator in the specified \a channel. + */ + sample& operator []( int channel ) const noexcept + { + return *this->m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel in the iterated region of interest, then returns a reference to + * this iterator. + */ + roi_pixel_iterator& operator ++() noexcept + { + this->Increment(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before incrementing it. + */ + roi_pixel_iterator operator ++( int ) noexcept + { + roi_pixel_iterator i0( *this ); + this->Increment(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated region of interest, then returns a reference to + * this iterator. + */ + roi_pixel_iterator& operator --() noexcept + { + this->Decrement(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before decrementing it. + */ + roi_pixel_iterator operator --( int ) noexcept + { + roi_pixel_iterator i0( *this ); + this->Decrement(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_pixel_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( delta%w, delta/w ); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_pixel_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( -delta%w, -delta/w ); + return *this; + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + roi_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + iterator_base::MoveBy( dx, dy ); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend roi_pixel_iterator operator +( const roi_pixel_iterator& i, distance_type delta ) noexcept + { + roi_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend roi_pixel_iterator operator +( distance_type delta, const roi_pixel_iterator& i ) noexcept + { + roi_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend roi_pixel_iterator operator -( const roi_pixel_iterator& i, distance_type delta ) noexcept + { + roi_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const roi_pixel_iterator& i, const roi_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const roi_pixel_iterator& i, const roi_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_roi_pixel_iterator + * \brief Immutable region-of-interest pixel iterator. + * + * An immutable, region-of-interest (ROI) pixel iterator provides read-only, + * random access to pixels within a rectangular subset of an image. + * + * \ingroup image_iterators + */ + class const_roi_pixel_iterator : private roi_pixel_iterator_base, const sample*> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + typedef roi_pixel_iterator_base, const sample*> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_roi_pixel_iterator() = default; + + /*! + * Constructs an immutable, region-of-interest (ROI) pixel iterator. + * + * \param image The constant image to iterate. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + */ + const_roi_pixel_iterator( const image_type& image, const Rect& rect = Rect( 0 ) ) + : iterator_base( image, rect ) + { + } + + /*! + * Copy constructor. + */ + const_roi_pixel_iterator( const const_roi_pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + const_roi_pixel_iterator& operator =( const const_roi_pixel_iterator& ) = default; + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && !this->m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator in the specified \a channel. + */ + const sample* Position( int channel ) const noexcept + { + return this->m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel iterator is active if it has not reached (or + * surpassed) its iteration limit, i.e. the bottom right corner of its + * iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator[0] < this->m_end; + } + + /*! + * Array subscript operator. Returns a reference to the constant pixel + * sample pointed to by this iterator in the specified \a channel. + */ + const sample& operator []( int channel ) const noexcept + { + return *this->m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * pixel in the iterated region of interest, then returns a reference to + * this iterator. + */ + const_roi_pixel_iterator& operator ++() noexcept + { + this->Increment(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before incrementing it. + */ + const_roi_pixel_iterator operator ++( int ) noexcept + { + const_roi_pixel_iterator i0( *this ); + this->Increment(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated region of interest, then returns a reference to + * this iterator. + */ + const_roi_pixel_iterator& operator --() noexcept + { + this->Decrement(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before decrementing it. + */ + const_roi_pixel_iterator operator --( int ) noexcept + { + const_roi_pixel_iterator i0( *this ); + this->Decrement(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_pixel_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( delta%w, delta/w ); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_pixel_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + iterator_base::MoveBy( -delta%w, -delta/w ); + return *this; + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + const_roi_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + iterator_base::MoveBy( dx, dy ); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_roi_pixel_iterator operator +( const const_roi_pixel_iterator& i, distance_type delta ) noexcept + { + const_roi_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_roi_pixel_iterator operator +( distance_type delta, const const_roi_pixel_iterator& i ) noexcept + { + const_roi_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_roi_pixel_iterator operator -( const const_roi_pixel_iterator& i, distance_type delta ) noexcept + { + const_roi_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const const_roi_pixel_iterator& i, const const_roi_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_roi_pixel_iterator& i, const const_roi_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + }; + + // ------------------------------------------------------------------------- + + template + class filter_pixel_iterator_base : public iterator_base + { + protected: + + filter_type m_filter; + sample_pointer m_begin = nullptr; + + filter_pixel_iterator_base() = default; + + filter_pixel_iterator_base( image_type& image, const filter_type& filter ) + : iterator_base( image ) + , m_filter( filter ) + , m_begin( iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + filter_pixel_iterator_base( const iterator_base& i, const filter_type& filter ) + : iterator_base( i ) + , m_filter( filter ) + , m_begin( iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + filter_pixel_iterator_base( const filter_pixel_iterator_base& ) = default; + + filter_pixel_iterator_base& operator =( const filter_pixel_iterator_base& ) = default; + + filter_pixel_iterator_base& operator =( const iterator_base& i ) noexcept + { + (void)iterator_base::operator =( i ); + JumpToNextValidSample(); + } + + void JumpToNextValidSample() noexcept + { + while ( this->m_iterator[0] < this->m_end && !this->m_filter( this->m_iterator ) ) + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + ++this->m_iterator[i]; + } + + void JumpToPrevValidSample() noexcept + { + while ( this->m_iterator[0] > this->m_begin && !this->m_filter( this->m_iterator ) ) + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + --this->m_iterator[i]; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::filter_pixel_iterator + * \brief Mutable filter pixel iterator. + * + * A mutable pixel iterator provides read/write, random access to all pixels + * in an image. A filter pixel iterator uses a predicate object to filter + * pixels within its iteration range. + * + * Filter Predicates + * + * For a mutable filter pixel iterator, the class template argument F must + * provide a function call operator of the form: + * + * \code bool F::operator()( const GenericVector\& f ) const \endcode + * + * Each component of the passed vector \a f is a pointer to a pixel sample + * in the corresponding channel of the iterated image. The function call + * operator must return true if the pointed pixel is valid in the context of + * the filter iterator. The filter iterator stores a private instance of F + * to validate pixels, so the F class must provide also copy constructor + * semantics, either explicitly or implicitly. + * + * Filter Iterators + * + * Each time a filter iterator is constructed, incremented, decremented, or + * moved forward or backward, the filter predicate is called to validate the + * pixel or pixel sample pointed to by the iterator. If the pointed item is + * not valid, the iterator is incremented or decremented (depending on the + * operation performed initially) until it finds a valid one, or until it + * reaches the end of the iteration range, whichever happens first. In this + * way a filter iterator gives access only to valid items in a completely + * automatic and transparent fashion. + * + * \ingroup image_iterators + */ + template + class filter_pixel_iterator : + public filter_pixel_iterator_base, pixel_iterator, sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef filter_pixel_iterator_base, pixel_iterator, sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + filter_pixel_iterator() = default; + + /*! + * Constructs a mutable filter pixel iterator. + * + * \param image The image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixels. + */ + filter_pixel_iterator( image_type& image, const F& filter ) + : iterator_base( image.EnsureUnique(), filter ) + { + } + + /*! + * Constructs a mutable filter pixel iterator from a mutable pixel + * iterator and the specified \a filter. + */ + filter_pixel_iterator( const pixel_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + filter_pixel_iterator( const filter_pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this iterator. + */ + filter_pixel_iterator& operator =( const filter_pixel_iterator& ) = default; + + /*! + * Assigns a mutable pixel iterator to this object. Returns a reference + * to this iterator. + */ + filter_pixel_iterator& operator =( const pixel_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && !this->m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator in + * the specified \a channel. + */ + sample* Position( int channel ) const noexcept + { + return this->m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel iterator is active if it has not reached (or + * surpassed) its iteration limit. + */ + operator bool() const noexcept + { + return this->m_iterator[0] < this->m_end; + } + + /*! + * Array subscript operator. Returns a reference to the pixel sample + * pointed to by this iterator in the specified \a channel. + */ + sample& operator []( int channel ) const noexcept + { + return *this->m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated image. Returns a reference to this + * iterator. + */ + filter_pixel_iterator& operator ++() noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + ++this->m_iterator[i]; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated image channel. Returns a copy of the + * iterator as it was before incrementing it. + */ + filter_pixel_iterator operator ++( int ) noexcept + { + filter_pixel_iterator i0( *this ); + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + ++this->m_iterator[i]; + this->JumpToNextValidSample(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated image channel, then returns a reference to + * this iterator. + */ + filter_pixel_iterator& operator --() noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + --this->m_iterator[i]; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated image channel. Returns a copy of the + * iterator as it was before decrementing it. + */ + filter_pixel_iterator operator --( int ) noexcept + { + filter_pixel_iterator i0( *this ); + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + --this->m_iterator[i]; + this->JumpToPrevValidSample(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixel samples. Negative + * increments move this iterator backward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + filter_pixel_iterator& operator +=( distance_type delta ) noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + this->m_iterator[i] += delta; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixel samples. Negative + * increments move this iterator forward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + filter_pixel_iterator& operator -=( distance_type delta ) noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + this->m_iterator[i] -= delta; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Moves this iterator on the iterated image by the specified horizontal + * and vertical increments in pixels, \a dx and \a dy respectively, + * relative to its current position. Positive (negative) \a dx increments + * move the iterator rightwards (leftwards). Positive (negative) \a dy + * increments move the iterator downwards (upwards). + */ + filter_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + distance_type d = distance_type( dy )*this->m_image->Width() + distance_type( dx ); + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + this->m_iterator[i] += d; + if ( d >= 0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend filter_pixel_iterator operator +( const filter_pixel_iterator& i, distance_type delta ) noexcept + { + filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend filter_pixel_iterator operator +( distance_type delta, const filter_pixel_iterator& i ) noexcept + { + filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend filter_pixel_iterator operator -( const filter_pixel_iterator& i, distance_type delta ) noexcept + { + filter_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const filter_pixel_iterator& i, const filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const filter_pixel_iterator& i, const filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_filter_pixel_iterator + * \brief Immutable filter pixel iterator. + * + * An immutable pixel iterator provides read-only, random access to all + * pixels in an image. A filter pixel iterator uses a predicate object to + * filter pixels within its iteration range. + * + * Filter Predicates + * + * For an immutable filter pixel iterator, the class template argument F + * must provide a function call operator of the form: + * + * \code bool F::operator()( const GenericVector\& f ) const \endcode + * + * Each component of the passed vector \a f is a pointer to a constant pixel + * sample in the corresponding channel of the iterated image. The function + * call operator must return true if the pointed pixel is valid in the + * context of the filter iterator. The filter iterator stores a private + * instance of F to validate pixels, so the F class must provide also copy + * constructor semantics, either explicitly or implicitly. + * + * Filter Iterators + * + * Each time a filter iterator is constructed, incremented, decremented, or + * moved forward or backward, the filter predicate is called to validate the + * pixel or pixel sample pointed to by the iterator. If the pointed item is + * not valid, the iterator is incremented or decremented (depending on the + * operation performed initially) until it finds a valid one, or until it + * reaches the end of the iteration range, whichever happens first. In this + * way a filter iterator gives access only to valid items in a completely + * automatic and transparent fashion. + * + * \ingroup image_iterators + */ + template + class const_filter_pixel_iterator : + public filter_pixel_iterator_base, const_pixel_iterator, const sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef filter_pixel_iterator_base, const_pixel_iterator, const sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_filter_pixel_iterator() = default; + + /*! + * Constructs an immutable filter pixel iterator. + * + * \param image The constant image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixels. + */ + const_filter_pixel_iterator( const image_type& image, const F& filter ) + : iterator_base( image, filter ) + { + } + + /*! + * Constructs an immutable filter pixel iterator from an immutable pixel + * iterator and the specified \a filter. + */ + const_filter_pixel_iterator( const const_pixel_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + const_filter_pixel_iterator( const const_filter_pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this iterator. + */ + const_filter_pixel_iterator& operator =( const const_filter_pixel_iterator& ) = default; + + /*! + * Assigns an immutable pixel iterator to this object. Returns a + * reference to this iterator. + */ + const_filter_pixel_iterator& operator =( const const_pixel_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && !this->m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator in the specified \a channel. + */ + const sample* Position( int channel ) const noexcept + { + return this->m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A pixel iterator is active if it has not reached (or + * surpassed) its iteration limit. + */ + operator bool() const noexcept + { + return this->m_iterator[0] < this->m_end; + } + + /*! + * Array subscript operator. Returns a reference to the constant pixel + * sample pointed to by this iterator in the specified \a channel. + */ + const sample& operator []( int channel ) const noexcept + { + return *this->m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated image. Returns a reference to this + * iterator. + */ + const_filter_pixel_iterator& operator ++() noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + ++this->m_iterator[i]; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated image channel. Returns a copy of the + * iterator as it was before incrementing it. + */ + const_filter_pixel_iterator operator ++( int ) noexcept + { + const_filter_pixel_iterator i0( *this ); + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + ++this->m_iterator[i]; + this->JumpToNextValidSample(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated image channel, then returns a reference to + * this iterator. + */ + const_filter_pixel_iterator& operator --() noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + --this->m_iterator[i]; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated image channel. Returns a copy of the + * iterator as it was before decrementing it. + */ + const_filter_pixel_iterator operator --( int ) noexcept + { + const_filter_pixel_iterator i0( *this ); + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + --this->m_iterator[i]; + this->JumpToPrevValidSample(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move forward by \a delta pixel samples. Negative + * increments move this iterator backward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + const_filter_pixel_iterator& operator +=( distance_type delta ) noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + this->m_iterator[i] += delta; + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position. Positive increments cause + * this iterator to move backward by \a delta pixel samples. Negative + * increments move this iterator forward by \a delta pixel samples. + * Returns a reference to this iterator. + */ + const_filter_pixel_iterator& operator -=( distance_type delta ) noexcept + { + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + this->m_iterator[i] -= delta; + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Moves this iterator on the iterated image by the specified horizontal + * and vertical increments in pixels, \a dx and \a dy respectively, + * relative to its current position. Positive (negative) \a dx increments + * move the iterator rightwards (leftwards). Positive (negative) \a dy + * increments move the iterator downwards (upwards). + */ + const_filter_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + distance_type d = distance_type( dy )*this->m_image->Width() + distance_type( dx ); + for ( int i = 0; i < this->m_iterator.Length(); ++i ) + this->m_iterator[i] += d; + if ( d >= 0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_filter_pixel_iterator operator +( const const_filter_pixel_iterator& i, distance_type delta ) noexcept + { + const_filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_filter_pixel_iterator operator +( distance_type delta, const const_filter_pixel_iterator& i ) noexcept + { + const_filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_filter_pixel_iterator operator -( const const_filter_pixel_iterator& i, distance_type delta ) noexcept + { + const_filter_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const const_filter_pixel_iterator& i, const const_filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_filter_pixel_iterator& i, const const_filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + }; + + // ------------------------------------------------------------------------- + + template + class roi_filter_pixel_iterator_base : public roi_pixel_iterator_base + { + protected: + + typedef roi_pixel_iterator_base + roi_iterator_base; + + filter_type m_filter; + sample_pointer m_begin = nullptr; + + roi_filter_pixel_iterator_base() = default; + + roi_filter_pixel_iterator_base( image_type& image, const filter_type& filter, const Rect& rect ) + : roi_iterator_base( image, rect ) + , m_filter( filter ) + , m_begin( roi_iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + roi_filter_pixel_iterator_base( const roi_iterator_base& i, const filter_type& filter ) + : roi_iterator_base( i ) + , m_filter( filter ) + , m_begin( roi_iterator_base::m_iterator ) + { + JumpToNextValidSample(); + } + + roi_filter_pixel_iterator_base( const roi_filter_pixel_iterator_base& ) = default; + + roi_filter_pixel_iterator_base& operator =( const roi_filter_pixel_iterator_base& ) = default; + + roi_filter_pixel_iterator_base& operator =( const roi_iterator_base& i ) noexcept + { + (void)roi_iterator_base::operator =( i ); + JumpToNextValidSample(); + return *this; + } + + void JumpToNextValidSample() noexcept + { + while ( this->m_iterator[0] < this->m_end && !this->m_filter( this->m_iterator ) ) + roi_iterator_base::Increment(); + } + + void JumpToPrevValidSample() noexcept + { + while ( this->m_iterator[0] > this->m_begin && !this->m_filter( this->m_iterator ) ) + roi_iterator_base::Decrement(); + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::roi_filter_pixel_iterator + * \brief Mutable region-of-interest, filter pixel iterator. + * + * A mutable, region-of-interest (ROI), filter pixel iterator combines the + * capabilities of roi_pixel_iterator and filter_pixel_iterator in a single + * iterator class. + * + * \ingroup image_iterators + */ + template + class roi_filter_pixel_iterator : public roi_filter_pixel_iterator_base, sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef roi_filter_pixel_iterator_base, sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + roi_filter_pixel_iterator() = default; + + /*! + * Constructs a mutable, region-of-interest (ROI), filter pixel iterator. + * + * \param image The image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + */ + roi_filter_pixel_iterator( image_type& image, const F& filter, const Rect& rect = Rect( 0 ) ) + : iterator_base( image.EnsureUnique(), filter, rect ) + { + } + + /*! + * Constructs a mutable, region-of-interest (ROI), filter pixel iterator + * from the specified ROI pixel iterator \a i and \a filter. + */ + roi_filter_pixel_iterator( const roi_pixel_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + roi_filter_pixel_iterator( const roi_filter_pixel_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + roi_filter_pixel_iterator& operator =( const roi_filter_pixel_iterator& ) = default; + + /*! + * Assigns a ROI pixel iterator. Returns a reference to this object. + */ + roi_filter_pixel_iterator& operator =( const roi_pixel_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && !this->m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the image being iterated by this object. + */ + image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the pixel sample pointed to by this iterator in + * the specified \a channel. + */ + sample* Position( int channel ) const noexcept + { + return this->m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel iterator is active if it has not reached (or + * surpassed) its iteration limit, i.e. the bottom right corner of its + * iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator[0] < this->m_end; + } + + /*! + * Array subscript operator. Returns a reference to the pixel sample + * pointed to by this iterator in the specified \a channel. + */ + sample& operator []( int channel ) const noexcept + { + return *this->m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated region of interest. Returns a reference to + * this iterator. + */ + roi_filter_pixel_iterator& operator ++() noexcept + { + this->Increment(); + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before incrementing it. + */ + roi_filter_pixel_iterator operator ++( int ) noexcept + { + roi_filter_pixel_iterator i0( *this ); + this->Increment(); + this->JumpToNextValidSample(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated region of interest, then returns a + * reference to this iterator. + */ + roi_filter_pixel_iterator& operator --() noexcept + { + this->Decrement(); + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before decrementing it. + */ + roi_filter_pixel_iterator operator --( int ) noexcept + { + roi_filter_pixel_iterator i0( *this ); + this->Decrement(); + this->JumpToPrevValidSample(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_filter_pixel_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( delta%w, delta/w ); + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + roi_filter_pixel_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( -delta%w, -delta/w ); + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + roi_filter_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + sample* __restrict__ i0 = this->m_iterator[0]; + iterator_base::MoveBy( dx, dy ); + if ( this->m_iterator[0] >= i0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend roi_filter_pixel_iterator operator +( const roi_filter_pixel_iterator& i, distance_type delta ) noexcept + { + roi_filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend roi_filter_pixel_iterator operator +( distance_type delta, const roi_filter_pixel_iterator& i ) noexcept + { + roi_filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend roi_filter_pixel_iterator operator -( const roi_filter_pixel_iterator& i, distance_type delta ) noexcept + { + roi_filter_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const roi_filter_pixel_iterator& i, const roi_filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const roi_filter_pixel_iterator& i, const roi_filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::GenericImage::const_roi_filter_pixel_iterator + * \brief Immutable region-of-interest, filter pixel iterator. + * + * An immutable, region-of-interest (ROI), filter pixel iterator combines + * the capabilities of const_roi_pixel_iterator and + * const_filter_pixel_iterator in a single iterator class. + * + * \ingroup image_iterators + */ + template + class const_roi_filter_pixel_iterator : public roi_filter_pixel_iterator_base, const sample*, F> + { + public: + + /*! + * Represents the type of the iterated image. + */ + typedef GenericImage

image_type; + + /*! + * Represents the pixel traits class used by the iterated image. + */ + typedef typename image_type::pixel_traits pixel_traits; + + /*! + * Represents a pixel sample of the iterated image. + */ + typedef typename image_type::sample sample; + + /*! + * Represents the type of the unary predicate used by this filter + * iterator. + */ + typedef F filter_type; + + typedef roi_filter_pixel_iterator_base, const sample*, F> + iterator_base; + + /*! + * Default constructor. Initializes an invalid iterator. + */ + const_roi_filter_pixel_iterator() = default; + + /*! + * Constructs an immutable, region-of-interest (ROI), filter pixel + * iterator. + * + * \param image The constant image to iterate. + * + * \param filter Reference to a predicate object that will be used to + * filter pixel sample values. + * + * \param rect Region of interest. If an empty rectangle is specified, + * the current rectangular selection in the \a image will + * be used. If the specified rectangle is not empty and + * extends beyond image boundaries, only the intersection + * with the image will be used. If that intersection does + * not exist, then the resulting iterator will be invalid, + * with an empty iteration range. The default value is an + * empty rectangle. + */ + const_roi_filter_pixel_iterator( const image_type& image, const F& filter, const Rect& rect = Rect( 0 ) ) + : iterator_base( image, filter, rect ) + { + } + + /*! + * Constructs an immutable, region-of-interest (ROI), filter pixel + * iterator from the specified ROI pixel iterator \a i and \a filter. + */ + const_roi_filter_pixel_iterator( const const_roi_pixel_iterator& i, const F& filter ) + : iterator_base( i, filter ) + { + } + + /*! + * Copy constructor. + */ + const_roi_filter_pixel_iterator( const const_roi_filter_pixel_iterator& ) = default; + + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + const_roi_filter_pixel_iterator& operator =( const const_roi_filter_pixel_iterator& ) = default; + + /*! + * Assigns a ROI pixel iterator. Returns a reference to this object. + */ + const_roi_filter_pixel_iterator& operator =( const const_roi_pixel_iterator& i ) noexcept + { + (void)iterator_base::operator =( i ); + return *this; + } + + /*! + * Returns true only if this iterator is valid. A valid iterator defines + * a valid iterated image and a non-null position. + */ + bool IsValid() const noexcept + { + return this->m_image != nullptr && !this->m_iterator.IsEmpty(); + } + + /*! + * Returns a reference to the constant image being iterated by this + * object. + */ + const image_type& Image() const noexcept + { + return *this->m_image; + } + + /*! + * Returns a reference to the immutable predicate object used by this + * filter iterator. + */ + const filter_type& Filter() const noexcept + { + return this->m_filter; + } + + /*! + * Returns a reference to the mutable predicate object used by this + * filter iterator. + */ + filter_type& Filter() noexcept + { + return this->m_filter; + } + + /*! + * Returns a pointer to the constant pixel sample pointed to by this + * iterator in the specified \a channel. + */ + const sample* Position( int channel ) const noexcept + { + return this->m_iterator[channel]; + } + + /*! + * Boolean type conversion operator. Returns true if this iterator is + * active. A ROI pixel iterator is active if it has not reached (or + * surpassed) its iteration limit, i.e. the bottom right corner of its + * iterated region of interest. + */ + operator bool() const noexcept + { + return this->m_iterator[0] < this->m_end; + } + + /*! + * Array subscript operator. Returns a reference to the constant pixel + * sample pointed to by this iterator in the specified \a channel. + */ + const sample& operator []( int channel ) const noexcept + { + return *this->m_iterator[channel]; + } + + /*! + * Pre-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated region of interest. Returns a reference to + * this iterator. + */ + const_roi_filter_pixel_iterator& operator ++() noexcept + { + this->Increment(); + this->JumpToNextValidSample(); + return *this; + } + + /*! + * Post-increment operator. Causes this iterator to point to the next + * valid pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before incrementing it. + */ + const_roi_filter_pixel_iterator operator ++( int ) noexcept + { + const_roi_filter_pixel_iterator i0( *this ); + this->Increment(); + this->JumpToNextValidSample(); + return i0; + } + + /*! + * Pre-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated region of interest, then returns a + * reference to this iterator. + */ + const_roi_filter_pixel_iterator& operator --() noexcept + { + this->Decrement(); + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Post-decrement operator. Causes this iterator to point to the previous + * valid pixel in the iterated region of interest. Returns a copy of the + * iterator as it was before decrementing it. + */ + const_roi_filter_pixel_iterator operator --( int ) noexcept + { + const_roi_filter_pixel_iterator i0( *this ); + this->Decrement(); + this->JumpToPrevValidSample(); + return i0; + } + + /*! + * Scalar assignment/addition operator. Increments this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move forward (rightwards and downwards) by \a delta pixel + * samples. Negative increments move this iterator backward (leftwards + * and upwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_filter_pixel_iterator& operator +=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( delta%w, delta/w ); + } + + /*! + * Scalar assignment/subtraction operator. Decrements this iterator by a + * distance \a delta from its current position, within the rectangular + * region of interest being iterated. Positive increments cause this + * iterator to move backward (leftwards and upwards) by \a delta pixel + * samples. Negative increments move this iterator forward (rightwards + * and downwards) by \a delta pixel samples. Returns a reference to this + * iterator. + */ + const_roi_filter_pixel_iterator& operator -=( distance_type delta ) noexcept + { + int w = this->m_rowEnd - this->m_rowBegin; + return MoveBy( -delta%w, -delta/w ); + } + + /*! + * Moves this iterator within its rectangular region of interest by the + * specified horizontal and vertical increments in pixels, \a dx and + * \a dy respectively, relative to its current position. Positive + * (negative) \a dx increments move the iterator rightwards (leftwards). + * Positive (negative) \a dy increments move the iterator downwards + * (upwards). + */ + const_roi_filter_pixel_iterator& MoveBy( int dx, int dy ) noexcept + { + const sample* __restrict__ i0 = this->m_iterator[0]; + iterator_base::MoveBy( dx, dy ); + if ( this->m_iterator[0] >= i0 ) + this->JumpToNextValidSample(); + else + this->JumpToPrevValidSample(); + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to the specified iterator \a i incremented by a distance \a delta. + */ + friend const_roi_filter_pixel_iterator operator +( const const_roi_filter_pixel_iterator& i, distance_type delta ) noexcept + { + const_roi_filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Iterator-to-scalar addition operator. This operator implements the + * commutative property of scalar-to-iterator addition. + */ + friend const_roi_filter_pixel_iterator operator +( distance_type delta, const const_roi_filter_pixel_iterator& i ) noexcept + { + const_roi_filter_pixel_iterator j( i ); + j += delta; + return j; + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * the specified iterator \a i decremented by a distance \a delta. + */ + friend const_roi_filter_pixel_iterator operator -( const const_roi_filter_pixel_iterator& i, distance_type delta ) noexcept + { + const_roi_filter_pixel_iterator j( i ); + j -= delta; + return j; + } + + /*! + * Equality operator. Returns true if two iterators \a i and \a j point + * to the same pixel. + */ + friend bool operator ==( const const_roi_filter_pixel_iterator& i, const const_roi_filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] == j.m_iterator[0]; + } + + /*! + * Less than operator. Returns true if the specified iterator \a i + * precedes another iterator \a j. + */ + friend bool operator <( const const_roi_filter_pixel_iterator& i, const const_roi_filter_pixel_iterator& j ) noexcept + { + return i.m_iterator[0] < j.m_iterator[0]; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * Returns true iff this %GenericImage template instantiation uses floating + * point pixel samples; returns false if it uses integer samples. + */ + static bool IsFloatSample() noexcept + { + return pixel_traits::IsFloatSample(); + } + + /*! + * Returns true iff this %GenericImage template instantiation uses complex + * pixel samples; returns false if it uses real samples. + */ + static bool IsComplexSample() noexcept + { + return pixel_traits::IsComplexSample(); + } + + /*! + * Returns the number of 8-bit bytes required to store a pixel sample in + * this %GenericImage template instantiation. + */ + static int BytesPerSample() noexcept + { + return P::BytesPerSample(); + } + + /*! + * Returns the number of bits in a pixel sample of this %GenericImage + * template instantiation. + */ + static int BitsPerSample() noexcept + { + return P::BitsPerSample(); + } + + /*! + * Returns true iff this object and another \a image use the same pixel + * sample type: + * + * \li Same sample size in bits. + * \li Both images using integer, floating point real, or complex samples. + */ + template + bool SameSampleType( const GenericImage& image ) const noexcept + { + return image.BitsPerSample() == BitsPerSample() && + image.IsFloatSample() == IsFloatSample() && + image.IsComplexSample() == IsComplexSample(); + } + + /*! + * Always returns true, indicating that this object and the specified + * \a image, both of the same template instantiation, use the same pixel + * sample type. + */ + bool SameSampleType( const GenericImage& image ) const noexcept + { + return true; + } + + // ------------------------------------------------------------------------- + + /*! + * Constructs a default local image. This object will be initialized as an + * empty grayscale image with local storage. + */ + GenericImage() + { + m_data = new Data( this ); + } + + /*! + * Copy constructor. Constructs a local image to store a copy of the + * currently selected pixel samples in a local or shared image. The behavior + * of this constructor depends on the current selections and storage type of + * the specified source \a image: + * + * \li If the source object is a shared image, then this constructor will + * create a duplicate of its current selection as a local image. + * + * \li If the source object is a completely selected local image + * (see the note below), then this object will reference the same image + * data, and hence no duplicate of the existing pixel data will be + * generated. This enables the copy-on-write (or implicit data sharing) + * functionality of %GenericImage. + * + * \li If the source image is only partially selected, then a local image + * will be initialized to store in this object a copy of the selected pixel + * samples in the source image. If the selected range of channels is smaller + * than the required number of nominal channels for the source color space, + * then this object will be in the grayscale space. Otherwise this object + * will inherit the color space of the source \a image. + * + * \note In a completely selected image, the current rectangular selection + * includes the entire image boundaries, and the range of selected channels + * comprises all existing channels, including all nominal and alpha + * channels. By default, all images are completely selected. A complete + * selection is also enabled after calling the inherited + * ImageGeometry::ResetSelections() member function. + */ + GenericImage( const GenericImage& image ) + { + if ( !image.IsShared() ) + if ( image.IsCompletelySelected() ) + { + image.m_data->Attach( this ); + m_data = image.m_data; + m_status = image.m_status; + ResetSelections(); + return; + } + + m_data = new Data( this ); + (void)Assign( image ); + } + + /*! + * Move constructor. + */ + GenericImage( GenericImage&& image ) + : AbstractImage( image ) + , m_data( image.m_data ) + { + image.m_data = nullptr; + } + + /*! + * Constructs a local image to store a copy of the specified \a image, which + * belongs to a different template instantiation. + * + * This constructor generates a uniquely referenced duplicate of the current + * selection of pixel samples in the specified \a image, converted to the + * sample type of this template instantiation. + * + * \note Don't confuse this constructor with the copy constructor for + * %GenericImage. Note that the source \a image argument is a reference to a + * different template instantiation of %GenericImage. + */ + template + GenericImage( const GenericImage& image ) + { + m_data = new Data( this ); + (void)Assign( image ); + } + + /*! + * Constructs a local image to store a copy of a subset of pixel samples in + * the specified \a image. + * + * \param image Source image. + * + * \param rect Source rectangular selection. If this parameter defines an + * empty rectangle, the current rectangular selection in the + * source \a image will be used. If the specified rectangle + * is not empty and extends beyond the boundaries of the + * source \a image, only the intersection with the source + * \a image will be used. If that intersection does not + * exist, this constructor will initialize an empty image. + * + * \param firstChannel Zero-based index of the first channel to copy. If + * a negative index is specified, the first selected channel + * in the source \a image will be used. If the specified + * index is larger than or equal to the number of existing + * channels in the source \a image, this constructor will + * initialize an empty image. The default value is -1. + * + * \param lastChannel Zero-based index of the last channel to copy. If + * a negative index is specified, the last selected channel + * in the source \a image will be used. If the specified + * index is larger than or equal to the number of existing + * channels in the source \a image, this constructor will + * initialize an empty image. The default value is -1. + * + * If the specified source \a image and this object use different pixel + * sample types, this constructor will use pixel traits primitives to + * perform all the necessary data type conversions between different pixel + * sample types transparently. + * + * \note This constructor will always generate a uniquely referenced, local + * image, irrespective of whether the \a rect, \a firstChannel and + * \a lastChannel parameters define a complete or partial selection for the + * specified source \a image. To make use of the implicit data sharing + * mechanism of %GenericImage, use the copy constructor and make sure that + * the source \a image is completely selected. + */ + template + GenericImage( const GenericImage& image, const Rect& rect, int firstChannel = -1, int lastChannel = -1 ) + { + m_data = new Data( this ); + (void)Assign( image, rect, firstChannel, lastChannel ); + } + + /*! + * Constructs a local image with the specified dimensions and color space. + * + * \param width Width in pixels of the newly created image. + * + * \param height Height in pixels of the newly created image. + * + * \param colorSpace Color space. See the ColorSpace namespace for + * symbolic constants. If this parameter is not specified, a + * grayscale image will be constructed. + * + * The number of channels in the constructed image will depend on the + * specified color space. Grayscale images will have a single channel. In + * general, color images will have three channels. + * + * \note Pixel samples in the newly constructed image are not initialized by + * this constructor, so the image will contain unpredictable values. + */ + GenericImage( int width, int height, color_space colorSpace = ColorSpace::Gray ) + { + m_data = new Data( this ); + m_data->Allocate( width, height, ColorSpace::NumberOfNominalChannels( colorSpace ), colorSpace ); + ResetSelections(); + } + + /*! + * Constructs a local image with data read from a raw-storage stream. + * + * \param stream Reference to an input stream where a raw image has been + * previously stored (e.g. with the Write() member function). + * + * The input \a stream must provide sample values in the sample data type of + * this image. The sample data type of an image is invariantly defined by + * its template instantiation, and thus cannot be changed. + * + * \warning If the image stored in the input \a stream and this image use + * different pixel sample data types, this function will throw an Error + * exception with the appropriate error message. + */ + explicit GenericImage( File& stream ) + { + m_data = new Data( this ); + Read( stream ); + } + + /*! + * Constructs a shared, client-side managed image corresponding to a + * server-side image living in the PixInsight core application. + * + * \param handle A low-level API handle to an existing image in the + * PixInsight core application. + * + * Shared images are alias objects referencing server-side images living + * within the PixInsight core application. Shared images allocate pixel data + * in the core application's heap, which we call shared memory. + * + * Local images exist within the user module's local heap, including all of + * their pixel data. + * + * PCL implements an abstraction mechanism that allows you to handle local + * and shared images transparently. Except in very few and special cases, + * you don't have to know whether you're working with a shared or a local + * image; your code will be exactly the same under both situations. + */ + explicit GenericImage( void* handle ) + { + m_data = new Data( this, handle ); + ResetSelections(); + } + + /*! + * Constructs a new shared image with the specified geometry and color. + * + * \param width Width in pixels of the newly created image. + * + * \param height Height in pixels of the newly created image. + * + * \param colorSpace Color space. See the ColorSpace namespace for + * symbolic constants. If this parameter is not specified, a + * grayscale image will be constructed. + * + * The first \c void* parameter is strictly formal. Its value will be + * ignored as its sole purpose is to distinguish this constructor from the + * corresponding local storage constructor. + * + * The number of channels in the constructed image will depend on the + * specified color space. Grayscale images will have a single channel. In + * general, color images will have three channels. + * + * A shared image created with this constructor can be used for intermodule + * communication tasks, such as file I/O operations with the FileFormat and + * FileFormatInstance classes, and execution of processes with Process and + * ProcessInstance. + * + * \note Pixel samples in the newly constructed image are not initialized by + * this constructor, so the image will contain unpredictable values. + */ + GenericImage( void*, int width, int height, color_space colorSpace = ColorSpace::Gray ) + { + m_data = new Data( this, width, height, ColorSpace::NumberOfNominalChannels( colorSpace ), colorSpace ); + ResetSelections(); + } + + /*! + * Destroys a %GenericImage instance. If this is a nonempty local or shared + * image, the image data associated with this object are dereferenced. If + * the image data become unreferenced, they are also destroyed. + * + * The internal allocator object does all the necessary clean-up work for + * both local and shared images transparently: + * + * \li When a local image becomes unreferenced, all the internal data + * structures are destroyed and the memory space in use to store pixel + * samples is released immediately in the local heap of the calling module. + * + * \li When a shared image becomes unreferenced, the server-side image is + * dereferenced. When the server-side shared image becomes unreferenced, it + * is garbage-collected and eventually destroyed by the PixInsight core + * application. + */ + virtual ~GenericImage() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + // ------------------------------------------------------------------------- + + /*! + * Returns true iff this object is a shared image. Returns false if this is + * a local image. + * + * Shared images are alias objects referencing actual images living within + * the PixInsight core application. Shared images allocate pixel data in + * the core application's heap, which we call shared memory. + * + * Local images exist within the user module's local heap, including all of + * their pixel data. + * + * PCL implements an abstraction mechanism that allows you to handle local + * and shared images transparently. Except in very few and special cases, + * you don't have to know whether you're working with a shared or a local + * image; your code will be exactly the same under both situations. + */ + bool IsShared() const noexcept + { + return m_data->IsShared(); + } + + /*! + * Returns true iff this object uniquely references its pixel data. Returns + * false if this object is sharing its pixel data with other %GenericImage + * instances. + * + * \note Don't confuse uniqueness of reference with local or shared storage + * of images. A %GenericImage can share its data with other instances living + * in the local heap of the calling module, irrespective of whether the + * pixel data is local or shared. + */ + bool IsUnique() const noexcept + { + return m_data->IsUnique(); + } + + /*! + * Ensures that this image uses local pixel data storage. Returns a + * reference to this image. + * + * If this object is already a local image, then calling this member + * function has no effect. + * + * If the image is shared, then this function creates a local duplicate, + * dereferences the previously referenced pixel data, and references the + * newly created local duplicate. Upon returning, this image will uniquely + * reference its pixel data. + */ + GenericImage& EnsureLocal() + { + if ( m_data->IsShared() ) + { + GenericImage local_; + GenericImage* local = &local_; // ### Workaround to GCC 7's 'dereferencing type-punned pointer' bugs + local->m_data->Allocate( m_width, m_height, m_numberOfChannels, m_colorSpace ); + local->m_RGBWS = m_RGBWS; + local->m_selected = m_selected; + local->m_savedSelections = m_savedSelections; + local->m_status = m_status; + for ( int c = 0; c < m_numberOfChannels; ++c ) + P::Copy( (*local)[c], m_channelData( c ), NumberOfPixels() ); + + local->m_data->Attach( this ); + DetachFromData(); + m_data = local->m_data; + } + return *this; + } + + /*! + * Ensures that this object uniquely references its pixel data, making a + * unique copy of its referenced pixel data if necessary. Returns a + * reference to this image. + * + * If this object is not sharing its pixel data with other %GenericImage + * instances, then calling this member function has no effect. + * + * If this object is sharing its pixel data with other instances, then the + * previously referenced pixel data are dereferenced, and a newly created + * copy of the pixel data is uniquely referenced by this image. In this case + * this object will always be a \e local image after calling this function: + * newly created duplicates of existing pixel data are always allocated in + * the local heap of the calling module. + */ + GenericImage& EnsureUnique() + { + if ( !m_data->IsUnique() ) + { + Data* newData = m_data->Clone( this ); + DetachFromData(); + m_data = newData; + } + return *this; + } + + /*! + * Returns a reference to the internal pixel allocator object associated + * with this image. + * + * The type of the allocator object is a template specialization of the + * PixelAllocator class for the sample data type of this image. The + * allocator is responsible for dynamic allocation of pixel data, including + * channel slots (pointers to pixel sample blocks) and pixel sample + * blocks (used to store channel pixel data). + * + * The allocator must be able to handle dynamic allocation for local and + * shared memory transparently. This means that the allocator object knows + * whether this is a local image (allocated in the calling module's heap) or + * a shared image (allocated in the PixInsight core's heap), and allows you + * to manage and allocate pixel data without distinction in both cases. + * + * \warning \e Never use the \c new and \c delete operators with pixel data + * memory blocks. Always call the Allocator() member function of + * %GenericImage to get a reference to its PixelAllocator object, then use + * its public member functions for all allocations and deallocations of + * pixel data. + */ + pixel_allocator& Allocator() const noexcept + { + return m_allocator; + } + + /*! + * \internal Synchronizes this object with the server-side shared image, if + * this is a shared client-side image. Does nothing if this is a local + * image allocated in the calling module's heap. + */ + void Synchronize() + { + m_data->SynchronizeWithSharedImage(); + ResetSelections(); + } + + /*! + * Allocates new pixel data with the specified geometry and color space. + * Returns a reference to this image. + * + * \param width New image width in pixels. + * + * \param height New image height in pixels. + * + * \param numberOfChannels Number of channels. Must be greater than or + * equal to the number of nominal channels corresponding to + * the specified color space: one for grayscale images; three + * for color images. If this parameter is not specified, a + * single grayscale channel will be allocated. + * + * \param colorSpace New color space. See the ColorSpace namespace + * for symbolic constants. If this parameter is not + * specified, new image data will be allocated in the + * grayscale space. + * + * If this object uniquely references its pixel data, then the previously + * existing pixel data are destroyed, deallocated, and replaced with a newly + * allocated local or shared image, preserving the storage space of this + * instance. + * + * If this object is not unique, then the previously referenced pixel data + * are dereferenced, and a newly created local image is uniquely referenced + * by this object and allocated with the specified parameters. + * + * All image selections are reset to the default full selection after + * calling this function. + * + * \note Newly allocated pixel samples are not initialized, so the image + * will contain unpredictable values after calling this member function. + */ + GenericImage& AllocateData( int width, int height, + int numberOfChannels = 1, + color_space colorSpace = ColorSpace::Gray ) + { + if ( !m_data->IsUnique() ) + { + Data* newData = new Data( this ); + DetachFromData(); + m_data = newData; + } + m_data->Allocate( width, height, numberOfChannels, colorSpace ); + ResetSelections(); + return *this; + } + + /*! + * Allocates new pixel data with the specified geometry and color space. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * AllocateData( rect.Width(), rect.Height(), numberOfChannels, colorSpace ); + * \endcode + */ + GenericImage& AllocateData( const Rect& rect, + int numberOfChannels = 1, + color_space colorSpace = ColorSpace::Gray ) + { + return AllocateData( rect.Width(), rect.Height(), numberOfChannels, colorSpace ); + } + + /*! + * Causes this object to reference an empty image. Returns a reference to + * this image. + * + * If this object uniquely references its pixel data, then the pixel data + * are destroyed and deallocated immediately. + * + * If this object is not unique, then the previously referenced pixel data + * are dereferenced, and a newly created empty local image is uniquely + * referenced by this object. + */ + GenericImage& FreeData() + { + if ( !m_data->IsEmpty() ) + if ( m_data->IsUnique() ) + m_data->Deallocate(); + else + { + Data* newData = new Data( this ); + DetachFromData(); + m_data = newData; + } + ResetSelections(); + return *this; + } + + /*! + * Forces this image to acquire the specified pixel data. Returns a + * reference to this image. + * + * \param data Starting address of the acquired pixel data. Must be + * either a null pointer, or a pointer to an array of + * contiguous blocks of pixel samples. + * + * \param width Width in pixels of the acquired pixel data. + * + * \param height Height in pixels of the acquired pixel data. + * + * \param numberOfChannels Number of channels in the acquired data. Must + * be greater than or equal to the number of nominal channels + * corresponding to the specified color space: one for + * grayscale images; three for color images. If this + * parameter is not specified, a single grayscale channel is + * assumed. + * + * \param colorSpace Color space of the acquired data. See the + * ColorSpace namespace for symbolic constants. If this + * parameter is not specified, the grayscale space is assumed + * for the acquired data. + * + * If this object uniquely references its pixel data, then the previously + * existing pixel data are destroyed, deallocated, and replaced with the + * specified local or shared \a data, preserving the storage space of this + * instance. + * + * If this object is a non-unique local image, then the previously + * referenced pixel data are dereferenced, and a newly created local image + * is uniquely referenced by this object and forced to own the specified + * local \a data. + * + * If this object is a non-unique shared image, then this member function + * throws an Error exception with the appropriate error message: An aliased + * shared image cannot be forced to store externally allocated pixel data. + * + * When successful, this function resets all image selections to the default + * full selection. + * + * \warning When calling this member function for a shared image, always + * make sure that the passed \a data array and the pointed data blocks have + * been allocated as shared memory. If you pass a locally-allocated array or + * block to this function (e.g., a \c new'ed block), you may cause severe + * heap corruption in the PixInsight core application. Similarly, if the + * image is local, only locally-allocated arrays and blocks must be used. In + * other words: shared and local pixel data and images cannot be mixed. + * + * \warning \e Never use the \c new and \c delete operators with pixel data + * memory blocks. Always call the Allocator() member function of + * %GenericImage to get a reference to its PixelAllocator object, then use + * its public member functions for all allocations and deallocations of + * pixel data. + */ + GenericImage& ImportData( sample** data, int width, int height, + int numberOfChannels = 1, color_space colorSpace = ColorSpace::Gray ) + { + if ( !m_data->IsUnique() ) + { + if ( m_data->IsShared() ) + throw Error( "GenericImage::ImportData(): Invalid operation for an aliased shared image" ); + Data* newData = new Data( this ); + DetachFromData(); + m_data = newData; + } + m_data->Import( data, width, height, numberOfChannels, colorSpace ); + ResetSelections(); + return *this; + } + + /*! + * Releases ownership of the pixel data allocated by this image. + * + * Returns an array of pointers to the channel data blocks that were owned + * by the image before calling this function. The returned array is a + * sequence of pointers p0, p1, ..., pn-1, where each pi is the starting + * address of a contiguous block containing the sample data of an image + * channel, and n is the number of channels in the image, including all + * nominal and alpha channels. + * + * After calling this function the image will be empty, but the returned + * data will not be deallocated; the caller will be responsible for + * deallocating it when it is no longer needed. + * + * If this member function is called for an aliased image, it throws an + * Error exception with the appropriate error message: Pixel data cannot be + * released if two or more %GenericImage instances are referencing them. + * The reason for this limitation is that if the data of a non-unique image + * were released, either all instances sharing the same data would be + * affected, which violates the implicit data sharing paradigm, or the newly + * allocated data of a unique clone would be released, which makes no sense. + * + * \warning When calling ReleaseData() for a shared image, always be aware + * that the returned \c sample** value points to a \e shared memory block. + * If you handle such a block as if it was a block within your local heap + * (e.g., if you call the \c delete operator to deallocate it), you may + * cause severe heap corruption. + * + * \warning \e Never use the \c new and \c delete operators with pixel data + * memory blocks. Always call the Allocator() member function of + * %GenericImage to get a reference to its PixelAllocator object, then use + * its public member functions for all allocations and deallocations of + * pixel data. + */ + sample** ReleaseData() + { + if ( !m_data->IsUnique() ) + throw Error( "GenericImage::ReleaseData(): Invalid operation for an aliased image" ); + sample** data = m_data->Release(); + ResetSelections(); + return data; + } + + // ------------------------------------------------------------------------- + + /*! + * Returns the size in bytes of a row of pixels in this image (also known as + * a scan line). + */ + size_type LineSize() const noexcept + { + return BytesPerSample() * size_type( m_width ); + } + + /*! + * Returns the size in bytes of a channel of this image. This is equal to + * the area in square pixels multiplied by BytesPerSample(). + */ + size_type ChannelSize() const noexcept + { + return BytesPerSample() * NumberOfPixels(); + } + + /*! + * Returns the size in bytes of all memory blocks required to store the + * pixel data in this image, including nominal and alpha channels. This is + * equal to the area in square pixels multiplied by the number of channels, + * multiplied by BytesPerSample(). + */ + size_type ImageSize() const noexcept + { + return ChannelSize() * size_type( m_numberOfChannels ); + } + + /*! + * Returns the size in bytes of all memory blocks required to store the + * pixel data in the nominal channels of this image (i.e., \e excluding + * alpha channels). + */ + size_type NominalSize() const noexcept + { + return ChannelSize() * NumberOfNominalChannels(); + } + + /*! + * Returns the size in bytes of all memory blocks required to store the + * pixel data in the alpha channels of this image (i.e., \e excluding + * nominal channels). Returns zero if this image has no alpha channels. + */ + size_type AlphaSize() const noexcept + { + return ChannelSize() * NumberOfAlphaChannels(); + } + + /*! + * Returns a pointer to the first pixel sample in the specified \a channel. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * The returned value is the address of the pixel at coordinates x=y=0 in + * the specified \a channel. + * + * If this image is aliased, it is made unique before returning from this + * member function. This involves making a local duplicate of the previously + * referenced pixel data. + */ + sample* PixelData( int channel = 0 ) + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + EnsureUnique(); + return m_channelData( channel ); + } + + /*! + * Returns a pointer to the constant first pixel sample in the specified + * \a channel. + * + * This member function is the immutable counterpart of PixelData( int ). + */ + const sample* PixelData( int channel = 0 ) const noexcept + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + return m_channelData( channel ); + } + + /*! + * Returns true only is this is a valid, nonempty image. + */ + operator bool() const noexcept + { + return m_data != nullptr && !m_data->IsEmpty(); + } + + /*! + * Returns a pointer to the first pixel sample in the specified \a channel. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. + * + * This operator is a convenience synonym for the PixelData( int ) member + * function. + */ + sample* operator []( int channel ) + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + return PixelData( channel ); + } + + /*! + * Returns a pointer to the constant first pixel sample in the specified + * \a channel. + * + * This operator function is the immutable counterpart of operator []( int ). + */ + const sample* operator []( int channel ) const noexcept + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + return PixelData( channel ); + } + + /*! + * Returns a pointer to the first pixel sample in the first channel of this + * image. + * + * For grayscale images, this function can be more readable and elegant than + * operator []( int ). + */ + sample* operator *() + { + PCL_PRECONDITION( 0 < m_numberOfChannels ) + return PixelData( 0 ); + } + + /*! + * Returns a pointer to the constant first pixel sample in the first channel + * of this image. + * + * This operator function is the immutable counterpart of operator *(). + */ + const sample* operator *() const noexcept + { + PCL_PRECONDITION( 0 < m_numberOfChannels ) + return PixelData( 0 ); + } + + /*! + * Returns the starting address of a scan line (i.e., a row of + * pixels) in this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, such that 0 ≤ \a y < \a h, where \a h is the + * height in pixels of this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * The returned value is a pointer to the sample at coordinates (x=0,y) in + * the specified \a channel. + * + * If this image is aliased, it is made unique before returning from this + * member function. This involves making a local duplicate of the previously + * referenced pixel data. + */ + sample* ScanLine( int y, int channel = 0 ) + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + PCL_PRECONDITION( 0 <= y && y < m_height ) + EnsureUnique(); + return m_channelData( channel ) + RowOffset( y ); + } + + /*! + * Returns the starting address of a constant scan line (i.e., a + * row of pixels) in this image. + * + * This member function is the immutable counterpart of ScanLine( int, int ). + */ + const sample* ScanLine( int y, int channel = 0 ) const noexcept + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + PCL_PRECONDITION( 0 <= y && y < m_height ) + return m_channelData( channel ) + RowOffset( y ); + } + + /*! + * Returns the address of a pixel sample in this image, given by its pixel + * coordinates and channel index. + * + * \param x Horizontal coordinate (or column index) of the desired + * pixel, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * The returned value is a pointer to the sample at coordinates (x,y) in the + * specified \a channel. + * + * If this image is aliased, it is made unique before returning from this + * member function. This involves making a local duplicate of the previously + * referenced pixel data. + */ + sample* PixelAddress( int x, int y, int channel = 0 ) + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + PCL_PRECONDITION( 0 <= x && x < m_width ) + PCL_PRECONDITION( 0 <= y && y < m_height ) + EnsureUnique(); + return m_channelData( channel ) + PixelOffset( x, y ); + } + + /*! + * Returns the address of a constant pixel sample in this image, given by + * its pixel coordinates and channel index. + * + * This member function is the immutable counterpart of PixelAddress( int, int, int ). + */ + const sample* PixelAddress( int x, int y, int channel = 0 ) const noexcept + { + PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels ) + PCL_PRECONDITION( 0 <= x && x < m_width ) + PCL_PRECONDITION( 0 <= y && y < m_height ) + return m_channelData( channel ) + PixelOffset( x, y ); + } + + /*! + * Returns the address of a pixel sample in this image, given by its pixel + * position and channel index. + * + * \param p Position of the desired pixel in image coordinates. The + * specified point must be included in the image bounds + * rectangle, that is, its coordinates must refer to an + * existing pixel in this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * The returned value is a pointer to the sample at coordinates (p.x,p.y) in + * the specified \a channel. + * + * If this image is aliased, it is made unique before returning from this + * member function. This involves making a local duplicate of the previously + * referenced pixel data. + */ + sample* PixelAddress( const Point& p, int channel = 0 ) + { + return PixelAddress( p.x, p.y, channel ); + } + + /*! + * Returns the address of a constant pixel sample in this image, given by + * its pixel position and channel index. + * + * This member function is the immutable counterpart of + * PixelAddress( const Point&, int ). + */ + const sample* PixelAddress( const Point& p, int channel = 0 ) const noexcept + { + return PixelAddress( p.x, p.y, channel ); + } + + /*! + * Returns a reference to a pixel sample in this image, given by its pixel + * coordinates and channel index. + * + * \param x Horizontal coordinate (or column index) of the desired + * pixel, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * If this image is aliased, it is made unique before returning from this + * member function. This involves making a local duplicate of the previously + * referenced pixel data. + */ + sample& operator ()( int x, int y, int channel = 0 ) + { + return *PixelAddress( x, y, channel ); + } + + /*! + * Returns a pixel sample value, given by its pixel coordinates and channel + * index. + * + * \param x Horizontal coordinate (or column index) of the desired + * pixel, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + */ + sample operator ()( int x, int y, int channel = 0 ) const noexcept + { + return *PixelAddress( x, y, channel ); + } + + /*! + * Returns a reference to a pixel sample in this image, given by its pixel + * position and channel index. + * + * \param p Position of the desired pixel in image coordinates. The + * specified point must be included in the image bounds + * rectangle, that is, its coordinates must refer to an + * existing pixel in this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * If this image is aliased, it is made unique before returning from this + * member function. This involves making a local duplicate of the previously + * referenced pixel data. + */ + sample& operator ()( const Point& p, int channel = 0 ) + { + return *PixelAddress( p, channel ); + } + + /*! + * Returns a pixel sample value, given by its pixel position and channel + * index. + * + * \param p Position of the desired pixel in image coordinates. The + * specified point must be included in the image bounds + * rectangle, that is, its coordinates must refer to an + * existing pixel in this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + */ + sample operator ()( const Point& p, int channel = 0 ) const noexcept + { + return *PixelAddress( p, channel ); + } + + /*! + * Returns a reference to a pixel sample in this image, given by its pixel + * coordinates and channel index. + * + * \deprecated This member function has been deprecated. Use + * GenericImage::operator()( int, int, int ) in newly produced code. + */ + sample& Pixel( int x, int y, int channel = 0 ) + { + return operator()( x, y, channel ); + } + + /*! + * Returns a pixel sample value, given by its pixel coordinates and channel + * index. + * + * \deprecated This member function has been deprecated. Use + * GenericImage::operator()( int, int, int ) const in newly produced code. + */ + sample Pixel( int x, int y, int channel = 0 ) const noexcept + { + return operator()( x, y, channel ); + } + + /*! + * Returns a reference to a pixel sample in this image, given by its pixel + * position and channel index. + * + * \deprecated This member function has been deprecated. Use + * GenericImage::operator()( const Point&, int ) in newly produced code. + */ + sample& Pixel( const Point& p, int channel = 0 ) + { + return operator()( p, channel ); + } + + /*! + * Returns a pixel sample value, given by its pixel position and channel + * index. + * + * \deprecated This member function has been deprecated. Use + * GenericImage::operator()( const Point&, int ) const in newly produced + * code. + */ + sample Pixel( const Point& p, int channel = 0 ) const noexcept + { + return operator()( p, channel ); + } + + // ------------------------------------------------------------------------- + + /*! + * Associates an RGB working space \a RGBWS with this image. + * + * \note For shared images (i.e. images living in the PixInsight core + * application), the RGB working space cannot be changed by calling this + * member function. + */ + void SetRGBWorkingSpace( const RGBColorSystem& RGBWS ) override + { + if ( !IsShared() ) + { + EnsureUnique(); + m_RGBWS = RGBWS; + } + } + + // ------------------------------------------------------------------------- + + /*! + * Copies pixel samples from the specified source \a image to this image. + * Returns a reference to this image. + * + * \param image Source image. + * + * \param rect Source rectangular selection. If this parameter defines an + * empty rectangle, the current rectangular selection in the + * source \a image will be used. If the specified rectangle + * is not empty and extends beyond source \a image + * boundaries, only the intersection with the source \a image + * will be used. If that intersection does not exist, then + * this image will be empty after calling this member + * function. The default value is an empty rectangle. + * + * \param firstChannel Zero-based index of the first channel to copy. If a + * negative value is specified, the first selected channel in + * the source \a image will be used. If the specified value + * is larger than or equal to the number of existing channels + * in the source \a image, then this image will be empty + * after calling this function. The default value is -1. + * + * \param lastChannel Zero-based index of the last channel to copy. If a + * negative value is specified, the last selected channel in + * the source \a image will be used. If the specified value + * is larger than or equal to the number of existing channels + * in the source \a image, then this image will be empty + * after calling this function. The default value is -1. + * + * Previously referenced data in this image will be dereferenced, and + * immediately destroyed if they become unreferenced. + * + * If this image and the specified source \a image are (a) compatible in + * terms of pixel sample types, (b) both are local images, and (c) the + * source \a image is completely selected, then this member function just + * references the same pixel data, enabling the implicit data sharing + * mechanism of %GenericImage. In this case, existing pixel data in the + * source \a image are not duplicated, and no allocation is performed. + * + * If this member function causes a reallocation of pixel data, the newly + * allocated data will be uniquely referenced by this image. + * + * The source \a image can be an instance of any supported template + * instantiation of %GenericImage, not necessarily of the same instantiation + * than this image. All the necessary data type conversions are performed + * transparently. If pixel sample types are different, source data are + * transformed to the data type of this image. This involves conversions + * from the source data type P1::sample to the target data type P::sample, + * as per pixel traits primitives. + * + * \note It is very important to point out that the storage class of an + * image cannot be changed with this member function, even if this image and + * the source image belong to the same template instantiation. For example: + * + * \code + * Image aSharedImage( (void*)0, 0, 0 ); + * ... + * Image local; + * ... + * local.Assign( aSharedImage ); // local continues being a local image. + * // It now stores a copy of aSharedImage's + * // pixel data. + * local = aSharedImage; // Same as above, since the assignment operator is + * // just an alias for the Assign() function. + * + * ImageVariant otherShared; + * otherShared.CreateSharedFloatImage(); + * otherShared.AssignImage( local ); // otherShared is still a shared image. + * \endcode + */ + template + GenericImage& Assign( const GenericImage& image, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + m_status = image.Status(); + + Rect r = rect; + if ( !image.ParseSelection( r, firstChannel, lastChannel ) ) + { + FreeData(); + return *this; + } + + int n = 1 + lastChannel - firstChannel; + AllocateData( r, n, (firstChannel == 0 && n >= ColorSpace::NumberOfNominalChannels( image.ColorSpace() )) ? + image.ColorSpace() : ColorSpace::Gray ); + + if ( !IsShared() ) // ### cannot modify a shared image's RGBWS + m_RGBWS = image.RGBWorkingSpace(); + + ResetSelections(); + + if ( r == image.Bounds() ) + for ( int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel ) + P::Copy( m_channelData( c ), image[firstChannel], NumberOfPixels() ); + else + for ( int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel ) + { + sample* f = m_channelData( c ); + const typename P1::sample* g = image.PixelAddress( r.LeftTop(), firstChannel ); + for ( int y = 0; y < m_height; ++y, f += m_width, g += image.Width() ) + P::Copy( f, g, m_width ); + } + + return *this; + } + + GenericImage& Assign( const GenericImage& image, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + m_status = image.Status(); + + Rect r = rect; + if ( !image.ParseSelection( r, firstChannel, lastChannel ) ) + { + FreeData(); + return *this; + } + +#define completeSelection (firstChannel == 0 && lastChannel == image.m_numberOfChannels-1 && r == image.Bounds()) + + if ( m_data == image.m_data ) + { + // Self-assignment + if ( !completeSelection ) + { + GenericImage result( image, r, firstChannel, lastChannel ); // ### implicit recursion + result.m_data->Attach( this ); + DetachFromData(); + m_data = result.m_data; + } + ResetSelections(); + return *this; + } + + if ( !IsShared() ) + if ( !image.IsShared() ) + if ( completeSelection ) + { + image.m_data->Attach( this ); + DetachFromData(); + m_data = image.m_data; + ResetSelections(); + return *this; + } + +#undef completeSelection + + int n = 1 + lastChannel - firstChannel; + AllocateData( r, n, (firstChannel == 0 && n >= ColorSpace::NumberOfNominalChannels( image.ColorSpace() )) ? + image.ColorSpace() : ColorSpace::Gray ); + + if ( !IsShared() ) // ### cannot modify a shared image's RGBWS + m_RGBWS = image.m_RGBWS; + + ResetSelections(); + + if ( r == image.Bounds() ) + for ( int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel ) + P::Copy( m_channelData( c ), image[firstChannel], NumberOfPixels() ); + else + for ( int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel ) + { + sample* f = m_channelData( c ); + const sample* g = image.PixelAddress( r.LeftTop(), firstChannel ); + for ( int y = 0; y < m_height; ++y, f += m_width, g += image.m_width ) + P::Copy( f, g, m_width ); + } + + return *this; + } + + /*! + * Copies pixel samples from the specified source \a image to this image. + * Returns a reference to this image. + * + * This operator is a convenience synonym for Assign(). + */ + template + GenericImage& operator =( const GenericImage& image ) + { + return Assign( image ); + } + + /*! + * Copy assignment operator. Copies pixel samples from the specified source + * \a image to this image. Returns a reference to this image. + * + * This operator is a synonym for Assign(), where both this object and the + * source \a image are instances of the same template instantiation of + * %GenericImage. The declaration of this operator is necessary for + * optimization purposes. It also provides a pure copy assignment operator + * for the %GenericImage template class. + */ + GenericImage& operator =( const GenericImage& image ) + { + return Assign( image ); + } + +#define TRANSFER_BODY() \ + if ( m_data != image.m_data ) \ + { \ + DetachFromData(); \ + m_data = image.m_data; \ + (void)AbstractImage::operator =( image ); \ + image.m_data = nullptr; \ + } \ + return *this + + /*! + * Transfers data from another \a image to this object. Returns a reference + * to this image. + * + * Decrements the reference counter of the current image data, and destroys + * it if it becomes unreferenced. + * + * Transfers the source image to this object, leaving empty and invalid the + * source \a image, which cannot be used and must be destroyed immediately + * after calling this function. + */ + GenericImage& Transfer( GenericImage& image ) + { + TRANSFER_BODY(); + } + + /*! + * Transfers data from another \a image to this object. Returns a reference + * to this image. + * + * Decrements the reference counter of the current image data, and destroys + * it if it becomes unreferenced. + * + * Transfers the source image to this object, leaving empty and invalid the + * source \a image, which cannot be used and must be destroyed immediately + * after calling this function. + */ + GenericImage& Transfer( GenericImage&& image ) + { + TRANSFER_BODY(); + } + +#undef TRANSFER_BODY + + /*! + * Move assignment operator. Returns a reference to this image. + * + * This operator is equivalent to Transfer( GenericImage& ). + */ + GenericImage& operator =( GenericImage&& image ) + { + return Transfer( image ); + } + + /*! + * Fills the current selection (selection rectangle and channel range) with + * a \a scalar. Returns a reference to this image. + * + * This operator is a convenience synonym for Fill(). + */ + GenericImage& operator =( sample scalar ) + { + return Fill( scalar ); + } + + /*! + * Exchanges two images \a x1 and \a x2 of the same template instantiation. + */ + friend void Swap( GenericImage& x1, GenericImage& x2 ) noexcept + { + x1.AbstractImage::Swap( x2 ); + pcl::Swap( x1.m_data, x2.m_data ); + } + + // ------------------------------------------------------------------------- + +#ifndef __PCL_NO_VECTOR_IMAGE_CONVERSION + + /*! + * Generates a vector of pixel samples from a row of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index. If this parameter is negative, the + * currently selected channel will be used. The default + * value is -1. + * + * The number of components in the returned vector will be equal to the + * width in pixels of this image. + * + * If this image is empty, if the specified vertical coordinate is out of + * range, or if a nonexistent channel is specified, this member function + * returns an empty vector. + */ + sample_vector RowVector( int y, int channel = -1 ) const + { + if ( channel < 0 ) + channel = m_channel; + if ( y < 0 || y >= m_height || channel < 0 || channel >= m_numberOfChannels ) + return sample_vector(); + sample_vector row( m_width ); + P::Get( row.Begin(), ScanLine( y, channel ), m_width ); + return row; + } + + /*! + * Generates a vector of pixel samples from a column of this image. + * + * \param x Horizontal coordinate (or column index) of the desired + * column, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param channel Channel index. If this parameter is negative, the + * currently selected channel will be used. The default + * value is -1. + * + * The number of components in the returned vector will be equal to the + * height in pixels of this image. + * + * If this image is empty, if the specified horizontal coordinate is out of + * range, or if a nonexistent channel is specified, this member function + * returns an empty vector. + */ + sample_vector ColumnVector( int x, int channel = -1 ) const + { + if ( channel < 0 ) + channel = m_channel; + if ( x < 0 || x >= m_width || channel < 0 || channel >= m_numberOfChannels ) + return sample_vector(); + sample_vector col( m_height ); + const sample* v = PixelAddress( x, 0, channel ); + for ( int y = 0; y < m_height; ++y, v += m_width ) + col[y] = *v; + return col; + } + + /*! + * A convenience synonym for ColumnVector( int, int ) const. + */ + sample_vector ColVector( int x, int channel = 0 ) const + { + return ColumnVector( x, channel ); + } + +#endif // !__PCL_NO_VECTOR_IMAGE_CONVERSION + + /*! + * Stores a duplicate of a row of pixel samples in the specified array, + * with implicit data type conversion. + * + * \param[out] buffer Starting address of a contiguous block where samples + * from the source row will be converted and copied. The + * length of this block must be at least equal to the + * width in pixels of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index. If this parameter is negative, the + * currently selected channel will be used. The default + * value is -1. + * + * If this image is empty, if the specified vertical coordinate is out of + * range, or if a nonexistent channel is specified, this member function + * does nothing. + */ + template + void GetRow( T* buffer, int y, int channel = -1 ) const + { + PCL_PRECONDITION( buffer != 0 ) + if ( channel < 0 ) + channel = m_channel; + if ( y >= 0 && y < m_height && channel >= 0 && channel < m_numberOfChannels ) + P::Get( buffer, ScanLine( y, channel ), m_width ); + } + + /*! + * Stores a duplicate of a column of pixel samples in the specified array, + * with implicit data type conversion. + * + * \param[out] buffer Starting address of a contiguous block where samples + * from the source column will be converted and copied. + * The length of this block must be at least equal to the + * height in pixels of this image. + * + * \param x Horizontal coordinate (or column index) of the desired + * column, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param channel Channel index. If this parameter is negative, the + * currently selected channel will be used. The default + * value is -1. + * + * If this image is empty, if the specified horizontal coordinate is out of + * range, or if a nonexistent channel is specified, this member function + * does nothing. + */ + template + void GetColumn( T* buffer, int x, int channel = -1 ) const + { + PCL_PRECONDITION( buffer != 0 ) + if ( channel < 0 ) + channel = m_channel; + if ( x >= 0 && x < m_width && channel >= 0 && channel < m_numberOfChannels ) + { + const sample* v = PixelAddress( x, 0, channel ); + for ( int y = 0; y < m_height; ++y, ++buffer, v += m_width ) + P::FromSample( *buffer, *v ); + } + } + + /*! + * Sets a row of pixel samples from values in the specified array, with + * implicit data type conversion. Returns a reference to this image. + * + * \param buffer Starting address of a contiguous block with source + * values that will be converted and copied to the target + * row in this image. The length of this block must be at + * least equal to the width in pixels of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index. If this parameter is negative, the + * currently selected channel will be used. The default + * value is -1. + * + * If this image is empty, if the specified vertical coordinate is out of + * range, or if a nonexistent channel is specified, this member function + * does nothing. + */ + template + GenericImage& SetRow( const T* buffer, int y, int channel = -1 ) + { + PCL_PRECONDITION( buffer != 0 ) + if ( channel < 0 ) + channel = m_channel; + if ( y >= 0 && y < m_height && channel >= 0 && channel < m_numberOfChannels ) + P::Copy( ScanLine( y, channel ), buffer, m_width ); + return *this; + } + + /*! + * Sets a column of pixel samples from values in the specified array, with + * implicit data type conversion. Returns a reference to this image. + * + * \param buffer Starting address of a contiguous block with source + * values that will be converted and copied to the target + * column in this image. The length of this block must be + * at least equal to the height in pixels of this image. + * + * \param x Horizontal coordinate (or column index) of the desired + * column, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param channel Channel index. If this parameter is negative, the + * currently selected channel will be used. The default + * value is -1. + * + * If this image is empty, if the specified horizontal coordinate is out of + * range, or if a nonexistent channel is specified, this member function + * does nothing. + */ + template + GenericImage& SetColumn( const T* buffer, int x, int channel = -1 ) + { + PCL_PRECONDITION( buffer != 0 ) + if ( channel < 0 ) + channel = m_channel; + if ( x >= 0 && x < m_width && channel >= 0 && channel < m_numberOfChannels ) + { + sample* v = PixelAddress( x, 0, channel ); + for ( int y = 0; y < m_height; ++y, ++buffer, v += m_width ) + *v = P::ToSample( *buffer ); + } + return *this; + } + + // ------------------------------------------------------------------------- + + /*! + * Creates \a n new alpha channels in this image. Alpha channels are those + * in excess of nominal channels, e.g. a fourth channel in an RGB color + * image, or a second channel in a grayscale image. Returns a reference to + * this image. + * + * Newly created channels are not initialized, so their pixel samples will + * contain unpredictable values. + */ + GenericImage& CreateAlphaChannels( int n ) + { + if ( n > 0 && m_numberOfChannels > 0 ) + { + EnsureUnique(); + sample** oldData = m_pixelData; + sample** newData = nullptr; + try + { + newData = m_allocator.AllocateChannelSlots( m_numberOfChannels+n ); + for ( int i = 0; i < m_numberOfChannels; ++i ) + newData[i] = oldData[i]; + for ( int i = 0; i < n; ++i ) + newData[m_numberOfChannels+i] = m_allocator.AllocatePixels( m_width, m_height ); + } + catch ( ... ) + { + if ( newData != nullptr ) + { + for ( int i = 0; i < n; ++i ) + if ( newData[m_numberOfChannels+i] != nullptr ) + m_allocator.Deallocate( newData[m_numberOfChannels+i] ); + m_allocator.Deallocate( newData ); + } + throw; + } + + m_allocator.SetSharedData( m_pixelData = newData ); + m_allocator.SetSharedGeometry( m_width, m_height, m_numberOfChannels += n ); + m_allocator.Deallocate( oldData ); + } + + return *this; + } + + /*! + * Forces this image to acquire the specified pixel sample data as a new + * alpha channel. Returns a reference to this image. + * + * \param data Starting address of the acquired pixel data. If this + * parameter is a null pointer, a single new alpha channel + * will be added to the image. + * + * The image will own the acquired pixel \a data. The new alpha channel is + * appended to the existing channels. + * + * \warning See the ImportData() member function documentation for an + * important warning notice that applies also to this function. + */ + GenericImage& AddAlphaChannel( sample* data = nullptr ) + { + // $$$ WARNING $$$ + // * If this is a shared image, data must either be null or point to a + // shared memory block. + // * If this is a local image, data must either be null or point to a + // block allocated in the local heap. + + if ( data == nullptr ) + CreateAlphaChannels( 1 ); + else if ( m_numberOfChannels > 0 ) + { + EnsureUnique(); + sample** oldData = m_pixelData; + sample** newData = nullptr; + try + { + newData = m_allocator.AllocateChannelSlots( m_numberOfChannels+1 ); + for ( int i = 0; i < m_numberOfChannels; ++i ) + newData[i] = oldData[i]; + newData[m_numberOfChannels] = data; + } + catch ( ... ) + { + if ( newData != nullptr ) + m_allocator.Deallocate( newData ); + throw; + } + + m_allocator.SetSharedData( m_pixelData = newData ); + m_allocator.SetSharedGeometry( m_width, m_height, ++m_numberOfChannels ); + m_allocator.Deallocate( oldData ); + } + + return *this; + } + + /*! + * Releases an alpha channel into another image. Returns a reference to this + * image. + * + * \param image Image that will receive the data from the released alpha + * channel. Its previous contents will be dereferenced and + * eventually destroyed. + * + * \param channel Zero-based index of the alpha channel to be released, + * 0 ≤ \a channel < \a n, where \a n is the number of + * existing alpha channels before calling this function. + * + * \note The specified \a channel index is an alpha channel index, + * not a normal channel index comprising nominal channels. That is, the + * first alpha channel is indexed as zero by this function. + * + * \warning If this image is a shared instance, then the specified target + * \a image must also be a reference to a shared image. Correspondingly, if + * this is a local image, the target \a image must also be local. Pixel data + * blocks cannot be transferred between local and shared images. If this + * rule is violated, this member function will throw an Error exception. + */ + GenericImage& ReleaseAlphaChannel( GenericImage& image, int channel ) + { + if ( IsShared() != image.IsShared() ) + throw Error( "GenericImage::ReleaseAlphaChannel(): Cannot release pixel data between local and shared images" ); + + if ( channel < 0 || channel >= NumberOfAlphaChannels() ) + { + image.FreeData(); + return *this; + } + + int c = NumberOfNominalChannels() + channel; + + sample** newData = nullptr; + try + { + newData = image.m_allocator.AllocateChannelSlots( 1 ); + *newData = m_pixelData[c]; + } + catch ( ... ) + { + if ( newData != nullptr ) + image.m_allocator.Deallocate( newData ); + throw; + } + + image.FreeData(); + + image.m_pixelData = newData; + image.m_width = m_width; + image.m_height = m_height; + image.m_numberOfChannels = 1; + image.m_colorSpace = ColorSpace::Gray; + image.m_data->UpdateSharedImage(); + image.ResetSelections(); + + m_pixelData[c] = nullptr; + ForgetAlphaChannel( channel ); + + return *this; + } + + /*! + * Destroys an alpha channel. Returns a reference to this image. + * + * \param channel Zero-based index of the alpha channel to be destroyed, + * 0 ≤ \a c < \a n, where \a n is the number of existing + * alpha channels before calling this function. + * + * \note The specified \a channel index is an alpha channel index, + * not a normal channel index comprising nominal channels. That is, the + * first alpha channel is indexed as zero by this function. + */ + GenericImage& DeleteAlphaChannel( int channel ) + { + if ( channel >= 0 && channel < NumberOfAlphaChannels() ) + { + EnsureUnique(); + int c = NumberOfNominalChannels() + channel; + m_allocator.Deallocate( m_pixelData[c] ); + m_pixelData[c] = nullptr; + ForgetAlphaChannel( channel ); + } + + return *this; + } + + /*! + * Forces this image to discard an existing alpha channel without + * deallocating it. Returns a reference to this image. + * + * \param channel Zero-based index of the alpha channel to be forgotten, + * 0 ≤ \a c < \a n, where \a n is the number of existing + * alpha channels before calling this function. + * + * \warning You should have gained control over the pixel data corresponding + * to the forgotten \a channel before calling this function, in order to be + * able to deallocate it when appropriate, or you'll induce a memory leak. + * + * \note The specified \a channel index is an alpha channel index, + * not a normal channel index comprising nominal channels. That is, the + * first alpha channel is indexed as zero by this function. + */ + GenericImage& ForgetAlphaChannel( int channel ) + { + if ( channel >= 0 && channel < NumberOfAlphaChannels() ) + { + EnsureUnique(); + sample** oldData = m_pixelData; + sample** newData = m_allocator.AllocateChannelSlots( m_numberOfChannels-1 ); + + int n0 = NumberOfNominalChannels(); + int c = n0 + channel; + + for ( int i = 0; i < c; ++i ) + newData[i] = oldData[i]; + for ( int i = c, j = c; ++j < m_numberOfChannels; ++i ) + newData[i] = oldData[j]; + + m_allocator.SetSharedData( m_pixelData = newData ); + m_allocator.SetSharedGeometry( m_width, m_height, --m_numberOfChannels ); + + if ( m_channel >= n0 || m_lastChannel >= n0 ) + ResetChannelRange(); + + m_allocator.Deallocate( oldData ); + } + + return *this; + } + + /*! + * Destroys all existing alpha channels in this image. Returns a reference + * to this image. + */ + GenericImage& DeleteAlphaChannels() + { + int n0 = NumberOfNominalChannels(); + int n = m_numberOfChannels; + if ( n > n0 ) + { + EnsureUnique(); + do + m_allocator.Deallocate( m_pixelData[--n] ), m_pixelData[n] = nullptr; + while ( n > n0 ); + ForgetAlphaChannels(); + } + + return *this; + } + + /*! + * Forces this image to discard all existing alpha channels without + * deallocating them. Returns a reference to this image. + * + * \warning You should have gained control over the pixel data for all alpha + * channels in this image before calling this function, in order to be able + * to deallocate them when appropriate, or you'll induce a memory leak. + */ + GenericImage& ForgetAlphaChannels() + { + int n0 = NumberOfNominalChannels(); + if ( m_numberOfChannels > n0 ) + { + EnsureUnique(); + sample** oldData = m_pixelData; + sample** newData = m_allocator.AllocateChannelSlots( n0 ); + + for ( int i = 0; i < n0; ++i ) + newData[i] = oldData[i]; + + m_allocator.SetSharedData( m_pixelData = newData ); + m_allocator.SetSharedGeometry( m_width, m_height, m_numberOfChannels = n0 ); + + if ( m_channel >= n0 || m_lastChannel >= n0 ) + ResetChannelRange(); + + m_allocator.Deallocate( oldData ); + } + + return *this; + } + + // ------------------------------------------------------------------------- + + /*! + * Fills a subset of pixel samples of this image with the specified + * \a scalar. Returns a reference to this image. + * + * \param scalar Scalar value to fill with. The specified value will be + * converted to the sample data type of this image. + * + * \param rect Target rectangular region. If this parameter defines an + * empty rectangle, the current rectangular selection will be + * used. If the specified rectangle is not empty and extends + * beyond image boundaries, only the intersection with this + * image will be used. If that intersection does not exist, + * then this member function has no effect. The default value + * is an empty rectangle. + * + * \param firstChannel Zero-based index of the first channel to fill. If a + * negative index is specified, the first selected channel + * will be used. If the specified index is larger than or + * equal to the number of channels in this image, then this + * member function has no effect. The default value is -1. + * + * \param lastChannel Zero-based index of the last channel to fill. If a + * negative index is specified, the last selected channel + * will be used. If the specified index is larger than or + * equal to the number of channels in this image, then this + * member function has no effect. The default value is -1. + * + * Previously referenced data in this image will be dereferenced, and + * immediately destroyed if they become unreferenced. + * + * If this member function causes a reallocation of pixel data, the newly + * allocated data will be local and uniquely referenced by this image. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Fill( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Filling image", N*(1 + lastChannel - firstChannel) ); + + sample v = P::ToSample( scalar ); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + P::Fill( m_pixelData[i], v, N ); + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width ) + P::Fill( f, v, w ); + } + + return *this; + } + + /*! + * Fills a subset of pixel samples of this image with the scalar components + * of a vector of per-channel filling \a values. Returns a reference to this + * image. + * + * \param values %Vector of filling values. Each component of this vector + * is a filling value for the corresponding channel in the + * pixel sample selection (i.e., the first component is the + * filling value for the first selected channel, the second + * component for the second selected channel, etc.). If the + * vector has less components than channels in the selection, + * the missing values are replaced with the minimum sample + * value in the native range of the image (usually zero). + * + * The rest of parameters of this function are identical to those of + * Fill( T, const Rect&, int, int ). + */ + template + GenericImage& Fill( const GenericVector& values, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Filling image", N*(1 + lastChannel - firstChannel) ); + + if ( r == Bounds() ) + for ( int i = firstChannel, c = 0; i <= lastChannel; ++i, ++c, m_status += N ) + { + sample v = (c < values.Length()) ? P::ToSample( values[c] ) : P::MinSampleValue(); + P::Fill( m_pixelData[i], v, N ); + } + else + for ( int i = firstChannel, c = 0, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, ++c, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + sample v = (c < values.Length()) ? P::ToSample( values[c] ) : P::MinSampleValue(); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width ) + P::Fill( f, v, w ); + } + + return *this; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * filled with the specified \a scalar. + * + * For information on the parameters of this member function, see the + * documentation for Fill( T, const Rect&, int, int ). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Filled( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Fill( scalar ); + return result; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * filled with the scalar components of a vector of per-channel filling + * \a values. + * + * For information on the parameters of this member function, see the + * documentation for Fill( const GenericVector&, const Rect&, int, int ). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Filled( const GenericVector& values, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Fill( values ); + return result; + } + + /*! + * Fills a subset of pixel samples with the constant value resulting from + * converting the floating point scalar zero (0.0) to the sample data type + * of the image. Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Fill( P::ToSample( 0.0 ), rect, firstChannel, lastChannel ); + * \endcode + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Zero( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Fill( P::ToSample( 0.0 ), rect, firstChannel, lastChannel ); + } + + /*! + * Fills a subset of pixel samples with the constant value resulting from + * converting the floating point scalar one (1.0) to the sample data type of + * the image. Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Fill( P::ToSample( 1.0 ), rect, firstChannel, lastChannel ); + * \endcode + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& One( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Fill( P::ToSample( 1.0 ), rect, firstChannel, lastChannel ); + } + + /*! + * Fills a subset of pixel samples with the minimum sample value in the + * native range of the image. Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Fill( P::MinSampleValue(), rect, firstChannel, lastChannel ); + * \endcode + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Black( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Fill( P::MinSampleValue(), rect, firstChannel, lastChannel ); + } + + /*! + * Fills a subset of pixel samples with the maximum sample value in the + * native range of the image. Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Fill( P::MaxSampleValue(), rect, firstChannel, lastChannel ); + * \endcode + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& White( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Fill( P::MaxSampleValue(), rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + + /*! + * Inverts a subset of pixel samples with respect to the specified + * \a scalar. Returns a reference to this image. + * + * The inverse of a pixel sample \a v with respect to a scalar \a r is equal + * to \a r - \a v. Normally (but not necessarily) the reference scalar used + * is the maximum sample value in the native range of the image. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Invert( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Inverting pixel samples", N*(1 + lastChannel - firstChannel) ); + + sample v = P::ToSample( scalar ); + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = v - *f; + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = v - *f; + } + } + + return *this; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * inverted with respect to the specified \a scalar. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Inverted( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Invert( scalar ); + return result; + } + + /*! + * Inverts a subset of pixel samples with respect to the maximum sample + * value in the native range of the image. Returns a reference to this + * image. + * + * This member function is a convenience shortcut for: + * + * \code + * Invert( P::MaxSampleValue(), rect, firstChannel, lastChannel ); + * \endcode + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Invert( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Invert( P::MaxSampleValue(), rect, firstChannel, lastChannel ); + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * inverted with respect to the maximum sample value in the native range of + * the image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage Inverted( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Invert(); + return result; + } + + /*! + * Returns an inverted duplicate of this image. The inversion operation is + * performed on the current pixel sample selection with respect to the + * maximum sample value in the native range of the image. + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage operator ~() const + { + GenericImage result( *this ); + (void)result.Invert(); + return result; + } + + /*! + * Replaces a subset of pixel samples with their bitwise logical NOT values. + * Returns a reference to this image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Not( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Bitwise Not", N*(1 + lastChannel - firstChannel) ); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + P::Not( *f ); + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + P::Not( *f ); + } + } + + return *this; + } + + /*! + * Truncates a subset of pixel samples to the specified range of values. + * Returns a reference to this image. + * + * \param lowerBound Lower bound of the truncation range. + * \param upperBound Upper bound of the truncation range. + * + * The specified truncation bounds are converted to the sample data type of + * this image, using pixel traits primitives. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Truncate( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Truncating pixel samples", N*(1 + lastChannel - firstChannel) ); + + sample b0 = P::ToSample( lowerBound ); + sample b1 = P::ToSample( upperBound ); + if ( b1 < b0 ) + pcl::Swap( b0, b1 ); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + if ( *f < b0 ) + *f = b0; + else if ( b1 < *f ) + *f = b1; + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( *f < b0 ) + *f = b0; + else if ( b1 < *f ) + *f = b1; + } + } + + return *this; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * truncated to the specified range of values. + * + * \param lowerBound Lower bound of the truncation range. + * \param upperBound Upper bound of the truncation range. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Truncated( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Truncate( lowerBound, upperBound ); + return result; + } + + /*! + * Truncates a subset of pixel samples to the native range of the image. + * Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Truncate( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel ); + * \endcode + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * Note that this function only makes sense for floating point real or + * complex images, where pixel samples can take arbitrary values. Integer + * pixel samples are constrained to their native range by nature, so calling + * this function for integer images has no effect. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Truncate( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Truncate( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel ); + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * truncated to the native range of the image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage Truncated( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Truncate(); + return result; + } + + /*! + * Rescales a subset of pixel samples to the specified range of values. + * Returns a reference to this image. + * + * \param lowerBound Lower bound of the rescaling range. + * \param upperBound Upper bound of the rescaling range. + * + * The specified rescaling bounds are converted to the sample data type of + * this image, using pixel traits primitives. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The rescaling operation is as follows. Given the following two ranges: + * + * \li \c m, \c M : The range of existing sample values in the selected set of + * pixel samples, + * \li \c r0, \c r1 : The rescaling range, + * + * the rescaled value \c r for a given sample \c s is: + * + *

+    * r = r0 + (s - m)*(r1 - r0)/(M - m)
+    * 
+ * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Rescale( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + size_type Ns = N*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Rescaling pixel samples", Ns ); + + sample b0 = P::ToSample( lowerBound ); + sample b1 = P::ToSample( upperBound ); + if ( b1 < b0 ) + pcl::Swap( b0, b1 ); + + sample v0, v1; + GetExtremePixelValues( v0, v1, r, firstChannel, lastChannel ); + if ( v0 == b0 && v1 == b1 ) + { + m_status += Ns; + return *this; + } + + EnsureUnique(); + + double d = 0; + if ( b0 != b1 ) + if ( v0 != v1 ) + d = (double( b1 ) - double( b0 ))/(double( v1 ) - double( v0 )); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + + if ( v0 != v1 ) + { + if ( b0 != b1 ) + { + if ( b0 == sample( 0 ) ) + { + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = P::FloatToSample( d*(*f - v0) ); + } + else + { + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = P::FloatToSample( d*(*f - v0) + b0 ); + } + } + else + P::Fill( f, b0, N ); + } + else + P::Fill( f, pcl::Range( v0, b0, b1 ), N ); + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + + if ( v0 != v1 ) + { + if ( b0 != b1 ) + { + if ( b0 == sample( 0 ) ) + { + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = P::FloatToSample( d*(*f - v0) ); + } + } + else + { + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = P::FloatToSample( d*(*f - v0) + b0 ); + } + } + } + else + { + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width ) + P::Fill( f, b0, w ); + } + } + else + { + sample v = pcl::Range( v0, b0, b1 ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width ) + P::Fill( f, v, w ); + } + } + + return *this; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * rescaled to the specified range of values. + * + * \param lowerBound Lower bound of the rescaling range. + * \param upperBound Upper bound of the rescaling range. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Rescaled( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Rescale( lowerBound, upperBound ); + return result; + } + + /*! + * Rescales a subset of pixel samples to the native range of the image. + * Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Rescale( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel ); + * \endcode + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Rescale( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Rescale( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel ); + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * rescaled to the native range of the image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage Rescaled( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Rescale(); + return result; + } + + /*! + * Normalizes a subset of pixel samples to the specified range of values. + * Returns a reference to this image. + * + * \param lowerBound Lower bound of the normalizing range. + * \param upperBound Upper bound of the normalizing range. + * + * The specified normalizing bounds are converted to the sample data type of + * this image, using pixel traits primitives. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * Normalization is a conditional rescaling operation: Pixel sample values + * are rescaled to the specified normalizing range only if the existing + * extreme sample values exceed that range. Given the following two ranges: + * + * \li \c m, \c M : The range of existing sample values in the selected set of + * pixel samples, + * \li \c n0, \c n1 : The normalizing range, + * + * the normalized value \c n for a given sample \c s is: + * + *
+    * if m < n0 or M > n1
+    *    n = n0 + (s - m)*(n1 - n0)/(M - m)
+    * else
+    *    n = s
+    * endif
+    * 
+ * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Normalize( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + size_type Ns = N*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Normalizing pixel samples", Ns ); + + sample b0 = P::ToSample( lowerBound ); + sample b1 = P::ToSample( upperBound ); + if ( b1 < b0 ) + pcl::Swap( b0, b1 ); + + sample v0, v1; + GetExtremePixelValues( v0, v1, r, firstChannel, lastChannel ); + + if ( v0 >= b0 && v1 <= b1 ) + { + m_status += Ns; + return *this; + } + + EnsureUnique(); + + double d = 0; + if ( b0 != b1 ) + if ( v0 != v1 ) + d = (double( b1 ) - double( b0 ))/(double( v1 ) - double( v0 )); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + + if ( v0 != v1 ) + { + if ( b0 != b1 ) + { + if ( b0 == sample( 0 ) ) + { + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = P::FloatToSample( d*(*f - v0) ); + } + else + { + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = P::FloatToSample( d*(*f - v0) + b0 ); + } + } + else + P::Fill( f, b0, N ); + } + else + P::Fill( f, pcl::Range( v0, b0, b1 ), N ); + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + + if ( v0 != v1 ) + { + if ( b0 != b1 ) + { + if ( b0 == sample( 0 ) ) + { + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = P::FloatToSample( d*(*f - v0) ); + } + } + else + { + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = P::FloatToSample( d*(*f - v0) + b0 ); + } + } + } + else + { + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width ) + P::Fill( f, b0, w ); + } + } + else + { + sample v = pcl::Range( v0, b0, b1 ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width ) + P::Fill( f, v, w ); + } + } + + return *this; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * normalized to the specified range of values. + * + * \param lowerBound Lower bound of the normalizing range. + * \param upperBound Upper bound of the normalizing range. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Normalized( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Normalize( lowerBound, upperBound ); + return result; + } + + /*! + * Normalizes a subset of pixel samples to the native range of the image. + * Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Normalize( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel ); + * \endcode + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Normalize( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Normalize( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel ); + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * normalized to the native range of the image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage Normalized( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Normalize(); + return result; + } + + /*! + * Binarizes a subset of pixel samples with respect to the specified + * \a threshold value. Returns a reference to this image. + * + * \param threshold Binarizing threshold. + * + * The specified binarizing threshold is converted to the sample data type + * of this image, using pixel traits primitives. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The binarized value \c b of a sample \c s is given by: + * + *
+    * if s < t
+    *    b = 0
+    * else
+    *    b = 1
+    * endif
+    * 
+ * + * where \c t is the binarizing threshold value, and 0 and 1 represent, + * respectively, the minimum and maximum pixel sample values in the native + * range of the image. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Binarize( T threshold, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Binarizing pixel samples", N*(1 + lastChannel - firstChannel) ); + + sample t = P::ToSample( threshold ); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = (*f < t) ? P::MinSampleValue() : P::MaxSampleValue(); + } + else + for ( int c = firstChannel, w = r.Width(), h = r.Height(); c <= lastChannel; ++c, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), c ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = (*f < t) ? P::MinSampleValue() : P::MaxSampleValue(); + } + } + + return *this; + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * binarized with respect to the specified \a threshold value. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Binarized( T threshold, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Binarize( threshold ); + return result; + } + + /*! + * Binarizes a subset of pixel samples with respect to the central value of + * the native range of the image. Returns a reference to this image. + * + * This member function is a convenience shortcut for: + * + * \code + * Binarize( (P::MinSampleValue() + P::MaxSampleValue())/2, rect, firstChannel, lastChannel ); + * \endcode + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& Binarize( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Binarize( (P::MinSampleValue() + P::MaxSampleValue())/2, rect, firstChannel, lastChannel ); + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * binarized with respect to the central value of the native range of the + * image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage Binarized( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Binarize(); + return result; + } + + /*! + * Replaces a subset of pixel samples with their absolute values. Returns a + * reference to this image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Note that this member function is a no-op for unsigned integer + * images (e.g., UInt8Image, UInt16Image and UInt32Image). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + GenericImage& SetAbsoluteValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing absolute value", N*(1 + lastChannel - firstChannel) ); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + PCL_IVDEP + for ( size_type j = 0; j < N; ++j, ++f ) + *f = pcl::Abs( *f ); + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); + PCL_IVDEP + for ( int j = 0; j < h; ++j, f += m_width-w ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + *f = pcl::Abs( *f ); + } + } + + return *this; + } + + /*! + * A synonym for SetAbsoluteValue(). + */ + GenericImage& Abs( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetAbsoluteValue( rect, firstChannel, lastChannel ); + } + + /*! + * Returns a local image with a subset of pixel samples from this image, + * replaced with their absolute values. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + GenericImage AbsoluteValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.SetAbsoluteValue(); + return result; + } + + // ------------------------------------------------------------------------- + + /* + * Implementation of Apply( scalar ) member functions. We have to have a + * separate implementation function to prevent infinite recursion in several + * template specializations of the Apply() member function. + */ + template + GenericImage& ApplyScalar( T scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( op == ImageOp::Div ) + if ( 1 + scalar == 1 ) + throw Error( "Division by zero or insignificant scalar" ); + + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Applying scalar: " + + ImageOp::Id( op ) + + ' ' + String( scalar ), N*(1 + lastChannel - firstChannel) ); + + if ( r == Bounds() ) + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; +#define ITERATE( Op ) \ + PCL_IVDEP \ + for ( size_type j = 0; j < N; ++j, ++f ) \ + P::Op( *f, scalar ) + switch ( op ) + { + case ImageOp::Mov: ITERATE( Mov ); break; + case ImageOp::Add: ITERATE( Add ); break; + case ImageOp::Sub: ITERATE( Sub ); break; + case ImageOp::Mul: ITERATE( Mul ); break; + case ImageOp::Div: ITERATE( Div ); break; + case ImageOp::Pow: ITERATE( Pow ); break; + case ImageOp::Dif: ITERATE( Dif ); break; + case ImageOp::Min: ITERATE( Min ); break; + case ImageOp::Max: ITERATE( Max ); break; + case ImageOp::Not: ITERATE( Not ); break; + case ImageOp::Or: ITERATE( Or ); break; + case ImageOp::Nor: ITERATE( Nor ); break; + case ImageOp::And: ITERATE( And ); break; + case ImageOp::Nand: ITERATE( Nand ); break; + case ImageOp::Xor: ITERATE( Xor ); break; + case ImageOp::Xnor: ITERATE( Xnor ); break; + case ImageOp::ColorBurn: ITERATE( ColorBurn ); break; + case ImageOp::LinearBurn: ITERATE( LinearBurn ); break; + case ImageOp::Screen: ITERATE( Screen ); break; + case ImageOp::ColorDodge: ITERATE( ColorDodge ); break; + case ImageOp::Overlay: ITERATE( Overlay ); break; + case ImageOp::SoftLight: ITERATE( SoftLight ); break; + case ImageOp::HardLight: ITERATE( HardLight ); break; + case ImageOp::VividLight: ITERATE( VividLight ); break; + case ImageOp::LinearLight: ITERATE( LinearLight ); break; + case ImageOp::PinLight: ITERATE( PinLight ); break; + case ImageOp::Exclusion: ITERATE( Exclusion ); break; + default: break; + } +#undef ITERATE + } + else + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i, m_status += N ) + { + sample* __restrict__ f = PixelAddress( r.LeftTop(), i ); +#define ITERATE( Op ) \ + PCL_IVDEP \ + for ( int j = 0; j < h; ++j, f += m_width-w ) \ + { \ + PCL_IVDEP \ + for ( int k = 0; k < w; ++k, ++f ) \ + P::Op( *f, scalar ); \ + } + switch ( op ) + { + case ImageOp::Mov: ITERATE( Mov ); break; + case ImageOp::Add: ITERATE( Add ); break; + case ImageOp::Sub: ITERATE( Sub ); break; + case ImageOp::Mul: ITERATE( Mul ); break; + case ImageOp::Div: ITERATE( Div ); break; + case ImageOp::Pow: ITERATE( Pow ); break; + case ImageOp::Dif: ITERATE( Dif ); break; + case ImageOp::Min: ITERATE( Min ); break; + case ImageOp::Max: ITERATE( Max ); break; + case ImageOp::Not: ITERATE( Not ); break; + case ImageOp::Or: ITERATE( Or ); break; + case ImageOp::Nor: ITERATE( Nor ); break; + case ImageOp::And: ITERATE( And ); break; + case ImageOp::Nand: ITERATE( Nand ); break; + case ImageOp::Xor: ITERATE( Xor ); break; + case ImageOp::Xnor: ITERATE( Xnor ); break; + case ImageOp::ColorBurn: ITERATE( ColorBurn ); break; + case ImageOp::LinearBurn: ITERATE( LinearBurn ); break; + case ImageOp::Screen: ITERATE( Screen ); break; + case ImageOp::ColorDodge: ITERATE( ColorDodge ); break; + case ImageOp::Overlay: ITERATE( Overlay ); break; + case ImageOp::SoftLight: ITERATE( SoftLight ); break; + case ImageOp::HardLight: ITERATE( HardLight ); break; + case ImageOp::VividLight: ITERATE( VividLight ); break; + case ImageOp::LinearLight: ITERATE( LinearLight ); break; + case ImageOp::PinLight: ITERATE( PinLight ); break; + case ImageOp::Exclusion: ITERATE( Exclusion ); break; + default: break; + } +#undef ITERATE + } + + return *this; + } + + /*! + * Replaces a subset of pixel samples with the result of an arithmetic, + * bitwise logical or pixel composition operation with a scalar. Returns a + * reference to this image. + * + * \param scalar Right-hand operand value. + * + * \param op Identifies an arithmetic, bitwise logical or pixel + * composition operator. For a list of supported operators, + * see the ImageOp namespace. The default value is + * ImageOp::Mov (replace target with source). + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If the specified \a scalar is zero or insignificant, and the \a op + * argument is ImageOp::Div, this function throws an Error exception to + * prevent a division by zero. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + GenericImage& Apply( T scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return ApplyScalar( scalar, op, rect, firstChannel, lastChannel ); + } + + GenericImage& Apply( float scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( ImageOp::IsArithmeticOperator( op ) || ImageOp::IsPixelCompositionOperator( op ) ) + return ApplyScalar( scalar, op, rect, firstChannel, lastChannel ); + return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel ); + } + + GenericImage& Apply( double scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( ImageOp::IsArithmeticOperator( op ) || ImageOp::IsPixelCompositionOperator( op ) ) + return ApplyScalar( scalar, op, rect, firstChannel, lastChannel ); + return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel ); + } + + GenericImage& Apply( pcl::Complex scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( ImageOp::IsArithmeticOperator( op ) || ImageOp::IsPixelCompositionOperator( op ) ) + return ApplyScalar( scalar, op, rect, firstChannel, lastChannel ); + return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel ); + } + + GenericImage& Apply( pcl::Complex scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( ImageOp::IsArithmeticOperator( op ) || ImageOp::IsPixelCompositionOperator( op ) ) + return ApplyScalar( scalar, op, rect, firstChannel, lastChannel ); + return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * performs an arithmetic or bitwise logical operation with a scalar. + * Returns the resulting image. + * + * \param scalar Right-hand operand value. + * + * \param op Identifies an arithmetic or bitwise logical operator. For + * a list of supported operators, see the ImageOp namespace. + * The default value is ImageOp::Mov (replace target with + * source). + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Applied( T scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Apply( scalar, op ); + return result; + } + + // ------------------------------------------------------------------------- + + /*! + * Performs an arithmetic or bitwise logical operation between a subset of + * pixel samples in this image and the corresponding samples of another + * operand \a image. Returns a reference to this image. + * + * \param image Right-hand operand image. + * + * \param op Identifies an arithmetic or bitwise logical operator. For + * a list of supported operators, see the ImageOp namespace. + * The default value is ImageOp::Mov (replace target with + * source). + * + * \param point Target point in image coordinates. This is the upper left + * corner of the target rectangular region where the source + * \a image will be applied to this image. If one or both + * point coordinates are equal to \c int_max (the maximum + * possible value of type \c int), then the current anchor + * point selection will be used. The default value is + * Point( int_max ). + * + * \param channel Target channel index (zero-based). This is the index of + * the first channel where source pixel samples will be + * applied. If this parameter is negative, then the currently + * selected channel will be used. The default value is -1. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The specified operation is performed with samples in the intersection + * between the specified (or implicit) rectangular selections for both + * images. Each channel in the specified channel range selection for this + * image is operated with its counterpart channel in the right-hand operand + * \a image, starting from the first selected channel in the right-hand + * operand \a image. + * + * The operation may involve conversions to the appropriate floating point + * data type for intermediate results, or LUT table lookups, as necessary + * to ensure preservation of the full native range of the image. Floating + * point conversions may take place even if both images share the same + * sample data type, depending on the selected operator. + * + * \note Increments the status monitoring object by the number of pixel + * samples in the intersection between both operand images. + */ + template + GenericImage& Apply( const GenericImage& image, image_op op = ImageOp::Mov, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !image.ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + if ( !ParseChannel( channel ) ) + return *this; + + Point p = point; + if ( p.x == int_max || p.y == int_max ) + p = m_point; + + if ( p.x < 0 ) + { + if ( (r.x0 -= p.x) >= r.x1 ) + return *this; + p.x = 0; + } + else if ( p.x >= m_width ) + return *this; + + if ( p.y < 0 ) + { + if ( (r.y0 -= p.y) >= r.y1 ) + return *this; + p.y = 0; + } + else if ( p.y >= m_height ) + return *this; + + r.ResizeTo( pcl::Min( m_width - p.x, r.Width() ), + pcl::Min( m_height - p.y, r.Height() ) ); + + lastChannel = pcl::Min( lastChannel, firstChannel + m_numberOfChannels - channel - 1 ); + + EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Applying image, op=" + ImageOp::Id( op ), N*(1 + lastChannel - firstChannel) ); + + if ( r == Bounds() && r == image.Bounds() ) + for ( int i = channel, j = firstChannel; j <= lastChannel; ++i, ++j, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + const typename P1::sample* __restrict__ g = image[j]; + +#define ITERATE( Op ) \ + PCL_IVDEP \ + for ( size_type k = 0; k < N; ++k, ++f, ++g ) \ + P::Op( *f, *g ) + switch ( op ) + { + case ImageOp::Mov: + P::Copy( f, g, N ); + break; + case ImageOp::Min: + P::CopyMin( f, g, N ); + break; + case ImageOp::Max: + P::CopyMax( f, g, N ); + break; + default: + switch ( op ) + { + case ImageOp::Add: ITERATE( Add ); break; + case ImageOp::Sub: ITERATE( Sub ); break; + case ImageOp::Mul: ITERATE( Mul ); break; + case ImageOp::Div: + for ( size_type j = 0; j < N; ++j, ++f, ++g ) + if ( *g != 0 ) + P::Div( *f, *g ); + else + *f = P::MaxSampleValue(); + break; + case ImageOp::Pow: ITERATE( Pow ); break; + case ImageOp::Dif: ITERATE( Dif ); break; + case ImageOp::Not: ITERATE( Not ); break; + case ImageOp::Or: ITERATE( Or ); break; + case ImageOp::Nor: ITERATE( Nor ); break; + case ImageOp::And: ITERATE( And ); break; + case ImageOp::Nand: ITERATE( Nand ); break; + case ImageOp::Xor: ITERATE( Xor ); break; + case ImageOp::Xnor: ITERATE( Xnor ); break; + case ImageOp::ColorBurn: ITERATE( ColorBurn ); break; + case ImageOp::LinearBurn: ITERATE( LinearBurn ); break; + case ImageOp::Screen: ITERATE( Screen ); break; + case ImageOp::ColorDodge: ITERATE( ColorDodge ); break; + case ImageOp::Overlay: ITERATE( Overlay ); break; + case ImageOp::SoftLight: ITERATE( SoftLight ); break; + case ImageOp::HardLight: ITERATE( HardLight ); break; + case ImageOp::VividLight: ITERATE( VividLight ); break; + case ImageOp::LinearLight: ITERATE( LinearLight ); break; + case ImageOp::PinLight: ITERATE( PinLight ); break; + case ImageOp::Exclusion: ITERATE( Exclusion ); break; + default: break; + } +#undef ITERATE + break; + } + } + else + for ( int i = channel, j = firstChannel, w = r.Width(), h = r.Height(); j <= lastChannel; ++i, ++j, m_status += N ) + { + sample* __restrict__ f = PixelAddress( p, i ); + const typename P1::sample* __restrict__ g = image.PixelAddress( r.LeftTop(), j ); + +#define ITERATE( Op ) \ + PCL_IVDEP \ + for ( int k = 0; k < h; ++k, f += m_width-w, g += image.Width()-w ) \ + { \ + PCL_IVDEP \ + for ( int l = 0; l < w; ++l, ++f, ++g ) \ + P::Op( *f, *g ); \ + } + switch ( op ) + { + case ImageOp::Mov: + for ( int k = 0; k < h; ++k, f += m_width, g += image.Width() ) + P::Copy( f, g, w ); + break; + case ImageOp::Min: + for ( int k = 0; k < h; ++k, f += m_width, g += image.Width() ) + P::CopyMin( f, g, w ); + break; + case ImageOp::Max: + for ( int k = 0; k < h; ++k, f += m_width, g += image.Width() ) + P::CopyMax( f, g, w ); + break; + case ImageOp::Add: ITERATE( Add ); break; + case ImageOp::Sub: ITERATE( Sub ); break; + case ImageOp::Mul: ITERATE( Mul ); break; + case ImageOp::Div: + PCL_IVDEP + for ( int k = 0; k < h; ++k, f += m_width-w, g += image.Width()-w ) + { + PCL_IVDEP + for ( int l = 0; l < w; ++l, ++f, ++g ) + if ( *g != 0 ) + P::Div( *f, *g ); + else + *f = P::MaxSampleValue(); + } + break; + case ImageOp::Pow: ITERATE( Pow ); break; + case ImageOp::Dif: ITERATE( Dif ); break; + case ImageOp::Not: ITERATE( Not ); break; + case ImageOp::Or: ITERATE( Or ); break; + case ImageOp::Nor: ITERATE( Nor ); break; + case ImageOp::And: ITERATE( And ); break; + case ImageOp::Nand: ITERATE( Nand ); break; + case ImageOp::Xor: ITERATE( Xor ); break; + case ImageOp::Xnor: ITERATE( Xnor ); break; + case ImageOp::ColorBurn: ITERATE( ColorBurn ); break; + case ImageOp::LinearBurn: ITERATE( LinearBurn ); break; + case ImageOp::Screen: ITERATE( Screen ); break; + case ImageOp::ColorDodge: ITERATE( ColorDodge ); break; + case ImageOp::Overlay: ITERATE( Overlay ); break; + case ImageOp::SoftLight: ITERATE( SoftLight ); break; + case ImageOp::HardLight: ITERATE( HardLight ); break; + case ImageOp::VividLight: ITERATE( VividLight ); break; + case ImageOp::LinearLight: ITERATE( LinearLight ); break; + case ImageOp::PinLight: ITERATE( PinLight ); break; + case ImageOp::Exclusion: ITERATE( Exclusion ); break; + break; + default: + break; + } +#undef ITERATE + } + + return *this; + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * performs an arithmetic or bitwise logical operation with the + * corresponding samples of another \a image. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Apply(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Applied( const GenericImage& image, image_op op = ImageOp::Mov, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + int c0 = (channel < 0) ? m_channel : channel; + int c1 = c0 + ((firstChannel < 0) ? image.FirstSelectedChannel() : firstChannel); + int c2 = c0 + ((lastChannel < 0) ? image.LastSelectedChannel() : lastChannel); + GenericImage result( *this, rect.MovedTo( point ), c1, c2 ); + (void)result.Apply( image, op, Point( 0 ), 0, rect, firstChannel, lastChannel ); + return result; + } + + // ------------------------------------------------------------------------- + + /*! + * Applies an image transformation to a subset of pixel samples. Returns a + * reference to this image. + * + * \param transformation An image transformation that will be applied to + * the selected subset of pixel samples. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If the applied \a transformation is bidirectional, then this function + * represents an inverse transformation, usually requiring a + * previous direct transformation. See the Transform() member + * function. + * + * Bidirectional transformations such as FourierTransform and + * ATrousWaveletTransform usually ignore the specified (or implicit) + * selections of a rectangular region and channel range. Other + * non-invertible transformations, especially geometric transformations such + * as Resample or Rotation, also ignore pixel sample selections. + * + * \note In general, the applied transformation increments the status + * monitoring object proportionally to the number of selected pixel samples. + * However, the specific increments depend on the applied transformations. + * + * \warning This member function is not thread safe, even if the + * subset of pixel samples is selected directly with the \a rect, + * \a firstChannel and \a lastChannel parameters. This is because image + * transformations always use the current image selection, which this + * function changes temporarily. + * + * \sa ImageTransformation + */ + GenericImage& Apply( const ImageTransformation& transformation, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ); + // ### Implemented in pcl/ImageTransformation.h (because of mutual dependencies) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * applies an image transformation to a subset of pixel samples. Returns the + * resulting image. + * + * \param transformation An image transformation that will be applied to + * the selected subset of pixel samples. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). For information on image transformations, + * see Apply( const ImageTransformation& ) and ImageTransformation. + * + * \warning This member function is not thread safe, even if the + * subset of pixel samples is selected directly with the \a rect, + * \a firstChannel and \a lastChannel parameters. This is because image + * transformations always use the current image selection, which this + * function changes temporarily. + */ + GenericImage Applied( const ImageTransformation& transformation, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Apply( transformation ); + return result; + } + + /*! + * Applies a \e direct image transformation to a subset of pixel samples. + * + * \param transform A bidirectional image transformation that will be + * applied to the selected subset of pixel samples. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note In general, the applied transformation increments the status + * monitoring object proportionally to the number of selected pixel samples. + * However, the specific increments depend on the applied transformations. + * + * \warning This member function is not thread safe, even if the + * subset of pixel samples is selected directly with the \a rect, + * \a firstChannel and \a lastChannel parameters. This is because image + * transformations always use the current image selection, which this + * function changes temporarily. + * + * \sa ImageTransformation + */ + void Transform( BidirectionalImageTransformation& transform, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const; + // ### Implemented in pcl/ImageTransformation.h (because of mutual dependencies) + + // ------------------------------------------------------------------------- + +#ifndef __PCL_IMAGE_NO_BITMAP + + /*! + * Blends a rectangular region of a 32-bit RGBA \a bitmap with this image. + * Returns a reference to this image. + * + * \param bitmap Reference to a constant source bitmap. + * + * \param point Target point in image coordinates. This is the upper left + * corner of the target rectangular region where the source + * \a bitmap will be applied to this image. If one or both + * point coordinates are equal to \c int_max (the maximum + * possible value of type \c int), then the current anchor + * point selection will be used. The default value is + * Point( int_max ). + * + * \param rect Source rectangular region in bitmap coordinates. If this + * parameter defines an empty rectangle, the whole source + * bitmap will be applied. If the specified rectangle is not + * empty and extends beyond image boundaries, only the + * intersection with the source bitmap will be used. If that + * intersection does not exist, then this member function has + * no effect. The default value is an empty rectangle. + * + * The blending operation involves only nominal image channels. The alpha + * channel of the source bitmap defines a transparency mask for combining + * bitmap pixel values and image pixel sample values. The resulting pixel + * sample value \c V1 after the blending operation is given in the + * normalized real range [0,1] by the following expression: + * + *
+    * V1 = V*(1 - A/255) + B * A/255
+    * 
+ * + * where \c V is the initial pixel value of this image, \c A is the alpha + * value of the source bitmap pixel, and \c B is one of the red, green or + * blue values in the source bitmap pixel. The expression above is applied + * respectively for each nominal sample of this image. + * + * \note Increments the status monitoring object by the number of pixels in + * the intersection between this image and the specified rectangular region + * of the source bitmap. + */ + GenericImage& Blend( const Bitmap& bitmap, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ) ) + { + Rect r = rect; + if ( r.IsRect() ) + r = bitmap.Bounds().Intersection( r ); + else + r = bitmap.Bounds(); + if ( !r.IsRect() ) + return *this; + + Point p = point; + if ( p.x == int_max || p.y == int_max ) + p = m_point; + + if ( p.x < 0 ) + { + if ( (r.x0 -= p.x) >= r.x1 ) + return *this; + p.x = 0; + } + else if ( p.x >= m_width ) + return *this; + + if ( p.y < 0 ) + { + if ( (r.y0 -= p.y) >= r.y1 ) + return *this; + p.y = 0; + } + else if ( p.y >= m_height ) + return *this; + + r.ResizeTo( pcl::Min( m_width - p.x, r.Width() ), + pcl::Min( m_height - p.y, r.Height() ) ); + + bool hasAlpha = HasAlphaChannels(); + int w = r.Width(); + int h = r.Height(); + + EnsureUnique(); + + if ( IsColor() ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Blending RGBA bitmap", size_type( w )*size_type( h ) ); + + sample* __restrict__ fR = nullptr; + sample* __restrict__ fG = nullptr; + sample* __restrict__ fB = nullptr; + sample* __restrict__ fA = nullptr; + + for ( int i = 0; i < h; ++i, ++p.y, m_status += w ) + { + fR = PixelAddress( p, 0 ); + fG = PixelAddress( p, 1 ); + fB = PixelAddress( p, 2 ); + if ( hasAlpha ) + fA = PixelAddress( p, 3 ); + + const RGBA* __restrict__ g = bitmap.ScanLine( r.y0 + i ) + r.x0; + + for ( int j = 0; j < w; ++j, ++fR, ++fG, ++fB, ++fA, ++g ) + { + RGBA rgba = *g; + + uint8 A = Alpha( rgba ); + + if ( hasAlpha ) + { + P::Mov( *fR, Red( rgba ) ); + P::Mov( *fG, Green( rgba ) ); + P::Mov( *fB, Blue( rgba ) ); + P::Mov( *fA, A ); + } + else if ( A != 0 ) + { + if ( A == 0xFF ) + { + P::Mov( *fR, Red( rgba ) ); + P::Mov( *fG, Green( rgba ) ); + P::Mov( *fB, Blue( rgba ) ); + } + else + { + double k = PTLUT->pDLUTA[A]; + double k1 = PTLUT->p1DLUT8[A]; + double v; + P::FromSample( v, *fR ), P::Mov( *fR, k*Red( rgba ) + k1*v ); + P::FromSample( v, *fG ), P::Mov( *fG, k*Green( rgba ) + k1*v ); + P::FromSample( v, *fB ), P::Mov( *fB, k*Blue( rgba ) + k1*v ); + } + } + } + } + } + else + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Blending grayscale bitmap", size_type( w )*size_type( h ) ); + + sample* __restrict__ fK = nullptr; + sample* __restrict__ fA = nullptr; + + for ( int i = 0; i < h; ++i, ++p.y, m_status += w ) + { + fK = PixelAddress( p, 0 ); + if ( hasAlpha ) + fA = PixelAddress( p, 1 ); + + const RGBA* __restrict__ g = bitmap.ScanLine( r.y0 + i ) + r.x0; + + for ( int j = 0; j < w; ++j, ++fK, ++fA, ++g ) + { + RGBA rgba = *g; + uint8 R = Red( rgba ); + uint8 G = Green( rgba ); + uint8 B = Blue( rgba ); + uint8 A = Alpha( rgba ); + + double K = 0.5*(pcl::Min( pcl::Min( R, G ), B ) + + pcl::Max( pcl::Max( R, G ), B )); + + if ( hasAlpha ) + { + P::Mov( *fK, K/255 ); + P::Mov( *fA, A ); + } + else if ( A != 0 ) + { + if ( A == 0xFF ) + P::Mov( *fK, K/255 ); + else + { + double v; + P::FromSample( v, *fK ); + P::Mov( *fK, PTLUT->pDLUTA[A]*K + PTLUT->p1DLUT8[A]*v ); + } + } + } + } + } + + return *this; + } + + /*! + * Returns a local duplicate of this image blended with a rectangular region + * of a 32-bit RGBA \a bitmap. + * + * For information on the parameters of this member function, see the + * documentation for Blend(). + * + * \note Increments the status monitoring object of the returned image by + * the number of pixels in the intersection between this image and the + * specified rectangular region of the source bitmap. + */ + GenericImage Blended( const Bitmap& bitmap, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ) ) const + { + GenericImage result( *this, Bounds(), 0, m_numberOfChannels-1 ); + (void)result.Blend( bitmap, point, rect ); + return result; + } + +#endif // !__PCL_IMAGE_NO_BITMAP + + // ------------------------------------------------------------------------- + + /*! + * Replaces a subset of pixel samples in this image with the specified + * constant \a scalar. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Mov, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Move( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Mov, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Move(). + */ + template + GenericImage& Mov( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Move( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * Adds the specified \a scalar to a subset of pixel samples in this image. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Add, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Add( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Add, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Add(). + */ + template + GenericImage& operator +=( T scalar ) + { + return Add( scalar ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * adds a \a scalar. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Added( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Add( scalar ); + return result; + } + + /*! + * Subtracts the specified \a scalar from a subset of pixel samples in this + * image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Sub, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Subtract( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Sub, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Subtract(). + */ + template + GenericImage& Sub( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Subtract( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Subtract(). + */ + template + GenericImage& operator -=( T scalar ) + { + return Subtract( scalar ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * subtracts a \a scalar. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Subtracted( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Subtract( scalar ); + return result; + } + + /*! + * Multiplies a subset of pixel samples in this image by the specified + * \a scalar. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Mul, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Multiply( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Mul, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Multiply(). + */ + template + GenericImage& Mul( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Multiply( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Multiply(). + */ + template + GenericImage& operator *=( T scalar ) + { + return Multiply( scalar ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * multiplies it by a \a scalar. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Multiplied( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Multiply( scalar ); + return result; + } + + /*! + * Divides a subset of pixel samples in this image by the specified + * \a scalar. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Div, rect, firstChannel, lastChannel ); + * \endcode + * + * \warning Make sure that the specified \a scalar is not zero or + * insignificant. + */ + template + GenericImage& Divide( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Div, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Divide(). + */ + template + GenericImage& Div( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Divide( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Divide(). + */ + template + GenericImage& operator /=( T scalar ) + { + return Divide( scalar ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * divides it by a \a scalar. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + * + * \warning Make sure that the specified \a scalar is not zero or + * insignificant. + */ + template + GenericImage Divided( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Divide( scalar ); + return result; + } + + /*! + * Raises (exponentiation operator) a subset of pixel samples in this image + * to the specified \a scalar. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Pow, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Raise( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Pow, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Raise(). + */ + template + GenericImage& Pow( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Raise( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Raise(). + */ + template + GenericImage& operator ^=( T scalar ) + { + return Raise( scalar ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * raises it to a \a scalar. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Raised( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.Raise( scalar ); + return result; + } + + /*! + * Replaces a subset of pixel samples in this image with the absolute + * values of their differences with the specified \a scalar. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Dif, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& SetAbsoluteDifference( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Dif, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for SetAbsoluteDifference(). + */ + template + GenericImage& Dif( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetAbsoluteDifference( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * computes the absolute values of their differences with the specified + * \a scalar. Returns the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage AbsoluteDifference( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.SetAbsoluteDifference( scalar ); + return result; + } + + /*! + * Replaces a subset of pixel samples in this image with the minimum of each + * sample and the specified \a scalar. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Min, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& SetMinimum( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Min, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for SetMinimum(). + */ + template + GenericImage& Min( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMinimum( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * computes the minimum of each sample and the specified \a scalar. Returns + * the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Minimum( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.SetMinimum( scalar ); + return result; + } + + /*! + * Replaces a subset of pixel samples in this image with the maximum of each + * sample and the specified \a scalar. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Max, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& SetMaximum( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Max, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for SetMaximum(). + */ + template + GenericImage& Max( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMaximum( scalar, rect, firstChannel, lastChannel ); + } + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * computes the maximum of each sample and the specified \a scalar. Returns + * the resulting image. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * \note Increments the status monitoring object of the returned image by + * the number of selected pixel samples. + */ + template + GenericImage Maximum( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + GenericImage result( *this, rect, firstChannel, lastChannel ); + (void)result.SetMaximum( scalar ); + return result; + } + + /*! + * Performs a bitwise OR (inclusive OR) operation between a subset of pixel + * samples in this image and the specified \a scalar. Returns a reference to + * this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Or, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Or( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Or, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise AND operation between a subset of pixel samples in + * this image and the specified \a scalar. Returns a reference to this + * image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::And, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& And( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::And, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise XOR (exclusive OR) operation between a subset of pixel + * samples in this image and the specified \a scalar. Returns a reference to + * this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Or, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Xor( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Xor, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise NOR (NOT inclusive OR) operation between a subset of + * pixel samples in this image and the specified \a scalar. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Nor, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Nor( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Nor, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise NAND (NOT AND) operation between a subset of pixel + * samples in this image and the specified \a scalar. Returns a reference to + * this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Nand, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Nand( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Nand, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise XNOR (exclusive NOR) operation between a subset of + * pixel samples in this image and the specified \a scalar. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( scalar, ImageOp::Xnor, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Xnor( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( scalar, ImageOp::Xnor, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + + /*! + * Replaces a subset of pixel samples in this image with samples from the + * specified source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Mov, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Move( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Mov, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Move(). + */ + template + GenericImage& Mov( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Move( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Adds pixel samples of the specified \a image to a subset of pixel samples + * in this image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Add, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Add( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Add, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Add(). + */ + template + GenericImage& operator +=( const GenericImage& image ) + { + return Add( image ); + } + + /*! + * Subtracts pixel samples of the specified \a image from a subset of pixel + * samples in this image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Sub, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Subtract( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Sub, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Subtract(). + */ + template + GenericImage& Sub( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Subtract( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Subtract(). + */ + template + GenericImage& operator -=( const GenericImage& image ) + { + return Subtract( image ); + } + + /*! + * Multiplies a subset of pixel samples in this image by samples from the + * specified source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Mul, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Multiply( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Mul, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Multiply(). + */ + template + GenericImage& Mul( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Multiply( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Multiply(). + */ + template + GenericImage& operator *=( const GenericImage& image ) + { + return Multiply( image ); + } + + /*! + * Divides a subset of pixel samples in this image by samples from the + * specified source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Div, point, channel, rect, firstChannel, lastChannel ); + * \endcode + * + * When a source pixel sample of the specified \a image is zero or + * insignificant, the corresponding target pixel sample is set to the + * maximum sample value in the native range of this image. + */ + template + GenericImage& Divide( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Div, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Divide(). + */ + template + GenericImage& Div( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Divide( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Divide(). + */ + template + GenericImage& operator /=( const GenericImage& image ) + { + return Divide( image ); + } + + /*! + * Raises (exponentiation operator) a subset of pixel samples in this image + * to samples from the specified source \a image. Returns a reference to + * this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Pow, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Raise( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Pow, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Raise(). + */ + template + GenericImage& Pow( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Raise( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for Raise(). + */ + template + GenericImage& operator ^=( const GenericImage& image ) + { + return Raise( image ); + } + + /*! + * Replaces a subset of pixel samples in this image with the absolute values + * of their differences with samples from the specified source \a image. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Dif, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& SetAbsoluteDifference( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Dif, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for SetAbsoluteDifference(). + */ + template + GenericImage& Dif( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetAbsoluteDifference( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Replaces a subset of pixel samples in this image with the minimum of each + * target sample and the corresponding source sample of the specified + * \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Min, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& SetMinimum( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Min, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for SetMinimum(). + */ + template + GenericImage& Min( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMinimum( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Replaces a subset of pixel samples in this image with the maximum of each + * target sample and the corresponding source sample of the specified + * \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Min, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& SetMaximum( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Max, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * A synonym for SetMaximum(). + */ + template + GenericImage& Max( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMaximum( image, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise OR (inclusive OR) operation between a subset of pixel + * samples in this image and the corresponding samples of the specified + * source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Or, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Or( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Or, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise AND operation between a subset of pixel samples in + * this image and the corresponding samples of the specified source + * \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::And, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& And( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::And, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise XOR (exclusive OR) operation between a subset of pixel + * samples in this image and the corresponding samples of the specified + * source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Xor, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Xor( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Xor, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise NOR (NOT inclusive OR) operation between a subset of + * pixel samples in this image and the corresponding samples of the + * specified source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Nor, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Nor( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Nor, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise NAND (NOT AND) operation between a subset of pixel + * samples in this image and the corresponding samples of the specified + * source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Nand, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Nand( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Nand, point, channel, rect, firstChannel, lastChannel ); + } + + /*! + * Performs a bitwise XNOR (NOT exclusive OR) operation between a subset of + * pixel samples in this image and the corresponding samples of the + * specified source \a image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Apply( image, ImageOp::Xnor, point, channel, rect, firstChannel, lastChannel ); + * \endcode + */ + template + GenericImage& Xnor( const GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Apply( image, ImageOp::Xnor, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + + /*! + * Exchanges a subset of pixel samples between this image and another + * operand \a image. Returns a reference to this image. + * + * \param image Operand image, whose pixel samples will be exchanged with + * samples from this image. + * + * \param point Target point in image coordinates. This is the upper left + * corner of the target rectangular region where the source + * \a image will be exchanged with this image. If one or both + * point coordinates are equal to \c int_max (the maximum + * possible value of type \c int), then the current anchor + * point selection will be used. The default value is + * Point( int_max ). + * + * \param channel Target channel index (zero-based). This is the index of + * the first channel of this image where pixel samples will + * be exchanged. If this parameter is negative, then the + * currently selected channel will be used. The default value + * is -1. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The specified operation is performed with samples in the intersection + * between the specified (or implicit) rectangular selections for both + * images. Each channel in the specified channel range selection for this + * image is operated with its counterpart channel in the operand \a image, + * starting from the first selected channel in the operand \a image. + * + * The operation may involve conversions to the appropriate floating point + * data type for intermediate results, or LUT table lookups, as necessary + * to ensure preservation of the full native range of both images. + * + * \note Increments the status monitoring object by the number of pixel + * samples in the intersection between both operand images. + */ + template + GenericImage& Exchange( GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + Rect r = rect; + if ( !image.ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + if ( !ParseChannel( channel ) ) + return *this; + + Point p = point; + if ( p.x == int_max || p.y == int_max ) + p = m_point; + + if ( p.x < 0 ) + { + if ( (r.x0 -= p.x) >= r.x1 ) + return *this; + p.x = 0; + } + else if ( p.x >= m_width ) + return *this; + + if ( p.y < 0 ) + { + if ( (r.y0 -= p.y) >= r.y1 ) + return *this; + p.y = 0; + } + else if ( p.y >= m_height ) + return *this; + + r.ResizeTo( pcl::Min( m_width - p.x, r.Width() ), + pcl::Min( m_height - p.y, r.Height() ) ); + + lastChannel = pcl::Min( lastChannel, firstChannel + m_numberOfChannels - channel - 1 ); + + EnsureUnique(); + image.EnsureUnique(); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Exchanging pixel samples", N*(1 + lastChannel - firstChannel) ); + + if ( r == Bounds() && r == image.Bounds() ) + for ( int i = channel, j = firstChannel; j <= lastChannel; ++i, ++j, m_status += N ) + { + sample* __restrict__ f = m_pixelData[i]; + typename P1::sample* __restrict__ g = image[j]; + PCL_IVDEP + for ( size_type k = 0; k < N; ++k, ++f, ++g ) + { + sample t = *f; + P1::FromSample( *f, *g ); + P::FromSample( *g, t ); + } + } + else + for ( int i = channel, j = firstChannel, w = r.Width(), h = r.Height(); j <= lastChannel; ++i, ++j, m_status += N ) + { + sample* __restrict__ f = PixelAddress( p, i ); + typename P1::sample* __restrict__ g = image.PixelAddress( r.LeftTop(), j ); + PCL_IVDEP + for ( int k = 0; k < h; ++k, f += m_width-w, g += image.Width()-w ) + { + PCL_IVDEP + for ( int l = 0; l < w; ++l, ++f, ++g ) + { + sample t = *f; + P1::FromSample( *f, *g ); + P::FromSample( *g, t ); + } + } + } + + return *this; + } + + /*! + * A synonym for Exchange(). + */ + template + GenericImage& Xchg( GenericImage& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Exchange( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + + /*! + * Returns the minimum value among a subset of pixel samples of this image. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * minimum sample value. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + sample MinimumSampleValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing minimum pixel sample value", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new MinThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( MinThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( MinThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + sample min = P::MinSampleValue(); + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + min = threads[i].min; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + if ( threads[i].min < min ) + min = threads[i].min; + break; + } + + threads.Destroy(); + m_status += N; + return min; + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * MinimumSampleValue() instead. + */ + sample MinimumPixelValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return MinimumSampleValue( rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * Returns the maximum value among a subset of pixel samples of this image. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * maximum sample value. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + sample MaximumSampleValue( const Rect& rect = Rect( 0 ), + int firstChannel = -1, int lastChannel = -1, int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing maximum pixel sample value", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new MaxThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( MaxThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( MaxThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + sample max = P::MinSampleValue(); + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + max = threads[i].max; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + if ( max < threads[i].max ) + max = threads[i].max; + break; + } + + threads.Destroy(); + m_status += N; + return max; + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * MaximumSampleValue() instead. + */ + sample MaximumPixelValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return MaximumSampleValue( rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * Obtains the extreme values among a subset of pixel samples of this image. + * + * \param[out] min Minimum sample value. + * + * \param[out] max Maximum sample value. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If necessary, the output values will be converted from the pixel sample + * data type of this image using pixel traits primitives. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * extreme sample values. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + void GetExtremeSampleValues( T& min, T& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + { + // ### Required for compatibility with PCL 1.x + P::FromSample( min, P::MinSampleValue() ); + max = min; + return; + } + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing extreme pixel sample values", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new MinMaxThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( MinMaxThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( MinMaxThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + sample vmin = P::MinSampleValue(); + sample vmax = P::MinSampleValue(); + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + vmin = threads[i].min; + vmax = threads[i].max; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + { + if ( threads[i].min < vmin ) + vmin = threads[i].min; + if ( vmax < threads[i].max ) + vmax = threads[i].max; + } + break; + } + + threads.Destroy(); + m_status += N; + P::FromSample( min, vmin ); + P::FromSample( max, vmax ); + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * GetExtremeSampleValues() instead. + */ + void GetExtremePixelValues( sample& min, sample& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + GetExtremeSampleValues( min, max, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * Returns the minimum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * \param[out] xmin Horizontal coordinate of the first occurrence of the + * returned minimum pixel sample value. + * + * \param[out] ymin Vertical coordinate of the first occurrence of the + * returned minimum pixel sample value. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * minimum sample value. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + sample LocateMinimumSampleValue( int& xmin, int& ymin, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + { + // ### Required for compatibility with PCL 1.x + xmin = ymin = 0; + return P::MinSampleValue(); + } + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Locating minimum pixel sample value", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new MinPosThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( MinPosThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( MinPosThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + xmin = ymin = -1; + sample min = P::MinSampleValue(); + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + min = threads[i].min; + xmin = threads[i].pmin.x; + ymin = threads[i].pmin.y; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + if ( threads[i].min < min ) + { + min = threads[i].min; + xmin = threads[i].pmin.x; + ymin = threads[i].pmin.y; + } + break; + } + + threads.Destroy(); + m_status += N; + return min; + } + + /*! + * Returns the minimum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * \param[out] pmin Coordinates of the first occurrence of the returned + * minimum pixel sample value. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * This member function is equivalent to: + * + * \code + * LocateMinimumSampleValue( pmin.x, pmin.y, rect, firstChannel, lastChannel ); + * \endcode + */ + sample LocateMinimumSampleValue( Point& pmin, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return LocateMinimumSampleValue( pmin.x, pmin.y, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * LocateMinimumSampleValue() instead. + */ + sample LocateMinimumPixelValue( int& xmin, int& ymin, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return LocateMinimumSampleValue( xmin, ymin, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * LocateMinimumSampleValue() instead. + */ + sample LocateMinimumPixelValue( Point& pmin, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return LocateMinimumSampleValue( pmin, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * Returns the maximum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * \param[out] xmax Horizontal coordinate of the first occurrence of the + * returned maximum pixel sample value. + * + * \param[out] ymax Vertical coordinate of the first occurrence of the + * returned maximum pixel sample value. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * maximum sample value. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + sample LocateMaximumSampleValue( int& xmax, int& ymax, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + { + // ### Required for compatibility with PCL 1.x + xmax = ymax = 0; + return P::MaxSampleValue(); + } + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Locating maximum pixel sample value", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new MaxPosThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( MaxPosThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( MaxPosThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + xmax = ymax = -1; + sample max = P::MinSampleValue(); + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + max = threads[i].max; + xmax = threads[i].pmax.x; + ymax = threads[i].pmax.y; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + if ( max < threads[i].max ) + { + max = threads[i].max; + xmax = threads[i].pmax.x; + ymax = threads[i].pmax.y; + } + break; + } + + threads.Destroy(); + m_status += N; + return max; + } + + /*! + * Returns the maximum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * \param[out] pmax Coordinates of the first occurrence of the returned + * maximum pixel sample value. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the parameters of this member function, see the + * documentation for Fill(). + * + * This member function is equivalent to: + * + * \code + * LocateMaximumSampleValue( pmax.x, pmax.y, rect, firstChannel, lastChannel ); + * \endcode + */ + sample LocateMaximumSampleValue( Point& pmax, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return LocateMaximumSampleValue( pmax.x, pmax.y, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * LocateMaximumSampleValue() instead. + */ + sample LocateMaximumPixelValue( int& xmax, int& ymax, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return LocateMaximumSampleValue( xmax, ymax, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * \deprecated This member function has been deprecated. It is still part of + * PCL only to keep existing code alive. In newly produced code, use + * LocateMaximumSampleValue() instead. + */ + sample LocateMaximumPixelValue( Point& pmax, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return LocateMaximumSampleValue( pmax, rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * Obtains the extreme values, and the image coordinates of their first + * occurrences, among a subset of pixel samples of this image. + * + * \param[out] xmin Horizontal coordinate of the first occurrence of the + * minimum pixel sample value. + * + * \param[out] ymin Vertical coordinate of the first occurrence of the + * minimum pixel sample value. + * + * \param[out] min Minimum pixel sample value in the selected subset. + * + * \param[out] xmax Horizontal coordinate of the first occurrence of the + * maximum pixel sample value. + * + * \param[out] ymax Vertical coordinate of the first occurrence of the + * maximum pixel sample value. + * + * \param[out] max Maximum pixel sample value in the selected subset. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * extreme sample values. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + template + void LocateExtremeSampleValues( int& xmin, int& ymin, T& min, + int& xmax, int& ymax, T& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + { + // ### Required for compatibility with PCL 1.x + xmin = ymin = xmax = ymax = 0; + P::FromSample( min, P::MinSampleValue() ); + max = min; + return; + } + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Locating extreme pixel sample values", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new MinMaxPosThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( MinMaxPosThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( MinMaxPosThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + xmin = ymin = xmax = ymax = -1; + sample vmin = P::MinSampleValue(); + sample vmax = P::MinSampleValue(); + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + vmin = threads[i].min; + xmin = threads[i].pmin.x; + ymin = threads[i].pmin.y; + vmax = threads[i].max; + xmax = threads[i].pmax.x; + ymax = threads[i].pmax.y; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + { + if ( threads[i].min < vmin ) + { + vmin = threads[i].min; + xmin = threads[i].pmin.x; + ymin = threads[i].pmin.y; + } + if ( vmax < threads[i].max ) + { + vmax = threads[i].max; + xmax = threads[i].pmax.x; + ymax = threads[i].pmax.y; + } + } + break; + } + + threads.Destroy(); + m_status += N; + P::FromSample( min, vmin ); + P::FromSample( max, vmax ); + } + + /*! + * Obtains the extreme values, and the image coordinates of their first + * occurrences, among a subset of pixel samples of this image. + * + * \param[out] pmin Coordinates of the first occurrence of the minimum + * pixel sample value. + * + * \param[out] min Minimum pixel sample value in the selected subset. + * + * \param[out] pmax Coordinates of the first occurrence of the maximum + * pixel sample value. + * + * \param[out] max Maximum pixel sample value in the selected subset. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account to search for the + * extreme sample values. + */ + template + void LocateExtremeSampleValues( Point& pmin, T& min, + Point& pmax, T& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + LocateExtremeSampleValues( pmin.x, pmin.y, min, + pmax.x, pmax.y, max, + rect, firstChannel, lastChannel, maxProcessors ); + } + + /*! + * Returns the number of pixel samples selectable for statistics calculation + * from a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account. If range clipping + * is disabled, the result of this member function will be the volume of the + * specified (or implicitly selected) region. + * + * When range clipping is enabled and this is a complex-valued image, this + * function uses the magnitudes (or absolute values) of all selected samples + * to compare them with the bounds of the current clipping range. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + size_type Count( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Counting pixel samples", N ); + + if ( !this->IsRangeClippingEnabled() ) + { + m_status += N; + return size_type( r.Width() ) * size_type( r.Height() ) * size_type( 1 + lastChannel - firstChannel ); + } + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new CountThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( CountThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( CountThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + size_type count = 0; + for ( const CountThread& thread : threads ) + count += thread.count; + + threads.Destroy(); + m_status += N; + return count; + } + + /*! + * Returns the arithmetic mean of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the mean in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the mean of the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the mean. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Mean( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing mean pixel sample value", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SumThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( SumThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s = 0; + double e = 0; + size_type n = 0; + for ( const SumThread& thread : threads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + n += thread.n; + } + + threads.Destroy(); + + m_status += N; + + if ( n == 0 ) + return 0; + return s/n; + } + + /*! + * Returns the median of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the median in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the median of the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the median. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Median( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing median pixel sample value", N ); + + if ( N <= 2560000 ) + { + SmpThread S( *this, r, firstChannel, lastChannel, 0, r.Height() ); + S.Run(); + if ( S.n == 0 ) + { + m_status += N; + return 0; + } + double m = double( *pcl::Select( S.samples.Begin(), S.samples.At( S.n ), S.n >> 1 ) )/double( P::MaxSampleValue() ); + if ( S.n & 1 ) + { + m_status += N; + return m; + } + m = (m + double( *pcl::Select( S.samples.Begin(), S.samples.At( S.n ), (S.n >> 1)-1 ) )/double( P::MaxSampleValue() ))/2; + m_status += N; + return m; + } + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors, 160*1024/*overheadLimitPx*/ ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + + double low, high; + size_type count = 0; + { + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new MinMaxThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ); + + if ( threads.Length() > 1 ) + { + int i = 0; + for ( MinMaxThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 ); + for ( MinMaxThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + sample slow = 0, shigh = 0; + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + slow = threads[i].min; + shigh = threads[i].max; + count = threads[i].count; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + { + if ( threads[i].min < slow ) + slow = threads[i].min; + if ( shigh < threads[i].max ) + shigh = threads[i].max; + count += threads[i].count; + } + break; + } + + threads.Destroy(); + + low = double( slow ); + high = double( shigh ); + } + + const double eps = P::IsComplexSample() ? 2*std::numeric_limits::epsilon() : + (P::IsFloatSample() ? 2*std::numeric_limits::epsilon() : + 0.5/Pow2( double( P::BitsPerSample() ) )); + if ( count == 0 ) + { + m_status += N; + return 0; + } + if ( high - low < eps ) + { + m_status += N; + return low/double( P::MaxSampleValue() ); + } + + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new HistogramThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ), low, high ); + + double mh = 0, l0 = low, h0 = high; + SzVector H0; + + for ( size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it ) + { + SzVector H; + if ( it == 0 && step ) + H = H0; + else + { + if ( threads.Length() > 1 ) + { + int i = 0; + for ( HistogramThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 ); + for ( HistogramThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + H = threads[0].H; + for ( size_type i = 1; i < threads.Length(); ++i ) + H += threads[i].H; + if ( it == 0 ) + if ( (count & 1) == 0 ) + H0 = H; + } + + for ( int i = 0; ; n += H[i++] ) + if ( n + H[i] > n2 ) + { + double range = high - low; + high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low; + low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low; + if ( high - low < eps ) + { + if ( count & 1 ) + { + threads.Destroy(); + m_status += N; + return low/double( P::MaxSampleValue() ); + } + if ( step ) + { + threads.Destroy(); + m_status += N; + return (low + mh)/2/double( P::MaxSampleValue() ); + } + mh = low; + low = l0; + high = h0; + n = 0; + --n2; + ++step; + it = 0; + } + break; + } + } + } + + /*! + * Returns an order statistic computed for a subset of pixel samples. + * + * \param k Selection point in the [0,1] range, where 0 corresponds to + * the minimum value in the ordered subset of selected pixel + * samples and 1 corresponds to the maximum value. If the value of + * this parameter is outside the [0,1] range, this function returns + * zero conventionally. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This function returns the requested order statistic in the normalized + * range [0,1], irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the requested order + * statistic for the set of magnitudes (or absolute values) of all selected + * samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double OrderStatistic( double k, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + if ( k < 0 || k > 1 ) + return 0; + + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing order statistic", N ); + + if ( N <= 2560000 ) + { + SmpThread S( *this, r, firstChannel, lastChannel, 0, r.Height() ); + S.Run(); + m_status += N; + if ( S.n == 0 ) + return 0; + return double( *pcl::Select( S.samples.Begin(), S.samples.At( S.n ), distance_type( k*(S.n - 1) ) ) )/double( P::MaxSampleValue() ); + } + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors, 160*1024/*overheadLimitPx*/ ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + + double low, high; + size_type count = 0; + { + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new MinMaxThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ); + + if ( threads.Length() > 1 ) + { + int i = 0; + for ( MinMaxThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 ); + for ( MinMaxThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + sample slow = 0, shigh = 0; + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + slow = threads[i].min; + shigh = threads[i].max; + count = threads[i].count; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + { + if ( threads[i].min < slow ) + slow = threads[i].min; + if ( shigh < threads[i].max ) + shigh = threads[i].max; + count += threads[i].count; + } + break; + } + + threads.Destroy(); + + low = double( slow ); + high = double( shigh ); + } + + const double eps = P::IsComplexSample() ? 2*std::numeric_limits::epsilon() : + (P::IsFloatSample() ? 2*std::numeric_limits::epsilon() : + 0.5/Pow2( double( P::BitsPerSample() ) )); + if ( count == 0 ) + { + m_status += N; + return 0; + } + if ( k == 0 || high - low < eps ) + { + m_status += N; + return low/double( P::MaxSampleValue() ); + } + if ( k == 1 ) + { + m_status += N; + return high/double( P::MaxSampleValue() ); + } + + size_type index = size_type( k*(count - 1) ); + + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new HistogramThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ), low, high ); + + for ( size_type n = 0;; ) + { + if ( threads.Length() > 1 ) + { + int i = 0; + for ( HistogramThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 ); + for ( HistogramThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + SzVector H = threads[0].H; + for ( size_type i = 1; i < threads.Length(); ++i ) + H += threads[i].H; + + for ( int i = 0; ; n += H[i++] ) + if ( n + H[i] > index ) + { + double range = high - low; + high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low; + low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low; + if ( high - low < eps ) + { + threads.Destroy(); + m_status += N; + return low/double( P::MaxSampleValue() ); + } + break; + } + } + } + + /*! + * Returns the variance from the mean of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the variance in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the variance of the + * magnitudes (or absolute values) of all selected samples. + * + * This implementation uses a two-pass compensated summation algorithm to + * minimize roundoff errors (see References). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the variance. + * + * \b References + * + * William H. Press et al., Numerical Recipes in C: The Art of + * Scientific Computing, Second Edition (1997 reprint) Cambridge + * University Press, page 613. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Variance( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing variance", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray sumThreads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + sumThreads.Add( new SumThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( sumThreads.Length() > 1 ) + { + int n = 0; + for ( SumThread& thread : sumThreads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumThread& thread : sumThreads ) + thread.Wait(); + } + else + sumThreads[0].Run(); + + double s = 0; + double e = 0; + size_type n = 0; + for ( const SumThread& thread : sumThreads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + n += thread.n; + } + + sumThreads.Destroy(); + + if ( n < 2 ) + return 0; + double mean = s/n; + + ReferenceArray varThreads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + varThreads.Add( new VarThread( *this, mean, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( varThreads.Length() > 1 ) + { + int n = 0; + for ( VarThread& thread : varThreads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( VarThread& thread : varThreads ) + thread.Wait(); + } + else + varThreads[0].Run(); + + double var = 0, eps = 0; + for ( const VarThread& thread : varThreads ) + var += thread.var, eps += thread.eps; + + varThreads.Destroy(); + m_status += N; + return (var - eps*eps/n)/(n - 1); + } + + /*! + * Returns the standard deviation from the mean of a subset of pixel + * samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the standard deviation in the normalized + * range [0,1], irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the standard deviation + * of the magnitudes (or absolute values) of all selected samples. + * + * This implementation uses a two-pass compensated summation algorithm to + * minimize roundoff errors (see References). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the variance. + * + * \b References + * + * William H. Press et al., Numerical Recipes in C: The Art of + * Scientific Computing, Second Edition (1997 reprint) Cambridge + * University Press, page 613. + */ + double StdDev( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + return pcl::Sqrt( Variance( rect, firstChannel, lastChannel, maxProcessors ) ); + } + + /*! + * Returns the mean absolute deviation of a subset of pixel samples with + * respect to the specified \a center value. + * + * \param center Reference central value for computation of the mean + * absolute deviation in the normalized range [0,1]. + * Typically, this parameter is set to the median value of + * the set of pixel samples used for calculation. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the mean absolute deviation with respect to + * \a center in the normalized range [0,1], irrespective of the sample data + * type of the image. + * + * For complex-valued images, this function returns the average absolute + * deviation of the magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the average absolute deviation. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double AvgDev( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing average absolute deviation", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SumAbsDevThread( *this, center, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( SumAbsDevThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumAbsDevThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s = 0; + double e = 0; + size_type n = 0; + for ( const SumAbsDevThread& thread : threads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + n += thread.n; + } + + threads.Destroy(); + + m_status += N; + + if ( n == 0 ) + return 0; + return s/n; + } + + /*! + * Returns the two-sided mean absolute deviation of a subset of pixel + * samples with respect to the specified \a center value. + * + * \param center Reference central value for computation of the mean + * absolute deviation in the normalized range [0,1]. + * Typically, the value of this parameter is the median of + * the set of pixel samples used for calculation. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * See AvgDev() for complete information and references. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + TwoSidedEstimate TwoSidedAvgDev( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing two-sided average absolute deviation", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new TwoSidedSumAbsDevThread( *this, center, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( TwoSidedSumAbsDevThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( TwoSidedSumAbsDevThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s0 = 0, s1 = 0; + double e0 = 0, e1 = 0; + size_type n0 = 0, n1 = 0; + for ( const TwoSidedSumAbsDevThread& thread : threads ) + { + double y = thread.s0 - e0; + double t = s0 + y; + e0 = (t - s0) - y; + s0 = t; + n0 += thread.n0; + y = thread.s1 - e1; + t = s1 + y; + e1 = (t - s1) - y; + s1 = t; + n1 += thread.n1; + } + + threads.Destroy(); + + m_status += N; + + return { (n0 > 0) ? s0/n0 : 0.0, + (n1 > 0) ? s1/n1 : 0.0 }; + } + + /*! + * Returns the median absolute deviation (MAD) of a subset of pixel samples + * with respect to the specified \a center value. + * + * \param center Reference central value for computation of MAD in the + * normalized range [0,1]. Normally, this value should be the + * median of the selected pixel samples, or the median of the + * whole image. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns MAD in the normalized range [0,1] with + * respect to \a center, irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the MAD of the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the median absolute deviation. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, it must be multiplied by the constant 1.4826. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double MAD( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing median absolute deviation", N ); + + if ( N <= 2560000 ) + { + AbsDevSmpThread S( *this, center, r, firstChannel, lastChannel, 0, r.Height() ); + S.Run(); + if ( S.n == 0 ) + { + m_status += N; + return 0; + } + double m = *pcl::Select( S.values.Begin(), S.values.At( S.n ), S.n >> 1 ); + if ( S.n & 1 ) + { + m_status += N; + return m; + } + m = (m + *pcl::Select( S.values.Begin(), S.values.At( S.n ), (S.n >> 1)-1 ))/2; + m_status += N; + return m; + } + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors, 160*1024/*overheadLimitPx*/ ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + + double low, high; + size_type count = 0; + { + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new ExtremeAbsDevThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ), center ); + + if ( threads.Length() > 1 ) + { + int n = 0; + for ( ExtremeAbsDevThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( ExtremeAbsDevThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].count > 0 ) + { + low = threads[i].minAbsDev; + high = threads[i].maxAbsDev; + count += threads[i].count; + while ( ++i < threads.Length() ) + if ( threads[i].count > 0 ) + { + if ( threads[i].minAbsDev < low ) + low = threads[i].minAbsDev; + if ( threads[i].maxAbsDev > high ) + high = threads[i].maxAbsDev; + count += threads[i].count; + } + break; + } + + threads.Destroy(); + } + + const double eps = 2*std::numeric_limits::epsilon(); + if ( count == 0 || high - low < eps ) + { + m_status += N; + return 0; + } + + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new AbsDevHistogramThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ), center, low, high ); + + double mh = 0, l0 = low, h0 = high; + SzVector H0; + + for ( size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it ) + { + SzVector H; + if ( it == 0 && step ) + H = H0; + else + { + if ( threads.Length() > 1 ) + { + int i = 0; + for ( AbsDevHistogramThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 ); + for ( AbsDevHistogramThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + H = threads[0].H; + for ( size_type i = 1; i < threads.Length(); ++i ) + H += threads[i].H; + if ( it == 0 ) + if ( (count & 1) == 0 ) + H0 = H; + } + + for ( int i = 0; ; n += H[i++] ) + if ( n + H[i] > n2 ) + { + double range = high - low; + high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low; + low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low; + if ( high - low < eps ) + { + if ( count & 1 ) + { + threads.Destroy(); + m_status += N; + return low; + } + if ( step ) + { + threads.Destroy(); + m_status += N; + return (low + mh)/2; + } + mh = low; + low = l0; + high = h0; + n = 0; + --n2; + ++step; + it = 0; + } + break; + } + } + } + + /*! + * Returns the two-sided median absolute deviation (MAD) of a subset of + * pixel samples with respect to the specified \a center value. + * + * \param center Reference central value for computation of MAD in the + * normalized range [0,1]. Normally, this value should be the + * median of the selected pixel samples, or the median of the + * whole image. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * See MAD() for more information and references. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + TwoSidedEstimate TwoSidedMAD( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing two-sided median absolute deviation", N ); + + if ( N <= 2560000 ) + { + TwoSidedAbsDevSmpThread S( *this, center, r, firstChannel, lastChannel, 0, r.Height() ); + S.Run(); + m_status += N; + return { pcl::Median( S.values.Begin(), S.p ), + pcl::Median( S.q, S.values.End() ) }; + } + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors, 160*1024/*overheadLimitPx*/ ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + + double minLow = 0, minHigh = 0, maxLow = 0, maxHigh = 0; + size_type nLow = 0, nHigh = 0; + { + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new TwoSidedExtremeAbsDevThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ), center ); + + if ( threads.Length() > 1 ) + { + int n = 0; + for ( TwoSidedExtremeAbsDevThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( TwoSidedExtremeAbsDevThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].nLow > 0 ) + { + minLow = threads[i].minAbsDevLow; + maxLow = threads[i].maxAbsDevLow; + nLow = threads[i].nLow; + while ( ++i < threads.Length() ) + if ( threads[i].nLow > 0 ) + { + if ( threads[i].minAbsDevLow < minLow ) + minLow = threads[i].minAbsDevLow; + if ( threads[i].maxAbsDevLow > maxLow ) + maxLow = threads[i].maxAbsDevLow; + nLow += threads[i].nLow; + } + break; + } + + for ( size_type i = 0; i < threads.Length(); ++i ) + if ( threads[i].nHigh > 0 ) + { + minHigh = threads[i].minAbsDevHigh; + maxHigh = threads[i].maxAbsDevHigh; + nHigh = threads[i].nHigh; + while ( ++i < threads.Length() ) + if ( threads[i].nHigh > 0 ) + { + if ( threads[i].minAbsDevHigh < minHigh ) + minHigh = threads[i].minAbsDevHigh; + if ( threads[i].maxAbsDevHigh > maxHigh ) + maxHigh = threads[i].maxAbsDevHigh; + nHigh += threads[i].nHigh; + } + break; + } + + threads.Destroy(); + } + + int side; + double sideLow, sideHigh; + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads << new TwoSidedAbsDevHistogramThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ), center, side, sideLow, sideHigh ); + + const double eps = 2*std::numeric_limits::epsilon(); + double mad[ 2 ]; + for ( side = 0; side < 2; ++side ) + { + size_type n = side ? nHigh : nLow; + if ( n < 2 ) + { + mad[side] = 0; + continue; + } + + sideLow = side ? minHigh : minLow; + sideHigh = side ? maxHigh : maxLow; + if ( sideHigh - sideLow < eps ) + { + mad[side] = 0; + continue; + } + + double mh = 0, h0 = sideHigh; + SzVector H0; + + for ( size_type count = 0, n2 = n >> 1, step = 0, it = 0;; ++it ) + { + SzVector H; + if ( it == 0 && step ) + H = H0; + else + { + if ( threads.Length() > 1 ) + { + int i = 0; + for ( TwoSidedAbsDevHistogramThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 ); + for ( TwoSidedAbsDevHistogramThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + H = threads[0].H; + for ( size_type i = 1; i < threads.Length(); ++i ) + H += threads[i].H; + if ( it == 0 ) + if ( (n & 1) == 0 ) + H0 = H; + } + + for ( int i = 0; ; count += H[i++] ) + if ( count + H[i] > n2 ) + { + double range = sideHigh - sideLow; + sideHigh = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow; + sideLow = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow; + if ( sideHigh - sideLow < eps ) + { + if ( n & 1 ) + { + mad[side] = sideLow; + goto __madNextSide; + } + if ( step ) + { + mad[side] = (sideLow + mh)/2; + goto __madNextSide; + } + mh = sideLow; + sideLow = 0; + sideHigh = h0; + count = 0; + --n2; + ++step; + it = 0; + } + break; + } + } + +__madNextSide: + ; + } + + threads.Destroy(); + m_status += N; + return { mad[0], mad[1] }; + } + + /*! + * Returns a biweight midvariance (BWMV) for a subset of pixel samples. + * + * \param center Reference center value in the [0,1] range. Normally, the + * median of the selected pixel samples should be used. + * + * \param sigma A reference estimate of dispersion in the [0,1] range. + * Normally, the median absolute deviation from the median + * (MAD) of the selected pixel samples should be used. + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The square root of the biweight midvariance is a robust estimator of + * scale. It is an efficient estimator with respect to many statistical + * distributions (about 87% Gaussian efficiency), and appears to have a + * breakdown point close to 0.5 (the same as MAD). + * + * This member function returns BWMV in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns a BWMV for the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the biweight midvariance. + * + * \b References + * + * Rand R. Wilcox (2012), Introduction to Robust Estimation and Hypothesis + * Testing, 3rd Edition, Elsevier Inc., Section 3.12.1. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double BiweightMidvariance( double center, double sigma, int k = 9, bool reducedLength = false, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + double kd = k * sigma; + if ( kd < 0 || 1 + kd == 1 ) + { + m_status += N; + return 0; + } + + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing biweight midvariance", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new BWMVThread( *this, center, kd, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( BWMVThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( BWMVThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double num = 0, den = 0; + size_type n = 0, nr = 0; + for ( const BWMVThread& thread : threads ) + { + num += thread.num; + den += thread.den; + n += thread.n; + nr += thread.nr; + } + + threads.Destroy(); + + m_status += N; + den *= den; + return (n >= 2 && 1 + den != 1) ? (reducedLength ? nr : n)*num/den : 0.0; + } + + /*! + * Returns a two-sided biweight midvariance (BWMV) for a subset of pixel + * samples. + * + * \param center Reference center value in the [0,1] range. Normally, the + * median of the selected pixel samples should be used. + * + * \param sigma Reference estimates of dispersion in the [0,1] range, + * respectively for samples below and above the reference \a center + * value (low and high members of the TwoSidedEstimate structure, + * respectively). Normally, a two-sided median absolute deviation + * from the median (two-sided MAD) for the selected pixel samples + * should be specified. + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * See the BiweightMidvariance() member function for more information and + * references. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + TwoSidedEstimate TwoSidedBiweightMidvariance( double center, const TwoSidedEstimate& sigma, int k = 9, bool reducedLength = false, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + double kd0 = k * sigma.low; + double kd1 = k * sigma.high; + if ( kd0 < 0 || 1 + kd0 == 1 || kd1 < 0 || 1 + kd1 == 1 ) + { + m_status += N; + return 0; + } + + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing two-sided biweight midvariance", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new TwoSidedBWMVThread( *this, center, kd0, kd1, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( TwoSidedBWMVThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( TwoSidedBWMVThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double num0 = 0, den0 = 0, num1 = 0, den1 = 0; + size_type n0 = 0, n1 = 0, nr0 = 0, nr1 = 0; + for ( const TwoSidedBWMVThread& thread : threads ) + { + num0 += thread.num0; + den0 += thread.den0; + num1 += thread.num1; + den1 += thread.den1; + n0 += thread.n0; + n1 += thread.n1; + nr0 += thread.nr0; + nr1 += thread.nr1; + } + + threads.Destroy(); + + m_status += N; + + den0 *= den0; + den1 *= den1; + return { (n0 >= 2 && 1 + den0 != 1) ? (reducedLength ? nr0 : n0)*num0/den0 : 0.0, + (n1 >= 2 && 1 + den1 != 1) ? (reducedLength ? nr1 : n1)*num1/den1 : 0.0 }; + } + + /*! + * Returns a percentage bend midvariance (PBMV) for a subset of pixel + * samples. + * + * \param center Reference center value in the [0,1] range. Normally, the + * median of the selected pixel samples should be used. + * + * \param beta Rejection parameter in the [0,0.5] range. Higher values + * improve robustness to outliers (i.e., increase the + * breakdown point of the estimator) at the expense of lower + * efficiency. The default value is beta=0.2. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The square root of the percentage bend midvariance is a robust estimator + * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With + * beta=0.1, its efficiency is 85% but its breakdown is only 0.1. + * + * This member function returns PBMV in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns a PBMV for the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the percentage bend midvariance. + * + * \b References + * + * Rand R. Wilcox (2012), Introduction to Robust Estimation and Hypothesis + * Testing, 3rd Edition, Elsevier Inc., Section 3.12.3. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double BendMidvariance( double center, double beta = 0.2, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing percentage bend midvariance", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new DSmpThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( DSmpThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( DSmpThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + Array values; + for ( DSmpThread& thread : threads ) + if ( !thread.values.IsEmpty() ) + { + values.Add( thread.values.Begin(), thread.values.At( thread.n ) ); + thread.values.Clear(); + } + + threads.Destroy(); + + double pbmv = pcl::BendMidvariance( values.Begin(), values.End(), center, beta ); + m_status += N; + return pbmv; + } + + /*! + * Sn scale estimator of Rousseeuw and Croux for a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * For a sample {x0,...,x_n-1}, the Sn estimator is given by: + * + * Sn = c * low_median( high_median( |x_i - x_j| ) ) + * + * where low_median() is the order statistic of rank (n + 1)/2, and + * high_median() is the order statistic of rank n/2 + 1. + * + * This member function returns Sn in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the Sn estimator of the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the Sn estimator. + * + * The constant c = 1.1926 must be used to make the Sn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for + * consistency with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median Absolute + * Deviation, Journal of the American Statistical Association, Vol. 88, + * pp. 1273-1283. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Sn( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing Sn scale estimate", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new DSmpThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( DSmpThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( DSmpThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + Array values; + for ( DSmpThread& thread : threads ) + if ( !thread.values.IsEmpty() ) + { + values.Add( thread.values.Begin(), thread.values.At( thread.n ) ); + thread.values.Clear(); + } + + threads.Destroy(); + + double sn = pcl::Sn( values.Begin(), values.End() ); + m_status += N; + return sn; + } + + /*! + * Qn scale estimator of Rousseeuw and Croux for a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * For a sample {x0,...,x_n-1}, the Qn estimator is given by: + * + * Qn = c * first_quartile( |x_i - x_j| : i < j ) + * + * where first_quartile() is the order statistic of rank (n + 1)/4. + * + * This member function returns Qn in the normalized range [0,1], + * irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the Qn estimator of the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the Qn estimator. + * + * The constant c = 2.2219 must be used to make the Qn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for + * consistency with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median Absolute + * Deviation, Journal of the American Statistical Association, Vol. 88, + * pp. 1273-1283. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Qn( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing Qn scale estimate", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new DSmpThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( DSmpThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( DSmpThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + Array values; + for ( DSmpThread& thread : threads ) + if ( !thread.values.IsEmpty() ) + { + values.Add( thread.values.Begin(), thread.values.At( thread.n ) ); + thread.values.Clear(); + } + + threads.Destroy(); + + double qn = pcl::Qn( values.Begin(), values.End() ); + m_status += N; + return qn; + } + + /*! + * Returns the norm of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The norm is the sum of all selected pixel sample values. This member + * function returns the norm in the normalized range [0,1], irrespective of + * the sample data type of the image. + * + * For real-valued integer images, this function returns the sum of all + * selected samples converted to the normalized range [0,1]. + * + * For floating-point real images, this function simply sums all selected + * samples, assuming that no selected samples have negative values. If there + * are some negative values, the returned value may make not sense, + * depending on the application. + * + * For complex-valued images, this function returns the sum of the + * magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the norm. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Norm( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing norm", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SumThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( SumThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s = 0; + double e = 0; + for ( const SumThread& thread : threads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + } + + threads.Destroy(); + m_status += N; + return (1 + s != 1) ? s : 0.0; // don't return insignificant nonzero values + } + + /*! + * Returns the modulus of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * The modulus is the sum of the absolute values of all selected pixel + * sample values. This member function returns the modulus in the normalized + * range [0,1], irrespective of the sample data type of the image. + * + * This member function only makes sense for real-valued floating point + * images. For the rest of image types, including unsigned integer and + * complex valued images, this function is always equivalent to Norm(). + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the modulus. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double Modulus( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing modulus", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SumAbsThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( SumAbsThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumAbsThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s = 0; + double e = 0; + for ( const SumAbsThread& thread : threads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + } + + threads.Destroy(); + m_status += N; + return (1 + s != 1) ? s : 0.0; // don't return insignificant nonzero values + } + + /*! + * Returns the sum of the squares of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the sum of squares in the normalized range + * [0,1], irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the sum of the + * squares of the magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the sum of squares. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double SumOfSquares( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing sum of squares", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SumSqrThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( SumSqrThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumSqrThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s = 0; + double e = 0; + for ( const SumSqrThread& thread : threads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + } + + threads.Destroy(); + m_status += N; + return (1 + s != 1) ? s : 0.0; // don't return insignificant nonzero values + } + + /*! + * Returns the mean of the squares of a subset of pixel samples. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This member function returns the mean of squares in the normalized range + * [0,1], irrespective of the sample data type of the image. + * + * For complex-valued images, this function returns the mean of the + * squares of the magnitudes (or absolute values) of all selected samples. + * + * If range clipping is enabled for this image, only pixel samples within + * the current clipping range will be taken into account for calculation of + * the mean of squares. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + double MeanOfSquares( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing mean of squares", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SumSqrThread( *this, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( SumSqrThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( SumSqrThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + double s = 0; + double e = 0; + size_type n = 0; + for ( const SumSqrThread& thread : threads ) + { + double y = thread.s - e; + double t = s + y; + e = (t - s) - y; + s = t; + n += thread.n; + } + + threads.Destroy(); + + m_status += N; + + if ( n < 1 ) + return 0; + return s/n; + } + + /*! + * Returns a vector of norms for a subset of pixel samples. + * + * \param maxDegree Maximum degree ≥ 1 of the computed vector of + * norms. The default value is 2, hence the L1 and L2 norms are + * computed if this parameter is not specified. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + * + * This function computes a series of image norms, up to \a maxDegree, in a + * single multithreaded operation for improved efficiency. The norms are + * returned as a vector. The first vector component is the L1 norm, which is + * the sum of all selected pixel sample values. The second vector component + * is the L2 norm, or the sum of squared pixel sample values, and so on. + * + * For the sake of performance, this function assumes that no negative + * values exist in the selected subset of pixel samples; otherwise, odd + * norms will provide meaningless results. All norms are returned expressed + * in the normalized range [0,1], irrespective of the sample data type of + * the image. + * + * This function implements a numerically stable summation algorithm to + * reduce roundoff errors to the machine's floating point precision. + * + * See the Norm() and SumOfSquares() member functions for more information + * and important implementation details. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + */ + Vector Norms( int maxDegree = 2, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + PCL_PRECONDITION( maxDegree > 0 ) + maxDegree = pcl::Max( 1, maxDegree ); + + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return 0; + + size_type N = size_type( r.Width() )*size_type( r.Height() )*(1 + lastChannel - firstChannel); + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing norms", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + bool useAffinity = m_parallel && Thread::IsRootThread(); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new NormThread( *this, maxDegree, r, firstChannel, lastChannel, n, n + int( L[i] ) ) ); + if ( threads.Length() > 1 ) + { + int n = 0; + for ( NormThread& thread : threads ) + thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 ); + for ( NormThread& thread : threads ) + thread.Wait(); + } + else + threads[0].Run(); + + Vector R( 0.0, maxDegree ); + Vector e( 0.0, maxDegree ); + for ( const NormThread& thread : threads ) + for ( int i = 0; i < maxDegree; ++i ) + { + double y = thread.R[i] - e[i]; + double t = R[i] + y; + e[i] = (t - R[i]) - y; + R[i] = t; + } + for ( int i = 0; i < maxDegree; ++i ) + if ( 1 + R[i] == 1 ) // don't return insignificant nonzero values + R[i] = 0; + + threads.Destroy(); + m_status += N; + return R; + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for the specified + * \a channel of this image. + * + * This function calls pcl::Hash64() for the internal pixel sample buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + */ + uint64 Hash64( int channel = -1, uint64 seed = 0 ) const noexcept + { + if ( !ParseChannel( channel ) ) + return 0; + return pcl::Hash64( m_channelData( channel ), ChannelSize(), seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for the specified + * \a channel of this image. + * + * This function calls pcl::Hash32() for the internal pixel sample buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + * + * For information on the rest of parameters of this member function, see + * the documentation for Fill(). + */ + uint32 Hash32( int channel = -1, uint32 seed = 0 ) const noexcept + { + if ( !ParseChannel( channel ) ) + return 0; + return pcl::Hash32( m_channelData( channel ), ChannelSize(), seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for the specified + * \a channel of this image. This function is a synonym for Hash64(). + */ + uint64 Hash( int channel = -1, uint64 seed = 0 ) const noexcept + { + return Hash64( channel, seed ); + } + + // ------------------------------------------------------------------------- + + /*! + * Writes a subset of pixel samples to a raw-storage output stream. Returns + * a reference to this image. + * + * \param file Output stream to write to. + * + * The generated raw-storage can be used to generate a new image with the + * Read() member function. + * + * \note Increments the status monitoring object by the number of pixel + * samples written to the specified \a file. + * + * \note This member function, together with the Read() function, implements + * a lightweight image reading/writing system with limited error detection + * and handling capabilities. For more powerful and sophisticated ways to + * serialize image data, see the ImageVariant class. + */ + GenericImage& Write( File& file, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return const_cast( *this ); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + int numberOfChannels = 1 + lastChannel - firstChannel; + + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Writing to raw-storage image stream", N*numberOfChannels ); + + file.WriteUI32( r.Width() ); + file.WriteUI32( r.Height() ); + file.WriteUI32( numberOfChannels ); + file.WriteUI32( (firstChannel == 0 && lastChannel >= 2) ? m_colorSpace : ColorSpace::Gray ); + + if ( r == Bounds() ) + { + for ( int i = firstChannel; i <= lastChannel; ++i, m_status += N ) + file.Write( (const void*)m_pixelData[i], fsize_type( ChannelSize() ) ); + } + else + { + for ( int i = firstChannel, w = r.Width(), h = r.Height(); i <= lastChannel; ++i ) + { + const sample* p = PixelAddress( r.LeftTop(), i ); + for ( int j = 0; j < h; ++j, p += m_width, m_status += w ) + file.Write( (const void*)p, w*BytesPerSample() ); + } + } + + return const_cast( *this ); + } + + /*! + * Writes a subset of pixel samples to a raw-storage file. Returns a + * reference to this image. + * + * \param filePath File path where a new file will be created with pixel + * data from this image. + * + * This member function is just a wrapper to the more general version: + * Write( File&, const Rect&, int, int ). + */ + GenericImage& Write( const String& filePath, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + File file = File::CreateFileForWriting( filePath ); + return Write( file, rect, firstChannel, lastChannel ); + } + + /*! + * Reads an image from a raw-storage stream. Returns a reference to this + * image. + * + * \param file Input stream to read from. + * + * If this object uniquely references its pixel data, then the previously + * existing pixel data are destroyed, deallocated, and replaced with a newly + * allocated local or shared image, preserving the storage space of this + * instance. + * + * The input stream must provide pixel sample values in the sample data type + * of this image. The sample data type of an image is invariantly defined by + * its template instantiation, and thus cannot be changed. If the image + * stored in the input stream uses a different sample data type than this + * image, this function will lead to unpredictable results, most likely an + * exception being thrown by the stream I/O routines. + * + * If this object is not unique, then the previously referenced pixel data + * are dereferenced, and a newly created local image is uniquely referenced + * by this object. + * + * All image selections are reset to the default full selection after + * calling this function. + * + * The data read from the specified \a file should have been generated by a + * previous call to Write(). + * + * \note Increments the status monitoring object by the number of pixel + * samples read from the specified \a file. + * + * \note This function, together with the Write() function, implements a + * lightweight image reading/writing system with limited error detection and + * handling capabilities. For more powerful and sophisticated ways to + * serialize image data, see the ImageVariant class. + */ + GenericImage& Read( File& file ) + { + int width, height, numberOfChannels, colorSpace; + file.ReadUI32( width ); + file.ReadUI32( height ); + file.ReadUI32( numberOfChannels ); + file.ReadUI32( colorSpace ); + + AllocateData( width, height, numberOfChannels, color_space( colorSpace ) ); + + ResetSelections(); + + size_type N = NumberOfPixels(); + if ( N > 0 ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Reading from raw-storage image stream", N*m_numberOfChannels ); + for ( int i = 0; i < m_numberOfChannels; ++i, m_status += N ) + file.Read( (void*)m_pixelData[i], fsize_type( ChannelSize() ) ); + } + + return *this; + } + + /*! + * Reads an image from a raw-storage file. Returns a reference to this + * image. + * + * \param filePath Path to an existing file from which new pixel data will + * be read. The contents of the existing file will not be + * modified in any way. + * + * This member function is just a wrapper to the more general version: + * Read( File& ). + */ + GenericImage& Read( const String& filePath ) + { + File file = File::OpenFileForReading( filePath ); + return Read( file ); + } + + // ------------------------------------------------------------------------- + + /*! + * Crops or extends the entire image by applying the specified margins. + * Returns a reference to this image. + * + * \param left Left margin in pixels. + * + * \param top Top margin in pixels. + * + * \param right Right margin in pixels. + * + * \param bottom Bottom margin in pixels. + * + * \param fillValues %Vector of filling sample values for extended areas, + * used when one or more margins are greater than zero. + * Each vector component is used for its corresponding + * channel (e.g., the first component is used to fill the + * red channel of an RGB image, the second component to + * fill the green channel, etc.). If there are less vector + * components than channels in the image, the minimum + * sample value in the native range of the image (usually + * zero or black) is used for the missing filling values. + * The default parameter value is an empty vector, so the + * extended areas are filled with black by default. + * + * Negative margins crop the image at their respective sides. Positive + * margin values add extra space. + * + * \note Increments the status monitoring object by the area in square + * pixels of the cropping rectangle. + */ + template + GenericImage& CropBy( int left, int top, int right, int bottom, const GenericVector& fillValues ) + { + if ( left == 0 && top == 0 && right == 0 && bottom == 0 ) + return *this; + + if ( m_width+left+right <= 0 || m_height+top+bottom <= 0 ) + { + FreeData(); + return *this; + } + + Rect r( -left, -top, m_width+right, m_height+bottom ); + int width = r.Width(); + int height = r.Height(); + + if ( !Intersects( r ) ) + return AllocateData( width, height, m_numberOfChannels, m_colorSpace ).Fill( fillValues ); + + size_type N = size_type( width )*size_type( height ); + + EnsureUnique(); + + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( String().Format( "Crop margins: %+d, %+d, %+d, %+d", + left, top, right, bottom ), N*m_numberOfChannels ); + + sample** newData = nullptr; + + try + { + newData = m_allocator.AllocateChannelSlots( m_numberOfChannels ); + + for ( int c = 0; c < m_numberOfChannels; ++c, m_status += N ) + { + sample* __restrict__ f = newData[c] = m_allocator.AllocatePixels( N ); + sample v = (c < fillValues.Length()) ? P::ToSample( fillValues[c] ) : P::MinSampleValue(); + + for ( int i = r.y0, j; i < r.y1; ) + { + for ( ; i < 0; ++i ) + { + PCL_IVDEP + for ( int j = 0; j < width; ++j ) + *f++ = v; + } + + PCL_IVDEP + for ( j = r.x0; j < 0; ++j ) + *f++ = v; + + for ( const sample* f0 = PixelAddress( j, i, c ); j < r.x1; ) + { + *f++ = *f0++; + if ( ++j == m_width ) + { + PCL_IVDEP + for ( ; j < r.x1; ++j ) + *f++ = v; + } + } + + if ( ++i == m_height ) + for ( ; i < r.y1; ++i ) + { + PCL_IVDEP + for ( int j = 0; j < width; ++j ) + *f++ = v; + } + } + } + + try + { + for ( int c = 0; c < m_numberOfChannels; ++c ) + { + m_allocator.Deallocate( m_pixelData[c] ); + m_pixelData[c] = newData[c]; + } + m_allocator.Deallocate( newData ); + newData = nullptr; + + m_allocator.SetSharedGeometry( m_width = width, m_height = height, m_numberOfChannels ); + + ResetPoint(); + ResetSelection(); + return *this; + } + catch ( ... ) + { + m_data->Deallocate(); + ResetSelections(); + throw; + } + } + catch ( ... ) + { + if ( newData != nullptr ) + { + for ( int i = 0; i < m_numberOfChannels; ++i ) + if ( newData[i] != nullptr ) + m_allocator.Deallocate( newData[i] ), newData[i] = nullptr; + m_allocator.Deallocate( newData ); + } + throw; + } + } + + /*! + * Crops or extends the entire image by applying the specified margins, + * filling extended regions with the minimum sample value in the native + * range of the image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * CropBy( left, top, right, bottom, sample_vector() ); + * \endcode + */ + GenericImage& CropBy( int left, int top, int right, int bottom ) + { + return CropBy( left, top, right, bottom, sample_vector() ); + } + + /*! + * Crops the image to the specified rectangular region. Returns a reference + * to this image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * CropBy( -rect.x0, -rect.y0, rect.x1 - m_width, rect.y1 - m_height, fillValues ); + * \endcode + */ + template + GenericImage& CropTo( const Rect& rect, const GenericVector& fillValues ) + { + Rect r = rect.Ordered(); + return CropBy( -r.x0, -r.y0, r.x1 - m_width, r.y1 - m_height, fillValues ); + } + + /*! + * Crops the image to the specified rectangular region, filling extended + * regions with the minimum sample value in the native range of the image. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * CropTo( rect, sample_vector() ); + * \endcode + */ + GenericImage& CropTo( const Rect& rect ) + { + return CropTo( rect, sample_vector() ); + } + + /*! + * Crops the image to the specified rectangular region. Returns a reference + * to this image. + * + * This member function is equivalent to: + * + * \code + * CropTo( Rect( x0, y0, x1, y1 ), fillValues ); + * \endcode + */ + template + GenericImage& CropTo( int x0, int y0, int x1, int y1, const GenericVector& fillValues ) + { + return CropTo( Rect( x0, y0, x1, y1 ), fillValues ); + } + + /*! + * Crops the image to the specified rectangular region, filling extended + * regions with the minimum sample value in the native range of the image. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * CropTo( x0, y0, x1, y1, sample_vector() ); + * \endcode + */ + GenericImage& CropTo( int x0, int y0, int x1, int y1 ) + { + return CropTo( x0, y0, x1, y1, sample_vector() ); + } + + /*! + * Crops the image to its current rectangular selection. Returns a reference + * to this image. + * + * This member function is equivalent to: + * + * \code + * CropTo( SelectedRectangle(), fillValues ); + * \endcode + */ + template + GenericImage& Crop( const GenericVector& fillValues ) + { + return CropTo( m_rectangle, fillValues ); + } + + /*! + * Crops the image to its current rectangular selection, filling extended + * regions with the minimum sample value in the native range of the image. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Crop( sample_vector() ); + * \endcode + */ + GenericImage& Crop() + { + return Crop( sample_vector() ); + } + + /*! + * Shifts (translates) this image by the specified increments in pixels. + * Returns a reference to this image. + * + * \param dx Horizontal displacement in pixels. + * + * \param dy Vertical displacement in pixels. + * + * \param fillValues %Vector of filling sample values for extended areas. + * See the documentation for CropBy() for more + * information. + * + * Positive increment values shift the image toward the right and bottom + * sides. Negative increments shift toward the left and top sides. + * + * This member function is equivalent to: + * + * \code + * CropBy( dx, dy, -dx, -dy, fillValues ); + * \endcode + */ + template + GenericImage& ShiftBy( int dx, int dy, const GenericVector& fillValues ) + { + return CropBy( dx, dy, -dx, -dy, fillValues ); + } + + /*! + * Shifts (translates) this image by the specified increments in pixels, + * filling extended regions with the minimum sample value in the native + * range of the image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftBy( dx, dy, sample_vector() ); + * \endcode + */ + GenericImage& ShiftBy( int dx, int dy ) + { + return ShiftBy( dx, dy, sample_vector() ); + } + + /*! + * Shifts (translates) the image to the specified coordinates. Returns a + * reference to this image. + * + * A synonym for ShiftBy( int, int, sample ). + */ + template + GenericImage& ShiftTo( int x, int y, const GenericVector& fillValues ) + { + return ShiftBy( x, y, fillValues ); + } + + /*! + * Shifts (translates) the image to the specified coordinates, filling + * extended regions with the minimum sample value in the native range of the + * image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftTo( x, y, sample_vector() ); + * \endcode + */ + GenericImage& ShiftTo( int x, int y ) + { + return ShiftTo( x, y, sample_vector() ); + } + + /*! + * Shifts (translates) the image to the specified coordinates. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftBy( p.x, p.y, fillValues ); + * \endcode + */ + template + GenericImage& ShiftTo( const Point& p, const GenericVector& fillValues ) + { + return ShiftBy( p.x, p.y, fillValues ); + } + + /*! + * Shifts (translates) the image to the specified coordinates, filling + * extended regions with the minimum sample value in the native range of the + * image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftTo( p, sample_vector() ); + * \endcode + */ + GenericImage& ShiftTo( const Point& p ) + { + return ShiftTo( p, sample_vector() ); + } + + /*! + * Extends or crops the image centered within the specified \a width and + * \a height in pixels. Returns a reference to this image. + */ + template + GenericImage& ShiftToCenter( int width, int height, const GenericVector& fillValues ) + { + int dx2 = (width - m_width) >> 1; + int dy2 = (height - m_height) >> 1; + return CropBy( dx2, dy2, width-m_width-dx2, height-m_height-dy2, fillValues ); + } + + /*! + * Extends or crops the image centered within the specified \a width and + * \a height in pixels, filling extended regions with the minimum sample + * value in the native range of the image. Returns a reference to this + * image. + * + * This member function is equivalent to: + * + * \code + * ShiftToCenter( width, height, sample_vector() ); + * \endcode + */ + GenericImage& ShiftToCenter( int width, int height ) + { + return ShiftToCenter( width, height, sample_vector() ); + } + + /*! + * Extends or crops the image at its right and bottom sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + */ + template + GenericImage& ShiftToTopLeft( int width, int height, const GenericVector& fillValues ) + { + int dx = width - m_width; + int dy = height - m_height; + return CropBy( 0, 0, dx, dy, fillValues ); + } + + /*! + * Extends or crops the image at its right and bottom sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftToTopLeft( width, height, sample_vector() ); + * \endcode + */ + GenericImage& ShiftToTopLeft( int width, int height ) + { + return ShiftToTopLeft( width, height, sample_vector() ); + } + + /*! + * Extends or crops the image at its left and bottom sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + */ + template + GenericImage& ShiftToTopRight( int width, int height, const GenericVector& fillValues ) + { + int dx = width - m_width; + int dy = height - m_height; + return CropBy( dx, 0, 0, dy, fillValues ); + } + + /*! + * Extends or crops the image at its left and bottom sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftToTopRight( width, height, sample_vector() ); + * \endcode + */ + GenericImage& ShiftToTopRight( int width, int height ) + { + return ShiftToTopRight( width, height, sample_vector() ); + } + + /*! + * Extends or crops the image at its right and top sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + */ + template + GenericImage& ShiftToBottomLeft( int width, int height, const GenericVector& fillValues ) + { + int dx = width - m_width; + int dy = height - m_height; + return CropBy( 0, dy, dx, 0, fillValues ); + } + + /*! + * Extends or crops the image at its right and top sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftToBottomLeft( width, height, sample_vector() ); + * \endcode + */ + GenericImage& ShiftToBottomLeft( int width, int height ) + { + return ShiftToBottomLeft( width, height, sample_vector() ); + } + + /*! + * Extends or crops the image at its left and top sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + */ + template + GenericImage& ShiftToBottomRight( int width, int height, const GenericVector& fillValues ) + { + int dx = width - m_width; + int dy = height - m_height; + return CropBy( dx, dy, 0, 0, fillValues ); + } + + /*! + * Extends or crops the image at its left and top sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftToBottomRight( width, height, sample_vector() ); + * \endcode + */ + GenericImage& ShiftToBottomRight( int width, int height ) + { + return ShiftToBottomRight( width, height, sample_vector() ); + } + + /*! + * Shifts (translates) the image to its current anchor point selection. + * Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * ShiftTo( SelectedPoint(), fillValues ); + * \endcode + */ + template + GenericImage& Shift( const GenericVector& fillValues ) + { + return ShiftTo( m_point, fillValues ); + } + + /*! + * Shifts (translates) the image to its current anchor point selection, + * filling extended regions with the minimum sample value in the native + * range of the image. Returns a reference to this image. + * + * This member function is equivalent to: + * + * \code + * Shift( sample_vector() ); + * \endcode + */ + GenericImage& Shift() + { + return Shift( sample_vector() ); + } + + // ------------------------------------------------------------------------- + + /*! + * Converts the image to the specified color space. Returns a reference to + * this object. + * + * \param colorSpace Specifies a color space to convert the image to. See + * the ColorSpace namespace for symbolic constants + * corresponding to all supported color spaces in this + * version of PCL. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * Color space conversion is performed in the current RGB working space + * (RGBWS) associated with this image. + * + * This function operates on the entire image; current selections are + * neither used nor modified (except the channel range selection, which is + * reset to defaults when the color space conversion involves a change in + * the number of nominal channels). Existing alpha channels are never + * modified by this member function. + * + * Before performing the requested color space conversion, this function + * ensures that the image data is uniquely referenced by this object. If + * necessary, the previously referenced data are dereferenced (and destroyed + * immediately if they become unreferenced), and a new local image is + * allocated and referenced. + * + * \note Increments the status monitoring object by the number of pixels + * (\e not samples) in the image. + */ + GenericImage& SetColorSpace( color_space colorSpace, int maxProcessors = 0 ) + { + size_type N = NumberOfPixels(); + if ( N == 0 ) + return *this; + + if ( colorSpace == m_colorSpace ) + { + m_status += N; + return *this; + } + + EnsureUnique(); + + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "In-place color space conversion: " + + ColorSpace::Name( m_colorSpace ) + + " -> " + + ColorSpace::Name( colorSpace ), N ); + + int n = m_numberOfChannels; + + if ( m_colorSpace == ColorSpace::Gray ) + { + sample** oldData = m_pixelData; + sample** newData = nullptr; + + try + { + // Make room for the G and B channels. + newData = m_allocator.AllocateChannelSlots( 2+n ); + + // Put the nominal gray channel into the R slot + newData[0] = oldData[0]; + + // Allocate and copy the G and B channels + newData[1] = m_allocator.AllocatePixels( N ); + ::memcpy( newData[1], oldData[0], ChannelSize() ); + newData[2] = m_allocator.AllocatePixels( N ); + ::memcpy( newData[2], oldData[0], ChannelSize() ); + + // Put existing alpha channels in their corresponding slots + for ( int i = 1; i < n; ++i ) + newData[i+2] = oldData[i]; + + try + { + m_pixelData = newData; + newData = nullptr; + m_numberOfChannels += 2; + m_colorSpace = ColorSpace::RGB; + m_data->UpdateSharedImage(); + + ResetChannelRange(); + + m_allocator.Deallocate( oldData ); + } + catch ( ... ) + { + m_data->Deallocate(); + ResetSelections(); + throw; + } + } + catch ( ... ) + { + if ( newData != nullptr ) + { + newData[0] = nullptr; + if ( newData[1] != nullptr ) + m_allocator.Deallocate( newData[1] ), newData[1] = nullptr; + if ( newData[2] != nullptr ) + m_allocator.Deallocate( newData[2] ), newData[2] = nullptr; + m_allocator.Deallocate( newData ); + throw; + } + } + + if ( colorSpace == ColorSpace::RGB ) + { + m_status += N; + return *this; + } + + n += 2; + } + + Array L = Thread::OptimalThreadLoads( N, + 16u/*overheadLimit*/, + m_parallel ? ((maxProcessors > 0) ? maxProcessors : m_maxProcessors) : 1 ); + ThreadData data( *this, N ); + ReferenceArray threads; + for ( size_type i = 0, n = 0; i < L.Length(); n += L[i++] ) + threads.Add( new ColorSpaceConversionThread( *this, data, colorSpace, n, n + L[i] ) ); + RunThreads( threads, data ); + threads.Destroy(); + + m_status = data.status; + + if ( colorSpace == ColorSpace::Gray ) + { + sample** oldData = m_pixelData; + sample** newData = nullptr; + + try + { + newData = m_allocator.AllocateChannelSlots( n-2 ); + newData[0] = oldData[0]; + for ( int i = 3; i < n; ++i ) + newData[i-2] = oldData[i]; + + m_pixelData = newData; + newData = nullptr; + m_numberOfChannels -= 2; + m_colorSpace = ColorSpace::Gray; + m_data->UpdateSharedImage(); + + ResetChannelRange(); + + m_allocator.Deallocate( oldData[1] ); + m_allocator.Deallocate( oldData[2] ); + m_allocator.Deallocate( oldData ); + } + catch ( ... ) + { + m_data->Deallocate(); + ResetSelections(); + if ( newData != nullptr ) + m_allocator.Deallocate( newData ); + throw; + } + } + else + { + m_allocator.SetSharedColor( m_colorSpace = colorSpace, m_RGBWS ); + } + + return *this; + } + + // ------------------------------------------------------------------------- + + /*! + * Computes the CIE Y component for a subset of pixel samples and stores it + * in a grayscale image. + * + * \param[out] Y Reference to a destination image, where the computed + * CIE Y component will be stored. This image can be an + * instance of any supported %GenericImage template + * instantiation; all the necessary data type conversions + * are carried out transparently. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * This member function computes the Y component of the CIE XYZ space. CIE Y + * component values are calculated in the RGB working space (RGBWS) + * currently associated with the image. + * + * If this image is in the grayscale color space, gray source samples are + * simply copied to the destination image, after conversion to the + * destination sample data type, if necessary, using pixel traits + * primitives. + * + * If this image is in the CIE XYZ color space, samples from the luminance + * channel (source channel #1) are simply copied to the destination image, + * after conversion to the destination sample data type, if necessary. + * + * For other color spaces, CIE Y values are obtained by means of the + * simplest possible intermediate transformation (usually to the CIE XYZ + * space), converted to the destination sample data type if necessary, and + * transferred to the destination image. + * + * The luminance is computed for the specified subset of pixel samples, or + * for the current rectangular selection, depending on parameter values. For + * more information on the rest of parameters of this function, see the + * documentation for Fill(). The current channel range selection is always + * ignored by this function. + * + * The previous contents of the destination image will be dereferenced (and + * immediately destroyed if they become unreferenced) and replaced with the + * computed, uniquely referenced CIE Y data. The destination image will be + * in the grayscale color space; it will have a single channel corresponding + * to the luminance of the specified pixel sample subset in this image. The + * dimensions of the destination image will be the same ones of the + * specified pixel sample subset, and it will be associated with the same + * RGBWS as this image. + * + * \note In general, computing luminance components as integer values is an + * error. The GenericPixelTraits instantiation P1 should correspond to a + * floating point real pixel sample type, either \c float or \c double, + * depending on the source data type. The recommended types are:\n + * \n + * \li FloatPixelTraits for 8-bit and 16-bit integer images, as well as for + * 32-bit floating point real and complex images.\n + * \li DoublePixelTraits for 32-bit integer images, as well as for 64-bit + * floating point real and complex images. + * + * \note Increments the status monitoring object by the number of selected + * pixel samples. + * + * \warning Please note that the computed lightness is meaningful as such + * \e exclusively in the RGB working space of this image. + */ + template + void GetLuminance( GenericImage& Y, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseRect( r ) ) + { + Y.FreeData(); + return; + } + + Y.AllocateData( r ); + if ( !Y.IsShared() ) + Y.SetRGBWorkingSpace( m_RGBWS ); + + size_type N = Y.NumberOfPixels(); + + if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIEXYZ ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Transferring pixel data", N ); + + typename GenericImage::sample* __restrict__ g = *Y; + int cY = (m_colorSpace == ColorSpace::Gray) ? 0 : 1; + if ( r == Bounds() ) + { + const sample* __restrict__ f = m_pixelData[cY]; + P1::Copy( g, f, N ); + } + else + { + const sample* __restrict__ f = PixelAddress( r.LeftTop(), cY ); + for ( int i = 0; i < Y.Height(); ++i, f += m_width, g += Y.Width() ) + P1::Copy( g, f, Y.Width() ); + } + + m_status += N; + } + else + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing CIE Y component", N ); + + Array L = OptimalThreadRows( Y.Height(), Y.Width(), maxProcessors ); + ThreadData data( *this, N ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new GetLuminanceThread( Y, *this, data, r, n, n + int( L[i] ) ) ); + RunThreads( threads, data ); + threads.Destroy(); + + m_status = data.status; + } + } + + /*! + * Computes the CIE Y component for a subset of pixel samples and stores it + * in a grayscale image, transported by an ImageVariant object. + * + * If the specified %ImageVariant does not transport an image, a new + * floating point image will be created with the appropriate sample type + * (either 32-bit or 64-bit floating point, depending on the sample data + * type of this image). + */ + void GetLuminance( ImageVariant& Y, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const; + // Implemented in pcl/ImageVariant.h + + /*! + * Computes the CIE L* component for a subset of pixel samples and stores it + * in a grayscale image. + * + * \param[out] L Reference to a destination image, where the computed + * CIE L* component will be stored. This image can be an + * instance of any supported %GenericImage template + * instantiation; all the necessary data type conversions + * are carried out transparently. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * This member function computes the L* component of the CIE L*a*b* space. + * CIE L* component values are calculated in the RGB working space (RGBWS) + * currently associated with this image. + * + * If this image is in the grayscale color space, gray source samples are + * simply copied to the destination image, after conversion to the + * destination sample data type, if necessary, using pixel traits + * primitives. + * + * If this image is in the CIE L*a*b* color space, samples from the + * lightness channel (source channel #0) are simply copied to the + * destination image, after conversion to the destination sample data type, + * if necessary. + * + * For other color spaces, CIE L* values are obtained by means of the + * simplest possible intermediate transformation (usually to the CIE L*a*b* + * space), converted to the destination sample data type if necessary, and + * transferred to the destination image. + * + * The lightness is computed for the specified subset of pixel samples, or + * for the current rectangular selection, depending on parameter values. For + * more information on the rest of parameters of this function, see the + * documentation for Fill(). The current channel range selection is always + * ignored by this function. + * + * The previous contents of the destination image will be dereferenced (and + * immediately destroyed if they become unreferenced) and replaced with the + * computed, uniquely referenced CIE L* data. The destination image will be + * in the grayscale color space; it will have a single channel corresponding + * to the lightness of the specified pixel sample subset in this image. The + * dimensions of the destination image will be the same ones of the + * specified pixel sample subset, and it will be associated with the same + * RGBWS as this image. + * + * \note In general, computing lightness components as integer values is an + * error. The GenericPixelTraits instantiation P1 should correspond to a + * floating point real pixel sample type, either \c float or \c double, + * depending on the source data type. The recommended types are:\n + * \n + * \li FloatPixelTraits for 8-bit and 16-bit integer images, as well as for + * 32-bit floating point real and complex images.\n + * \li DoublePixelTraits for 32-bit integer images, as well as for 64-bit + * floating point real and complex images. + * + * \note Increments the status monitoring object by the number of modified + * pixels (\e not samples). + * + * \warning Please note that the computed lightness is meaningful as such + * \e exclusively in the RGB working space of this image. + */ + template + void GetLightness( GenericImage& L, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseRect( r ) ) + { + L.FreeData(); + return; + } + + L.AllocateData( r ); + if ( !L.IsShared() ) + L.SetRGBWorkingSpace( m_RGBWS ); + + size_type N = L.NumberOfPixels(); + + if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIELab || m_colorSpace == ColorSpace::CIELch ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Transferring pixel data", N ); + + typename GenericImage::sample* g = *L; + if ( r == Bounds() ) + { + const sample* __restrict__ f = *m_pixelData; + P1::Copy( g, f, N ); + } + else + { + const sample* __restrict__ f = PixelAddress( r.LeftTop() ); + for ( int i = 0; i < L.Height(); ++i, f += m_width, g += L.Width() ) + P1::Copy( g, f, L.Width() ); + } + + m_status += N; + } + else + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing CIE L* component", N ); + + Array R = OptimalThreadRows( L.Height(), L.Width(), maxProcessors ); + ThreadData data( *this, N ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) ) + threads.Add( new GetLightnessThread( L, *this, data, r, n, n + int( R[i] ) ) ); + RunThreads( threads, data ); + threads.Destroy(); + + m_status = data.status; + } + } + + /*! + * Computes the CIE L* component for a subset of pixel samples and stores it + * in a grayscale image, transported by an ImageVariant object. + * + * If the specified %ImageVariant does not transport an image, a new + * floating point image will be created with the appropriate sample type + * (either 32-bit or 64-bit floating point, depending on the sample data + * type of this image). + */ + void GetLightness( ImageVariant& L, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const; + // Implemented in pcl/ImageVariant.h + + /*! + * Computes the intensity HSI component for a subset of pixel samples and + * stores it in a grayscale image. + * + * \param[out] I Reference to a destination image, where the computed + * intensity component will be stored. This image can be + * an instance of any supported %GenericImage template + * instantiation; all the necessary data type conversions + * are carried out transparently. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * This member function computes the I intensity component in the HSI color + * ordering scheme. The intensity is useful for applications where a + * colorimetrically correct component, such as luminance or lightness, is + * not necessary. For example, the intensity component can be used for + * feature detection (e.g., star detection) on RGB color images. + * + * The intensity component I of an RGB pixel is given by: + * + *
+    * I = (Max(R,G,B) + Min(R,G,B))/2
+    * 
+ * + * where R, G and B are the red, green and blue components of the RGB pixel, + * respectively. + * + * If this image is in the grayscale or HSI spaces, gray or intensity source + * samples are simply copied to the destination image, after conversion to + * the destination sample data type, if necessary, using pixel traits + * primitives. + * + * If this image is in the RGB color space, the intensity components for + * each pixel is calculated as described above. For other color spaces + * intermediate RGB components are computed on the fly. + * + * The intensity is computed for the specified subset of pixel samples, or + * for the current rectangular selection, depending on parameter values. For + * more information on the rest of parameters of this function, see the + * documentation for Fill(). The current channel range selection is always + * ignored by this function. + * + * The previous contents of the destination image will be dereferenced (and + * immediately destroyed if they become unreferenced) and replaced with the + * computed, uniquely referenced intensity data. The destination image will + * be in the grayscale color space; it will have a single channel + * corresponding to the intensity of the specified pixel sample subset in + * this image. The dimensions of the destination image will be the same ones + * of the specified pixel sample subset, and it will be associated with the + * same RGBWS as this image. + * + * \note Increments the status monitoring object by the number of modified + * pixels (\e not samples). + */ + template + void GetIntensity( GenericImage& I, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const + { + Rect r = rect; + if ( !ParseRect( r ) ) + { + I.FreeData(); + return; + } + + I.AllocateData( r ); + if ( !I.IsShared() ) + I.SetRGBWorkingSpace( m_RGBWS ); + + size_type N = I.NumberOfPixels(); + + if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::HSI ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Transferring pixel data", N ); + + typename GenericImage::sample* __restrict__ g = *I; + int cI = (m_colorSpace == ColorSpace::Gray) ? 0 : 2; + if ( r == Bounds() ) + { + const sample* __restrict__ f = m_pixelData[cI]; + P1::Copy( g, f, N ); + } + else + { + const sample* __restrict__ f = PixelAddress( r.LeftTop(), cI ); + for ( int i = 0; i < I.Height(); ++i, f += m_width, g += I.Width() ) + P1::Copy( g, f, I.Width() ); + } + + m_status += N; + } + else + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Computing intensity component", N ); + + Array L = OptimalThreadRows( I.Height(), I.Width(), maxProcessors ); + ThreadData data( *this, N ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new GetIntensityThread( I, *this, data, r, n, n + int( L[i] ) ) ); + RunThreads( threads, data ); + threads.Destroy(); + + m_status = data.status; + } + } + + /*! + * Computes the intensity HSI component for a subset of pixel samples and + * stores it in a grayscale image, transported by an ImageVariant object. + * + * If the specified %ImageVariant does not transport an image, a new + * floating point image will be created with the appropriate sample type + * (either 32-bit or 64-bit floating point, depending on the sample data + * type of this image). + */ + void GetIntensity( ImageVariant& I, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const; + // Implemented in pcl/ImageVariant.h + + // ------------------------------------------------------------------------- + + /*! + * Replaces the CIE Y component of a subset of pixel samples with data + * extracted from another image. + * + * \param Y Reference to a source image, from which the CIE Y + * components will be obtained. This image can be in any + * supported color space, and can be an instance of any + * supported template instantiation of %GenericImage; all + * the necessary color space and data type conversions are + * carried out transparently. + * + * \param point Target point in image coordinates. This is the upper + * left corner of the target rectangular region in this + * image where CIE Y components will be replaced with + * source values. If one or both point coordinates are + * equal to \c int_max (the maximum possible value of type + * \c int), then the current anchor point selection will + * be used. The default value is Point( int_max ). + * + * \param rect Source rectangular region. If this parameter defines an + * empty rectangle, the current rectangular selection in + * the source image will be used. If the specified + * rectangle is not empty and extends beyond source image + * boundaries, only the intersection with the source image + * will be used. If that intersection does not exist, then + * this member function has no effect. The default value + * is an empty rectangle. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * This member function computes and replaces the Y component of the CIE XYZ + * color space. Source CIE Y component values are calculated in the RGB + * working space (RGBWS) associated with the source image \a Y. Replacement + * of CIE Y components in this (target) image is performed by + * transformations in the RGBWS associated with this image. This ensures + * that only pure illumination data is transferred between both images, + * without any chrominance contamination. + * + * If the source image is in the grayscale or CIE XYZ color spaces, samples + * from its first or second channel, respectively, are directly taken as + * source values, requiring no additional conversion. + * + * Once a source CIE Y value is available, either by direct extraction or + * through the simplest possible intermediate transformation (usually to the + * CIE L*a*b* or CIE XYZ spaces), it is inserted in the corresponding + * destination pixel by means of a series of transformations in the target + * RGBWS, whose number and complexity depend on the destination color space. + * Additional sample data type conversions may take place using pixel traits + * primitives, if the source and destination data types differ. Roundoff + * errors are minimized during the whole process. + * + * \note Increments the status monitoring object by the number of modified + * pixels (\e not samples). + */ + template + GenericImage& SetLuminance( const GenericImage& Y, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ), + int maxProcessors = 0 ) + { + Rect r = rect; + if ( !Y.ParseRect( r ) ) + return *this; + + Point p = point; + if ( p.x == int_max || p.y == int_max ) + p = m_point; + + if ( p.x < 0 ) + { + if ( (r.x0 -= p.x) >= r.x1 ) + return *this; + p.x = 0; + } + else if ( p.x >= m_width ) + return *this; + + if ( p.y < 0 ) + { + if ( (r.y0 -= p.y) >= r.y1 ) + return *this; + p.y = 0; + } + else if ( p.y >= m_height ) + return *this; + + r.ResizeTo( pcl::Min( m_width - p.x, r.Width() ), + pcl::Min( m_height - p.y, r.Height() ) ); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + + EnsureUnique(); + + if ( m_colorSpace == ColorSpace::Gray && + (Y.ColorSpace() == ColorSpace::Gray || Y.ColorSpace() == ColorSpace::CIEXYZ) ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Transferring pixel data", N ); + + int c0 = (Y.ColorSpace() == ColorSpace::Gray) ? 0 : 1; + const typename GenericImage::sample* __restrict__ g = Y.PixelAddress( r.LeftTop(), c0 ); + sample* __restrict__ f = PixelAddress( p ); + for ( int i = 0, w = r.Width(), h = r.Height(); i < h; ++i, f += m_width, g += Y.Width(), m_status += w ) + P::Copy( f, g, w ); + } + else + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Importing CIE Y component", N ); + + Array L = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + ThreadData data( *this, N ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SetLuminanceThread( *this, Y, data, p, r, n, n + int( L[i] ) ) ); + RunThreads( threads, data ); + threads.Destroy(); + + m_status = data.status; + } + + return *this; + } + + /*! + * Replaces the CIE Y component of a subset of pixel samples with data + * extracted from another image, transported by an ImageVariant object. + * + * If the specified %ImageVariant does not transport an image, a new + * floating point image will be created with the appropriate sample type + * (either 32-bit or 64-bit floating point, depending on the sample data + * type of this image). + */ + GenericImage& SetLuminance( const ImageVariant& Y, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ), + int maxProcessors = 0 ); + // Implemented in pcl/ImageVariant.h + + /*! + * Replaces the CIE L* component of a subset of pixel samples with data + * extracted from another image. + * + * \param L Reference to a source image, from which the CIE L* + * components will be obtained. This image can be in any + * supported color space, and can be an instance of any + * supported template instantiation of %GenericImage; all + * the necessary color space and data type conversions are + * carried out transparently. + * + * \param point Target point in image coordinates. This is the upper + * left corner of the target rectangular region in this + * image where CIE L* components will be replaced with + * source values. If one or both point coordinates are + * equal to \c int_max (the maximum possible value of type + * \c int), then the current anchor point selection will + * be used. The default value is Point( int_max ). + * + * \param rect Source rectangular region. If this parameter defines an + * empty rectangle, the current rectangular selection in + * the source image will be used. If the specified + * rectangle is not empty and extends beyond source image + * boundaries, only the intersection with the source image + * will be used. If that intersection does not exist, then + * this member function has no effect. The default value + * is an empty rectangle. + * + * \param maxProcessors If a value greater than zero is specified, it is + * the maximum number of concurrent threads that this function can + * execute. If zero or a negative value is specified, the current + * thread limit for this image will be used instead (see + * AbstractImage::SetMaxProcessors()). The default value is zero. + * + * This member function computes and replaces the L* component of the CIE + * L*a*b* color space. Source CIE L* component values are calculated in the + * RGB working space (RGBWS) associated with the source image \a L. + * Replacement of CIE L* components in this (target) image is performed by + * transformations in the RGBWS associated with this image. This ensures + * that only pure illumination data is transferred between both images, + * without any chrominance contamination. + * + * If the source image is in the grayscale, CIE L*a*b* or CIE L*c*h* color + * spaces, samples from its first channel are directly taken as source + * values, requiring no additional conversion. + * + * Once a source CIE L* value is available, either by direct extraction or + * through the simplest possible intermediate transformation (usually to the + * CIE L*a*b* or CIE XYZ spaces), it is inserted in the corresponding + * destination pixel by means of a series of transformations in the target + * RGBWS, whose number and complexity depend on the destination color space. + * Additional sample data type conversions may take place using pixel traits + * primitives, if the source and destination data types differ. Roundoff + * errors are minimized during the whole process. + * + * \note Increments the status monitoring object by the number of modified + * pixels (\e not samples). + */ + template + GenericImage& SetLightness( const GenericImage& L, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ), + int maxProcessors = 0 ) + { + Rect r = rect; + if ( !L.ParseRect( r ) ) + return *this; + + Point p = point; + if ( p.x == int_max || p.y == int_max ) + p = m_point; + + if ( p.x < 0 ) + { + if ( (r.x0 -= p.x) >= r.x1 ) + return *this; + p.x = 0; + } + else if ( p.x >= m_width ) + return *this; + + if ( p.y < 0 ) + { + if ( (r.y0 -= p.y) >= r.y1 ) + return *this; + p.y = 0; + } + else if ( p.y >= m_height ) + return *this; + + r.ResizeTo( pcl::Min( m_width - p.x, r.Width() ), + pcl::Min( m_height - p.y, r.Height() ) ); + + size_type N = size_type( r.Width() )*size_type( r.Height() ); + + EnsureUnique(); + + if ( m_colorSpace == ColorSpace::Gray && + (L.ColorSpace() == ColorSpace::Gray || + L.ColorSpace() == ColorSpace::CIELab || L.ColorSpace() == ColorSpace::CIELch) ) + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Transferring pixel data", N ); + + const typename GenericImage::sample* __restrict__ g = L.PixelAddress( r.LeftTop() ); + sample* __restrict__ f = PixelAddress( p ); + for ( int i = 0, w = r.Width(), h = r.Height(); i < h; ++i, f += m_width, g += L.Width(), m_status += w ) + P::Copy( f, g, w ); + } + else + { + if ( m_status.IsInitializationEnabled() ) + m_status.Initialize( "Importing CIE L* component", N ); + + Array R = OptimalThreadRows( r.Height(), r.Width(), maxProcessors ); + ThreadData data( *this, N ); + ReferenceArray > threads; + for ( int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) ) + threads.Add( new SetLightnessThread( *this, L, data, p, r, n, n + int( R[i] ) ) ); + RunThreads( threads, data ); + threads.Destroy(); + + m_status = data.status; + } + + return *this; + } + + /*! + * Replaces the CIE L* component of a subset of pixel samples with data + * extracted from another image, transported by an ImageVariant object. + * + * If the specified %ImageVariant does not transport an image, a new + * floating point image will be created with the appropriate sample type + * (either 32-bit or 64-bit floating point, depending on the sample data + * type of this image). + */ + GenericImage& SetLightness( const ImageVariant& L, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ), + int maxProcessors = 0 ); + // Implemented in pcl/ImageVariant.h + + /*! + * Compression of image pixel samples. + * + * \param compressor A compression algorithm that will be used to compress + * pixel sample data from this image. + * + * \param rect A rectangular region in image pixel coordinates. This + * region determines the subset of pixel samples that will + * be compressed. If this parameter is not specified, or + * if an empty rectangle is specified, this function will + * compress pixel samples in the current rectangular + * selection of this image, that is, SelectedRectangle(). + * + * \param channel Channel index. Must be the zero-based index of an + * existing channel in this image, or an integer < 0. If + * this parameter is not specified or a negative integer, + * this function will compress pixel samples in the + * currently selected channel of this image, that is, + * SelectedChannel(). + * + * \param perf If non-null, pointer to a Compression::Performance + * structure where performance data will be provided. + * + * Returns a dynamic array of compressed sub-blocks. Each array element is a + * Compression::Subblock structure with the compressed data and the + * corresponding uncompressed length in bytes. If compression succeeds, the + * returned array will have at least one element. + * + * Data will be compressed for the intersection of the specified (or + * implicitly selected) rectangular region with this image. All predefined + * pixel sample types are supported, including integer, real and complex + * pixels. + * + * If there is no intersection between the rectangular region and the image, + * if an invalid channel index is specified, or if one or more sub-blocks + * are not compressible with the specified compression algorithm, this + * function returns an empty array. + */ + Compression::subblock_list Compress( const Compression& compressor, + const Rect& rect = Rect( 0 ), int channel = -1, + Compression::Performance* perf = nullptr ) const + { + Rect r = rect; + if ( !ParseSelection( r, channel ) ) + return Compression::subblock_list(); + if ( r == Bounds() ) + return compressor.Compress( m_channelData( channel ), ChannelSize(), perf ); + GenericImage

subimage( *this, r, channel, channel ); + return compressor.Compress( subimage[0], subimage.ChannelSize(), perf ); + } + + // ------------------------------------------------------------------------- + +private: + + /*! + * \struct Data + * \internal + * Reference-counted image data structure. + */ + struct Data : public ReferenceCounter + { + /*! + * Pixel data + * + * Each element in the data array points to a contiguous block of pixel + * samples that stores one channel of the image. This includes all + * nominal and alpha channels. + */ + sample** data = nullptr; + + /*! + * Pixel allocator + * + * The allocator is responsible for all allocations and deallocations of + * pixel data and the associated structures. The allocator works on local + * or external storage, depending on whether this instance is a local or + * a shared image. For shared images, the allocator takes into account + * ownership of the shared object for controlled destruction of shared + * resources. + */ + pixel_allocator allocator; + + /*! + * Image geometry + */ + Geometry geometry; + + /*! + * Image color + */ + Color color; + + /*! + * Constructs an empty local image. + */ + Data( GenericImage* image ) + { + LinkWithClientImage( image ); + } + + /*! + * Constructs an aliased shared image. + */ + Data( GenericImage* image, void* handle ) + : allocator( handle ) + { + SynchronizeWithSharedImage(); + LinkWithClientImage( image ); + } + + /*! + * Constructs a newly created shared image. + */ + Data( GenericImage* image, int width, int height, int numberOfChannels, int colorSpace ) + : allocator( width, height, numberOfChannels, colorSpace ) + { + SynchronizeWithSharedImage(); + LinkWithClientImage( image ); + } + + void Attach( GenericImage* image ) + { + ReferenceCounter::Attach(); + LinkWithClientImage( image ); + } + + ~Data() + { + if ( IsShared() ) + Reset(); + else + Deallocate(); + } + + bool IsShared() const noexcept + { + return allocator.IsShared(); + } + + bool IsEmpty() const noexcept + { + return data == nullptr; + } + + void Allocate( int width, int height, int numberOfChannels, color_space colorSpace ) + { + if ( width <= 0 || height <= 0 || numberOfChannels <= 0 ) + { + Deallocate(); + return; + } + + if ( numberOfChannels < ColorSpace::NumberOfNominalChannels( colorSpace ) ) + throw Error( "GenericImage::Data::Allocate(): Insufficient number of channels" ); + + if ( data != nullptr ) + { + if ( size_type( width )*size_type( height ) == geometry.NumberOfPixels() ) + { + if ( numberOfChannels != geometry.numberOfChannels ) + { + sample** newData = nullptr; + int m = pcl::Min( geometry.numberOfChannels, numberOfChannels ); + + try + { + newData = allocator.AllocateChannelSlots( numberOfChannels ); + for ( int i = 0; i < m; ++i ) + newData[i] = data[i]; + for ( int i = m; i < numberOfChannels; ++i ) + newData[i] = allocator.AllocatePixels( width, height ); + + try + { + for ( int i = m; i < geometry.numberOfChannels; ++i ) + if ( data[i] != nullptr ) + allocator.Deallocate( data[i] ), data[i] = nullptr; + allocator.Deallocate( data ); + data = newData; + newData = nullptr; + } + catch ( ... ) + { + Deallocate(); + throw; + } + } + catch ( ... ) + { + if ( newData != nullptr ) + { + for ( int i = m; i < numberOfChannels; ++i ) + if ( newData[i] != nullptr ) + allocator.Deallocate( newData[i] ), newData[i] = nullptr; + allocator.Deallocate( newData ); + } + throw; + } + } + } + else + { + sample** newData = nullptr; + + try + { + newData = allocator.AllocateChannelSlots( numberOfChannels ); + for ( int i = 0; i < numberOfChannels; ++i ) + newData[i] = allocator.AllocatePixels( width, height ); + + try + { + for ( int i = 0; i < geometry.numberOfChannels; ++i ) + if ( data[i] != nullptr ) + allocator.Deallocate( data[i] ), data[i] = nullptr; + allocator.Deallocate( data ); + data = newData; + newData = nullptr; + } + catch ( ... ) + { + Deallocate(); + throw; + } + } + catch ( ... ) + { + if ( newData != nullptr ) + { + for ( int i = 0; i < numberOfChannels; ++i ) + if ( newData[i] != nullptr ) + allocator.Deallocate( newData[i] ), newData[i] = nullptr; + allocator.Deallocate( newData ); + } + throw; + } + } + } + else + { + try + { + data = allocator.AllocateChannelSlots( numberOfChannels ); + for ( int i = 0; i < numberOfChannels; ++i ) + data[i] = allocator.AllocatePixels( width, height ); + } + catch ( ... ) + { + if ( data != nullptr ) + { + for ( int i = 0; i < numberOfChannels; ++i ) + if ( data[i] != nullptr ) + allocator.Deallocate( data[i] ), data[i] = nullptr; + allocator.Deallocate( data ); + Reset(); + } + throw; + } + } + + geometry.width = width; + geometry.height = height; + geometry.numberOfChannels = numberOfChannels; + + color.colorSpace = colorSpace; + + UpdateSharedImage(); + } + + void Import( sample** newData, int width, int height, int numberOfChannels, color_space colorSpace ) + { + if ( newData != data ) + { + Deallocate(); + + if ( newData != nullptr && width > 0 && height > 0 && numberOfChannels > 0 ) + { + if ( numberOfChannels < ColorSpace::NumberOfNominalChannels( colorSpace ) ) + throw Error( "GenericImage::Data::Import(): Insufficient number of channels" ); + + data = newData; + + geometry.width = width; + geometry.height = height; + geometry.numberOfChannels = numberOfChannels; + + color.colorSpace = colorSpace; + + UpdateSharedImage(); + } + } + } + + sample** Release() + { + sample** oldData = data; + Reset(); + UpdateSharedImage(); + return oldData; + } + + void Deallocate() + { + if ( data != nullptr ) + { + for ( int i = 0; i < geometry.numberOfChannels; ++i ) + if ( data[i] != nullptr ) + allocator.Deallocate( data[i] ), data[i] = nullptr; + allocator.Deallocate( data ); + Reset(); + UpdateSharedImage(); + } + } + + Data* Clone( GenericImage* image ) const + { + Data* clone = nullptr; + try + { + clone = new Data; + + if ( !IsEmpty() ) + { + clone->data = clone->allocator.AllocateChannelSlots( geometry.numberOfChannels ); + for ( int i = 0; i < geometry.numberOfChannels; ++i ) + { + clone->data[i] = clone->allocator.AllocatePixels( geometry.width, geometry.height ); + P::Copy( clone->data[i], data[i], geometry.NumberOfPixels() ); + } + + clone->geometry.Assign( geometry ); + clone->color.Assign( color ); + } + + clone->LinkWithClientImage( image ); + return clone; + } + catch ( ... ) + { + if ( clone != nullptr ) + { + clone->Deallocate(); + delete clone; + } + throw; + } + } + + void Reset() + { + data = nullptr; + geometry.Reset(); + color.Reset(); + } + + void UpdateSharedImage() + { + allocator.SetSharedData( data ); + allocator.SetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels ); + allocator.SetSharedColor( color.colorSpace, color.RGBWS ); + } + + void SynchronizeWithSharedImage() + { + data = allocator.GetSharedData(); + allocator.GetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels ); + allocator.GetSharedColor( color.colorSpace, color.RGBWS ); + } + + private: + + Data() = default; + + void LinkWithClientImage( GenericImage* image ) + { + if ( image != nullptr ) + { + image->m_geometry = &geometry; + image->m_color = &color; + } + } + }; + + /*! + * \internal + * The reference-counted image data. + */ + Data* m_data = nullptr; + + /*! + * \internal + * Dereferences image data and disposes it if it becomes garbage. + */ + void DetachFromData() + { + if ( !m_data->Detach() ) + delete m_data; + } + + // ------------------------------------------------------------------------- + + class RectThreadBase : public Thread + { + public: + + RectThreadBase( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : m_image( image ) + , m_rect( rect ) + , m_ch1( ch1 ) + , m_ch2( ch2 ) + , m_firstRow( firstRow ) + , m_endRow( endRow ) + { + } + + virtual void Run() = 0; + + protected: + + const GenericImage& m_image; + const Rect& m_rect; + int m_ch1, m_ch2; + int m_firstRow, m_endRow; + + template void Execute( F process ) noexcept + { + int w = m_rect.Width(); + int dw = m_image.Width() - w; + + if ( m_image.IsLowRangeClippingEnabled() ) + { + sample clipLow = P::ToSample( m_image.RangeClipLow() ); + if ( m_image.IsHighRangeClippingEnabled() ) + { + sample clipHigh = P::ToSample( m_image.RangeClipHigh() ); + for ( int i = m_ch1; i <= m_ch2; ++i ) + { + const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i ); + for ( int j = m_firstRow; j < m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( clipLow < *f ) + if ( *f < clipHigh ) + process( f ); + } + } + } + else + { + for ( int i = m_ch1; i <= m_ch2; ++i ) + { + const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i ); + for ( int j = m_firstRow; j < m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( clipLow < *f ) + process( f ); + } + } + } + } + else if ( m_image.IsHighRangeClippingEnabled() ) + { + sample clipHigh = P::ToSample( m_image.RangeClipHigh() ); + for ( int i = m_ch1; i <= m_ch2; ++i ) + { + const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i ); + for ( int j = m_firstRow; j < m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( *f < clipHigh ) + process( f ); + } + } + } + else + { + for ( int i = m_ch1; i <= m_ch2; ++i ) + { + const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i ); + for ( int j = m_firstRow; j < m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + process( f ); + } + } + } + } + }; + + // ------------------------------------------------------------------------- + + class CountThread : public RectThreadBase + { + public: + + size_type count = 0; + + CountThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + void Run() final + { + /* + * N.B. These threads are only used when range clipping is enabled. + */ + int w = this->m_rect.Width(); + int dw = this->m_image.Width() - w; + + if ( this->m_image.IsLowRangeClippingEnabled() ) + { + sample clipLow = P::ToSample( this->m_image.RangeClipLow() ); + if ( this->m_image.IsHighRangeClippingEnabled() ) + { + sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() ); + for ( int i = this->m_ch1; i <= this->m_ch2; ++i ) + { + const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i ); + for ( int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( clipLow < *f ) + if ( *f < clipHigh ) + ++count; + } + } + } + else + { + for ( int i = this->m_ch1; i <= this->m_ch2; ++i ) + { + const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i ); + for ( int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( clipLow < *f ) + ++count; + } + } + } + } + else if ( this->m_image.IsHighRangeClippingEnabled() ) + { + sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() ); + for ( int i = this->m_ch1; i <= this->m_ch2; ++i ) + { + const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i ); + for ( int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw ) + { + PCL_IVDEP + for ( int k = 0; k < w; ++k, ++f ) + if ( *f < clipHigh ) + ++count; + } + } + } + else // ?! this should not happen + count = size_type( 1 + this->m_ch2 - this->m_ch1 ) * size_type( w ) * size_type( this->m_rect.Height() ); + } + }; + + // ------------------------------------------------------------------------- + + class MinThread : public RectThreadBase + { + public: + + sample min; + size_type count; + + MinThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + void Run() final + { + min = P::HighestSampleValue(); + count = 0; + this->Execute( [=]( const sample* f ) + { + if ( *f < min ) + min = *f; + ++count; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class MaxThread : public RectThreadBase + { + public: + + sample max; + size_type count; + + MaxThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + void Run() final + { + max = P::LowestSampleValue(); + count = 0; + this->Execute( [=]( const sample* f ) + { + if ( max < *f ) + max = *f; + ++count; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class MinMaxThread : public RectThreadBase + { + public: + + sample min; + sample max; + size_type count; + + MinMaxThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + void Run() final + { + min = P::HighestSampleValue(); + max = P::LowestSampleValue(); + count = 0; + this->Execute( [=]( const sample* f ) + { + if ( *f < min ) + min = *f; + if ( max < *f ) + max = *f; + ++count; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class ExtremePosThreadBase : public RectThreadBase + { + public: + + int cmin, cmax; + Point pmin, pmax; + size_type count; + + ExtremePosThreadBase( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + void Run() final + { + count = 0; + m_amin = m_amax = nullptr; + DoExecute(); + + if ( count > 0 ) + { + if ( m_amin != 0 ) + for ( int i = this->m_ch1; i <= this->m_ch2; ++i ) + if ( m_amin >= this->m_image[i] && m_amin < (this->m_image[i] + this->m_image.NumberOfPixels()) ) + { + cmin = i; + pmin.x = (m_amin - this->m_image[i]) % this->m_image.Width(); + pmin.y = (m_amin - this->m_image[i]) / this->m_image.Width(); + break; + } + if ( m_amax != 0 ) + for ( int i = this->m_ch1; i <= this->m_ch2; ++i ) + if ( m_amax >= this->m_image[i] && m_amax < (this->m_image[i] + this->m_image.NumberOfPixels()) ) + { + cmax = i; + pmax.x = (m_amax - this->m_image[i]) % this->m_image.Width(); + pmax.y = (m_amax - this->m_image[i]) / this->m_image.Width(); + break; + } + } + } + + protected: + + const sample* m_amin; + const sample* m_amax; + + virtual void DoExecute() = 0; + }; + + // ------------------------------------------------------------------------- + + class MinPosThread : public ExtremePosThreadBase + { + public: + + sample min; + + MinPosThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + private: + + void DoExecute() override + { + min = P::HighestSampleValue(); + this->Execute( [=]( const sample* f ) + { + if ( *f < min ) + min = *(this->m_amin = f); + ++this->count; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class MaxPosThread : public ExtremePosThreadBase + { + public: + + sample max; + + MaxPosThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + private: + + void DoExecute() override + { + max = P::LowestSampleValue(); + this->Execute( [=]( const sample* f ) + { + if ( max < *f ) + max = *(this->m_amax = f); + ++this->count; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class MinMaxPosThread : public ExtremePosThreadBase + { + public: + + sample min, max; + + MinMaxPosThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + private: + + void DoExecute() override + { + min = P::HighestSampleValue(); + max = P::LowestSampleValue(); + this->Execute( [=]( const sample* f ) + { + if ( *f < min ) + min = *(this->m_amin = f); + if ( max < *f ) + max = *(this->m_amax = f); + ++this->count; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class SumThread : public RectThreadBase + { + public: + + double s; + size_type n; + + SumThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + void Run() final + { + s = e = 0; + n = 0; + DoExecute(); + } + + protected: + + double e; + + void SumStep( double x ) noexcept + { + double y = x - e; + double t = s + y; + e = (t - s) - y; + s = t; + ++n; + } + + virtual void DoExecute() + { + this->Execute( [=]( const sample* f ) + { + double v; P::FromSample( v, *f ); + SumStep( v ); + } ); + } + }; + + // ------------------------------------------------------------------------- + + class SumSqrThread : public SumThread + { + public: + + SumSqrThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : SumThread( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + private: + + void DoExecute() override + { + this->Execute( [=]( const sample* f ) + { + double v; P::FromSample( v, *f ); + this->SumStep( v*v ); + } ); + } + }; + + // ------------------------------------------------------------------------- + + class SumAbsThread : public SumThread + { + public: + + SumAbsThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : SumThread( image, rect, ch1, ch2, firstRow, endRow ) + { + } + + private: + + void DoExecute() override + { + this->Execute( [=]( const sample* f ) + { + double v; P::FromSample( v, *f ); + this->SumStep( pcl::Abs( v ) ); + } ); + } + }; + + // ------------------------------------------------------------------------- + + class NormThread : public RectThreadBase + { + public: + + Vector R; + size_type n; + + NormThread( const GenericImage& image, int degree, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , R( degree ) + , e( degree ) + { + } + + void Run() final + { + R = e = 0.0; + n = 0; + this->Execute( [=]( const sample* f ) + { + double v; P::FromSample( v, *f ); + for ( int i = 0;; ) + { + NormStep( i, v ); + if ( ++i == R.Length() ) + break; + v *= v; + } + ++n; + } ); + } + + protected: + + Vector e; + + void NormStep( int i, double x ) noexcept + { + double y = x - e[i]; + double t = R[i] + y; + e[i] = (t - R[i]) - y; + R[i] = t; + } + }; + + // ------------------------------------------------------------------------- + + class HistogramThread : public RectThreadBase + { + public: + + SzVector H; + + HistogramThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow, + const double& low, const double& high ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , H( __PCL_MEDIAN_HISTOGRAM_LENGTH ) + , m_low( low ) + , m_high( high ) + { + } + + void Run() final + { + H = size_type( 0 ); + m_range = m_high - m_low; +// Workaround for clang compiler bug on macOS: +// https://pixinsight.com/forum/index.php?threads/pi-always-crash-when-stf.15830/ +#ifdef __PCL_MACOSX + if ( 1 + m_range != 1 ) +#endif + this->Execute( [=]( const sample* f ) + { + if ( *f >= m_low ) + if ( *f <= m_high ) + ++H[TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (double( *f ) - m_low)/m_range )]; + } ); + } + + private: + + const double& m_low; + const double& m_high; + double m_range; + }; + + // ------------------------------------------------------------------------- + + class ExtremeAbsDevThread : public RectThreadBase + { + public: + + double minAbsDev, maxAbsDev; + size_type count; + + ExtremeAbsDevThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow, double center ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + { + } + + void Run() final + { + minAbsDev = std::numeric_limits::max(); + maxAbsDev = 0; + count = 0; + this->Execute( [=]( const sample* f ) + { + double d; P::FromSample( d, *f ); + d = pcl::Abs( d - m_center ); + if ( d < minAbsDev ) + minAbsDev = d; + if ( d > maxAbsDev ) + maxAbsDev = d; + ++count; + } ); + } + + private: + + double m_center; + }; + + // ------------------------------------------------------------------------- + + class TwoSidedExtremeAbsDevThread : public RectThreadBase + { + public: + + double minAbsDevLow, minAbsDevHigh; + double maxAbsDevLow, maxAbsDevHigh; + size_type nLow, nHigh; + + TwoSidedExtremeAbsDevThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow, double center ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + { + } + + void Run() final + { + minAbsDevLow = minAbsDevHigh = std::numeric_limits::max(); + maxAbsDevLow = maxAbsDevHigh = 0; + nLow = nHigh = 0; + this->Execute( [=]( const sample* f ) + { + double x; P::FromSample( x, *f ); + if ( x <= m_center ) + { + double d = m_center - x; + if ( d < minAbsDevLow ) + minAbsDevLow = d; + if ( d > maxAbsDevLow ) + maxAbsDevLow = d; + ++nLow; + } + else + { + double d = x - m_center; + if ( d < minAbsDevHigh ) + minAbsDevHigh = d; + if ( d > maxAbsDevHigh ) + maxAbsDevHigh = d; + ++nHigh; + } + } ); + } + + private: + + double m_center; + }; + + // ------------------------------------------------------------------------- + + class AbsDevHistogramThread : public RectThreadBase + { + public: + + SzVector H; + + AbsDevHistogramThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow, + double center, const double& low, const double& high ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , H( __PCL_MEDIAN_HISTOGRAM_LENGTH ) + , m_center( center ) + , m_low( low ) + , m_high( high ) + { + } + + void Run() final + { + H = size_type( 0 ); + m_range = m_high - m_low; +// Workaround for clang compiler bug on macOS: +// https://pixinsight.com/forum/index.php?threads/pi-always-crash-when-stf.15830/ +#ifdef __PCL_MACOSX + if ( 1 + m_range != 1 ) +#endif + this->Execute( [=]( const sample* f ) + { + double d; P::FromSample( d, *f ); + d = pcl::Abs( d - m_center ); + if ( d >= m_low ) + if ( d <= m_high ) + ++H[TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )]; + } ); + } + + private: + + double m_center; + const double& m_low; + const double& m_high; + double m_range; + }; + + // ------------------------------------------------------------------------- + + class TwoSidedAbsDevHistogramThread : public RectThreadBase + { + public: + + SzVector H; + + TwoSidedAbsDevHistogramThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow, + double center, const int& side, const double& low, const double& high ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , H( __PCL_MEDIAN_HISTOGRAM_LENGTH ) + , m_center( center ) + , m_side( side ) + , m_low( low ) + , m_high( high ) + { + } + + void Run() final + { + H = size_type( 0 ); + m_range = m_high - m_low; +// Workaround for clang compiler bug on macOS: +// https://pixinsight.com/forum/index.php?threads/pi-always-crash-when-stf.15830/ +#ifdef __PCL_MACOSX + if ( 1 + m_range != 1 ) +#endif + this->Execute( [=]( const sample* f ) + { + double x; P::FromSample( x, *f ); + if ( m_side > 0 == x > m_center ) + { + double d = m_side ? x - m_center : m_center - x; + if ( d >= m_low ) + if ( d <= m_high ) + ++H[TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )]; + } + } ); + } + + private: + + double m_center; + const int& m_side; + const double& m_low; + const double& m_high; + double m_range; + }; + + // ------------------------------------------------------------------------- + + class VarThread : public RectThreadBase + { + public: + + double var, eps; + + VarThread( const GenericImage& image, double mean, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , m_mean( mean ) + { + } + + void Run() final + { + var = eps = 0; + this->Execute( [=]( const sample* f ) + { + double d; P::FromSample( d, *f ); + d -= m_mean; + var += d*d; + eps += d; + } ); + } + + private: + + double m_mean; + }; + + // ------------------------------------------------------------------------- + + class SumAbsDevThread : public SumThread + { + public: + + SumAbsDevThread( const GenericImage& image, double center, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : SumThread( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + { + } + + private: + + double m_center; + + void DoExecute() override + { + this->Execute( [=]( const sample* f ) + { + double v; P::FromSample( v, *f ); + this->SumStep( pcl::Abs( v - m_center ) ); + } ); + } + }; + + // ------------------------------------------------------------------------- + + class TwoSidedSumAbsDevThread : public RectThreadBase + { + public: + + double s0, s1; + size_type n0, n1; + + TwoSidedSumAbsDevThread( const GenericImage& image, double center, + const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + { + } + + void Run() final + { + s0 = s1 = 0; + n0 = n1 = 0; + this->Execute( [=]( const sample* f ) + { + double v; P::FromSample( v, *f ); + if ( v <= m_center ) + { + s0 += m_center - v; + ++n0; + } + else + { + s1 += v - m_center; + ++n1; + } + } ); + } + + private: + + double m_center; + }; + + // ------------------------------------------------------------------------- + + class BWMVThread : public RectThreadBase + { + public: + + double num, den; + size_type n, nr; + + BWMVThread( const GenericImage& image, double center, double kd, + const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + , m_kd( kd ) + { + } + + void Run() final + { + num = den = 0; + n = nr = 0; + this->Execute( [=]( const sample* f ) + { + ++n; + double xc; P::FromSample( xc, *f ); xc -= m_center; + double y = xc/m_kd; + if ( pcl::Abs( y ) < 1 ) + { + double y2 = y*y; + double y21 = 1 - y2; + num += xc*xc * y21*y21*y21*y21; + den += y21 * (1 - 5*y2); + ++nr; + } + } ); + } + + private: + + double m_center; + double m_kd; + }; + + // ------------------------------------------------------------------------- + + class TwoSidedBWMVThread : public RectThreadBase + { + public: + + double num0, den0; + double num1, den1; + size_type n0, n1, nr0, nr1; + + TwoSidedBWMVThread( const GenericImage& image, double center, double kd0, double kd1, + const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + , m_kd0( kd0 ) + , m_kd1( kd1 ) + { + } + + void Run() final + { + num0 = den0 = num1 = den1 = 0; + n0 = n1 = nr0 = nr1 = 0; + this->Execute( [=]( const sample* f ) + { + double xc; P::FromSample( xc, *f ); xc -= m_center; + bool low = xc <= 0; + if ( low ) + ++n0; + else + ++n1; + + double y = xc/(low ? m_kd0 : m_kd1); + if ( pcl::Abs( y ) < 1 ) + { + double y2 = y*y; + double y21 = 1 - y2; + double num = xc*xc * y21*y21*y21*y21; + double den = y21 * (1 - 5*y2); + if ( low ) + { + num0 += num; + den0 += den; + ++nr0; + } + else + { + num1 += num; + den1 += den; + ++nr1; + } + } + } ); + } + + private: + + double m_center; + double m_kd0; + double m_kd1; + }; + + // ------------------------------------------------------------------------- + + class SmpThread : public RectThreadBase + { + public: + + Array samples; + size_type n; + + SmpThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + size_type N = size_type( this->m_rect.Width() ) + * size_type( this->m_endRow - this->m_firstRow ) + * (1 + this->m_ch2 - this->m_ch1); + samples = Array( N ); + } + + void Run() final + { + n = 0; + this->Execute( [=]( const sample* f ) + { + samples[n++] = *f; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class DSmpThread : public RectThreadBase + { + public: + + Array values; + size_type n; + + DSmpThread( const GenericImage& image, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow ) + { + size_type N = size_type( this->m_rect.Width() ) + * size_type( this->m_endRow - this->m_firstRow ) + * (1 + this->m_ch2 - this->m_ch1); + values = Array( N ); + } + + void Run() final + { + n = 0; + DoExecute(); + } + + protected: + + virtual void DoExecute() + { + this->Execute( [=]( const sample* f ) + { + P::FromSample( values[n++], *f ); + } ); + } + }; + + // ------------------------------------------------------------------------- + + class AbsDevSmpThread : public DSmpThread + { + public: + + AbsDevSmpThread( const GenericImage& image, double center, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : DSmpThread( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + { + } + + private: + + double m_center; + + void DoExecute() override + { + this->Execute( [=]( const sample* f ) + { + double d; P::FromSample( d, *f ); + this->values[this->n++] = pcl::Abs( d - m_center ); + } ); + } + }; + + // ------------------------------------------------------------------------- + + class TwoSidedAbsDevSmpThread : public DSmpThread + { + public: + + Array::iterator p, q; + + TwoSidedAbsDevSmpThread( const GenericImage& image, double center, const Rect& rect, int ch1, int ch2, int firstRow, int endRow ) + : DSmpThread( image, rect, ch1, ch2, firstRow, endRow ) + , m_center( center ) + { + } + + private: + + double m_center; + + void DoExecute() override + { + p = this->values.Begin(); + q = this->values.End(); + this->Execute( [=]( const sample* f ) + { + double x; P::FromSample( x, *f ); + if ( x <= m_center ) + *p++ = m_center - x; + else + *--q = x - m_center; + ++this->n; + } ); + } + }; + + // ------------------------------------------------------------------------- + + class ColorSpaceConversionThread : public Thread + { + public: + + ColorSpaceConversionThread( GenericImage& image, ThreadData& data, + color_space toColorSpace, size_type begin, size_type end ) + : m_image( image ) + , m_data( data ) + , m_toColorSpace( toColorSpace ) + , m_begin( begin ) + , m_end( end ) + { + } + + void Run() final + { + INIT_THREAD_MONITOR() + + const RGBColorSystem& rgbws = m_image.RGBWorkingSpace(); + + typename P::sample* f0 = m_image[0] + m_begin; + typename P::sample* f1 = m_image[1] + m_begin; + typename P::sample* f2 = m_image[2] + m_begin; + typename P::sample* fN = m_image[0] + m_end; + + for ( ; f0 < fN; ++f0, ++f1, ++f2 ) + { + RGBColorSystem::sample r0, r1, r2; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB : + switch ( m_toColorSpace ) + { + case ColorSpace::Gray : + rgbws.RGBToGray( r0, r0, r1, r2 ); + break; + case ColorSpace::HSV : + rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI : + rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ : + rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab : + rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch : + rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + case ColorSpace::HSV : + rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + switch ( m_toColorSpace ) + { + case ColorSpace::Gray : + rgbws.RGBToGray( r0, r0, r1, r2 ); + break; + case ColorSpace::RGB : + break; + case ColorSpace::HSI : + rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ : + rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab : + rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch : + rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + case ColorSpace::HSI : + rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + switch ( m_toColorSpace ) + { + case ColorSpace::Gray : + rgbws.RGBToGray( r0, r0, r1, r2 ); + break; + case ColorSpace::RGB : + break; + case ColorSpace::HSV : + rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ : + rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab : + rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch : + rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + case ColorSpace::CIEXYZ : + switch ( m_toColorSpace ) + { + case ColorSpace::Gray : + rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToGray( r0, r0, r1, r2 ); + break; + case ColorSpace::RGB : + rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSV : + rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI : + rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab : + rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch : + rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 ); + rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + case ColorSpace::CIELab : + switch ( m_toColorSpace ) + { + case ColorSpace::Gray : + rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToGray( r0, r0, r1, r2 ); + break; + case ColorSpace::RGB : + rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSV : + rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI : + rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ : + rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch : + rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + case ColorSpace::CIELch : + switch ( m_toColorSpace ) + { + case ColorSpace::Gray : + rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToGray( r0, r0, r1, r2 ); + break; + case ColorSpace::RGB : + rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSV : + rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI : + rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 ); + rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ : + rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 ); + rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab : + rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + default: + break; + } + + *f0 = P::ToSample( r0 ); + + if ( m_toColorSpace != ColorSpace::Gray ) + { + *f1 = P::ToSample( r1 ); + *f2 = P::ToSample( r2 ); + } + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + + private: + + GenericImage& m_image; + ThreadData& m_data; + color_space m_toColorSpace; + size_type m_begin, m_end; + }; + + // ------------------------------------------------------------------------- + + template + class GetLuminanceThread : public Thread + { + public: + + GetLuminanceThread( GenericImage& luminance, const GenericImage& image, ThreadData& data, + const Rect& rect, int firstRow, int endRow ) + : m_luminance( luminance ) + , m_image( image ) + , m_data( data ) + , m_rect( rect ) + , m_firstRow( firstRow ) + , m_endRow( endRow ) + { + } + + void Run() final + { + INIT_THREAD_MONITOR() + + const RGBColorSystem& rgbws = m_image.RGBWorkingSpace(); + + const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 ); + const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 ); + const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 ); + + typename P1::sample* fY = m_luminance.ScanLine( m_firstRow ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY ) + { + RGBColorSystem::sample r0, r1, r2, rY; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + rY = rgbws.CIEY( r0, r1, r2 ); + break; + + case ColorSpace::CIELch: + rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 ); + // fall through + case ColorSpace::CIELab: + rgbws.CIELabToCIEXYZ( r0, rY, r2, r0, r1, r2 ); + break; + + default: // ?! + rY = 0; + break; + } + + *fY = P1::ToSample( rY ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + + private: + + GenericImage& m_luminance; + const GenericImage& m_image; + ThreadData& m_data; + const Rect& m_rect; + int m_firstRow, m_endRow; + }; + + // ------------------------------------------------------------------------- + + template + class GetLightnessThread : public Thread + { + public: + + GetLightnessThread( GenericImage& lightness, const GenericImage& image, ThreadData& data, + const Rect& rect, int firstRow, int endRow ) + : m_lightness( lightness ) + , m_image( image ) + , m_data( data ) + , m_rect( rect ) + , m_firstRow( firstRow ) + , m_endRow( endRow ) + { + } + + void Run() final + { + INIT_THREAD_MONITOR() + + const RGBColorSystem& rgbws = m_image.RGBWorkingSpace(); + + const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 ); + const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 ); + const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 ); + + typename P1::sample* fL = m_lightness.ScanLine( m_firstRow ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL ) + { + RGBColorSystem::sample r0, r1, r2, rL; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + case ColorSpace::CIEXYZ: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ: + rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + rL = rgbws.CIEL( r0, r1, r2 ); + break; + + default: // ?! + rL = 0; + break; + } + + *fL = P1::ToSample( rL ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + + private: + + GenericImage& m_lightness; + const GenericImage& m_image; + ThreadData& m_data; + const Rect& m_rect; + int m_firstRow, m_endRow; + }; + + // ------------------------------------------------------------------------- + + template + class GetIntensityThread : public Thread + { + public: + + GetIntensityThread( GenericImage& luminance, const GenericImage& image, ThreadData& data, + const Rect& rect, int firstRow, int endRow ) + : m_intensity( luminance ) + , m_image( image ) + , m_data( data ) + , m_rect( rect ) + , m_firstRow( firstRow ) + , m_endRow( endRow ) + { + } + + void Run() final + { + INIT_THREAD_MONITOR() + + const RGBColorSystem& rgbws = m_image.RGBWorkingSpace(); + + const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 ); + const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 ); + const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 ); + + typename P1::sample* fI = m_intensity.ScanLine( m_firstRow ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fI ) + { + RGBColorSystem::sample r0, r1, r2; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + break; + case ColorSpace::HSV: + rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ: + rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab: + rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch: + rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + + *fI = P1::ToSample( rgbws.Intensity( r0, r1, r2 ) ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + + private: + + GenericImage& m_intensity; + const GenericImage& m_image; + ThreadData& m_data; + const Rect& m_rect; + int m_firstRow, m_endRow; + }; + + // ------------------------------------------------------------------------- + + template + class SetLuminanceThread : public Thread + { + public: + + SetLuminanceThread( GenericImage& image, const GenericImage& luminance, ThreadData& data, + const Point& target, const Rect& rect, int firstRow, int endRow ) + : m_image( image ) + , m_luminance( luminance ) + , m_data( data ) + , m_target( target ) + , m_rect( rect ) + , m_firstRow( firstRow ) + , m_endRow( endRow ) + { + } + + void Run() final + { + INIT_THREAD_MONITOR() + + const RGBColorSystem& sourceRGBWS = m_luminance.RGBWorkingSpace(); + const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace(); + + typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 ); + typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 ); + typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 ); + + if ( m_luminance.ColorSpace() == ColorSpace::Gray || m_luminance.ColorSpace() == ColorSpace::CIEXYZ ) + { + int cY = (m_luminance.ColorSpace() == ColorSpace::Gray) ? 0 : 1; + const typename P1::sample* fY = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, cY ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw, fY += dwY ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY ) + { + RGBColorSystem::sample r0, r1, r2, rY; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + P1::FromSample( rY, *fY ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: // RGB + break; + } + targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 ); + targetRGBWS.CIELabToRGB( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 ); + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + default: // RGB + break; + } + break; + + case ColorSpace::CIEXYZ: + targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 ); + targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 ); + break; + + case ColorSpace::CIELab: + case ColorSpace::CIELch: + r0 = sourceRGBWS.CIEYToCIEL( rY ); + break; + + default: // ??? + break; + } + + *f0 = P::ToSample( r0 ); + *f1 = P::ToSample( r1 ); + *f2 = P::ToSample( r2 ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + else + { + const typename P1::sample* g0 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 ); + const typename P1::sample* g1 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 ); + const typename P1::sample* g2 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwY, g1 += dwY, g2 += dwY ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 ) + { + typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + P1::FromSample( s0, *g0 ); + P1::FromSample( s1, *g1 ); + P1::FromSample( s2, *g2 ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + case ColorSpace::CIEXYZ: + case ColorSpace::CIELab: + case ColorSpace::CIELch: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ: + targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab: // NOOP + case ColorSpace::CIELch: // NOOP + break; + default: // ?! + break; + } + + switch ( m_luminance.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_luminance.ColorSpace() ) + { + case ColorSpace::HSV: + sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 ); + break; + case ColorSpace::HSI: + sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 ); + break; + default: + break; + } + r0 = sourceRGBWS.CIEL( s0, s1, s2 ); + break; + case ColorSpace::CIEXYZ: + sourceRGBWS.CIEXYZToCIELab( r0, s1, s2, s0, s1, s2 ); + break; + case ColorSpace::CIELab: + case ColorSpace::CIELch: + r0 = s0; + break; + default: // ?! + break; + } + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + default: // RGB + break; + } + break; + case ColorSpace::CIEXYZ: + targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELab: // NOOP + case ColorSpace::CIELch: // NOOP + break; + default: // ?! + break; + } + break; + + default: // ?! + break; + } + + *f0 = P::ToSample( r0 ); + *f1 = P::ToSample( r1 ); + *f2 = P::ToSample( r2 ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + } + + private: + + GenericImage& m_image; + const GenericImage& m_luminance; + ThreadData& m_data; + const Point& m_target; + const Rect& m_rect; + int m_firstRow, m_endRow; + }; + + // ------------------------------------------------------------------------- + + template + class SetLightnessThread : public Thread + { + public: + + SetLightnessThread( GenericImage& image, const GenericImage& lightness, ThreadData& data, + const Point& target, const Rect& rect, int firstRow, int endRow ) + : m_image( image ) + , m_lightness( lightness ) + , m_data( data ) + , m_target( target ) + , m_rect( rect ) + , m_firstRow( firstRow ) + , m_endRow( endRow ) + { + } + + void Run() final + { + INIT_THREAD_MONITOR() + + const RGBColorSystem& sourceRGBWS = m_lightness.RGBWorkingSpace(); + const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace(); + + typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 ); + typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 ); + typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 ); + + if ( m_lightness.ColorSpace() == ColorSpace::Gray || + m_lightness.ColorSpace() == ColorSpace::CIELab || m_lightness.ColorSpace() == ColorSpace::CIELch ) + { + const typename P1::sample* fL = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw, fL += dwL ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL ) + { + RGBColorSystem::sample r0, r1, r2, rL; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + P1::FromSample( rL, *fL ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 ); + targetRGBWS.CIELabToRGB( r0, r1, r2, rL, r1, r2 ); + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + + case ColorSpace::CIEXYZ: + r1 = targetRGBWS.CIELToCIEY( rL ); + break; + + case ColorSpace::CIELab: + case ColorSpace::CIELch: + r0 = rL; + break; + + default: // ??? + break; + } + + *f0 = P::ToSample( r0 ); + *f1 = P::ToSample( r1 ); + *f2 = P::ToSample( r2 ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + else + { + const typename P1::sample* g0 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 ); + const typename P1::sample* g1 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 ); + const typename P1::sample* g2 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 ); + + for ( int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width(); + y < m_endRow; + ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwL, g1 += dwL, g2 += dwL ) + { + const typename P::sample* fN = f0 + m_rect.Width(); + + for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 ) + { + typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2; + P::FromSample( r0, *f0 ); + P::FromSample( r1, *f1 ); + P::FromSample( r2, *f2 ); + P1::FromSample( s0, *g0 ); + P1::FromSample( s1, *g1 ); + P1::FromSample( s2, *g2 ); + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + case ColorSpace::CIEXYZ: + case ColorSpace::CIELab: + case ColorSpace::CIELch: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIEXYZ: + targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch: + targetRGBWS.CIELchToCIELab( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + + switch ( m_lightness.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + switch ( m_lightness.ColorSpace() ) + { + case ColorSpace::HSV: + sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 ); + break; + case ColorSpace::HSI: + sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 ); + break; + default: + break; + } + r0 = sourceRGBWS.CIEL( s0, s1, s2 ); + break; + case ColorSpace::CIEXYZ: + r0 = sourceRGBWS.CIEYToCIEL( s1 ); + break; + default: // ??? + break; + } + + switch ( m_image.ColorSpace() ) + { + case ColorSpace::RGB: + case ColorSpace::HSV: + case ColorSpace::HSI: + targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 ); + switch ( m_image.ColorSpace() ) + { + case ColorSpace::HSV: + targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::HSI: + targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + break; + case ColorSpace::CIEXYZ: + targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 ); + break; + case ColorSpace::CIELch: + targetRGBWS.CIELabToCIELch( r0, r1, r2, r0, r1, r2 ); + break; + default: + break; + } + + default: // ??? + break; + } + + *f0 = P::ToSample( r0 ); + *f1 = P::ToSample( r1 ); + *f2 = P::ToSample( r2 ); + + UPDATE_THREAD_MONITOR( 65536 ) + } + } + } + } + + private: + + GenericImage& m_image; + const GenericImage& m_lightness; + ThreadData& m_data; + const Point& m_target; + const Rect& m_rect; + int m_firstRow, m_endRow; + }; + + // ------------------------------------------------------------------------- + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + friend class pi::SharedImage; +#endif +}; + +#undef m_pixelData +#undef m_channelData +#undef m_allocator +#undef m_width +#undef m_height +#undef m_numberOfChannels +#undef m_colorSpace +#undef m_RGBWS +#undef m_channel +#undef m_lastChannel +#undef m_point +#undef m_rectangle +#undef m_clipLow +#undef m_clipHigh +#undef m_clippedLow +#undef m_clippedHigh + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup image_scalar_operators Image Scalar Operators + */ + +/*! + * Returns the sum of an \a image and a \a scalar. The operation is performed + * on the current selection of the specified \a image. + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator +( const GenericImage

& image, T scalar ) +{ + GenericImage

result( image ); + (void)(result += scalar); + return result; +} + +/*! + * Returns the sum of a \a scalar and an \a image. The operation is performed + * on the current selection of the specified \a image. + * + * This operator implements the commutative property of image scalar addition. + * + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator +( T scalar, const GenericImage

& image ) +{ + return image + scalar; +} + +/*! + * Returns the subtraction of a \a scalar from an \a image. The operation is + * performed on the current selection of the specified \a image. + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator -( const GenericImage

& image, T scalar ) +{ + GenericImage

result( image ); + (void)(result -= scalar); + return result; +} + +/*! + * Returns the product of an \a image by a \a scalar. The operation is + * performed on the current selection of the specified \a image. + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator *( const GenericImage

& image, T scalar ) +{ + GenericImage

result( image ); + (void)(result *= scalar); + return result; +} + +/*! + * Returns the product of a \a scalar by an \a image. The operation is + * performed on the current selection of the specified \a image. + * + * This operator implements the commutative property of image scalar + * multiplication. + * + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator *( T scalar, const GenericImage

& image ) +{ + return image * scalar; +} + +/*! + * Returns the result of dividing an \a image by a \a scalar. The operation is + * performed on the current selection of the specified \a image. + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator /( const GenericImage

& image, T scalar ) +{ + GenericImage

result( image ); + (void)(result /= scalar); + return result; +} + +/*! + * Returns the result of raising an \a image to a \a scalar. The operation is + * performed on the current selection of the specified \a image. + * \ingroup image_scalar_operators + */ +template inline +GenericImage

operator ^( const GenericImage

& image, T scalar ) +{ + GenericImage

result( image ); + (void)(result ^= scalar); + return result; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup image_operators Image Operators + */ + +/*! + * Returns the sum of two images. + * + * The image addition operation is performed for the current selection of the + * right-hand operand image, and is applied at the current anchor point of the + * left-hand image. + * + * The result is an image of the same template instantiation as the left-hand + * operand image. + * + * \ingroup image_operators + */ +template inline +GenericImage operator +( const GenericImage& image1, const GenericImage& image2 ) +{ + GenericImage result( image1 ); + (void)(result += image2); + return result; +} + +/*! + * Returns the difference of two images. + * + * The image subtraction operation is performed for the current selection of + * the right-hand operand image, and is applied at the current anchor point of + * the left-hand image. + * + * The result is an image of the same template instantiation as the left-hand + * operand image. + * + * \ingroup image_operators + */ +template inline +GenericImage operator -( const GenericImage& image1, const GenericImage& image2 ) +{ + GenericImage result( image1 ); + (void)(result -= image2); + return result; +} + +/*! + * Returns the product of two images. + * + * The image multiplication operation is performed for the current selection of + * the right-hand operand image, and is applied at the current anchor point of + * the left-hand image. + * + * The result is an image of the same template instantiation as the left-hand + * operand image. + * + * \ingroup image_operators + */ +template inline +GenericImage operator *( const GenericImage& image1, const GenericImage& image2 ) +{ + GenericImage result( image1 ); + (void)(result *= image2); + return result; +} + +/*! + * Returns the result of dividing one image \a image1 by another image + * \a image2. + * + * The image division operation is performed for the current selection of the + * right-hand operand image, and is applied at the current anchor point of the + * left-hand image. + * + * The result is an image of the same template instantiation as the left-hand + * operand image. + * + * \ingroup image_operators + */ +template inline +GenericImage operator /( const GenericImage& image1, const GenericImage& image2 ) +{ + GenericImage result( image1 ); + (void)(result /= image2); + return result; +} + +/*! + * Returns the result of raising one image \a image1 to another image + * \a image2. + * + * The image exponentiation operation is performed for the current selection of + * the right-hand operand image, and is applied at the current anchor point of + * the left-hand image. + * + * The result is an image of the same template instantiation as the left-hand + * operand image. + * + * \ingroup image_operators + */ +template inline +GenericImage operator ^( const GenericImage& image1, const GenericImage& image2 ) +{ + GenericImage result( image1 ); + (void)(result ^= image2); + return result; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_IMAGE_INSTANTIATE + +/*! + * \defgroup image_types_2d Image Types + */ + +/*! + * \class pcl::FImage + * \ingroup image_types_2d + * \brief 32-bit floating point real image. + * + * %FImage is a template instantiation of GenericImage for FloatPixelTraits. + */ +typedef GenericImage FImage; + +/*! + * \class pcl::DImage + * \ingroup image_types_2d + * \brief 64-bit floating point real image. + * + * %DImage is a template instantiation of GenericImage for DoublePixelTraits. + */ +typedef GenericImage DImage; + +/*! + * \class pcl::FComplexImage + * \ingroup image_types_2d + * \brief 32-bit floating point complex image. + * + * %FComplexImage is a template instantiation of GenericImage for the + * ComplexPixelTraits class. + */ +typedef GenericImage FComplexImage; + +/*! + * \class pcl::DComplexImage + * \ingroup image_types_2d + * \brief 64-bit floating point complex image. + * + * %DComplexImage is a template instantiation of GenericImage for the + * DComplexPixelTraits class. + */ +typedef GenericImage DComplexImage; + +/*! + * \class pcl::UInt8Image + * \ingroup image_types_2d + * \brief 8-bit unsigned integer image. + * + * %UInt8Image is a template instantiation of GenericImage for the + * UInt8PixelTraits class. + */ +typedef GenericImage UInt8Image; + +/*! + * \class pcl::UInt16Image + * \ingroup image_types_2d + * \brief 16-bit unsigned integer image. + * + * %UInt16Image is a template instantiation of GenericImage for the + * UInt16PixelTraits class. + */ +typedef GenericImage UInt16Image; + +/*! + * \class pcl::UInt32Image + * \ingroup image_types_2d + * \brief 32-bit unsigned integer image. + * + * %UInt32Image is a template instantiation of GenericImage for the + * UInt32PixelTraits class. + */ +typedef GenericImage UInt32Image; + +/*! + * \class pcl::Image + * \ingroup image_types_2d + * \brief 32-bit floating point real image. + * + * %Image is an alias for FImage. It is a template instantiation of + * GenericImage for the FloatPixelTraits class. + */ +typedef FImage Image; + +/*! + * \class pcl::ComplexImage + * \ingroup image_types_2d + * \brief 32-bit floating point complex image. + * + * %ComplexImage is an alias for FComplexImage. It is a template instantiation + * of GenericImage for the ComplexPixelTraits class. + */ +typedef FComplexImage ComplexImage; + +#endif // __PCL_NO_IMAGE_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_IMAGE_VARIANT_AUTO + +#ifndef __PCL_ImageVariant_h +#include +#endif + +#endif // __PCL_NO_IMAGE_VARIANT_AUTO + +// ---------------------------------------------------------------------------- + +#endif // __PCL_Image_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Image.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageColor.h b/3rdparty/include/pcl/ImageColor.h new file mode 100644 index 0000000..4183ece --- /dev/null +++ b/3rdparty/include/pcl/ImageColor.h @@ -0,0 +1,258 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageColor.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_ImageColor_h +#define __PCL_ImageColor_h + +/// \file pcl/ImageColor.h + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_colorSpace m_color->colorSpace +#define m_RGBWS m_color->RGBWS + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageColor + * \brief Implements color space properties of images. + * + * %ImageColor defines the color space and the RGB Working Space for an image. + * + * Supported color spaces are defined and enumerated by the ColorSpace class. + * + * An RGB Working Space (RGBWS) is used by PCL and the PixInsight core + * application to perform luminance/chrominance separations and color space + * conversions. Note that a RGBWS has nothing to do with color management and + * ICC profiles in the PixInsight/PCL environment. An RGBWS is used for image + * processing tasks exclusively, and \e never for color management tasks. + * + * RGB working spaces are implemented by the RGBColorSystem class. + * + * Note that for a shared image (that is, an image living in the PixInsight + * core application) the RGBWS is controlled exclusively by its parent + * ImageWindow. + * + * \sa ImageGeometry, AbstractImage, GenericImage + */ +class PCL_CLASS ImageColor +{ +public: + + /*! + * An enumerated type that represents the set of supported color spaces. + * Valid constants for this enumeration are defined in the ColorSpace + * namespace. + */ + typedef ColorSpace::value_type color_space; + + /*! + * Returns a reference to the RGB working space associated with this image. + */ + const RGBColorSystem& RGBWorkingSpace() const noexcept + { + return m_RGBWS; + } + + /*! + * Associates a given RGB working space (RGBWS) with this image. + * + * \note For shared images (that is, images living in the PixInsight core + * application), the RGB working space cannot be changed by calling this + * function. This is because the RGBWS of a shared image is a property + * controlled by its parent image window. See the documentation for the + * ImageWindow class. + */ + virtual void SetRGBWorkingSpace( const RGBColorSystem& RGBWS ) + { + m_RGBWS = RGBWS; + } + + /*! + * Returns a reference to the current default RGB working space (RGBWS). If + * you don't change it, the factory-default RGBWS corresponds to the sRGB + * color space. + * + * \note This function only works for local images. For shared images, the + * default RGBWS is controlled by the ImageWindow class. + */ + static const RGBColorSystem& DefaultRGBWorkingSpace() noexcept + { + return s_defaultRGBWS; + } + + /*! + * Selects the specified RGB working space \a RGBWS as the default RGB + * working space for local images. The default RGBWS is associated with + * newly created local images; existing images won't be affected by this + * setting. + * + * \note This function only works for local images. For shared images, the + * default RGBWS is controlled exclusively by the ImageWindow class. + */ + static void SetDefaultRGBWorkingSpace( const RGBColorSystem& RGBWS ) + { + s_defaultRGBWS = RGBWS; + } + + /*! + * Resets the default RGB working space (RGBWS) to the factory-default sRGB + * color space. + */ + static void ResetDefaultRGBWorkingSpace() + { + s_defaultRGBWS = RGBColorSystem::sRGB; + } + + /*! + * Returns true iff this is a color image. Returns false if this is a + * grayscale monochrome image. + */ + bool IsColor() const noexcept + { + return m_colorSpace != ColorSpace::Gray; + } + + /*! + * Returns the color space of this image. This function returns the value of + * a symbolic constant enumerated by the ColorSpace namespace. + */ + color_space ColorSpace() const noexcept + { + return m_colorSpace; + } + + /*! + * Returns the identifier of a nominal channel \a c in the current color + * space of this image. + */ + String ChannelId( int c ) const noexcept + { + return ColorSpace::ChannelId( m_colorSpace, c ); + } + +protected: + + struct Color + { + color_space colorSpace; + RGBColorSystem RGBWS; + + Color( color_space cs = ColorSpace::Gray ) + : colorSpace( cs ) + , RGBWS( s_defaultRGBWS ) + { + } + + Color( const Color& ) = default; + + void Assign( const Color& x ) + { + colorSpace = x.colorSpace; + RGBWS = x.RGBWS; + } + + void Reset() noexcept + { + colorSpace = ColorSpace::Gray; + } + }; + + Color* m_color = nullptr; + + /* + * The default RGB Working Space + * + * Unless explicitly modified, this corresponds to the sRGB space. + * + * Note that shared images don't use this default RGBWS, but the global + * RGBWS currently selected in the PixInsight core application. + */ + static RGBColorSystem s_defaultRGBWS; + + ImageColor() = default; + ImageColor( const ImageColor& ) = default; + ImageColor& operator =( const ImageColor& ) = default; + + virtual ~ImageColor() + { + m_color = nullptr; + } + + void Swap( ImageColor& image ) noexcept + { + pcl::Swap( m_color, image.m_color ); + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_colorSpace +#undef m_RGBWS + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageColor_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageColor.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageDescription.h b/3rdparty/include/pcl/ImageDescription.h new file mode 100644 index 0000000..135fe6b --- /dev/null +++ b/3rdparty/include/pcl/ImageDescription.h @@ -0,0 +1,141 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageDescription.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_ImageDescription_h +#define __PCL_ImageDescription_h + +/// \file pcl/ImageDescription.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageDescription + * \brief A structure to transport basic information and options for an image + * stored in an image file + * + * This structure is used (instantiated in ImageDescriptionArray containers) by + * the FileFormatImplementation and FileFormaInstance classes to describe + * individual images stored in image files. + * + * \sa ImageInfo, ImageOptions, FileFormatImplementation, FileFormatInstance + */ +struct PCL_CLASS ImageDescription +{ + ImageInfo info; //!< Basic image information: dimensions and color space. + ImageOptions options; //!< Format-independent image file options. + IsoString id; //!< Identifier of this image. Usually a running counter starting from zero. + + /*! + * Default constructor. + */ + ImageDescription() = default; + + /*! + * Constructs an %ImageDescription object from the specified ImageInfo, + * ImageOptions and image identifier. + */ + ImageDescription( const ImageInfo& i, const ImageOptions& o, const IsoString& s = IsoString() ) + : info( i ), options( o ), id( s ) + { + } + + ImageDescription( const ImageInfo& i, const ImageOptions& o, const String& s ) + : ImageDescription( i, o, IsoString( s ) ) + { + } + + /*! + * Constructs an %ImageDescription object from the specified ImageInfo + * structure with default format-independent options and an empty image + * identifier. + */ + ImageDescription( const ImageInfo& i ) + : info( i ) + { + } + + /*! + * Copy constructor. + */ + ImageDescription( const ImageDescription& ) = default; + + /*! + * Cop assignment operator. Returns a reference to this object. + */ + ImageDescription& operator =( const ImageDescription& ) = default; +}; + +/*! + * \class pcl::ImageDescriptionArray + * \brief Dynamic array of ImageDescription structures + * + * %ImageDescriptionArray is a template instantiation of Array for + * ImageDescription. + */ +typedef Array ImageDescriptionArray; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageDescription_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageDescription.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageGeometry.h b/3rdparty/include/pcl/ImageGeometry.h new file mode 100644 index 0000000..8538ec7 --- /dev/null +++ b/3rdparty/include/pcl/ImageGeometry.h @@ -0,0 +1,404 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageGeometry.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_ImageGeometry_h +#define __PCL_ImageGeometry_h + +/// \file pcl/ImageGeometry.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_width m_geometry->width +#define m_height m_geometry->height +#define m_numberOfChannels m_geometry->numberOfChannels + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageGeometry + * \brief Implements geometric properties of two-dimensional images. + * + * %ImageGeometry defines the dimensions in pixels and the channel count of a + * two-dimensional image. + * + * \sa ImageColor, Abstractmage, GenericImage + */ +class PCL_CLASS ImageGeometry +{ +public: + + /*! + * Returns the width of this image in pixels. + */ + int Width() const noexcept + { + return m_width; + } + + /*! + * Returns the height of this image in pixels. + */ + int Height() const noexcept + { + return m_height; + } + + /*! + * Returns the total number of channels in this image, including nominal and + * alpha channels. + */ + int NumberOfChannels() const noexcept + { + return m_numberOfChannels; + } + + /*! + * Returns the index of the last existing channel in this image. This is the + * largest valid channel index that can be used with this image, + * corresponding to a nominal or alpha channel. If this image is empty, this + * function returns -1. + */ + int LastChannel() const noexcept + { + return m_numberOfChannels-1; + } + + /*! + * Returns true iff the specified channel index \a c is valid. A valid + * channel index corresponds to an existing channel in this image. + */ + bool IsValidChannelIndex( int c ) const noexcept + { + return c >= 0 && c < m_numberOfChannels; + } + + /*! + * Returns true iff this image is empty, i.e. if its area is zero. + */ + bool IsEmpty() const noexcept + { + return m_width <= 0 || m_height <= 0 || m_numberOfChannels <= 0; + } + + /*! + * Returns the bounding rectangle of this image. The upper left corner of + * the returned rectangle (x0, y0) is always (0,0). The lower right corner + * coordinates (x1, y1) correspond to the width and height of the image. + */ + Rect Bounds() const noexcept + { + return Rect( m_width, m_height ); + } + + /*! + * Returns true iff this image includes the specified point \a p in image + * coordinates. + */ + template + bool Includes( const GenericPoint& p ) const noexcept + { + return Includes( p.x, p.y ); + } + + /*! + * Returns true iff this image includes the specified rectangle \a r in image + * coordinates. + */ + template + bool Includes( const GenericRectangle& r ) const noexcept + { + return Includes( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Returns true iff this image includes a rectangle given by its separate + * image coordinates. + * + * \param x0,y0 Upper left corner coordinates (horizontal, vertical). + * \param x1,y1 Lower right corner coordinates (horizontal, vertical). + */ + template + bool Includes( T x0, T y0, T x1, T y1 ) const noexcept + { + pcl::OrderRect( x0, y0, x1, y1 ); + return Includes( x0, y0 ) && Includes( x1-T( 1 ), y1-T( 1 ) ); + } + + /*! + * Returns true iff this image includes a point given by its separate image + * coordinates. + * + * \param x Horizontal coordinate. + * \param y Vertical coordinate. + */ + template + bool Includes( T x, T y ) const noexcept + { + return x < m_width && y < m_height && x >= 0 && y >= 0; + } + + /*! + * Returns true iff this image intersects with the specified rectangle \a r + * in image coordinates. + */ + template + bool Intersects( const pcl::GenericRectangle& r ) const noexcept + { + return Intersects( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Returns true iff this image intersects with a rectangle given by its + * separate image coordinates. + * + * \param x0,y0 Upper left corner coordinates (horizontal, vertical). + * \param x1,y1 Lower right corner coordinates (horizontal, vertical). + */ + template + bool Intersects( T x0, T y0, T x1, T y1 ) const noexcept + { + pcl::OrderRect( x0, y0, x1, y1 ); + return x0 < m_width && y0 < m_height && x1 > T( 0 ) && y1 > T( 0 ); + } + + /*! + * Constrains a point \a p to stay within the boundaries of this image. + * Returns true iff the original point location is included in this image. + */ + template + bool Clip( pcl::GenericPoint& p ) const noexcept + { + return Clip( p.x, p.y ); + } + + /*! + * Constrains two point coordinates \a x and \a y to stay within the + * boundaries of this image. + * + * \param[out] x Horizontal coordinate of the clipped point. + * \param[out] y Vertical coordinate of the clipped point. + * + * Returns true iff the original point location is included in this image. + */ + template + bool Clip( T& x, T& y ) const noexcept + { + bool in = false; + + if ( x >= T( m_width ) ) x = T( m_width-1 ); + else if ( x < T( 0 ) ) x = T( 0 ); + else in = true; + + if ( y >= T( m_height ) ) y = T( m_height-1 ); + else if ( y < T( 0 ) ) y = T( 0 ); + else return in; + + return false; + } + + /*! + * Constrains a rectangular region \a r in image coordinates to fit into the + * boundaries of this image. Also ensures coherence of clipped rectangular + * coordinates such that r.x0 <= r.x1 and r.y0 <= r.y1. + * + * Returns true iff the original rectangle intersects this image. + */ + template + bool Clip( pcl::GenericRectangle& r ) const noexcept + { + return Clip( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Constrains a rectangular region, given by its separate image + * coordinates, to fit into the boundaries of this image. Also ensures + * coherence of rectangular coordinates, such that x0 <= x1 and y0 <= y1. + * + * \param[out] x0,y0 Upper left corner coordinates (horizontal, vertical) + * of the rectangle that will be clipped. + * + * \param[out] x1,y1 Lower right corner coordinates (horizontal, vertical) + * of the rectangle that will be clipped. + * + * Returns true iff the original rectangle intersects the image. + */ + template + bool Clip( T& x0, T& y0, T& x1, T& y1 ) const noexcept + { + pcl::OrderRect( x0, y0, x1, y1 ); + + int out = 0; + + if ( x0 >= T( m_width ) ) x0 = T( m_width ), ++out; + else if ( x0 < T( 0 ) ) x0 = T( 0 ); + + if ( y0 >= T( m_height ) ) y0 = T( m_height ), ++out; + else if ( y0 < T( 0 ) ) y0 = T( 0 ); + + if ( x1 > T( m_width ) ) x1 = T( m_width ); + else if ( x1 <= T( 0 ) ) x1 = T( 0 ), ++out; + + if ( y1 > T( m_height ) ) y1 = T( m_height ); + else if ( y1 <= T( 0 ) ) y1 = T( 0 ), ++out; + + return !out; + } + + /*! + * Returns the number of pixels in this image, or its area in square pixels. + */ + size_type NumberOfPixels() const noexcept + { + return size_type( m_width )*size_type( m_height ); + } + + /*! + * Returns the total number of samples in this image, or the area in square + * pixels multiplied by the number of channels, including alpha channels. + */ + size_type NumberOfSamples() const noexcept + { + return NumberOfPixels()*size_type( m_numberOfChannels ); + } + + /*! + * Returns the offset of a given pixel row \a y (also known as scan + * line) from the beginning of a channel's data block. + */ + distance_type RowOffset( int y ) const noexcept + { + return distance_type( y )*distance_type( m_width ); + } + + /*! + * Returns the offset of a given pixel from the beginning of a channel's + * data block. + * + * \param x Horizontal pixel coordinate. + * \param y Vertical pixel coordinate. + */ + distance_type PixelOffset( int x, int y ) const noexcept + { + return RowOffset( y ) + distance_type( x ); + } + +protected: + + /* + * Image geometry + */ + struct Geometry + { + int width = 0; + int height = 0; + int numberOfChannels = 0; + + Geometry() = default; + Geometry( const Geometry& ) = default; + + size_type NumberOfPixels() const noexcept + { + return size_type( width )*size_type( height ); + } + + void Assign( const Geometry& x ) noexcept + { + width = x.width; + height = x.height; + numberOfChannels = x.numberOfChannels; + } + + void Reset() noexcept + { + width = height = numberOfChannels = 0; + } + }; + + Geometry* m_geometry = nullptr; + + ImageGeometry() = default; + ImageGeometry( const ImageGeometry& ) = default; + ImageGeometry& operator =( const ImageGeometry& ) = default; + + virtual ~ImageGeometry() + { + m_geometry = nullptr; + } + + void Swap( ImageGeometry& image ) noexcept + { + pcl::Swap( m_geometry, image.m_geometry ); + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_width +#undef m_height +#undef m_numberOfChannels + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageGeometry_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageGeometry.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageInfo.h b/3rdparty/include/pcl/ImageInfo.h new file mode 100644 index 0000000..73f733c --- /dev/null +++ b/3rdparty/include/pcl/ImageInfo.h @@ -0,0 +1,180 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageInfo.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_ImageInfo_h +#define __PCL_ImageInfo_h + +/// \file pcl/ImageInfo.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageInfo + * \brief A simple structure to hold basic information about images + */ +class PCL_CLASS ImageInfo +{ +public: + + /*! + * Represents a color space. See the ColorSpace namespace for supported + * values. + */ + typedef ColorSpace::value_type color_space; + + int width; //!< %Image width in pixels + int height; //!< %Image height in pixels + int numberOfChannels; //!< Number of channels, including alpha channels + color_space colorSpace; //!< %Color space, compatible with ImageColor::color_space + bool supported; //!< Whether we support this image + + /*! + * Constructs an %ImageInfo object with default values. + */ + ImageInfo() + { + Reset(); + } + + /*! + * Copy constructor. + */ + ImageInfo( const ImageInfo& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ImageInfo& operator =( const ImageInfo& ) = default; + + /*! + * Constructs an %ImageInfo object with data obtained from the specified + * \a image. + * + * The width, height and numberOfChannels data members are set to the + * dimensions of the selected rectangle and the number of selected channels + * in \a image, respectively. + */ + ImageInfo( const AbstractImage& image ) + { + width = image.SelectedRectangle().Width(); + height = image.SelectedRectangle().Height(); + numberOfChannels = image.NumberOfSelectedChannels(); + colorSpace = image.ColorSpace(); + supported = IsValid(); + } + + /*! + * Returns the number of pixels in the image, or width*height. + */ + size_type NumberOfPixels() const + { + return size_type( width )*size_type( height ); + } + + /*! + * Returns the number of samples in the image, or + * width*height*numberOfChannels. + */ + size_type NumberOfSamples() const + { + return NumberOfPixels()*size_type( numberOfChannels ); + } + + /*! + * Initializes this %ImageInfo structure with default values, corresponding + * to an empty image. + */ + void Reset() + { + width = height = numberOfChannels = 0; + colorSpace = ColorSpace::Unknown; + supported = false; + } + + /*! + * Returns true iff this object describes a valid nonempty image. + */ + bool IsValid() const + { + return width > 0 && + height > 0 && + colorSpace != ColorSpace::Unknown && + numberOfChannels >= ((colorSpace == ColorSpace::Gray) ? 1 : 3); + } + + /*! + * Returns true iff this object is equal to another instance \a x. + */ + bool operator ==( const ImageInfo& x ) const + { + return width == x.width && + height == x.height && + numberOfChannels == x.numberOfChannels && + colorSpace == x.colorSpace; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageInfo_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageInfo.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageOptions.h b/3rdparty/include/pcl/ImageOptions.h new file mode 100644 index 0000000..a370446 --- /dev/null +++ b/3rdparty/include/pcl/ImageOptions.h @@ -0,0 +1,186 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageOptions.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_ImageOptions_h +#define __PCL_ImageOptions_h + +/// \file pcl/ImageOptions.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::CFAType + * \brief Color Filter Array types. + * + * A CFA (Color Filter Array) is a mosaic of color filters placed in front of + * an image sensor, such as CMOS sensors of digital cameras. This enumeration + * defines the CFA types currently supported in PCL. + * + * + * + * + * + *
CFAType::None The image uses no CFA pattern, or the CFA pattern is unsupported.
CFAType::BGGR, CFAType::GRBG, CFAType::GBRG, CFAType::RGGB RGB CFA types.
CFAType::CYGM Cyan/Yellow/Green/Magenta CFA (used by a few digital cameras).
+ */ +namespace CFAType +{ + enum value_type { None, BGGR, GRBG, GBRG, RGGB, CYGM, NumberOfCFATypes }; + + /*! + * Returns a string representing a type of color filter array. + * + * \param cfa A supported CFA type, identified by its corresponding + * symbolic constant. + */ + String Name( int cfa ); +} + +/*! + * \class ImageOptions + * \brief Format-independent, fundamental image stream options. + */ +class PCL_CLASS ImageOptions +{ +public: + + uint8 bitsPerSample : 8; //!< Number of bits per sample: 8, 16, 32 or 64. The default value is 16. + bool ieeefpSampleFormat : 1; //!< Sample type: IEEE 754 floating point (true) or integers (false). The default value is false. + bool complexSample : 1; //!< Sample type: Complex (true) or real (false) samples. The default value is false. + bool signedIntegers : 1; //!< Integer sample values are signed (true) or unsigned (false). The default value is false. + bool metricResolution : 1; //!< Resolution units: centimeter (true) or inch (false). The default value is false. + bool readNormalized : 1; //!< Normalize floating-point sample values after reading. The default value is true. + bool embedICCProfile : 1; //!< Embed an ICC profile (when available). The default value is true. + bool embedThumbnail : 1; //!< Embed thumbnail images (when available). The default value is false. + bool embedProperties : 1; //!< Embed data properties (when available). The default value is true. + bool embedRGBWS : 1; //!< Embed RGB working space parameters. The default value is true. + bool embedDisplayFunction : 1; //!< Embed display function (aka STF) parameters. The default value is true. + bool embedColorFilterArray : 1; //!< Embed color filter array (CFA) description. The default value is true. + bool embedProcessingHistory : 1; //!< Embed existing processing history as an XML document. The default value is false. + bool embedPreviewRects : 1; //!< Embed existing preview rectangles and their identifiers. The default value is false. + int __rsv__ : 11; // Reserved for future extensions; must be zero. + + double lowerRange; //!< Lower limit to normalize read floating-point samples. The default value is 0. + double upperRange; //!< Upper limit to normalize read floating-point samples. The default value is 1. + + double xResolution; //!< Horizontal resolution in pixels per resolution unit (0=unknown). The default value is 72. + double yResolution; //!< Vertical resolution in pixels per resolution unit (0=unknown). The default value is 72. + + int isoSpeed; //!< ISO speed as specified in ISO 12232 (0=unknown) + float exposure; //!< Exposure in seconds (0=unknown) + float aperture; //!< Focal length divided by lens diameter (F/D) (0=unknown) + float focalLength; //!< Focal length in millimeters (0=unknown) + int cfaType; //!< Color Filter Array type. See CFAType namespace for possible values (0=none). + + /*! + * Constructs an %ImageOptions structure with default values. + */ + ImageOptions() + { + Reset(); + } + + /*! + * Copy constructor. + */ + ImageOptions( const ImageOptions& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ImageOptions& operator =( const ImageOptions& ) = default; + + /*! + * Initializes all data members to default values. + */ + void Reset() + { + bitsPerSample = 16; + ieeefpSampleFormat = false; + complexSample = false; + signedIntegers = false; + metricResolution = false; + readNormalized = true; + embedICCProfile = true; + embedThumbnail = false; + embedProperties = true; + embedRGBWS = true; + embedDisplayFunction = true; + embedColorFilterArray = true; + embedProcessingHistory = false; + embedPreviewRects = false; + __rsv__ = 0; + lowerRange = 0; + upperRange = 1; + xResolution = 72; + yResolution = 72; + isoSpeed = 0; + exposure = 0; + aperture = 0; + focalLength = 0; + cfaType = CFAType::None; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageOptions_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageOptions.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageRenderingModes.h b/3rdparty/include/pcl/ImageRenderingModes.h new file mode 100644 index 0000000..f1826a1 --- /dev/null +++ b/3rdparty/include/pcl/ImageRenderingModes.h @@ -0,0 +1,189 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageRenderingModes.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_ImageRenderingModes_h +#define __PCL_ImageRenderingModes_h + +/// \file pcl/ImageRenderingModes.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::DisplayChannel + * \brief Rendering modes for image display and bitmap renditions. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
DisplayChannel::Invalid Represents an invalid or undefined display mode
DisplayChannel::RGBK Composite RGB or Gray (normal display mode)
DisplayChannel::Red Red channel as grayscale
DisplayChannel::Green Green channel as grayscale
DisplayChannel::Blue Blue channel as grayscale
DisplayChannel::CIE_L CIE L* component
DisplayChannel::Lightness A synomym for DisplayChannel::CIE_L
DisplayChannel::ChrominanceRG Chrominance, CIE a*,b* as red+green composite
DisplayChannel::ChrominanceLFixed Chrominance, CIE L* fixed to 0.5
DisplayChannel::CIE_a CIE a* component
DisplayChannel::CIE_b CIE b* component
DisplayChannel::CIE_c CIE c* component
DisplayChannel::CIE_h CIE h* component
DisplayChannel::CIE_X CIE X component
DisplayChannel::CIE_Y CIE Y component
DisplayChannel::CIE_Z CIE Z component
DisplayChannel::Hue Hue from the HSV/HSI spaces
DisplayChannel::SaturationHSV Saturation from HSV
DisplayChannel::SaturationHSI Saturation from HSI
DisplayChannel::Value Value from HSV (V = Max(R,G,B))
DisplayChannel::Intensity Intensity from HSI (I = 0.5*(Min(R,G,B) + Max(R,G,B)))
DisplayChannel::Alpha First alpha channel (the rest as Alpha+n)
+ */ +namespace DisplayChannel +{ + enum value_type + { + Invalid = -1, + RGBK = 0, // Composite RGB or Gray (normal display mode) + Red, // Red channel as grayscale + Green, // Green channel as grayscale + Blue, // Blue channel as grayscale + CIE_L, // CIE L* + Lightness = CIE_L, // Lightness = CIE L* + Luminance = CIE_L, // ### Deprecated - retained for compatibility -> suppress in PCL 2.0 + ChrominanceRG, // Chrominance, CIE a*,b* as red+green composite + ChrominanceLFixed, // Chrominance, CIE L* fixed to 0.5 + CIE_a, // CIE a* + CIE_b, // CIE b* + CIE_c, // CIE c* + CIE_h, // CIE h* + CIE_X, // CIE X + CIE_Y, // CIE Y + CIE_Z, // CIE Z + Hue, // Hue from the HSV/HSI spaces + SaturationHSV, // Saturation from HSV + SaturationHSI, // Saturation from HSI + Value, // Value from HSV (V = Max(R,G,B)) + Intensity, // Intensity from HSI (I = 0.5*(Min(R,G,B) + Max(R,G,B))) + Alpha // First alpha channel (the rest as Alpha+n) + }; + + inline bool IsLuminanceOrChrominance( value_type c ) + { + return c >= Lightness && c < Hue; + } +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::MaskMode + * \brief Mask rendering modes for image display and bitmap renditions. + * + * Mask rendering modes define how masked pixels are represented on bitmap + * renditions of images. The \e traditional mode used by PixInsight has always + * been MaskMode::Multiply, which simply multiplies each pixel of a screen + * rendition by its mask image counterpart. + * + * Since PixInsight version 1.5.5, an additional set of \e overlay mask + * rendering modes is available, providing more accurate representations in + * several user-selectable colors. A new \e replace mode has also been + * implemented to facilitate blinking comparisons between images and masks. The + * default mask rendering mode has been set to MaskMode::OverlayRed. + * + * + * + * + * + * + * + * + * + * + * + * + * + *
MaskMode::Replace Replaces the image by the mask.
MaskMode::Multiply Multiplies the image by the mask. This is the \e traditional mask rendering mode used by PixInsight before version 1.5.5.
MaskMode::OverlayRed Represents mask-protected pixels as red pixels on screen renditions.
MaskMode::OverlayGreen Represents mask-protected pixels as green pixels on screen renditions.
MaskMode::OverlayBlue Represents mask-protected pixels as blue pixels on screen renditions.
MaskMode::OverlayYellow Represents mask-protected pixels as yellow pixels (red+green) on screen renditions.
MaskMode::OverlayMagenta Represents mask-protected pixels as magenta pixels (red+blue) on screen renditions.
MaskMode::OverlayCyan Represents mask-protected pixels as cyan pixels (green+blue) on screen renditions.
MaskMode::OverlayOrange Represents mask-protected pixels as orange pixels (red + 1/2*green) on screen renditions.
MaskMode::OverlayViolet Represents mask-protected pixels as violet pixels (1/2*red + blue) on screen renditions.
MaskMode::Default Identifies the default mask rendering mode used by the PixInsight core application. Currently this corresponds to MaskMode::OverlayRed.
+ */ +namespace MaskMode +{ + enum value_type + { + Replace, // Replaces the image by the mask + Multiply, // Multiplies the image by the mask (PI's traditional mode) + OverlayRed, // Red mask + OverlayGreen, // Green mask + OverlayBlue, // Blue mask + OverlayYellow, // Yellow mask (red+green) + OverlayMagenta, // Magenta mask (red+blue) + OverlayCyan, // Cyan mask (green+blue) + OverlayOrange, // Orange mask (red + 1/2*green) + OverlayViolet, // Violet mask (1/2*red + blue) + + NumberOfModes, + + Default = OverlayRed + }; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageRenderingModes_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageRenderingModes.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageResolution.h b/3rdparty/include/pcl/ImageResolution.h new file mode 100644 index 0000000..e56ed43 --- /dev/null +++ b/3rdparty/include/pcl/ImageResolution.h @@ -0,0 +1,207 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageResolution.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_ImageResolution_h +#define __PCL_ImageResolution_h + +/// \file pcl/ImageResolution.h + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageResolution + * \brief %Image resolution data + * + * ### TODO: Write a detailed description for %ImageResolution. + */ +class PCL_CLASS ImageResolution +{ +public: + + /*! + * Constructs a default %ImageResolution object. + */ + ImageResolution() = default; + + /*! + * Copy constructor. + */ + ImageResolution( const ImageResolution& ) = default; + + /*! + * Assignment operator. Returns a reference to this object. + */ + ImageResolution& operator =( const ImageResolution& ) = default; + + /*! + * Gets resolution values for both \a x and \a y axes in pixels per + * resolution unit. + * + * \sa HorizontalResolution(), VerticalResolution() + */ + void GetResolution( double& x, double& y ) + { + x = xResolution; y = yResolution; + } + + /*! + * Returns the horizontal (X-axis) resolution in pixels per resolution unit. + * + * \sa VerticalResolution(), GetResolution() + */ + double HorizontalResolution() const + { + return xResolution; + } + + /*! + * Returns the vertical (Y-axis) resolution in pixels per resolution unit. + * + * \sa HorizontalResolution(), GetResolution() + */ + double VerticalResolution() const + { + return yResolution; + } + + /*! + * Sets resolution values for both \a x and \a y axes in pixels per + * resolution unit. + * + * \sa GetResolution(), SetResolution( double ) + */ + void SetResolution( double x, double y ) + { + PCL_PRECONDITION( x >= 0 ) + PCL_PRECONDITION( y >= 0 ) + xResolution = pcl::Max( 0.0, x ); yResolution = pcl::Max( 0.0, y ); + } + + /*! + * Returns the resolution for both axes, in pixels per resolution unit. + * + * This member function is more meaningful for contexts where separate + * horizontal and vertical resolutions are not supported. + * + * \sa GetResolution(), SetResolution( double ), SetResolution( double, double ) + */ + double Resolution() const + { + return xResolution; + } + + /*! + * Sets the resolution for both axes, in pixels per resolution unit. + * + * This member function is more meaningful for contexts where separate + * horizontal and vertical resolutions are not supported. + * + * \sa Resolution(), HorizontalResolution(), VerticalResolution(), GetResolution() + */ + void SetResolution( double r ) + { + PCL_PRECONDITION( r >= 0 ) + xResolution = yResolution = pcl::Max( 0.0, r ); + } + + /*! + * Returns true iff this object express resolution in pixels per centimeter; + * false if it express resolution in pixels per inch. + * + * \sa SetMetricResolution() + */ + bool IsMetricResolution() const + { + return metric; + } + + /*! + * Sets the resolution unit for this %ImageResolution object. + * + * \param m If true, enables resolution in pixels per centimeter (metric + * resolution). If false, enables resolution in pixels per inch. + * + * \sa IsMetricResolution() + */ + void SetMetricResolution( bool m ) + { + metric = m; + } + +protected: + + /* + * Resolution in pixels per resolution unit (centimeters or inches). + */ + double xResolution = 72; + double yResolution = 72; + + /* + * Flag true when resolution values are expressed in pixels per centimeter. + * Pixels per inch otherwise. + */ + bool metric = false; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageResolution_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageResolution.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageSelections.h b/3rdparty/include/pcl/ImageSelections.h new file mode 100644 index 0000000..4062309 --- /dev/null +++ b/3rdparty/include/pcl/ImageSelections.h @@ -0,0 +1,122 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageSelections.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_ImageSelections_h +#define __PCL_ImageSelections_h + +/// \file pcl/ImageSelections.h + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \struct ImageSelections + * \brief A structure used to store rectangular image selections, channel + * ranges, anchor points, and clipping ranges. + * + * %ImageSelections defines a rectangular area, a channel range, and an anchor + * point that can be used as a selection for 2D images. + * + * This structure also defines a clipping range in the normalized [0,1] range. + * Range clipping is used for calculation of statistics such as mean, median, + * standard deviation, average and median deviations, etc. + */ +struct PCL_CLASS ImageSelections +{ + int channel = 0; //!< First selected channel + int lastChannel = 0; //!< Last selected channel + Point point = 0; //!< Current anchor point + Rect rectangle = 0; //!< Current rectangular selection + double clipLow = 0.0; //!< Clipping range, lower bound + double clipHigh = 1.0; //!< Clipping range, upper bound + bool clippedLow = false; //!< Use range clipping, low pixels + bool clippedHigh = false; //!< Use range clipping, high pixels + + /*! + * Constructs a default %ImageSelections instance: + * + * \li Only the first channel selected: channel = lastChannel = 0. + * \li Empty rectangular selection: rectangle = Rect( 0 ). + * \li Anchor point at the origin of image coordinates: point = Point( 0 ). + * \li Clipping range lower bound = 0.0 + * \li Clipping range upper bound = 1.0 + * \li Range clipping disabled. + */ + ImageSelections() = default; + + /*! + * Copy constructor. + */ + ImageSelections( const ImageSelections& ) = default; + + /*! + * Assignment operator. Returns a reference to this object. + */ + ImageSelections& operator =( const ImageSelections& ) = default; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageSelections_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageSelections.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageStatistics.h b/3rdparty/include/pcl/ImageStatistics.h new file mode 100644 index 0000000..977d97b --- /dev/null +++ b/3rdparty/include/pcl/ImageStatistics.h @@ -0,0 +1,1000 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageStatistics.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_ImageStatistics_h +#define __PCL_ImageStatistics_h + +/// \file pcl/ImageStatistics.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageStatistics + * \brief Descriptive image statistics. + * + * %ImageStatistics provides basic descriptive statistics of pixel sample + * values: + * + * \li Pixel sample count. + * + * \li Arithmetic mean. + * + * \li Median. + * + * \li Variance and standard deviation from the mean. + * + * \li Sum of squared samples. + * + * \li Average deviation from the median. + * + * \li Median absolute deviation from the median (MAD). + * + * \li Biweight midvariance. + * + * \li Percentage bend midvariance. + * + * \li Sn and Qn scale estimators of Rousseeuw/Croux. + * + * \li Extreme pixel sample values: minimum and maximum, and the image + * coordinates of their first occurrences. + * + * All statistics can be enabled/disabled individually. + * + * %ImageStatistics works like a unidirectional image transformation, although + * it isn't actually a derived class of ImageTransformation. Example of use: + * + * \code + * Image image; + * // ... + * ImageStatistics S; + * S.DisableVariance(); // disable variance and sigma calculations + * image.SelectChannel( 2 ); // select the third channel of image + * image.SelectRectangle( 80, 100, 450, 600 ); // select a rectangular region + * S << image; // calculate image statistics for selected samples + * Console().WriteLn( String().Format( "\\The median is: %.5f", S.Median() ) ); + * \endcode + * + * %ImageStatistics calculates statistical values for the currently selected + * region and channel of its source image. + */ +class PCL_CLASS ImageStatistics : public ParallelProcess +{ +public: + + /*! + * \class pcl::ImageStatistics::Data + * \brief Statistical data in the normalized [0,1] range. + */ + struct PCL_CLASS Data + { + size_type count = 0; //!< Total number of evaluated samples. + double mean = 0; //!< Arithmetic mean. + double sumOfSquares = 0; //!< Sum of squared samples. + double median = 0; //!< Median sample value. + double variance = 0; //!< Variance from the mean. + double stdDev = 0; //!< Standard deviation (=Sqrt(variance)). + double avgDev = 0; //!< Average deviation from the median. + double MAD = 0; //!< Median absolute deviation from the median. + double bwmv = 0; //!< Biweight midvariance. + double pbmv = 0; //!< Percentage bend midvariance. + double Sn = 0; //!< Sn scale estimator of Rousseeuw and Croux. + double Qn = 0; //!< Qn scale estimator of Rousseeuw and Croux. + double minimum = 0; //!< Minimum sample value. + Point minPos = Point( 0 ); //!< Position of the minimum sample value. + double maximum = 0; //!< Maximum sample value. + Point maxPos = Point( 0 ); //!< Position of the maximum sample value. + double low = 0; //!< If rejectLow, ignore samples less than or equal to this value. + double high = 0; //!< If rejectHigh, ignore samples greater than or equal to this value. + bool rejectLow = false; //!< Ignore samples with values less than or equal to low. + bool rejectHigh = false; //!< Ignore samples with values greater than or equal to high. + bool noExtremes = false; //!< Do not compute minimum and maximum sample values. + bool noMean = false; //!< Do not compute the mean, variance, and standard deviation. + bool noSumOfSquares = false; //!< Do not compute the sum of squared samples. + bool noVariance = false; //!< Do not compute variance and standard deviation. + bool noMedian = false; //!< Do not compute median, average deviation, MAD, biweight and bend midvariances. + bool noAvgDev = false; //!< Do not compute average deviation. + bool noMAD = false; //!< Do not compute MAD. + bool noBWMV = false; //!< Do not compute biweight midvariance. + bool noPBMV = false; //!< Do not compute percentage bend midvariance. + bool noSn = true; //!< Do not compute Sn estimator of scale. + bool noQn = true; //!< Do not compute Qn estimator of scale. + + /*! + * Constructs a default %ImageStatistics::Data structure. + */ + Data() = default; + + /*! + * Copy constructor. + */ + Data( const Data& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Data& operator =( const Data& ) = default; + + /*! + * Copies all data items from another instance \a x. + */ + void Assign( const Data& x ) + { + (void)operator =( x ); + } + + /*! + * Copies only statistical data items from another instance \a x. Does + * not copy operating parameters (such as low, high, noVariance, etc.). + */ + void AssignStatisticalData( const Data& x ) + { + count = x.count; + mean = x.mean; + sumOfSquares = x.sumOfSquares; + median = x.median; + variance = x.variance; + stdDev = x.stdDev; + avgDev = x.avgDev; + MAD = x.MAD; + bwmv = x.bwmv; + pbmv = x.pbmv; + Sn = x.Sn; + Qn = x.Qn; + minimum = x.minimum; + minPos = x.minPos; + maximum = x.maximum; + maxPos = x.maxPos; + } + }; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an %ImageStatistics object. + */ + ImageStatistics() = default; + + /*! + * Copy constructor. + */ + ImageStatistics( const ImageStatistics& ) = default; + + /*! + * Destroys an %ImageStatistics object. + */ + virtual ~ImageStatistics() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ImageStatistics& operator =( const ImageStatistics& ) = default; + + /*! + * Copies other %ImageStatistics object \a x to this object. + */ + void Assign( const ImageStatistics& x ) + { + (void)operator =( x ); + } + + /*! + * Returns a constant reference to the statistical data in this object. + */ + const Data& GetData() const + { + return m_data; + } + + /*! + * Returns the total number of evaluated samples. + */ + size_type Count() const + { + return m_data.count; + } + + /*! + * Returns the arithmetic mean of the evaluated sample values in the + * normalized [0,1] range. + */ + double Mean() const + { + return m_data.mean; + } + + /*! + * Returns the sum of squares for the evaluated sample values. Samples are + * evaluated in the normalized [0,1] range. + */ + double SumOfSquares() const + { + return m_data.sumOfSquares; + } + + /*! + * Returns the median of the evaluated sample values in the normalized [0,1] + * range. + */ + double Median() const + { + return m_data.median; + } + + /*! + * Returns the variance from the mean of the evaluated sample valuess in the + * normalized [0,1] range. + */ + double Variance() const + { + return m_data.variance; + } + + /*! + * Returns the variance from the mean of the evaluated sample valuess in the + * normalized [0,1] range. + * + * This member function is a synonym for Variance(). + */ + double Var() const + { + return Variance(); + } + + /*! + * Returns the standard deviation from the mean of the evaluated sample + * values in the normalized [0,1] range. + */ + double StandardDeviation() const + { + return m_data.stdDev; + } + + /*! + * Returns the standard deviation from the mean of the evaluated sample + * values in the normalized [0,1] range. + * + * This member function is a synonym for StandardDeviation(). + */ + double StdDev() const + { + return StandardDeviation(); + } + + /*! + * Returns the average deviation from the median of the evaluated sample + * values in the normalized [0,1] range. + * + * The average deviation is an estimator of the variability of a + * distribution around its central value. In the case of a deep sky image, + * the average deviation provides a good estimation of the width of the + * main histogram peak. + */ + double AverageDeviation() const + { + return m_data.avgDev; + } + + /*! + * Returns the average deviation from the median of the evaluated sample + * values in the normalized [0,1] range. + * + * This member function is a synonym for AverageDeviation(). + */ + double AvgDev() const + { + return AverageDeviation(); + } + + /*! + * Returns the median absolute deviation from the median (MAD) of the + * evaluated sample values in the normalized [0,1] range. + * + * The MAD is a well-known robust estimator of dispersion. + */ + double MAD() const + { + return m_data.MAD; + } + + /*! + * Returns the biweight midvariance of the evaluated pixel sample values in + * the normalized [0,1] range. + * + * The square root of the biweight midvariance is a robust estimator of + * scale. It is an efficient estimator with respect to many statistical + * distributions (about 87% Gaussian efficiency), and appears to have a + * breakdown point close to 0.5 (the best possible breakdown). + */ + double BiweightMidvariance() const + { + return m_data.bwmv; + } + + /*! + * Returns the biweight midvariance of the evaluated pixel sample values in + * the normalized [0,1] range. + * + * This member function is a synonym for BiweightMidvariance(). + */ + double BWMV() const + { + return m_data.bwmv; + } + + /*! + * Returns the percentage bend midvariance of the evaluated pixel sample + * values in the normalized [0,1] range. + * + * The square root of the percentage bend midvariance is a robust estimator + * of scale. As implemented in %ImageStatistics (beta=0.2), its Gaussian + * efficiency is 67%. + */ + double BendMidvariance() const + { + return m_data.pbmv; + } + + /*! + * Returns the percentage bend midvariance of the evaluated pixel sample + * values in the normalized [0,1] range. + * + * This member function is a synonym for BendMidvariance(). + */ + double PBMV() const + { + return m_data.pbmv; + } + + /*! + * Returns the Sn scale estimator of Rousseeuw and Croux in the normalized + * [0,1] range. + * + * Sn is a robust estimator of scale (dispersion). It has the same outlier + * rejection properties as the MAD but its Gaussian efficiency is higher + * (58%; the efficiency of MAD is only 37%). Unlike the MAD, Sn does not + * measure variability around a central value, but between pairs of data + * points. This makes Sn a potentially better estimator for asymmetrical or + * skewed distributions. + */ + double Sn() const + { + return m_data.Sn; + } + + /*! + * Returns the Qn scale estimator of Rousseeuw and Croux in the normalized + * [0,1] range. + * + * Qn is a robust estimator of scale (dispersion). It has the same outlier + * rejection properties as the MAD, but its Gaussian efficiency is higher + * (87%; the efficiency of MAD is only 37%). Unlike the MAD, Qn does not + * measure variability around a central value, but between pairs of data + * points. This makes Qn a potentially better estimator for asymmetrical or + * skewed distributions. + */ + double Qn() const + { + return m_data.Qn; + } + + /*! + * Returns the minimum evaluated sample value in the normalized [0,1] range. + */ + double Minimum() const + { + return m_data.minimum; + } + + /*! + * Returns the minimum evaluated sample value in the normalized [0,1] range. + * + * This member function is a synonym for Maximum(). + */ + double Min() const + { + return Minimum(); + } + + /*! + * Returns the position (x,y coordinates) of the first occurrence of the + * minimum evaluated sample value. + */ + Point MinimumPosition() const + { + return m_data.minPos; + } + + /*! + * Returns the position (x,y coordinates) of the first occurrence of the + * minimum evaluated sample value. + * + * This member function is a synonym for MinimumPosition(). + */ + Point MinPos() const + { + return MinimumPosition(); + } + + /*! + * Returns the maximum evaluated sample value in the normalized [0,1] range. + */ + double Maximum() const + { + return m_data.maximum; + } + + /*! + * Returns the maximum evaluated sample value in the normalized [0,1] range. + * + * This member function is a synonym for Maximum(). + */ + double Max() const + { + return Maximum(); + } + + /*! + * Returns the position (x,y coordinates) of the first occurrence of the + * maximum evaluated sample value. + */ + Point MaximumPosition() const + { + return m_data.maxPos; + } + + /*! + * Returns the position (x,y coordinates) of the first occurrence of the + * maximum evaluated sample value. + * + * This member function is a synonym for MaximumPosition(). + */ + Point MaxPos() const + { + return MaximumPosition(); + } + + /*! + * Returns the low sample rejection limit in the [0,1] range. + * + * When low sample rejection is enabled, sample values less than or equal to + * the value returned by this function will be ignored during statistics + * calculation. + */ + double RejectionLow() const + { + return m_data.low; + } + + /*! + * Returns the high sample rejection limit in the [0,1] range. + * + * When high sample rejection is enabled, sample values greater than or + * equal to the value returned by this function will be ignored during + * statistics calculation. + */ + double RejectionHigh() const + { + return m_data.high; + } + + /*! + * Sets the \a low and \a high rejection limits in the [0,1] range. + * + * When sample rejection is enabled, sample values inside the ranges [0,low] + * and [high,1] will be ignored during statistics calculation. + */ + void SetRejectionLimits( double low, double high ) + { + m_data.low = Range( low, 0.0, 1.0 ); + m_data.high = Range( high, 0.0, 1.0 ); + if ( m_data.high < m_data.low ) + pcl::Swap( m_data.low, m_data.high ); + } + + /*! + * Returns true iff low sample rejection is enabled in this %ImageStatistics + * object. + * + * When low sample rejection is enabled, sample values less than or equal to + * the low sample rejection limit will be ignored during statistics + * calculation. + */ + bool IsLowRejectionEnabled() const + { + return m_data.rejectLow; + } + + /*! + * Returns true iff high sample rejection is enabled in this %ImageStatistics + * object. + * + * When high sample rejection is enabled, sample values greater than or + * equal to the high sample rejection limit will be ignored during + * statistics calculation. + */ + bool IsHighRejectionEnabled() const + { + return m_data.rejectHigh; + } + + /*! + * Enables low and/or high sample rejections. + * + * When sample rejection is enabled, sample values inside the ranges [0,low] + * and [high,1] will be ignored during statistics calculation (where low and + * high are the current low and high rejection limits). + */ + void EnableRejection( bool enableLow = true, bool enableHigh = true ) + { + m_data.rejectLow = enableLow; + m_data.rejectHigh = enableHigh; + } + + /*! + * Disables low and/or high sample rejection. + * + * This is a convenience member function, equivalent to + * EnableRejection( !disableLow, !disableHigh ). + */ + void DisableRejection( bool disableLow = true, bool disableHigh = true ) + { + EnableRejection( !disableLow, !disableHigh ); + } + + /*! + * Returns true iff calculation of extreme pixel sample values is currently + * enabled for this instance of %ImageStatistics. + */ + bool IsExtremesEnabled() const + { + return !m_data.noExtremes; + } + + /*! + * Enables calculation of extreme pixel sample values for this + * %ImageStatistics object. + */ + void EnableExtremes( bool enable = true ) + { + m_data.noExtremes = !enable; + } + + /*! + * Disables calculation of extreme pixel sample values for this + * %ImageStatistics object. + */ + void DisableExtremes( bool disable = true ) + { + m_data.noExtremes = disable; + } + + /*! + * Returns true iff calculation of the arithmetic mean is currently enabled + * for this instance of %ImageStatistics. + * + * When arithmetic mean calculation is disabled, the variance (and hence the + * standard deviation) is also disabled implicitly. + */ + bool IsMeanEnabled() const + { + return !m_data.noMean; + } + + /*! + * Enables calculation of the arithmetic mean for this %ImageStatistics + * object. + * + * When arithmetic mean calculation is disabled, the variance (and hence the + * standard deviation) is also disabled implicitly. + */ + void EnableMean( bool enable = true ) + { + m_data.noMean = !enable; + } + + /*! + * Disables calculation of the arithmetic mean for this %ImageStatistics + * object. + * + * When arithmetic mean calculation is disabled, the variance (and hence the + * standard deviation) is also disabled implicitly. + */ + void DisableMean( bool disable = true ) + { + m_data.noMean = disable; + } + + /*! + * Returns true iff calculation of the sum of squares is currently enabled + * for this instance of %ImageStatistics. + */ + bool IsSumOfSquaresEnabled() const + { + return !m_data.noSumOfSquares; + } + + /*! + * Enables calculation of the sum of squares for this object. + */ + void EnableSumOfSquares( bool enable = true ) + { + m_data.noSumOfSquares = !enable; + } + + /*! + * Disables calculation of the sum of squares for this object. + */ + void DisableSumOfSquares( bool disable = true ) + { + m_data.noSumOfSquares = disable; + } + + /*! + * Returns true iff calculation of the variance is currently enabled for + * this instance of %ImageStatistics. + */ + bool IsVarianceEnabled() const + { + return !m_data.noVariance; + } + + /*! + * Enables calculation of the variance for this %ImageStatistics object. + */ + void EnableVariance( bool enable = true ) + { + m_data.noVariance = !enable; + } + + /*! + * Disables calculation of the variance for this %ImageStatistics object. + */ + void DisableVariance( bool disable = true ) + { + m_data.noVariance = disable; + } + + /*! + * Returns true iff calculation of the median is currently enabled for this + * instance of %ImageStatistics. + * + * When median calculation is disabled, the average deviation, MAD and + * biweight midvariance estimators are also disabled implicitly. + */ + bool IsMedianEnabled() const + { + return !m_data.noMedian; + } + + /*! + * Enables calculation of the median for this %ImageStatistics object. + * + * When median calculation is disabled, the average deviation, MAD, biweight + * midvariance and bend midvariance estimators are also disabled implicitly. + */ + void EnableMedian( bool enable = true ) + { + m_data.noMedian = !enable; + } + + /*! + * Disables calculation of the median for this %ImageStatistics object. + * + * When median calculation is disabled, the average deviation, MAD, biweight + * midvariance and bend midvariance estimators are also disabled implicitly. + */ + void DisableMedian( bool disable = true ) + { + m_data.noMedian = disable; + } + + /*! + * Returns true iff calculation of the average deviation from the median is + * currently enabled for this instance of %ImageStatistics. + */ + bool IsAvgDevEnabled() const + { + return !m_data.noAvgDev; + } + + /*! + * Enables calculation of the average deviation from the median for this + * %ImageStatistics object. + */ + void EnableAvgDev( bool enable = true ) + { + m_data.noAvgDev = !enable; + } + + /*! + * Disables calculation of the average deviation from the median for this + * %ImageStatistics object. + */ + void DisableAvgDev( bool disable = true ) + { + m_data.noAvgDev = disable; + } + + /*! + * Returns true iff calculation of the median deviation from the median (MAD) + * is currently enabled for this instance of %ImageStatistics. + * + * When MAD calculation is disabled, the biweight midvariance estimator is + * also disabled implicitly. + */ + bool IsMADEnabled() const + { + return !m_data.noMAD; + } + + /*! + * Enables calculation of the median deviation from the median (MAD) for + * this %ImageStatistics object. + * + * When MAD calculation is disabled, the biweight midvariance estimator is + * also disabled implicitly. + */ + void EnableMAD( bool enable = true ) + { + m_data.noMAD = !enable; + } + + /*! + * Disables calculation of the median deviation from the median (MAD) for + * this %ImageStatistics object. + * + * When MAD calculation is disabled, the biweight midvariance estimator is + * also disabled implicitly. + */ + void DisableMAD( bool disable = true ) + { + m_data.noMAD = disable; + } + + /*! + * Returns true iff calculation of the biweight midvariance (BWMV) is + * currently enabled for this instance of %ImageStatistics. + */ + bool IsBWMVEnabled() const + { + return !m_data.noBWMV; + } + + /*! + * Enables calculation of the biweight midvariance (BWMV) for this + * %ImageStatistics object. + */ + void EnableBWMV( bool enable = true ) + { + m_data.noBWMV = !enable; + } + + /*! + * Disables calculation of the biweight midvariance (BWMV) for this + * %ImageStatistics object. + */ + void DisableBWMV( bool disable = true ) + { + m_data.noBWMV = disable; + } + + /*! + * Returns true iff calculation of the percentage bend midvariance (PBMV) is + * currently enabled for this instance of %ImageStatistics. + */ + bool IsPBMVEnabled() const + { + return !m_data.noPBMV; + } + + /*! + * Enables calculation of the percentage bend midvariance (PBMV) for this + * %ImageStatistics object. + */ + void EnablePBMV( bool enable = true ) + { + m_data.noPBMV = !enable; + } + + /*! + * Disables calculation of the percentage bend midvariance (PBMV) for this + * %ImageStatistics object. + */ + void DisablePBMV( bool disable = true ) + { + m_data.noPBMV = disable; + } + + /*! + * Returns true iff calculation of the Rousseeuw/Croux Sn estimator of scale + * is currently enabled for this instance of %ImageStatistics. + * + * \note The Sn estimator is disabled by default. + */ + bool IsSnEnabled() const + { + return !m_data.noSn; + } + + /*! + * Enables calculation of the Rousseeuw/Croux Sn estimator of scale for + * this %ImageStatistics object. + * + * \note The Sn estimator is disabled by default. + */ + void EnableSn( bool enable = true ) + { + m_data.noSn = !enable; + } + + /*! + * Disables calculation of the Rousseeuw/Croux Sn estimator of scale for + * this %ImageStatistics object. + * + * \note The Sn estimator is disabled by default. + */ + void DisableSn( bool disable = true ) + { + m_data.noSn = disable; + } + + /*! + * Returns true iff calculation of the Rousseeuw/Croux Qn estimator of scale + * is currently enabled for this instance of %ImageStatistics. + * + * \note The Qn estimator is disabled by default. + */ + bool IsQnEnabled() const + { + return !m_data.noQn; + } + + /*! + * Enables calculation of the Rousseeuw/Croux Qn estimator of scale for + * this %ImageStatistics object. + * + * \note The Qn estimator is disabled by default. + */ + void EnableQn( bool enable = true ) + { + m_data.noQn = !enable; + } + + /*! + * Disables calculation of the Rousseeuw/Croux Qn estimator of scale for + * this %ImageStatistics object. + * + * \note The Qn estimator is disabled by default. + */ + void DisableQn( bool disable = true ) + { + m_data.noQn = disable; + } + + /*! + * Calculates statistical data for a 32-bit floating point image. Returns a + * reference to the source \a image. + */ + const Image& operator <<( const Image& image ); + + /*! + * Calculates statistical data for a 64-bit floating point image. Returns a + * reference to the source \a image. + */ + const DImage& operator <<( const DImage& image ); + + /*! + * Calculates statistical data for an 8-bit unsigned integer image. Returns + * a reference to the source \a image. + */ + const UInt8Image& operator <<( const UInt8Image& image ); + + /*! + * Calculates statistical data for a 16-bit unsigned integer image. Returns + * a reference to the source \a image. + */ + const UInt16Image& operator <<( const UInt16Image& image ); + + /*! + * Calculates statistical data for a 32-bit unsigned integer image. Returns + * a reference to the source \a image. + */ + const UInt32Image& operator <<( const UInt32Image& image ); + + /*! + * Calculates statistical data for an image transported by an ImageVariant + * instance. Returns a reference to the source \a image. + */ + const ImageVariant& operator <<( const ImageVariant& image ) + { + if ( image ) + if ( !image.IsComplexSample() ) + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: *this << static_cast( *image ); break; + case 64: *this << static_cast( *image ); break; + } + else + switch ( image.BitsPerSample() ) + { + case 8: *this << static_cast( *image ); break; + case 16: *this << static_cast( *image ); break; + case 32: *this << static_cast( *image ); break; + } + return image; + } + +protected: + + Data m_data; // statistical data + + friend class View; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageStatistics_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageStatistics.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageTransformation.h b/3rdparty/include/pcl/ImageTransformation.h new file mode 100644 index 0000000..693b034 --- /dev/null +++ b/3rdparty/include/pcl/ImageTransformation.h @@ -0,0 +1,436 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageTransformation.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_ImageTransformation_h +#define __PCL_ImageTransformation_h + +/// \file pcl/ImageTransformation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageTransformation + * \brief Root base class of all PCL image transformations. + * + * %ImageTransformation represents a generic transformation that can be applied + * to any image type defined in PCL. + * + * %ImageTransformation is a base class for all PCL image transformations, + * including both unidirectional (single-step) and bidirectional (invertible, + * two-step) transformations. + * + * For single-step processes, %ImageTransformation represents a direct + * transformation that applies to a target image. + * + * Two-step invertible processes are derived classes of + * BidirectionalImageTransformation in PCL. For these processes + * %ImageTransformation represents an inverse transformation that + * applies to a target image after a previous direct transformation, + * usually performed by the same class. + * + * \sa BidirectionalImageTransformation + */ +class PCL_CLASS ImageTransformation +{ +public: + + /*! + * Constructs a default %ImageTransformation object. + */ + ImageTransformation() = default; + + /*! + * Copy constructor. + */ + ImageTransformation( const ImageTransformation& ) = default; + + /*! + * Destroys an %ImageTransformation object. + */ + virtual ~ImageTransformation() + { + } + + /*! + * Applies this transformation to a target \a image. Returns a reference to + * the target image. + * + * If this is a bidirectional transformation, then this function represents + * an inverse transformation requiring a previous direct + * transformation, usually performed by the same class. + */ + template + GenericImage

& operator >>( GenericImage

& image ) const + { + Apply( image ); + return image; + } + + /*! + * Applies this transformation to the current selection in a target \a image + * transported by the specified ImageVariant object. Returns a reference to + * the target %ImageVariant. + * + * If this is a bidirectional transformation, then this function represents + * an inverse transformation requiring a previous direct + * transformation, usually performed by the same class. + * + * \sa BidirectionalImageTransformation + */ + ImageVariant& operator >>( ImageVariant& image ) const + { + if ( image ) + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: Apply( static_cast( *image ) ); break; + case 64: Apply( static_cast( *image ) ); break; + } + else if ( image.IsComplexSample() ) + switch ( image.BitsPerSample() ) + { + case 32: Apply( static_cast( *image ) ); break; + case 64: Apply( static_cast( *image ) ); break; + } + else + switch ( image.BitsPerSample() ) + { + case 8: Apply( static_cast( *image ) ); break; + case 16: Apply( static_cast( *image ) ); break; + case 32: Apply( static_cast( *image ) ); break; + } + return image; + } + +protected: + + /*! + * Applies this transformation to a 32-bit floating point \a image. + */ + virtual void Apply( pcl::Image& image ) const + { + throw NotImplemented( *this, "Apply to 32-bit floating-point images" ); + } + + /*! + * Applies this transformation to a 64-bit floating point \a image. + */ + virtual void Apply( pcl::DImage& image ) const + { + throw NotImplemented( *this, "Apply to 64-bit floating-point images" ); + } + + /*! + * Applies this transformation to a 32-bit complex \a image. + */ + virtual void Apply( pcl::ComplexImage& image ) const + { + throw NotImplemented( *this, "Apply to 32-bit complex images" ); + } + + /*! + * Applies this transformation to a 64-bit complex \a image. + */ + virtual void Apply( pcl::DComplexImage& image ) const + { + throw NotImplemented( *this, "Apply to 64-bit complex images" ); + } + + /*! + * Applies this transformation to an 8-bit unsigned integer \a image. + */ + virtual void Apply( pcl::UInt8Image& image ) const + { + throw NotImplemented( *this, "Apply to 8-bit integer images" ); + } + + /*! + * Applies this transformation to a 16-bit unsigned integer \a image. + */ + virtual void Apply( pcl::UInt16Image& image ) const + { + throw NotImplemented( *this, "Apply to 16-bit integer images" ); + } + + /*! + * Applies this transformation to a 32-bit unsigned integer \a image. + */ + virtual void Apply( pcl::UInt32Image& image ) const + { + throw NotImplemented( *this, "Apply to 32-bit integer images" ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BidirectionalImageTransformation + * \brief Root base class for bidirectional PCL image transformations. + * + * %BidirectionalImageTransformation represents a two-step, invertible process + * that can be applied to any image type defined in PCL. + * + * Two-step invertible processes can perform an inverse transformation + * after a previous direct transformation. The inverse transformation + * functionality is provided by the ImageTransformation base class. + * + * \sa ImageTransformation + */ +class PCL_CLASS BidirectionalImageTransformation : public ImageTransformation +{ +public: + + /*! + * Constructs a default %BidirectionalImageTransformation object + */ + BidirectionalImageTransformation() = default; + + /*! + * Copy constructor. + */ + BidirectionalImageTransformation( const BidirectionalImageTransformation& ) = default; + + /*! + * Destroys a %BidirectionalImageTransformation object. + */ + virtual ~BidirectionalImageTransformation() + { + } + + /*! + * Applies this transformation to the current selection in a target + * \a image. Returns a reference to the target image. + * + * This function represents a direct transformation applied to the + * target image. An inverse transformation is performed by the + * operator >>( const GenericImage& ) member function, inherited from + * ImageTransformation. + */ + template + const GenericImage

& operator <<( const GenericImage

& image ) + { + Transform( image ); + return image; + } + + /*! + * Applies this transformation to the current selection in a target \a image + * transported by the specified ImageVariant object. Returns a reference to + * the target %ImageVariant. + * + * This function represents a direct transformation applied to the + * target image. An inverse transformation is performed by the + * operator >>( const ImageVariant& ) member function, inherited from + * ImageTransformation. + */ + const ImageVariant& operator <<( const ImageVariant& image ) + { + if ( image ) + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: Transform( static_cast( *image ) ); break; + case 64: Transform( static_cast( *image ) ); break; + } + else if ( image.IsComplexSample() ) + switch ( image.BitsPerSample() ) + { + case 32: Transform( static_cast( *image ) ); break; + case 64: Transform( static_cast( *image ) ); break; + } + else + switch ( image.BitsPerSample() ) + { + case 8: Transform( static_cast( *image ) ); break; + case 16: Transform( static_cast( *image ) ); break; + case 32: Transform( static_cast( *image ) ); break; + } + return image; + } + +protected: + + /*! + * Transforms a 32-bit floating point \a image. + */ + virtual void Transform( const pcl::Image& image ) + { + throw NotImplemented( *this, "Transformation of 32-bit floating-point images" ); + } + + /*! + * Transforms a 64-bit floating point \a image. + */ + virtual void Transform( const pcl::DImage& image ) + { + throw NotImplemented( *this, "Transformation of 64-bit floating-point images" ); + } + + /*! + * Transforms a 32-bit complex \a image. + */ + virtual void Transform( const pcl::ComplexImage& image ) + { + throw NotImplemented( *this, "Transformation of 32-bit complex images" ); + } + + /*! + * Transforms a 64-bit complex \a image. + */ + virtual void Transform( const pcl::DComplexImage& image ) + { + throw NotImplemented( *this, "Transformation of 64-bit complex images" ); + } + + /*! + * Transforms an 8-bit unsigned integer \a image. + */ + virtual void Transform( const pcl::UInt8Image& image ) + { + throw NotImplemented( *this, "Transformation of 8-bit integer images" ); + } + + /*! + * Transforms a 16-bit unsigned integer \a image. + */ + virtual void Transform( const pcl::UInt16Image& image ) + { + throw NotImplemented( *this, "Transformation of 16-bit integer images" ); + } + + /*! + * Transforms a 32-bit unsigned integer \a image. + */ + virtual void Transform( const pcl::UInt32Image& image ) + { + throw NotImplemented( *this, "Transformation of 32-bit integer images" ); + } +}; + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +/* + * Implementation of members of GenericImage<> requiring a complete declaration + * of ImageTransformation. + */ + +// ---------------------------------------------------------------------------- + +template inline +GenericImage

& GenericImage

::Apply( const ImageTransformation& transformation, + const Rect& rect, int firstChannel, int lastChannel ) +{ + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return *this; + + PushSelections(); + SelectRectangle( r ); + SelectChannelRange( firstChannel, lastChannel ); + + try + { + transformation >> *this; + PopSelections(); + } + catch ( ... ) + { + PopSelections(); + throw; + } + + return *this; +} + +// ---------------------------------------------------------------------------- + +template inline +void GenericImage

::Transform( BidirectionalImageTransformation& transform, + const Rect& rect, int firstChannel, int lastChannel ) const +{ + Rect r = rect; + if ( !ParseSelection( r, firstChannel, lastChannel ) ) + return; + + PushSelections(); + SelectRectangle( r ); + SelectChannelRange( firstChannel, lastChannel ); + + try + { + transform << *this; + PopSelections(); + } + catch ( ... ) + { + PopSelections(); + throw; + } +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageVariant.h b/3rdparty/include/pcl/ImageVariant.h new file mode 100644 index 0000000..74c6a37 --- /dev/null +++ b/3rdparty/include/pcl/ImageVariant.h @@ -0,0 +1,7277 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageVariant.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_ImageVariant_h +#define __PCL_ImageVariant_h + +/// \file pcl/ImageVariant.h + +#include + +#include +#include + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +namespace pi +{ + class SharedImage; +} +#endif + +#define SOLVE_TEMPLATE( F ) \ + if ( IsComplexSample() ) \ + switch ( BitsPerSample() ) \ + { \ + case 32: F( ComplexImage ); break; \ + case 64: F( DComplexImage ); break; \ + } \ + else if ( IsFloatSample() ) \ + switch ( BitsPerSample() ) \ + { \ + case 32: F( Image ); break; \ + case 64: F( DImage ); break; \ + } \ + else \ + switch ( BitsPerSample() ) \ + { \ + case 8: F( UInt8Image ); break; \ + case 16: F( UInt16Image ); break; \ + case 32: F( UInt32Image ); break; \ + } + +#define SOLVE_TEMPLATE_2( I, F ) \ + if ( I.IsComplexSample() ) \ + switch ( I.BitsPerSample() ) \ + { \ + case 32: F( ComplexImage ); break; \ + case 64: F( DComplexImage ); break; \ + } \ + else if ( I.IsFloatSample() ) \ + switch ( I.BitsPerSample() ) \ + { \ + case 32: F( Image ); break; \ + case 64: F( DImage ); break; \ + } \ + else \ + switch ( I.BitsPerSample() ) \ + { \ + case 8: F( UInt8Image ); break; \ + case 16: F( UInt16Image ); break; \ + case 32: F( UInt32Image ); break; \ + } + +#define SOLVE_TEMPLATE_REAL( F ) \ + if ( IsFloatSample() ) \ + switch ( BitsPerSample() ) \ + { \ + case 32: F( Image ); break; \ + case 64: F( DImage ); break; \ + } \ + else \ + switch ( BitsPerSample() ) \ + { \ + case 8: F( UInt8Image ); break; \ + case 16: F( UInt16Image ); break; \ + case 32: F( UInt32Image ); break; \ + } + +#define SOLVE_TEMPLATE_REAL_2( I, F ) \ + if ( I.IsFloatSample() ) \ + switch ( I.BitsPerSample() ) \ + { \ + case 32: F( Image ); break; \ + case 64: F( DImage ); break; \ + } \ + else \ + switch ( I.BitsPerSample() ) \ + { \ + case 8: F( UInt8Image ); break; \ + case 16: F( UInt16Image ); break; \ + case 32: F( UInt32Image ); break; \ + } + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::SwapCompression + * \brief Compression algorithms for raw image file generation. + * + * This namespace enumerates the compression algorithms supported by the + * ImageVariant::WriteSwapFile() and ImageVariant::WriteSwapFiles() functions. + * + * Supported compression algorithms: + * + * + * + * + * + * + * + * + * + *
SwapCompression::None Do not use compression.
SwapCompression::ZLib ZLib (deflate) compression.
SwapCompression::ZLib_SH ZLib (deflate) compression with byte shuffling.
SwapCompression::LZ4 LZ4 fast compression.
SwapCompression::LZ4_Sh LZ4 fast compression with byte shuffling.
SwapCompression::LZ4HC LZ4-HC compression.
SwapCompression::LZ4HC_Sh LZ4-HC compression with byte shuffling.
+ */ +namespace SwapCompression +{ + enum value_type + { + None, // Do not use compression. + ZLib, // ZLib (deflate) compression. + ZLib_SH, // ZLib (deflate) compression with byte shuffling. + LZ4, // LZ4 fast compression. + LZ4_Sh, // LZ4 fast compression with byte shuffling. + LZ4HC, // LZ4-HC compression. + LZ4HC_Sh, // LZ4-HC compression with byte shuffling. + + NumberOfAlgorithms + }; +} + +/*! + * \class ImageVariant + * \brief Acts like a union for all types of images in PCL, with optional + * class-wide ownership of transported images. + * + * An instance of %ImageVariant owns a pointer to AbstractImage. That allows it + * to transport and manage all template instantiations of GenericImage + * transparently with a unique abstract interface: Image, ComplexImage, + * UInt16Image, and so on. + * + * + * Image Template Instantiation Resolution + * + * %ImageVariant provides functionality to identify the particular data type + * that the transported image uses to represent its pixel samples. Once we know + * the pixel data type, we can resolve the template instantiation of + * GenericImage, which in turn gives us access to the whole data and + * functionality of the transported image. The following code snippet shows a + * typical example of template resolution with %ImageVariant: + * + * \code + * ImageVariant image; + * // ... + * if ( image ) // if the ImageVariant transports a valid image + * { + * if ( image.IsComplexImage() ) + * throw Error( "Complex images are not supported in DoSomething()" ); + * if ( image.IsFloatSample() ) + * switch ( image.BitsPerSample() ) + * { + * case 32 : DoSomething( static_cast( *image ) ); break; + * case 64 : DoSomething( static_cast( *image ) ); break; + * } + * else + * switch ( image.BitsPerSample() ) + * { + * case 8 : DoSomething( static_cast( *image ) ); break; + * case 16 : DoSomething( static_cast( *image ) ); break; + * case 32 : DoSomething( static_cast( *image ) ); break; + * } + * } + * \endcode + * + * In this code, \c DoSomething is a template function to deal with an image of + * a particular pixel sample type. In the code above, all standard PCL images + * are supported except complex images. For example, \c DoSomething could be + * like this function: + * + * \code + * template void DoSomething( GenericImage

& image ) + * { + * image.ShiftToCenter( image.Width()+20, image.Height()+20 ); + * } + * \endcode + * + * This \c DoSomething function adds a 10-pixel black frame around the passed + * \a image. + * + * + * Generalized Image Manipulation + * + * Besides identifying image template instantiations, %ImageVariant provides + * generalized wrappers for most of the member functions of GenericImage. This + * allows you to work with an instance of %ImageVariant just as if it were its + * transported image, without even knowing its pixel data type in most cases. + * The example we have seen above could be implemented in a much simpler way as + * follows: + * + * \code + * void DoSomething( ImageVariant& image ) + * { + * if ( image ) + * { + * if ( image.IsComplexImage() ) + * throw Error( "Complex images are not supported in DoSomething()" ); + * image.ShiftToCenter( image.Width()+20, image.Height()+20 ); + * } + * } + * \endcode + * + * The above code works because %ImageVariant defines a \c ShiftToCenter member + * function as a wrapper to GenericImage::ShiftToCenter(), with implicit + * template instantiation resolution. As we have said, virtually all of + * GenericImage's functionality can be used transparently in a type-independent + * way through %ImageVariant. + * + * + * Image Ownership + * + * Transported images can optionally be owned by %ImageVariant. When + * %ImageVariant owns a transported image, the image is destroyed when all + * instances of %ImageVariant referencing that image are destroyed. It is + * important to know that ownership of transported images is a class-wide + * property of %ImageVariant, not a private property of any particular + * %ImageVariant instance. + * + * Class-wide ownership means that an image is not owned only by a particular + * instance of %ImageVariant, but by \e all existing instances that transport + * the same image. Consider the following code snippets: + * + * \code + * Image image; + * ImageVariant var( &image ); // ImageVariant does not own image + * \endcode + * + * In this first case, we have an image and create an %ImageVariant object to + * transport it. When the \c var object gets out of scope, \c image will + * continue existing and won't be destroyed. + * + * \code + * ImageVariant var; + * var.CreateFloatImage(); // ImageVariant owns a newly created image + * \endcode + * + * In this case, we have an %ImageVariant object and tell it to create a new + * image (a 32-bit floating point image in the example). The newly created + * image will be transported by \c var and is now owned by %ImageVariant. when + * the last instance of %ImageVariant transporting the image is destroyed, the + * image will also be destroyed automatically. + * + * You can also switch on and off %ImageVariant's ownership: + * + * \code + * Image* image = new Image; + * ImageVariant var( image ); + * var.SetOwnership( true ); // now ImageVariant owns image + * \endcode + * + * %ImageVariant implements an \e explicit data sharing mechanism, which makes + * it different from the \e implicit data sharing implemented by rest of + * container classes in PCL. It is important to state clearly that ownership of + * image data is not a property of any particular object in this case, but of + * the whole %ImageVariant class. + * + * \sa AbstractImage, GenericImage + */ +class PCL_CLASS ImageVariant +{ +public: + + /*! + * An enumerated type that represents the set of supported color spaces. + * Valid constants for this enumeration are defined in the ColorSpace + * namespace. + */ + typedef AbstractImage::color_space color_space; + + /*! + * An enumerated type that represents the set of supported arithmetic and + * bitwise pixel operations. Valid constants for this enumeration are + * defined in the ImageOp namespace. + */ + typedef ImageOp::value_type image_op; + + /* + * An enumerated type that represents a compression algorithm for raw + * storage file generation. Valid constants for this enumeration are defined + * in the SwapCompression namespace. + */ + typedef SwapCompression::value_type swap_compression; + + /*! + * Constructs an empty %ImageVariant. An empty %ImageVariant instance does + * not transport an image. + */ + ImageVariant() + { + m_data = new Data; + } + + /*! + * Constructs an %ImageVariant instance to transport the specified \a image. + * + * By default, the transported image is not owned by %ImageVariant object. + * To cause %ImageVariant to own the transported image, the SetOwnership() + * member function must be called explicitly. + */ + template + ImageVariant( GenericImage

* image ) + { + m_data = new Data; + m_data->Update( image ); + } + + /*! + * Copy constructor. Constructs an %ImageVariant instance as an alias of an + * existing %ImageVariant object. + * + * This constructor simply increments the reference counter of the + * transported image. When all references to a transported image are + * removed, and the transported image is owned by %ImageVariant, it is + * destroyed and deallocated. + */ + ImageVariant( const ImageVariant& image ) + : m_data( image.m_data ) + { + m_data->Attach(); + } + + /*! + * Move constructor. + */ + ImageVariant( ImageVariant&& image ) + : m_data( image.m_data ) + { + image.m_data = nullptr; + } + + /*! + * Destroys an %ImageVariant instance. + * + * If the transported image exists and is owned by %ImageVariant, and there + * are no more %ImageVariant references to it, then it is also destroyed. + */ + virtual ~ImageVariant() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + /*! + * Returns a pointer to the unmodifiable image transported by this + * %ImageVariant object. + */ + const AbstractImage* ImagePtr() const noexcept + { + return m_data->image; + } + + /*! + * Returns a pointer to the image transported by this %ImageVariant object. + */ + AbstractImage* ImagePtr() noexcept + { + return m_data->image; + } + + /*! + * Returns true iff this %ImageVariant transports the same image as another + * \a image. + * + * This member function also returns true if \e both objects transport no + * image. + */ + bool IsSameImage( const ImageVariant& image ) const noexcept + { + return m_data->image == image.m_data->image; + } + + /*! + * Returns true iff this %ImageVariant instance transports a floating point + * image. + */ + bool IsFloatSample() const noexcept + { + return m_data->isFloatSample; + } + + /*! + * Returns true iff this %ImageVariant instance transports a complex image. + */ + bool IsComplexSample() const noexcept + { + return m_data->isComplexSample; + } + + /*! + * Returns the number of bits per sample of the image transported by this + * %ImageVariant object, or zero if it transports no image. + */ + int BitsPerSample() const noexcept + { + return m_data->bitsPerSample; + } + + /*! + * Returns the number of 8-bit bytes per sample of the image transported by + * this %ImageVariant, or zero if this object transports no image. + */ + int BytesPerSample() const noexcept + { + return m_data->bitsPerSample >> 3; + } + + /*! + * Returns the width in pixels of the image transported by this + * %ImageVariant, or zero if this object transports no image. + */ + int Width() const noexcept + { + return m_data->image ? m_data->image->Width() : 0; + } + + /*! + * Returns the height in pixels of the image transported by this + * %ImageVariant, or zero if this object transports no image. + */ + int Height() const noexcept + { + return m_data->image ? m_data->image->Height() : 0; + } + + /*! + * Returns the number of pixels in the image transported by this + * %ImageVariant, or zero if this object transports no image. + * + * The returned value is equal to Width()*Height(). + */ + size_type NumberOfPixels() const noexcept + { + return m_data->image ? m_data->image->NumberOfPixels() : 0; + } + + /*! + * Returns the total number of channels in the image transported by this + * %ImageVariant, or zero if this object transports no image. + */ + int NumberOfChannels() const noexcept + { + return m_data->image ? m_data->image->NumberOfChannels() : 0; + } + + /*! + * Returns the index of the last existing channel in this image. This is the + * largest valid channel index that can be used with this image, + * corresponding to a nominal or alpha channel. If the image transported by + * this object is empty, or if this object does not transport an image, this + * function returns -1. + */ + int LastChannel() const noexcept + { + return m_data->image ? m_data->image->LastChannel() : -1; + } + + /*! + * Returns true iff the specified channel index \a c is valid. A valid + * channel index corresponds to an existing channel in this image. Returns + * false if this object does not transport an image. + */ + bool IsValidChannelIndex( int c ) const noexcept + { + return m_data->image && m_data->image->IsValidChannelIndex( c ); + } + + /*! + * Returns the number of nominal channels in the image transported by this + * %ImageVariant, or zero if this object transports no image. + * + * Nominal channels are those defined by the color space of the image: One + * channel for monochrome grayscale images, and three channels for RGB color + * images. Additional channels are known as alpha channels. + */ + int NumberOfNominalChannels() const noexcept + { + return m_data->image ? m_data->image->NumberOfNominalChannels() : 0; + } + + /*! + * Returns true iff this %ImageVariant object transports an image with one or + * more alpha channels. + * + * Alpha channels are those in excess of the nominal channels corresponding + * to the color space of the image; for example, a second channel in a + * grayscale image, or a fourth channel in an RGB color image. + */ + bool HasAlphaChannels() const noexcept + { + return m_data->image && m_data->image->HasAlphaChannels(); + } + + /*! + * Returns the number of alpha channels in the image transported by this + * %ImageVariant, or zero if this object transports no image. + * + * Alpha channels are those in excess of the nominal channels corresponding + * to the color space of the image; for example, a second channel in a + * grayscale image, or a fourth channel in an RGB color image. + */ + int NumberOfAlphaChannels() const noexcept + { + return m_data->image ? m_data->image->NumberOfAlphaChannels() : 0; + } + + /*! + * Returns the total number of samples in the image transported by this + * %ImageVariant, or zero if this object does not transport an image. + * + * The number of samples is equal to NumberOfPixels()*NumberOfChannels(). + */ + size_type NumberOfSamples() const noexcept + { + return m_data->image ? m_data->image->NumberOfSamples() : 0; + } + + /*! + * Returns the total number of nominal samples in the image transported by + * this %ImageVariant, or zero if this object does not transport an image. + * + * The number of nominal samples is equal to + * NumberOfPixels()*NumberOfNominalChannels(). + */ + size_type NumberOfNominalSamples() const noexcept + { + return m_data->image ? m_data->image->NumberOfNominalSamples() : 0; + } + + /*! + * Returns the total number of alpha samples in the image transported by + * this %ImageVariant, or zero if this object does not transport an image. + * + * The number of alpha samples is equal to + * NumberOfPixels()*NumberOfAlphaChannels(). + */ + size_type NumberOfAlphaSamples() const noexcept + { + return m_data->image ? m_data->image->NumberOfAlphaSamples() : 0; + } + + /*! + * Returns the bounding rectangle of this image. + * + * The upper left corner of the returned rectangle (x0, y0) is always (0,0). + * The lower right corner coordinates (x1, y1) correspond to the width and + * height of the image. + * + * If this object transports no image, this function returns an empty + * rectangle. + */ + Rect Bounds() const noexcept + { + return m_data->image ? m_data->image->Bounds() : Rect( 0 ); + } + + /*! + * Returns true iff this image includes the specified point \a p in image + * coordinates. + * + * If this object transports no image, this function returns false. + */ + template + bool Includes( const GenericPoint& p ) const noexcept + { + return m_data->image && m_data->image->Includes( p ); + } + + /*! + * Returns true iff this image includes the specified rectangle \a r in image + * coordinates. + * + * If this object transports no image, this function returns false. + */ + template + bool Includes( const GenericRectangle& r ) const noexcept + { + return m_data->image && m_data->image->Includes( r ); + } + + /*! + * Returns true iff this image includes a rectangle given by its separate + * image coordinates. + * + * \param x0,y0 Upper left corner coordinates (horizontal, vertical). + * \param x1,y1 Lower right corner coordinates (horizontal, vertical). + * + * If this object transports no image, this function returns false. + */ + template + bool Includes( T x0, T y0, T x1, T y1 ) const noexcept + { + return m_data->image && m_data->image->Includes( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this image includes a point given by its separate image + * coordinates. + * + * \param x Horizontal coordinate. + * \param y Vertical coordinate. + * + * If this object transports no image, this function returns false. + */ + template + bool Includes( T x, T y ) const noexcept + { + return m_data->image && m_data->image->Includes( x, y ); + } + + /*! + * Returns true iff this image intersects with the specified rectangle \a r + * in image coordinates. + * + * If this object transports no image, this function returns false. + */ + template + bool Intersects( const pcl::GenericRectangle& r ) const noexcept + { + return m_data->image && m_data->image->Intersects( r ); + } + + /*! + * Returns true iff this image intersects with a rectangle given by its + * separate image coordinates. + * + * \param x0,y0 Upper left corner coordinates (horizontal, vertical). + * \param x1,y1 Lower right corner coordinates (horizontal, vertical). + * + * If this object transports no image, this function returns false. + */ + template + bool Intersects( T x0, T y0, T x1, T y1 ) const noexcept + { + return m_data->image && m_data->image->Intersects( x0, y0, x1, y1 ); + } + + /*! + * Constrains a point \a p to stay within the boundaries of this image. + * Returns true iff the original point location is included in this image. + * + * If this object transports no image, this function does nothing and + * returns false. + */ + template + bool Clip( pcl::GenericPoint& p ) const noexcept + { + return m_data->image && m_data->image->Clip( p ); + } + + /*! + * Constrains two point coordinates \a x and \a y to stay within the + * boundaries of this image. + * + * \param[out] x Horizontal coordinate of the clipped point. + * \param[out] y Vertical coordinate of the clipped point. + * + * Returns true iff the original point location is included in this image. + * + * If this object transports no image, this function does nothing and + * returns false. + */ + template + bool Clip( T& x, T& y ) const noexcept + { + return m_data->image && m_data->image->Clip( x, y ); + } + + /*! + * Constrains a rectangular region \a r in image coordinates to fit into the + * boundaries of this image. Also ensures coherence of clipped rectangular + * coordinates such that r.x0 ≤ r.x1 and r.y0 ≤ r.y1. + * + * Returns true iff the original rectangle intersects this image. + * + * If this object transports no image, this function does nothing and + * returns false. + */ + template + bool Clip( pcl::GenericRectangle& r ) const noexcept + { + return m_data->image && m_data->image->Clip( r ); + } + + /*! + * Constrains a rectangular region, given by its separate image coordinates, + * to fit into the boundaries of this image. Also ensures coherence of + * rectangular coordinates, such that x0 ≤ x1 and y0 ≤ y1. + * + * \param[out] x0,y0 Upper left corner coordinates (horizontal, vertical) + * of the rectangle that will be clipped. + * + * \param[out] x1,y1 Lower right corner coordinates (horizontal, vertical) + * of the rectangle that will be clipped. + * + * Returns true iff the original rectangle intersects the image. + * + * If this object transports no image, this function does nothing and + * returns false. + */ + template + bool Clip( T& x0, T& y0, T& x1, T& y1 ) const noexcept + { + return m_data->image && m_data->image->Clip( x0, y0, x1, y1 ); + } + + /*! + * Selects a single channel. + * + * \param c Channel index, 0 ≤ \a c < \a n, where \a n is the total + * number of channels in this image, including alpha channels. + */ + void SelectChannel( int c ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectChannel( c ); + } + + /*! + * Returns the index of the currently selected channel, or -1 if this object + * does not transport an image. + * + * If the current channel selection includes more than one channel, this + * function returns the index of the first selected channel. + * + * This function is a convenience synonym for FirstSelectedChannel(). + */ + int SelectedChannel() const noexcept + { + return m_data->image ? m_data->image->SelectedChannel() : -1; + } + + /*! + * Selects a range of channels by their channel indices. The selected range + * \e includes the two channels specified. + * + * \param c0 Index of the first channel to select. + * \param c1 Index of the last channel to select. + */ + void SelectChannelRange( int c0, int c1 ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectChannelRange( c0, c1 ); + } + + /*! + * Sets the current channel range selection to include all nominal channels + * exclusively, excluding alpha channels. + */ + void SelectNominalChannels() const noexcept + { + if ( m_data->image ) + m_data->image->SelectNominalChannels(); + } + + /*! + * Sets the current channel range selection to include the existing alpha + * channels only, excluding the nominal channels. + * + * \note If this image has no alpha channels, this function selects the last + * nominal channel. The channel range selection cannot be empty by design. + */ + void SelectAlphaChannels() const noexcept + { + if ( m_data->image ) + m_data->image->SelectAlphaChannels(); + } + + /*! + * Resets the channel range selection to include all existing channels (all + * nominal and alpha channels) in this image. + */ + void ResetChannelRange() const noexcept + { + if ( m_data->image ) + m_data->image->ResetChannelRange(); + } + + /*! + * Returns the number of selected channels, or zero if this object does not + * transport an image. + */ + int NumberOfSelectedChannels() const noexcept + { + return m_data->image ? m_data->image->NumberOfSelectedChannels() : 0; + } + + /*! + * Returns the channel index of the first selected channel, or -1 if this + * object does not transport an image. + */ + int FirstSelectedChannel() const noexcept + { + return m_data->image ? m_data->image->FirstSelectedChannel() : -1; + } + + /*! + * Returns the channel index of the last selected channel, or -1 if this + * object does not transport an image. + */ + int LastSelectedChannel() const noexcept + { + return m_data->image ? m_data->image->LastSelectedChannel() : -1; + } + + /*! + * Copies the first and last channel indices of the current channel + * selection to the specified variables. + * + * \param[out] c0 Index of the first selected channel. + * \param[out] c1 Index of the last selected channel. + */ + void GetSelectedChannelRange( int& c0, int& c1 ) const noexcept + { + if ( m_data->image ) + m_data->image->GetSelectedChannelRange( c0, c1 ); + } + + /*! + * Selects an anchor point by its separate image coordinates. + * + * \param x Horizontal coordinate of the new anchor point. + * \param y Vertical coordinate of the new anchor point. + */ + void SelectPoint( int x, int y ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectPoint( x, y ); + } + + /*! + * Selects a new anchor point \a p in image coordinates. + */ + void SelectPoint( const Point& p ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectPoint( p ); + } + + /*! + * Resets the anchor point to the origin of image coordinates, i.e to x=y=0. + */ + void ResetPoint() const noexcept + { + if ( m_data->image ) + m_data->image->ResetPoint(); + } + + /*! + * Returns the current anchor point, or zero if this object does not + * transport an image. + */ + Point SelectedPoint() const noexcept + { + return m_data->image ? m_data->image->SelectedPoint() : Point( 0 ); + } + + /*! + * Defines the current rectangular selection by its separate image + * coordinates. + * + * \param x0,y0 Upper left corner coordinates (horizontal, vertical) of + * the new rectangular selection. + * + * \param x1,y1 Lower right corner coordinates (horizontal, vertical) of + * the new rectangular selection. + * + * The resulting selection is constrained to stay within the image + * boundaries. + */ + void SelectRectangle( int x0, int y0, int x1, int y1 ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectRectangle( x0, y0, x1, y1 ); + } + + /*! + * Defines the current rectangular selection by its separate corner + * points in image coordinates. + * + * \param p0 Position of the upper left corner of the new selection. + * + * \param p1 Position of the lower right corner of the new selection. + */ + void SelectRectangle( const Point& p0, const Point& p1 ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectRectangle( p0, p1 ); + } + + /*! + * Defines the current rectangular selection as the specified rectangle \a r + * in image coordinates. + */ + void SelectRectangle( const Rect& r ) const noexcept + { + if ( m_data->image ) + m_data->image->SelectRectangle( r ); + } + + /*! + * Resets the rectangular selection to include the entire image boundaries. + */ + void ResetSelection() const noexcept + { + if ( m_data->image ) + m_data->image->ResetSelection(); + } + + /*! + * Returns true iff the current selection is empty, i.e. if its area is zero. + * Returns false if the current selection is not empty, or if this object + * does not transport an image. + */ + bool IsEmptySelection() const noexcept + { + return m_data->image ? m_data->image->IsEmptySelection() : false; + } + + /*! + * Returns true iff the current rectangular selection comprises the entire + * image. Returns false if the selection is not complete, or if this object + * does not transport an image. + */ + bool IsFullSelection() const noexcept + { + return m_data->image ? m_data->image->IsFullSelection() : false; + } + + /*! + * Returns the current rectangular selection, or zero if this object does + * not transport an image. + */ + Rect SelectedRectangle() const noexcept + { + return m_data->image ? m_data->image->SelectedRectangle() : Rect( 0 ); + } + + /*! + * Returns true if this image is completely selected; false if it is + * only partially selected, or if this object does not transport an image. + * + * In a completely selected image, the current rectangular selection + * includes the whole image, and the current channel range selection + * comprises all existing channels, including nominal and alpha channels. + */ + bool IsCompletelySelected() const noexcept + { + return m_data->image ? m_data->image->IsCompletelySelected() : false; + } + + /*! + * Returns the number of selected pixels. This is the area in square pixels + * of the current selection rectangle. Returns zero if this object does not + * transport an image. + */ + size_type NumberOfSelectedPixels() const noexcept + { + return m_data->image ? m_data->image->NumberOfSelectedPixels() : 0; + } + + /*! + * Returns the number of selected samples. This is the area in square pixels + * of the current selection rectangle multiplied by the number of selected + * channels. Returns zero if this object does not transport an image. + */ + size_type NumberOfSelectedSamples() const noexcept + { + return m_data->image ? m_data->image->NumberOfSelectedSamples() : 0; + } + + /*! + * Returns true iff range clipping is currently enabled for this image. + * Returns false if range clipping is disabled, or if this object does not + * transport an image. + * + * When range clipping is enabled, pixel samples outside the current + * clipping range: + * + * ( RangeClipLow(), RangeClipHigh() ) + * + * are ignored by statistics calculation routines. Note that range bounds + * are always excluded, since the range is open on both sides. The clipping + * range is always defined in the normalized [0,1] range for all pixel + * sample data types; the necessary conversions are performed transparently. + * + * When range clipping is disabled, the clipping range is ignored and all + * pixel samples are considered for statistical calculations. + * + * To make it more flexible, range clipping can be enabled/disabled + * separately for the low and high bounds. + * + * The default clipping range is the normalized (0,1) range. Range clipping + * is disabled by default. + */ + bool IsRangeClippingEnabled() const noexcept + { + return m_data->image ? m_data->image->IsRangeClippingEnabled() : false; + } + + /*! + * Returns true iff range clipping is currently enabled for the low clipping + * bound. Returns false if this object does not transport an image. + * + * When this function returns true, pixel samples with values less than or + * equal to the low clipping bound (as reported by RangeClipLow() ) will be + * rejected for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + bool IsLowRangeClippingEnabled() const noexcept + { + return m_data->image ? m_data->image->IsLowRangeClippingEnabled() : false; + } + + /*! + * Returns true iff range clipping is currently enabled for the high + * clipping bound. Returns false if this object does not transport an image. + * + * When this function returns true, pixel samples with values greater than + * or equal to the high clipping bound (as reported by RangeClipHigh() ) + * will be rejected for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + bool IsHighRangeClippingEnabled() const noexcept + { + return m_data->image ? m_data->image->IsHighRangeClippingEnabled() : false; + } + + /*! + * Enables range clipping for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void EnableRangeClipping( bool enableLow = true, bool enableHigh = true ) const noexcept + { + if ( m_data->image ) + m_data->image->EnableRangeClipping( enableLow, enableHigh ); + } + + /*! + * Disables range clipping for statistical calculations. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void DisableRangeClipping( bool disableLow = true, bool disableHigh = true ) const noexcept + { + if ( m_data->image ) + m_data->image->DisableRangeClipping( disableLow, disableHigh ); + } + + /*! + * Returns the lower bound of the current clipping range. Returns zero if + * this object does not transport an image. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + double RangeClipLow() const noexcept + { + return m_data->image ? m_data->image->RangeClipLow() : 0.0; + } + + /*! + * Returns the upper bound of the current clipping range. Returns zero if + * this object does not transport an image. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + double RangeClipHigh() const noexcept + { + return m_data->image ? m_data->image->RangeClipHigh() : 0.0; + } + + /*! + * Sets the lower bound of the clipping range. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void SetRangeClipLow( double clipLow ) const noexcept + { + if ( m_data->image ) + m_data->image->SetRangeClipLow( clipLow ); + } + + /*! + * Sets the upper bound of the clipping range. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void SetRangeClipHigh( double clipHigh ) const noexcept + { + if ( m_data->image ) + m_data->image->SetRangeClipHigh( clipHigh ); + } + + /*! + * Sets the lower and upper bounds of the clipping range and enables range + * clipping (both low and high clipping bounds), in a single function call. + * + * See IsRangeClippingEnabled() for more information on range clipping. + */ + void SetRangeClipping( double clipLow, double clipHigh ) const noexcept + { + if ( m_data->image ) + m_data->image->SetRangeClipping( clipLow, clipHigh ); + } + + /*! + * Resets the range clipping parameters: + * + * Clipping range lower bound = 0.0 + * Clipping range upper bound = 1.0 + * Range clipping disabled + */ + void ResetRangeClipping() const noexcept + { + if ( m_data->image ) + m_data->image->ResetRangeClipping(); + } + + /*! + * Resets all image selections to default values: + * + * \li All channels are selected, including nominal and alpha channels. + * \li The anchor point is located at {0,0}, that is the upper left corner. + * \li The rectangular selection is set to comprise the entire image. + * \li The clipping range is set to [0,1]. + * \li Range clipping is disabled. + * + * Calling this member function is equivalent to: + * + * \code + * ResetChannelRange(); + * ResetPoint(); + * ResetSelection(); + * ResetRangeClipping(); + * \endcode + */ + void ResetSelections() const noexcept + { + if ( m_data->image ) + m_data->image->ResetSelections(); + } + + /*! + * Returns a reference to the internal ImageSelections object in the image + * transported by this %ImageVariant. + * + * \note This member function assumes that this object transports a valid + * image. Do not call it otherwise. + */ + ImageSelections& Selections() const noexcept + { + return m_data->image->Selections(); + } + + /*! + * Saves the current selections (rectangular area, channel range, anchor + * point and range clipping), pushing them to the internal selection stack. + */ + void PushSelections() const + { + if ( m_data->image ) + m_data->image->PushSelections(); + } + + /*! + * Restores and pops (removes) the current selections (rectangular area, + * channel range, anchor point and range clipping) from the internal + * selection stack. + * + * If no selections have been previously pushed to the internal selection + * stack, this function is ignored. + */ + void PopSelections() const + { + if ( m_data->image ) + m_data->image->PopSelections(); + } + + /*! + * Returns true if one or more selections have been pushed to the internal + * selection stack, that is, if the PopSelections() function can be called + * to restore them. Returns false otherwise, or if this object does not + * transport an image. + */ + bool CanPopSelections() const noexcept + { + return m_data->image ? m_data->image->CanPopSelections() : false; + } + + /*! + * Returns a reference to the status monitoring object associated with the + * image transported by this %ImageVariant. + * + * \note This member function assumes that this object transports a valid + * image. Do not call it otherwise. + */ + StatusMonitor& Status() const noexcept + { + PCL_PRECONDITION( m_data->image != nullptr ) + return m_data->image->Status(); + } + + /*! + * Returns the address of the status monitoring callback object currently + * selected for the image transported by this %ImageVariant, or zero if this + * object does not transport an image. + */ + pcl::StatusCallback* StatusCallback() const noexcept + { + return m_data->image ? m_data->image->StatusCallback() : nullptr; + } + + /*! + * Specifies the address of an object that will be used to perform status + * monitoring callbacks for the image transported by this %ImageVariant. + * + * If this object does not transport an image, calling this member function + * has no effect. + */ + void SetStatusCallback( pcl::StatusCallback* callback ) const noexcept + { + if ( m_data->image ) + m_data->image->SetStatusCallback( callback ); + } + + /*! + * Returns true iff this image is allowed to use multiple parallel execution + * threads (when multiple threads are permitted and available) for member + * functions that support parallel execution. + * + * If this object does not transport an image, this member function returns + * false. + */ + bool IsParallelProcessingEnabled() const noexcept + { + return m_data->image != nullptr && m_data->image->IsParallelProcessingEnabled(); + } + + /*! + * Enables parallel processing for this image. + * + * \param enable Whether to enable or disable parallel processing. True by + * default. + * + * \param maxProcessors The maximum number of processors allowed for this + * image. If \a enable is false this parameter is ignored. A + * value ≤ 0 is ignored. The default value is zero. + * + * If this object does not transport an image, calling this member function + * has no effect. + */ + void EnableParallelProcessing( bool enable = true, int maxProcessors = 0 ) noexcept + { + if ( m_data->image ) + m_data->image->EnableParallelProcessing( enable, maxProcessors ); + } + + /*! + * Disables parallel processing for this image. + * + * This is a convenience function, equivalent to: + * EnableParallelProcessing( !disable ) + * + * If this object does not transport an image, calling this member function + * has no effect. + */ + void DisableParallelProcessing( bool disable = true ) noexcept + { + if ( m_data->image ) + m_data->image->DisableParallelProcessing( disable ); + } + + /*! + * Returns the maximum number of processors allowed for this image, or zero + * if this object does not transport an image. + * + * The returned nonzero value is the maximum number of processors that this + * image can use in member functions that support parallel execution. + * + * Irrespective of the value returned by this function, a module should not + * use more processors than the maximum number of parallel threads allowed + * for external modules on the PixInsight platform. This number is given by + * the "Process/MaxProcessors" global variable (refer to the GlobalSettings + * class for information on global variables). + */ + int MaxProcessors() const noexcept + { + return m_data->image ? m_data->image->MaxProcessors() : 0; + } + + /*! + * Sets the maximum number of processors allowed for this image. + * + * The specified \a maxProcessors parameter is the maximum number of + * processors that this image can use in member functions that support + * parallel execution. + * + * In the current versions of PCL, a module can use a maximum of 1023 + * processors. The term \e processor actually refers to the number of + * threads a module can execute concurrently. + * + * Irrespective of the value specified by this function, a module should not + * use more processors than the maximum number of parallel threads allowed + * for external modules on the PixInsight platform. This number is given by + * the "Process/MaxProcessors" global variable (refer to the GlobalSettings + * class for information on global variables). + * + * If this object does not transport an image, calling this member function + * has no effect. + */ + void SetMaxProcessors( int maxProcessors ) noexcept + { + if ( m_data->image ) + m_data->image->SetMaxProcessors( maxProcessors ); + } + + /*! + * Returns the size in bytes of a row of pixels (also known as a scan + * line) in the image transported by this %ImageVariant image, or zero + * if this object transports no image. + * + * The returned value is BytesPerSample()*Width(). + */ + size_type LineSize() const noexcept + { + return m_data->image ? BytesPerSample() * size_type( m_data->image->Width() ) : 0; + } + + /*! + * Returns the size in bytes of a channel in the image transported by this + * %ImageVariant, or zero if this object transports no image. + * + * The returned value is BytesPerSample()*NumberOfPixels(). + */ + size_type ChannelSize() const noexcept + { + return BytesPerSample() * NumberOfPixels(); + } + + /*! + * Returns the size in bytes of the allocated pixel data in the image + * transported by this %ImageVariant, or zero if this object transports no + * image. + * + * The returned value is NumberOfSamples()*BytesPerSample(). + */ + size_type ImageSize() const noexcept + { + return ChannelSize() * size_type( NumberOfChannels() ); + } + + /*! + * Returns the size in bytes of all memory blocks required to store the + * pixel data in the nominal channels (i.e., \e excluding alpha channels) of + * the image transported by this %ImageVariant, or zero if this object + * transports no image. + * + * The returned value is ChannelSize()*NumberOfNominalChannels(). + */ + size_type NominalSize() const noexcept + { + return ChannelSize() * size_type( NumberOfNominalChannels() ); + } + + /*! + * Returns the size in bytes of all memory blocks required to store the + * pixel data in the alpha channels (i.e., \e excluding nominal channels) + * of this image. Returns zero if this image has no alpha channels, or if + * this object transports no image. + * + * The returned value is ChannelSize()*NumberOfAlphaChannels(). + */ + size_type AlphaSize() const noexcept + { + return ChannelSize() * size_type( NumberOfAlphaChannels() ); + } + + /*! + * Returns true iff this %ImageVariant transports a color image. Returns + * false if this object transports a grayscale image, or if it does not + * transport any image. + */ + bool IsColor() const noexcept + { + return m_data->image && m_data->image->IsColor(); + } + + /*! + * Returns the identifier of the color space of the image transported by + * this %ImageVariant. + * + * This function returns the value of a symbolic constant enumerated by the + * ColorSpace namespace. If this object transports no image, this function + * returns ColorSpace::Unknown. + */ + color_space ColorSpace() const noexcept + { + return m_data->image ? m_data->image->ColorSpace() : ColorSpace::Unknown; + } + + /*! + * Returns the identifier of a nominal channel or component \a c in the + * color space of the image transported by this %ImageVariant, or an empty + * string if this object transports no image. + */ + String ChannelId( int c ) const noexcept + { + return m_data->image ? m_data->image->ChannelId( c ) : String(); + } + + /*! + * Returns a reference to the RGB working space associated with the image + * transported by this %ImageVariant object. + * + * \warning Do not call this member function if the %ImageVariant does not + * transport an image. + */ + const RGBColorSystem& RGBWorkingSpace() const noexcept + { + PCL_PRECONDITION( m_data->image != nullptr ) + return m_data->image->RGBWorkingSpace(); + } + + /*! + * Associates a given RGB working space ( RGBWS ) with the image transported + * by this %ImageVariant object. + * + * \note For shared images ( i.e. images living in the PixInsight core + * application ), the RGB working space cannot be changed by calling this + * function. + * + * \warning If this member function is called for a shared image, it throws + * an Error exception with the appropriate error message. + */ + void SetRGBWorkingSpace( const RGBColorSystem& rgbws ) + { + if ( m_data->image ) + m_data->image->SetRGBWorkingSpace( rgbws ); + } + + // ------------------------------------------------------------------------- + +#define __ABSOLUTE_DIFFERENCE( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).AbsoluteDifference( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * computes the absolute values of their differences with the specified + * \a scalar. Returns the resulting image. + * + * This member function is a generalized wrapper for + * GenericImage::AbsoluteDifference() + */ + template + ImageVariant AbsoluteDifference( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __ABSOLUTE_DIFFERENCE ) + return result; + } + +#undef __ABSOLUTE_DIFFERENCE + + // ------------------------------------------------------------------------- + +#define __ABSOLUTE_VALUE( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).AbsoluteValue( rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * replaced with their absolute values. + * + * This member function is a generalized wrapper for + * GenericImage::AbsoluteValue() + */ + ImageVariant AbsoluteValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __ABSOLUTE_VALUE ) + return result; + } + +#undef __ABSOLUTE_VALUE + + // ------------------------------------------------------------------------- + +#define __ADD( I ) \ + static_cast( **this ).Add( scalar, rect, firstChannel, lastChannel ) + + /*! + * Adds the specified \a scalar to a subset of pixel samples in this image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Add() + */ + template + ImageVariant& Add( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __ADD ) + return *this; + } + +#undef __ADD + + // ------------------------------------------------------------------------- + +#define __ADD_1( I ) \ + ImageVariant::Add( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __ADD_2( I ) \ + image1.Add( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Add( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __ADD_2 ) + } + +public: + + /*! + * Adds pixel samples of the specified \a image to a subset of pixel samples + * in this image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Add() + */ + ImageVariant& Add( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __ADD_1 ) + return *this; + } + +#undef __ADD_1 +#undef __ADD_2 + + // ------------------------------------------------------------------------- + +#define __ADDED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Added( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * adds a \a scalar. Returns the resulting image. + * + * This member function is a generalized wrapper for GenericImage::Added() + */ + template + ImageVariant Added( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __ADDED ) + return result; + } + +#undef __ADDED + + // ------------------------------------------------------------------------- + +#define __ALLOCATE_DATA( I ) \ + static_cast( **this ).AllocateData( width, height, numberOfChannels, colorSpace ) + + /*! + * Allocates new pixel data with the specified geometry and color space. + * Returns a reference to this image. + * + * If this object transports no image, a new local image is created in + * 32-bit floating point format by calling CreateImage(). + * + * This member function is a generalized wrapper for + * GenericImage::AllocateData() + */ + ImageVariant& AllocateData( int width, int height, int numberOfChannels = 1, color_space colorSpace = ColorSpace::Gray ) + { + if ( !*this ) + CreateImage(); + SOLVE_TEMPLATE( __ALLOCATE_DATA ) + return *this; + } + +#undef __ALLOCATE_DATA + + // ------------------------------------------------------------------------- + +#define __ALLOCATE_DATA( I ) \ + static_cast( **this ).AllocateData( rect, numberOfChannels, colorSpace ) + + /*! + * Allocates new pixel data with the specified geometry and color space. + * Returns a reference to this image. + * + * If this object transports no image, a new local image is created in + * 32-bit floating point format by calling CreateImage(). + * + * This member function is a generalized wrapper for + * GenericImage::AllocateData() + */ + ImageVariant& AllocateData( const Rect& rect, int numberOfChannels = 1, color_space colorSpace = ColorSpace::Gray ) + { + if ( !*this ) + CreateImage(); + SOLVE_TEMPLATE( __ALLOCATE_DATA ) + return *this; + } + +#undef __ALLOCATE_DATA + + // ------------------------------------------------------------------------- + +#define __AND( I ) \ + static_cast( **this ).And( scalar, rect, firstChannel, lastChannel ) + + /*! + * Performs a bitwise AND operation between a subset of pixel samples in + * this image and the specified \a scalar. Returns a reference to this + * image. + * + * This member function is a generalized wrapper for GenericImage::And() + */ + template + ImageVariant& And( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __AND ) + return *this; + } + +#undef __AND + + // ------------------------------------------------------------------------- + +#define __AND_1( I ) \ + ImageVariant::And( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __AND_2( I ) \ + image1.And( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void And( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_REAL_2( image2, __AND_2 ) + } + +public: + + /*! + * Performs a bitwise AND operation between a subset of pixel samples in + * this image and the corresponding samples of the specified source + * \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::And() + */ + ImageVariant& And( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE_REAL( __AND_1 ) + return *this; + } + +#undef __AND_1 +#undef __AND_2 + + // ------------------------------------------------------------------------- + +#define __APPLIED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Applied( scalar, op, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * performs an arithmetic or bitwise logical operation with a scalar. + * Returns the resulting image. + * + * This member function is a generalized wrapper for + * GenericImage::Applied( T ) + */ + template + ImageVariant Applied( T scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __APPLIED ) + return result; + } + +#undef __APPLIED + + // ------------------------------------------------------------------------- + +#define __APPLIED_1( I ) \ + result = ImageVariant::Applied( static_cast( **this ), image, op, point, channel, rect, firstChannel, lastChannel ) + +#define __APPLIED_2( I ) \ + result.SetImage( *new pcl::I( image1.Applied( static_cast( *image2 ), op, point, channel, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + +private: + + template static + ImageVariant Applied( const GenericImage

& image1, const ImageVariant& image2, + image_op op, const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + ImageVariant result; + SOLVE_TEMPLATE_2( image2, __APPLIED_2 ) + return result; + } + +public: + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * performs an arithmetic or bitwise logical operation with the + * corresponding samples of another \a image. Returns the resulting image. + * + * This member function is a generalized wrapper for + * GenericImage::Applied( const GenericImage& ) + */ + ImageVariant Applied( const ImageVariant& image, image_op op = ImageOp::Mov, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __APPLIED_1 ) + return result; + } + +#undef __APPLIED_1 +#undef __APPLIED_2 + + // ------------------------------------------------------------------------- + +#define __APPLIED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Applied( transformation, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * applies an image transformation. Returns the resulting image. + * + * This member function is a generalized wrapper for + * GenericImage::Applied( const ImageTransformation& ) + */ + ImageVariant Applied( const ImageTransformation& transformation, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __APPLIED ) + return result; + } + +#undef __APPLIED + + // ------------------------------------------------------------------------- + +#define __APPLY( I ) \ + static_cast( **this ).Apply( scalar, op, rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples with the result of an arithmetic, + * bitwise logical or pixel composition operation with a scalar. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Apply( T ) + */ + template + ImageVariant& Apply( T scalar, image_op op = ImageOp::Mov, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __APPLY ) + return *this; + } + +#undef __APPLY + + // ------------------------------------------------------------------------- + +#define __APPLY_1( I ) \ + ImageVariant::Apply( static_cast( **this ), image, op, point, channel, rect, firstChannel, lastChannel ) + +#define __APPLY_2( I ) \ + image1.Apply( static_cast( *image2 ), op, point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Apply( GenericImage

& image1, const ImageVariant& image2, + image_op op, const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __APPLY_2 ) + } + +public: + + /*! + * Performs an arithmetic, bitwise logical or pixel composition operation + * between a subset of pixel samples in this image and the corresponding + * samples of another operand \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Apply( const GenericImage& ) + */ + ImageVariant& Apply( const ImageVariant& image, image_op op = ImageOp::Mov, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __APPLY_1 ) + return *this; + } + +#undef __APPLY_1 +#undef __APPLY_2 + + // ------------------------------------------------------------------------- + +#define __APPLY( I ) \ + static_cast( **this ).Apply( transformation, rect, firstChannel, lastChannel ) + + /*! + * Applies an image transformation to a subset of pixel samples. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Apply( const ImageTransformation& ) + */ + ImageVariant& Apply( const ImageTransformation& transformation, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __APPLY ) + return *this; + } + +#undef __APPLY + + // ------------------------------------------------------------------------- + +#define __ASSIGN_IMAGE_1( I ) \ + ImageVariant::AssignImage( static_cast( **this ), image, rect, firstChannel, lastChannel ) + +#define __ASSIGN_IMAGE_2( I ) \ + image1.Assign( static_cast( *image2 ), rect, firstChannel, lastChannel ) + +private: + + template static + void AssignImage( GenericImage

& image1, const ImageVariant& image2, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __ASSIGN_IMAGE_2 ) + } + +public: + + /*! + * Copies pixel samples from the specified source \a image to this image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Assign() + */ + ImageVariant& AssignImage( const ImageVariant& image, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __ASSIGN_IMAGE_1 ) + return *this; + } + +#undef __ASSIGN_IMAGE_1 +#undef __ASSIGN_IMAGE_2 + + // ------------------------------------------------------------------------- + +#define __AVG_DEV( I ) \ + result = static_cast( **this ).AvgDev( center, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the mean absolute deviation of a subset of pixel samples with + * respect to the specified \a center value. + * + * This member function is a generalized wrapper for GenericImage::AvgDev() + */ + double AvgDev( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __AVG_DEV ) + return result; + } + +#undef __AVG_DEV + + // ------------------------------------------------------------------------- + +#define __2SIDED_AVG_DEV( I ) \ + result = static_cast( **this ).TwoSidedAvgDev( center, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the two-sided mean absolute deviation of a subset of pixel + * samples with respect to the specified \a center value. + * + * This member function is a generalized wrapper for + * GenericImage::TwoSidedAvgDev() + */ + TwoSidedEstimate TwoSidedAvgDev( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + TwoSidedEstimate result( 0 ); + if ( *this ) + SOLVE_TEMPLATE( __2SIDED_AVG_DEV ) + return result; + } + +#undef __2SIDED_AVG_DEV + + // ------------------------------------------------------------------------- + +#define __BINARIZE( I ) \ + static_cast( **this ).Binarize( threshold, rect, firstChannel, lastChannel ) + + /*! + * Binarizes a subset of pixel samples with respect to the specified + * \a threshold value. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Binarize() + */ + template + ImageVariant& Binarize( T threshold, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __BINARIZE ) + return *this; + } + +#undef __BINARIZE + + // ------------------------------------------------------------------------- + +#define __BINARIZE( I ) \ + static_cast( **this ).Binarize( rect, firstChannel, lastChannel ) + + /*! + * Binarizes a subset of pixel samples with respect to the specified + * \a threshold value. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Binarize() + */ + ImageVariant& Binarize( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __BINARIZE ) + return *this; + } + +#undef __BINARIZE + + // ------------------------------------------------------------------------- + +#define __BINARIZED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Binarized( threshold, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * binarized with respect to the specified \a threshold value. + * + * This member function is a generalized wrapper for + * GenericImage::Binarized() + */ + template + ImageVariant Binarized( T threshold, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __BINARIZED ) + return result; + } + +#undef __BINARIZED + + // ------------------------------------------------------------------------- + +#define __BINARIZED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Binarized( rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Binarizes a subset of pixel samples with respect to the central value of + * the native range of the image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Binarized() + */ + ImageVariant Binarized( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __BINARIZED ) + return result; + } + +#undef __BINARIZED + + // ------------------------------------------------------------------------- + +#define __PBMV( I ) \ + result = static_cast( **this ).BendMidvariance( center, beta, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns a percentage bend midvariance (PBMV) for a subset of pixel + * samples, with respect the the specified \a center value, with the + * specified \a beta rejection parameter. + * + * This member function is a generalized wrapper for + * GenericImage::BendMidvariance() + */ + double BendMidvariance( double center, double beta = 0.2, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __PBMV ) + return result; + } + +#undef __PBMV + + // ------------------------------------------------------------------------- + +#define __BWMV( I ) \ + result = static_cast( **this ).BiweightMidvariance( center, sigma, k, reducedLength, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns a biweight midvariance (BWMV) for a subset of pixel samples, with + * respect the the specified \a center value, \a sigma estimate of + * dispersion, and \a k threshold in sigma units. + * + * This member function is a generalized wrapper for + * GenericImage::BiweightMidvariance() + */ + double BiweightMidvariance( double center, double sigma, int k = 9, bool reducedLength = false, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __BWMV ) + return result; + } + +#undef __BWMV + + // ------------------------------------------------------------------------- + +#define __2SIDED_BWMV( I ) \ + result = static_cast( **this ).TwoSidedBiweightMidvariance( center, sigma, k, reducedLength, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns a two-sided biweight midvariance (BWMV) for a subset of pixel + * samples, with respect the the specified \a center value, two-sided + * \a sigma estimate of dispersion, and \a k threshold in sigma units. + * + * This member function is a generalized wrapper for + * GenericImage::TwoSidedBiweightMidvariance() + */ + TwoSidedEstimate TwoSidedBiweightMidvariance( double center, const TwoSidedEstimate& sigma, int k = 9, bool reducedLength = false, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + TwoSidedEstimate result( 0 ); + if ( *this ) + SOLVE_TEMPLATE( __2SIDED_BWMV ) + return result; + } + +#undef __2SIDED_BWMV + + // ------------------------------------------------------------------------- + +#define __BLACK( I ) \ + static_cast( **this ).Black( rect, firstChannel, lastChannel ) + + /*! + * Fills a subset of pixel samples with the minimum sample value in the + * native range of the image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Black() + */ + ImageVariant& Black( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __BLACK ) + return *this; + } + +#undef __BLACK + + // ------------------------------------------------------------------------- + +#define __BLEND( I ) \ + static_cast( **this ).Blend( bitmap, point, rect ) + + /*! + * Blends a rectangular region of a 32-bit RGBA \a bitmap with this image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Blend() + */ + ImageVariant& Blend( const Bitmap& bitmap, + const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ) ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __BLEND ) + return *this; + } + +#undef __BLEND + + // ------------------------------------------------------------------------- + +#define __BLENDED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Blended( bitmap, point, rect ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local duplicate of this image blended with a rectangular region + * of a 32-bit RGBA \a bitmap. + * + * This member function is a generalized wrapper for GenericImage::Blended() + */ + ImageVariant Blended( const Bitmap& bitmap, const Point& point = Point( int_max ), const Rect& rect = Rect( 0 ) ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __BLENDED ) + return result; + } + +#undef __BLENDED + + // ------------------------------------------------------------------------- + +#define __COUNT( I ) \ + result = static_cast( **this ).Count( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the number of pixel samples selectable for statistics calculation + * from a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Count() + */ + uint64 Count( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, int maxProcessors = 0 ) const + { + uint64 result = 0; + if ( *this ) + SOLVE_TEMPLATE( __COUNT ) + return result; + } + +#undef __COUNT + + // ------------------------------------------------------------------------- + +#define __CREATE_ALPHA_CHANNELS( I ) \ + static_cast( **this ).CreateAlphaChannels( n ) + + /*! + * Creates \a n new alpha channels in this image. Alpha channels are those + * in excess of nominal channels, e.g. a fourth channel in an RGB color + * image, or a second channel in a grayscale image. Returns a reference to + * this image. + * + * Newly created channels are not initialized, so their pixel samples will + * contain unpredictable values. + * + * This member function is a generalized wrapper for + * GenericImage::CreateAlphaChannels() + */ + void CreateAlphaChannels( int n ) + { + if ( *this ) + SOLVE_TEMPLATE( __CREATE_ALPHA_CHANNELS ) + } + +#undef __CREATE_ALPHA_CHANNELS + + // ------------------------------------------------------------------------- + +#define __CROP( I ) \ + static_cast( **this ).Crop( fillValues ) + + /*! + * Crops the image to its current rectangular selection. Returns a reference + * to this image. + * + * This member function is a generalized wrapper for GenericImage::Crop() + */ + template + ImageVariant& Crop( const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP ) + return *this; + } + +#undef __CROP + + // ------------------------------------------------------------------------- + +#define __CROP( I ) \ + static_cast( **this ).Crop() + + /*! + * Crops the image to its current rectangular selection, filling extended + * regions with the minimum sample value in the native range of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Crop() + */ + ImageVariant& Crop() + { + if ( *this ) + SOLVE_TEMPLATE( __CROP ) + return *this; + } + +#undef __CROP + + // ------------------------------------------------------------------------- + +#define __CROP_BY( I ) \ + static_cast( **this ).CropBy( left, top, right, bottom, fillValues ) + + /*! + * Crops or extends the entire image by applying the specified margins. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::CropBy() + */ + template + ImageVariant& CropBy( int left, int top, int right, int bottom, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP_BY ) + return *this; + } + +#undef __CROP_BY + + // ------------------------------------------------------------------------- + +#define __CROP_BY( I ) \ + static_cast( **this ).CropBy( left, top, right, bottom ) + + /*! + * Crops or extends the entire image by applying the specified margins. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::CropBy() + */ + ImageVariant& CropBy( int left, int top, int right, int bottom ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP_BY ) + return *this; + } + +#undef __CROP_BY + + // ------------------------------------------------------------------------- + +#define __CROP_TO( I ) \ + static_cast( **this ).CropTo( rect, fillValues ) + + /*! + * Crops the image to the specified rectangular region. Returns a reference + * to this image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::CropTo() + */ + template + ImageVariant& CropTo( const Rect& rect, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP_TO ) + return *this; + } + +#undef __CROP_TO + + // ------------------------------------------------------------------------- + +#define __CROP_TO( I ) \ + static_cast( **this ).CropTo( rect ) + + /*! + * Crops the image to the specified rectangular region, filling extended + * regions with the minimum sample value in the native range of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::CropTo() + */ + ImageVariant& CropTo( const Rect& rect ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP_TO ) + return *this; + } + +#undef __CROP_TO + + // ------------------------------------------------------------------------- + +#define __CROP_TO( I ) \ + static_cast( **this ).CropTo( x0, y0, x1, y1, fillValues ) + + /*! + * Crops the image to the specified rectangular region. Returns a reference + * to this image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::CropTo() + */ + template + ImageVariant& CropTo( int x0, int y0, int x1, int y1, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP_TO ) + return *this; + } + +#undef __CROP_TO + + // ------------------------------------------------------------------------- + +#define __CROP_TO( I ) \ + static_cast( **this ).CropTo( x0, y0, x1, y1 ) + + /*! + * Crops the image to the specified rectangular region, filling extended + * regions with the minimum sample value in the native range of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::CropTo() + */ + ImageVariant& CropTo( int x0, int y0, int x1, int y1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __CROP_TO ) + return *this; + } + +#undef __CROP_TO + + // ------------------------------------------------------------------------- + +#define __DELETE_ALPHA_CHANNEL( I ) \ + static_cast( **this ).DeleteAlphaChannel( channel ) + + /*! + * Destroys an alpha channel. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::DeleteAlphaChannel() + */ + void DeleteAlphaChannel( int channel ) + { + if ( *this ) + SOLVE_TEMPLATE( __DELETE_ALPHA_CHANNEL ) + } + +#undef __DELETE_ALPHA_CHANNEL + + // ------------------------------------------------------------------------- + +#define __DELETE_ALPHA_CHANNELS( I ) \ + static_cast( **this ).DeleteAlphaChannels() + + /*! + * Destroys all existing alpha channels in this image. Returns a reference + * to this image. + * + * This member function is a generalized wrapper for + * GenericImage::DeleteAlphaChannels() + */ + void DeleteAlphaChannels() + { + if ( *this ) + SOLVE_TEMPLATE( __DELETE_ALPHA_CHANNELS ) + } + +#undef __DELETE_ALPHA_CHANNELS + + // ------------------------------------------------------------------------- + +#define __DIVIDE( I ) \ + static_cast( **this ).Divide( scalar, rect, firstChannel, lastChannel ) + + /*! + * Divides a subset of pixel samples in this image by the specified + * \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Divide() + */ + template + ImageVariant& Divide( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __DIVIDE ) + return *this; + } + +#undef __DIVIDE + + /*! + * A synonym for Divide(). + */ + template + ImageVariant& Div( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Divide( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __DIVIDE_1( I ) \ + ImageVariant::Divide( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __DIVIDE_2( I ) \ + image1.Divide( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Divide( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __DIVIDE_2 ) + } + +public: + + /*! + * Divides a subset of pixel samples in this image by samples from the + * specified source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Divide() + */ + ImageVariant& Divide( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __DIVIDE_1 ) + return *this; + } + +#undef __DIVIDE_1 +#undef __DIVIDE_2 + + /*! + * A synonym for Divide(). + */ + ImageVariant& Div( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Divide( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __DIVIDED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Divided( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * divides it by a \a scalar. Returns the resulting image. + * + * This member function is a generalized wrapper for GenericImage::Divided() + */ + template + ImageVariant Divided( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __DIVIDED ) + return result; + } + +#undef __DIVIDED + + // ------------------------------------------------------------------------- + +#define __EXCHANGE_1( I ) \ + ImageVariant::Exchange( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __EXCHANGE_2( I ) \ + image1.Exchange( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Exchange( GenericImage

& image1, ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __EXCHANGE_2 ) + } + +public: + + /*! + * Exchanges a subset of pixel samples between this image and another + * operand \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Exchange() + */ + ImageVariant& Exchange( ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __EXCHANGE_1 ) + return *this; + } + +#undef __EXCHANGE_1 +#undef __EXCHANGE_2 + + /*! + * A synonym for Exchange(). + */ + ImageVariant& Xchg( ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Exchange( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __FILL( I ) \ + static_cast( **this ).Fill( scalar, rect, firstChannel, lastChannel ) + + /*! + * Fills a subset of pixel samples of this image with the specified + * \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Fill() + */ + template + ImageVariant& Fill( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __FILL ) + return *this; + } + +#undef __FILL + + // ------------------------------------------------------------------------- + +#define __FILL( I ) \ + static_cast( **this ).Fill( values, rect, firstChannel, lastChannel ) + + /*! + * Fills a subset of pixel samples of this image with the scalar components + * of a vector of per-channel filling \a values. Returns a reference to this + * image. + * + * This member function is a generalized wrapper for GenericImage::Fill() + */ + template + ImageVariant& Fill( const GenericVector& values, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __FILL ) + return *this; + } + +#undef __FILL + + // ------------------------------------------------------------------------- + +#define __FILLED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Filled( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * filled with the specified \a scalar. + * + * This member function is a generalized wrapper for GenericImage::Filled() + */ + template + ImageVariant Filled( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __FILLED ) + return result; + } + +#undef __FILLED + + // ------------------------------------------------------------------------- + +#define __FILLED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Filled( values, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * filled with the scalar components of a vector of per-channel filling + * \a values. + * + * This member function is a generalized wrapper for GenericImage::Filled() + */ + template + ImageVariant Filled( const GenericVector& values, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __FILLED ) + return result; + } + +#undef __FILLED + + // ------------------------------------------------------------------------- + +#define __FORGET_ALPHA_CHANNEL( I ) \ + static_cast( **this ).ForgetAlphaChannel( channel ) + + /*! + * Forces this image to discard an existing alpha channel without + * deallocating it. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ForgetAlphaChannel() + */ + void ForgetAlphaChannel( int channel ) + { + if ( *this ) + SOLVE_TEMPLATE( __FORGET_ALPHA_CHANNEL ) + } + +#undef __FORGET_ALPHA_CHANNEL + + // ------------------------------------------------------------------------- + +#define __FORGET_ALPHA_CHANNELS( I ) \ + static_cast( **this ).ForgetAlphaChannels() + + /*! + * Forces this image to discard all existing alpha channels without + * deallocating them. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ForgetAlphaChannels() + */ + void ForgetAlphaChannels() + { + if ( *this ) + SOLVE_TEMPLATE( __FORGET_ALPHA_CHANNELS ) + } + +#undef __FORGET_ALPHA_CHANNELS + + // ------------------------------------------------------------------------- + +#define __GET_COLUMN( I ) \ + static_cast( **this ).GetColumn( buffer, x, channel ) + + /*! + * Stores a duplicate of a column of pixel samples in the specified array, + * with implicit data type conversion. + * + * This member function is a generalized wrapper for + * GenericImage::GetColumn() + */ + template + void GetColumn( T* buffer, int x, int channel = -1 ) const + { + PCL_PRECONDITION( buffer != 0 ) + if ( *this ) + SOLVE_TEMPLATE( __GET_COLUMN ) + } + +#undef __GET_COLUMN + + // ------------------------------------------------------------------------- + +#define __GET_EXTREME_SAMPLE_VALUES( I ) \ + static_cast( **this ).GetExtremeSampleValues( min, max, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Obtains the extreme values among a subset of pixel samples of this image. + * + * This member function is a generalized wrapper for + * GenericImage::GetExtremeSampleValues() + */ + template + void GetExtremeSampleValues( T& min, T& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + PCL_PRECONDITION( buffer != 0 ) + if ( *this ) + SOLVE_TEMPLATE( __GET_EXTREME_SAMPLE_VALUES ) + } + +#undef __GET_EXTREME_SAMPLE_VALUES + + // ------------------------------------------------------------------------- + +#define __GET_INTENSITY_1( I ) \ + ImageVariant::GetIntensity( Y, static_cast( **this ), rect, maxProcessors ) + +#define __GET_INTENSITY_2( I ) \ + image.GetIntensity( static_cast( *Y ), rect, maxProcessors ) + +private: + + template static + void GetIntensity( ImageVariant& Y, const GenericImage

& image, const Rect& rect, int maxProcessors ) + { + if ( !Y.IsComplexSample() ) + SOLVE_TEMPLATE_REAL_2( Y, __GET_INTENSITY_2 ) + } + +public: + + /*! + * Computes the intensity HSI component for a subset of pixel samples and + * stores it in a grayscale image. + * + * \param[out] Y Reference to a destination %ImageVariant where the + * computed intensity component will be stored. If this + * object does not transport an image, a new 32-bit floating + * point image will be created. + * + * This member function is a generalized wrapper for + * GenericImage::GetIntensity(). + */ + void GetIntensity( ImageVariant& Y, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const + { + if ( *this ) + if ( !IsComplexSample() ) + { + if ( !Y ) + Y.CreateFloatImage( 32 ); + + SOLVE_TEMPLATE_REAL( __GET_INTENSITY_1 ) + } + } + +#undef __GET_INTENSITY_1 +#undef __GET_INTENSITY_2 + + // ------------------------------------------------------------------------- + +#define __GET_LIGHTNESS_1( I ) \ + ImageVariant::GetLightness( L, static_cast( **this ), rect, maxProcessors ) + +#define __GET_LIGHTNESS_2( I ) \ + image.GetLightness( static_cast( *L ), rect, maxProcessors ) + +private: + + template static + void GetLightness( ImageVariant& L, const GenericImage

& image, const Rect& rect, int maxProcessors ) + { + if ( !L.IsComplexSample() ) + SOLVE_TEMPLATE_REAL_2( L, __GET_LIGHTNESS_2 ) + } + +public: + + /*! + * Computes the CIE L* component for a subset of pixel samples and stores it + * in a grayscale image. + * + * \param[out] L Reference to a destination %ImageVariant where the + * computed CIE L* component will be stored. If this object + * does not transport an image, a new floating point image + * will be created with the appropriate sample type (either + * 32-bit or 64-bit floating point, depending on the sample + * data type of this image). + * + * This member function is a generalized wrapper for + * GenericImage::GetLightness(). + */ + void GetLightness( ImageVariant& L, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const + { + if ( *this ) + if ( !IsComplexSample() ) + { + if ( !L ) + L.CreateFloatImage( ( BitsPerSample() < 32 ) ? 32 : ( IsFloatSample() ? BitsPerSample() : 64 ) ); + + SOLVE_TEMPLATE_REAL( __GET_LIGHTNESS_1 ) + } + } + +#undef __GET_LIGHTNESS_1 +#undef __GET_LIGHTNESS_2 + + // ------------------------------------------------------------------------- + +#define __GET_LUMINANCE_1( I ) \ + ImageVariant::GetLuminance( Y, static_cast( **this ), rect, maxProcessors ) + +#define __GET_LUMINANCE_2( I ) \ + image.GetLuminance( static_cast( *Y ), rect, maxProcessors ) + +private: + + template static + void GetLuminance( ImageVariant& Y, const GenericImage

& image, const Rect& rect, int maxProcessors ) + { + if ( !Y.IsComplexSample() ) + SOLVE_TEMPLATE_REAL_2( Y, __GET_LUMINANCE_2 ) + } + +public: + + /*! + * Computes the CIE Y component for a subset of pixel samples and stores it + * in a grayscale image. + * + * \param[out] Y Reference to a destination %ImageVariant where the + * computed CIE Y component will be stored. If this object + * does not transport an image, a new floating point image + * will be created with the appropriate sample type (either + * 32-bit or 64-bit floating point, depending on the sample + * data type of this image). + * + * This member function is a generalized wrapper for + * GenericImage::GetLuminance(). + */ + void GetLuminance( ImageVariant& Y, const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) const + { + if ( *this ) + if ( !IsComplexSample() ) + { + if ( !Y ) + Y.CreateFloatImage( ( BitsPerSample() < 32 ) ? 32 : ( IsFloatSample() ? BitsPerSample() : 64 ) ); + + SOLVE_TEMPLATE_REAL( __GET_LUMINANCE_1 ) + } + } + +#undef __GET_LUMINANCE_1 +#undef __GET_LUMINANCE_2 + + // ------------------------------------------------------------------------- + +#define __GET_ROW( I ) \ + static_cast( **this ).GetRow( buffer, y, channel ) + + /*! + * Stores a duplicate of a row of pixel samples in the specified array, + * with implicit data type conversion. + * + * This member function is a generalized wrapper for GenericImage::GetRow() + */ + template + void GetRow( T* buffer, int y, int channel = -1 ) const + { + PCL_PRECONDITION( buffer != 0 ) + if ( *this ) + SOLVE_TEMPLATE( __GET_ROW ) + } + +#undef __GET_ROW + + // ------------------------------------------------------------------------- + +#define __INVERT( I ) \ + static_cast( **this ).Invert( scalar, rect, firstChannel, lastChannel ) + + /*! + * Inverts a subset of pixel samples with respect to the specified + * \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Invert() + */ + template + ImageVariant& Invert( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __INVERT ) + return *this; + } + +#undef __INVERT + + // ------------------------------------------------------------------------- + +#define __INVERT( I ) \ + static_cast( **this ).Invert( rect, firstChannel, lastChannel ) + + /*! + * Inverts a subset of pixel samples with respect to the maximum sample + * value in the native range of the image. Returns a reference to this + * image. + * + * This member function is a generalized wrapper for GenericImage::Invert() + */ + ImageVariant& Invert( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __INVERT ) + return *this; + } + +#undef __INVERT + + // ------------------------------------------------------------------------- + +#define __INVERTED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Inverted( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * inverted with respect to the specified \a scalar. + * + * This member function is a generalized wrapper for + * GenericImage::Inverted() + */ + template + ImageVariant Inverted( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __INVERTED ) + return result; + } + +#undef __INVERTED + + // ------------------------------------------------------------------------- + +#define __INVERTED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Inverted( rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * inverted with respect to the maximum sample value in the native range of + * the image. + * + * This member function is a generalized wrapper for + * GenericImage::Inverted() + */ + ImageVariant Inverted( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __INVERTED ) + return result; + } + +#undef __INVERTED + + // ------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#define __IS_SHARED_IMAGE( I ) \ + result = static_cast( **this ).IsShared() + + /*! + * Returns true iff this %ImageVariant object transports a shared image. + * Returns false if the transported image is local, or if this object + * transports no image. + * + * This member function is a generalized wrapper for + * GenericImage::IsShared() + */ + bool IsSharedImage() const noexcept + { + bool result = false; + if ( *this ) + SOLVE_TEMPLATE( __IS_SHARED_IMAGE ) + return result; + } + +#undef __IS_SHARED_IMAGE + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + + // ------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#define __SHARED_IMAGE_HANDLE( I ) \ + handle = static_cast( **this ).Allocator().Handle() + + /*! + * Returns the handle to the shared image transported by this %ImageVariant + * object, or zero (a null pointer) if the transported image is local, or if + * this object transports no image. + */ + void* SharedImageHandle() const noexcept + { + void* handle = nullptr; + if ( *this ) + SOLVE_TEMPLATE( __SHARED_IMAGE_HANDLE ) + return handle; + } + +#undef __SHARED_IMAGE_HANDLE + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + + // ------------------------------------------------------------------------- + +#define __IS_UNIQUE_IMAGE( I ) \ + result = static_cast( **this ).IsUnique() + + /*! + * Returns true iff this %ImageVariant object transports an image that + * uniquely references its pixel data. Returns false if the transported + * image is sharing its pixel data with other instances, or if this object + * transports no image. + * + * This member function is a generalized wrapper for + * GenericImage::IsUnique() + */ + bool IsUniqueImage() const noexcept + { + bool result = false; + if ( *this ) + SOLVE_TEMPLATE( __IS_UNIQUE_IMAGE ) + return result; + } + +#undef __IS_UNIQUE_IMAGE + + // ------------------------------------------------------------------------- + +#define __LOCATE_EXTREME_SAMPLE_VALUES( I ) \ + static_cast( **this ).LocateExtremeSampleValues( xmin, ymin, min, xmax, ymax, max, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Obtains the extreme values, and the image coordinates of their first + * occurrences, among a subset of pixel samples of this image. + * + * This member function is a generalized wrapper for + * GenericImage::LocateExtremeSampleValues() + */ + template + void LocateExtremeSampleValues( int& xmin, int& ymin, T& min, + int& xmax, int& ymax, T& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __LOCATE_EXTREME_SAMPLE_VALUES ) + } + +#undef __LOCATE_EXTREME_SAMPLE_VALUES + + // ------------------------------------------------------------------------- + +#define __LOCATE_EXTREME_SAMPLE_VALUES( I ) \ + static_cast( **this ).LocateExtremeSampleValues( pmin, min, pmax, max, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Obtains the extreme values, and the image coordinates of their first + * occurrences, among a subset of pixel samples of this image. + * + * This member function is a generalized wrapper for + * GenericImage::LocateExtremeSampleValues() + */ + template + void LocateExtremeSampleValues( Point& pmin, T& min, + Point& pmax, T& max, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __LOCATE_EXTREME_SAMPLE_VALUES ) + } + +#undef __LOCATE_EXTREME_SAMPLE_VALUES + + // ------------------------------------------------------------------------- + +#define __LOCATE_MAXIMUM_SAMPLE_VALUE( I ) \ + pcl::I::pixel_traits::FromSample( result, static_cast( **this ).LocateMaximumSampleValue( xmax, ymax, rect, firstChannel, lastChannel, maxProcessors ) ) + + /*! + * Returns the maximum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * This member function is a generalized wrapper for + * GenericImage::LocateMaximumSampleValue() + */ + double LocateMaximumSampleValue( int& xmax, int& ymax, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __LOCATE_MAXIMUM_SAMPLE_VALUE ) + return result; + } + +#undef __LOCATE_MAXIMUM_SAMPLE_VALUE + + // ------------------------------------------------------------------------- + +#define __LOCATE_MAXIMUM_SAMPLE_VALUE( I ) \ + pcl::I::pixel_traits::FromSample( result, static_cast( **this ).LocateMaximumSampleValue( pmax, rect, firstChannel, lastChannel, maxProcessors ) ) + + /*! + * Returns the maximum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * This member function is a generalized wrapper for + * GenericImage::LocateMaximumSampleValue() + */ + double LocateMaximumSampleValue( Point& pmax, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __LOCATE_MAXIMUM_SAMPLE_VALUE ) + return result; + } + +#undef __LOCATE_MAXIMUM_SAMPLE_VALUE + + // ------------------------------------------------------------------------- + +#define __LOCATE_MINIMUM_SAMPLE_VALUE( I ) \ + pcl::I::pixel_traits::FromSample( result, static_cast( **this ).LocateMinimumSampleValue( xmin, ymin, rect, firstChannel, lastChannel, maxProcessors ) ) + + /*! + * Returns the minimum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * This member function is a generalized wrapper for + * GenericImage::LocateMinimumSampleValue() + */ + double LocateMinimumSampleValue( int& xmin, int& ymin, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __LOCATE_MINIMUM_SAMPLE_VALUE ) + return result; + } + +#undef __LOCATE_MINIMUM_SAMPLE_VALUE + + // ------------------------------------------------------------------------- + +#define __LOCATE_MINIMUM_SAMPLE_VALUE( I ) \ + pcl::I::pixel_traits::FromSample( result, static_cast( **this ).LocateMinimumSampleValue( pmin, rect, firstChannel, lastChannel, maxProcessors ) ) + + /*! + * Returns the minimum value among a subset of pixel samples of this image, + * and obtains the image coordinates of its first occurrence. + * + * This member function is a generalized wrapper for + * GenericImage::LocateMinimumSampleValue() + */ + double LocateMinimumSampleValue( Point& pmin, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __LOCATE_MINIMUM_SAMPLE_VALUE ) + return result; + } + +#undef __LOCATE_MINIMUM_SAMPLE_VALUE + + // ------------------------------------------------------------------------- + +#define __MAD( I ) \ + result = static_cast( **this ).MAD( center, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the median absolute deviation (MAD) of a subset of pixel samples + * with respect to the specified \a center value. + * + * This member function is a generalized wrapper for GenericImage::MAD() + */ + double MAD( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MAD ) + return result; + } + +#undef __MAD + +// ------------------------------------------------------------------------- + +#define __2SIDED_MAD( I ) \ + result = static_cast( **this ).TwoSidedMAD( center, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the two-sided median absolute deviation (MAD) of a subset of + * pixel samples with respect to the specified \a center value. + * + * This member function is a generalized wrapper for + * GenericImage::TwoSidedMAD() + */ + TwoSidedEstimate TwoSidedMAD( double center, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + TwoSidedEstimate result( 0 ); + if ( *this ) + SOLVE_TEMPLATE( __2SIDED_MAD ) + return result; + } + +#undef __2SIDED_MAD + +// ------------------------------------------------------------------------- + +#define __MAXIMUM( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Maximum( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * computes the maximum of each sample and the specified \a scalar. Returns + * the resulting image. + * + * This member function is a generalized wrapper for GenericImage::Maximum() + */ + template + ImageVariant Maximum( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __MAXIMUM ) + return result; + } + +#undef __MAXIMUM + + // ------------------------------------------------------------------------- + +#define __MAXIMUM_SAMPLE_VALUE( I ) \ + pcl::I::pixel_traits::FromSample( result, static_cast( **this ).MaximumSampleValue( rect, firstChannel, lastChannel, maxProcessors ) ) + + /*! + * Returns the maximum value among a subset of pixel samples of this image. + * + * This member function is a generalized wrapper for + * GenericImage::MaximumSampleValue() + */ + double MaximumSampleValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MAXIMUM_SAMPLE_VALUE ) + return result; + } + +#undef __MAXIMUM_SAMPLE_VALUE + + // ------------------------------------------------------------------------- + +#define __MEAN( I ) \ + result = static_cast( **this ).Mean( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the arithmetic mean of a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Mean() + */ + double Mean( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MEAN ) + return result; + } + +#undef __MEAN + + // ------------------------------------------------------------------------- + +#define __MEAN_OF_SQUARES( I ) \ + result = static_cast( **this ).MeanOfSquares( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the mean of the squares of a subset of pixel samples. + * + * This member function is a generalized wrapper for + * GenericImage::MeanOfSquares() + */ + double MeanOfSquares( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MEAN_OF_SQUARES ) + return result; + } + +#undef __MEAN_OF_SQUARES + + // ------------------------------------------------------------------------- + +#define __MEDIAN( I ) \ + result = static_cast( **this ).Median( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the median of a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Median() + */ + double Median( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MEDIAN ) + return result; + } + +#undef __MEDIAN + + // ------------------------------------------------------------------------- + +#define __ORDER_STATISTIC( I ) \ + result = static_cast( **this ).OrderStatistic( k, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns an order statistic computed for a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::OrderStatistic() + */ + double OrderStatistic( double k, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __ORDER_STATISTIC ) + return result; + } + +#undef __ORDER_STATISTIC + + // ------------------------------------------------------------------------- + +#define __MINIMUM( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Minimum( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * computes the minimum of each sample and the specified \a scalar. Returns + * the resulting image. + * + * This member function is a generalized wrapper for GenericImage::Minimum() + */ + template + ImageVariant Minimum( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __MINIMUM ) + return result; + } + +#undef __MINIMUM + + // ------------------------------------------------------------------------- + +#define __MINIMUM_SAMPLE_VALUE( I ) \ + pcl::I::pixel_traits::FromSample( result, static_cast( **this ).MinimumSampleValue( rect, firstChannel, lastChannel, maxProcessors ) ) + + /*! + * Returns the minimum value among a subset of pixel samples of this image. + * + * This member function is a generalized wrapper for + * GenericImage::MinimumSampleValue() + */ + double MinimumSampleValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MINIMUM_SAMPLE_VALUE ) + return result; + } + +#undef __MINIMUM_SAMPLE_VALUE + + // ------------------------------------------------------------------------- + +#define __MODULUS( I ) \ + result = static_cast( **this ).Modulus( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the modulus of a subset of pixel samples. The modulus is the sum + * of the absolute values of all selected pixel sample values. + * + * This member function is a generalized wrapper for GenericImage::Modulus() + */ + double Modulus( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __MODULUS ) + return result; + } + +#undef __MODULUS + + // ------------------------------------------------------------------------- + +#define __MOVE( I ) \ + static_cast( **this ).Move( scalar, rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples in this image with the specified + * constant \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Move() + */ + template + ImageVariant& Move( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __MOVE ) + return *this; + } + +#undef __MOVE + + /*! + * A synonym for Move(). + */ + template + ImageVariant& Mov( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Move( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __MOVE_1( I ) \ + ImageVariant::Move( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __MOVE_2( I ) \ + image1.Move( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Move( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __MOVE_2 ) + } + +public: + + /*! + * Replaces a subset of pixel samples in this image with samples from the + * specified source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Move() + */ + ImageVariant& Move( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __MOVE_1 ) + return *this; + } + +#undef __MOVE_1 +#undef __MOVE_2 + + ImageVariant& Mov( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Move( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __MULTIPLY( I ) \ + static_cast( **this ).Multiply( scalar, rect, firstChannel, lastChannel ) + + /*! + * Multiplies a subset of pixel samples in this image by the specified + * \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Multiply() + */ + template + ImageVariant& Multiply( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __MULTIPLY ) + return *this; + } + +#undef __MULTIPLY + + /*! + * A synonym for Multiply(). + */ + template + ImageVariant& Mul( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Multiply( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __MULTIPLY_1( I ) \ + ImageVariant::Multiply( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __MULTIPLY_2( I ) \ + image1.Multiply( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Multiply( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __MULTIPLY_2 ) + } + +public: + + /*! + * Multiplies a subset of pixel samples in this image by samples from the + * specified source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Multiply() + */ + ImageVariant& Multiply( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __MULTIPLY_1 ) + return *this; + } + +#undef __MULTIPLY_1 +#undef __MULTIPLY_2 + + /*! + * A synonym for Multiply(). + */ + ImageVariant& Mul( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Multiply( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __MULTIPLIED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Multiplied( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * multiplies it by a \a scalar. Returns the resulting image. + * + * This member function is a generalized wrapper for + * GenericImage::Multiplied() + */ + template + ImageVariant Multiplied( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __MULTIPLIED ) + return result; + } + +#undef __MULTIPLIED + + // ------------------------------------------------------------------------- + +#define __NAND( I ) \ + static_cast( **this ).Nand( scalar, rect, firstChannel, lastChannel ) + + /*! + * Performs a bitwise NAND (NOT AND) operation between a subset of pixel + * samples in this image and the specified \a scalar. Returns a reference to + * this image. + * + * This member function is a generalized wrapper for GenericImage::Nand() + */ + template + ImageVariant& Nand( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __NAND ) + return *this; + } + +#undef __NAND + + // ------------------------------------------------------------------------- + +#define __NAND_1( I ) \ + ImageVariant::Nand( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __NAND_2( I ) \ + image1.Nand( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Nand( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_REAL_2( image2, __NAND_2 ) + } + +public: + + /*! + * Performs a bitwise NAND (NOT AND) operation between a subset of pixel + * samples in this image and the corresponding samples of the specified + * source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Nand() + */ + ImageVariant& Nand( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE_REAL( __NAND_1 ) + return *this; + } + +#undef __NAND_1 +#undef __NAND_2 + + // ------------------------------------------------------------------------- + +#define __NOR( I ) \ + static_cast( **this ).Nor( scalar, rect, firstChannel, lastChannel ) + + /*! + * Performs a bitwise NOR (NOT inclusive OR) operation between a subset of + * pixel samples in this image and the specified \a scalar. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Nor() + */ + template + ImageVariant& Nor( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __NOR ) + return *this; + } + +#undef __NOR + + // ------------------------------------------------------------------------- + +#define __NOR_1( I ) \ + ImageVariant::Nor( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __NOR_2( I ) \ + image1.Nor( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Nor( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_REAL_2( image2, __NOR_2 ) + } + +public: + + /*! + * Performs a bitwise NOR (NOT inclusive OR) operation between a subset of + * pixel samples in this image and the corresponding samples of the + * specified source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Nor() + */ + ImageVariant& Nor( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE_REAL( __NOR_1 ) + return *this; + } + +#undef __NOR_1 +#undef __NOR_2 + + // ------------------------------------------------------------------------- + +#define __NORM( I ) \ + result = static_cast( **this ).Norm( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the norm of a subset of pixel samples. The norm is the sum of all + * selected pixel sample values. + * + * This member function is a generalized wrapper for GenericImage::Norm() + */ + double Norm( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __NORM ) + return result; + } + +#undef __NORM + + // ------------------------------------------------------------------------- + +#define __NORMS( I ) \ + result = static_cast( **this ).Norms( maxDegree, rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns a vector of norms for a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Norms() + */ + Vector Norms( int maxDegree, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + Vector result; + if ( *this ) + SOLVE_TEMPLATE( __NORMS ) + return result; + } + +#undef __NORM + + // ------------------------------------------------------------------------- + +#define __NORMALIZE( I ) \ + static_cast( **this ).Normalize( lowerBound, upperBound, rect, firstChannel, lastChannel ) + + /*! + * Normalizes a subset of pixel samples to the specified range of values. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Normalize() + */ + template + ImageVariant& Normalize( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __NORMALIZE ) + return *this; + } + +#undef __NORMALIZE + + // ------------------------------------------------------------------------- + +#define __NORMALIZE( I ) \ + static_cast( **this ).Normalize( rect, firstChannel, lastChannel ) + + /*! + * Normalizes a subset of pixel samples to the native range of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Normalize() + */ + ImageVariant& Normalize( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __NORMALIZE ) + return *this; + } + +#undef __NORMALIZE + + // ------------------------------------------------------------------------- + +#define __NORMALIZED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Normalized( lowerBound, upperBound, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * normalized to the specified range of values. + * + * This member function is a generalized wrapper for + * GenericImage::Normalized() + */ + template + ImageVariant Normalized( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __NORMALIZED ) + return result; + } + +#undef __NORMALIZED + + // ------------------------------------------------------------------------- + +#define __NORMALIZED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Normalized( rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * normalized to the native range of the image. + * + * This member function is a generalized wrapper for + * GenericImage::Normalized() + */ + ImageVariant Normalized( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __NORMALIZED ) + return result; + } + +#undef __NORMALIZED + + // ------------------------------------------------------------------------- + +#define __NOT( I ) \ + static_cast( **this ).Not( rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples with their bitwise logical NOT values. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Not() + */ + ImageVariant& Not( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __NOT ) + return *this; + } + +#undef __NOT + + // ------------------------------------------------------------------------- + +#define __ONE( I ) \ + static_cast( **this ).One( rect, firstChannel, lastChannel ) + + /*! + * Fills a subset of pixel samples with the constant value resulting from + * converting the scalar one (1) to the sample data type of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::One() + */ + ImageVariant& One( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __ONE ) + return *this; + } + +#undef __ONE + + // ------------------------------------------------------------------------- + +#define __MULTIPLY( I ) \ + static_cast( **this ) *= scalar + + /*! + * A synonym for Multiply(). + */ + template + ImageVariant& operator *=( T scalar ) + { + if ( *this ) + SOLVE_TEMPLATE( __MULTIPLY ) + return *this; + } + +#undef __MULTIPLY + + // ------------------------------------------------------------------------- + +#define __MULTIPLY_1( I ) \ + ImageVariant::Multiply( static_cast( **this ), image ) + +#define __MULTIPLY_2( I ) \ + image1 *= static_cast( *image2 ) + +private: + + template static + void Multiply( GenericImage

& image1, const ImageVariant& image2 ) + { + SOLVE_TEMPLATE_2( image2, __MULTIPLY_2 ) + } + +public: + + /*! + * A synonym for Multiply(). + */ + ImageVariant& operator *=( const ImageVariant& image ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __MULTIPLY_1 ) + return *this; + } + +#undef __MULTIPLY_1 +#undef __MULTIPLY_2 + + // ------------------------------------------------------------------------- + +#define __ADD( I ) \ + static_cast( **this ) += scalar + + /*! + * A synonym for Add(). + */ + template + ImageVariant& operator +=( T scalar ) + { + if ( *this ) + SOLVE_TEMPLATE( __ADD ) + return *this; + } + +#undef __ADD + + // ------------------------------------------------------------------------- + +#define __ADD_1( I ) \ + ImageVariant::Add( static_cast( **this ), image ) + +#define __ADD_2( I ) \ + image1 += static_cast( *image2 ) + +private: + + template static + void Add( GenericImage

& image1, const ImageVariant& image2 ) + { + SOLVE_TEMPLATE_2( image2, __ADD_2 ) + } + +public: + + /*! + * A synonym for Add(). + */ + ImageVariant& operator +=( const ImageVariant& image ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __ADD_1 ) + return *this; + } + +#undef __ADD_1 +#undef __ADD_2 + + // ------------------------------------------------------------------------- + +#define __SUBTRACT( I ) \ + static_cast( **this ) -= scalar + + /*! + * A synonym for Subtract(). + */ + template + ImageVariant& operator -=( T scalar ) + { + if ( *this ) + SOLVE_TEMPLATE( __SUBTRACT ) + return *this; + } + +#undef __SUBTRACT + + // ------------------------------------------------------------------------- + +#define __SUBTRACT_1( I ) \ + ImageVariant::Subtract( static_cast( **this ), image ) + +#define __SUBTRACT_2( I ) \ + image1 -= static_cast( *image2 ) + +private: + + template static + void Subtract( GenericImage

& image1, const ImageVariant& image2 ) + { + SOLVE_TEMPLATE_2( image2, __SUBTRACT_2 ) + } + +public: + + /*! + * A synonym for Subtract(). + */ + ImageVariant& operator -=( const ImageVariant& image ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __SUBTRACT_1 ) + return *this; + } + +#undef __SUBTRACT_1 +#undef __SUBTRACT_2 + + // ------------------------------------------------------------------------- + +#define __DIVIDE( I ) \ + static_cast( **this ) /= scalar + + /*! + * A synonym for Divide(). + */ + template + ImageVariant& operator /=( T scalar ) + { + if ( *this ) + SOLVE_TEMPLATE( __DIVIDE ) + return *this; + } + +#undef __DIVIDE + + // ------------------------------------------------------------------------- + +#define __DIVIDE_1( I ) \ + ImageVariant::Divide( static_cast( **this ), image ) + +#define __DIVIDE_2( I ) \ + image1 /= static_cast( *image2 ) + +private: + + template static + void Divide( GenericImage

& image1, const ImageVariant& image2 ) + { + SOLVE_TEMPLATE_2( image2, __DIVIDE_2 ) + } + +public: + + /*! + * A synonym for Divide(). + */ + ImageVariant& operator /=( const ImageVariant& image ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __DIVIDE_1 ) + return *this; + } + +#undef __DIVIDE_1 +#undef __DIVIDE_2 + + // ------------------------------------------------------------------------- + +#define __RAISE( I ) \ + static_cast( **this ) ^= scalar + + /*! + * A synonym for Raise(). + */ + template + ImageVariant& operator ^=( T scalar ) + { + if ( *this ) + SOLVE_TEMPLATE( __RAISE ) + return *this; + } + +#undef __RAISE + + // ------------------------------------------------------------------------- + +#define __RAISE_1( I ) \ + ImageVariant::Raise( static_cast( **this ), image ) + +#define __RAISE_2( I ) \ + image1 ^= static_cast( *image2 ) + +private: + + template static + void Raise( GenericImage

& image1, const ImageVariant& image2 ) + { + SOLVE_TEMPLATE_2( image2, __RAISE_2 ) + } + +public: + + /*! + * A synonym for Raise(). + */ + ImageVariant& operator ^=( const ImageVariant& image ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __RAISE_1 ) + return *this; + } + +#undef __RAISE_1 +#undef __RAISE_2 + + // ------------------------------------------------------------------------- + +#define __INVERTED( I ) \ + result.SetImage( *new pcl::I( ~static_cast( **this ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns an inverted duplicate of this image. The inversion operation is + * performed on the current pixel sample selection with respect to the + * maximum sample value in the native range of the image. + * + * This member function is a generalized wrapper for + * GenericImage::operator ~() + */ + ImageVariant operator ~() const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __INVERTED ) + return result; + } + +#undef __INVERTED + + // ------------------------------------------------------------------------- + +#define __OR( I ) \ + static_cast( **this ).Or( scalar, rect, firstChannel, lastChannel ) + + /*! + * Performs a bitwise OR (inclusive OR) operation between a subset of pixel + * samples in this image and the specified \a scalar. Returns a reference to + * this image. + * + * This member function is a generalized wrapper for GenericImage::Or() + */ + template + ImageVariant& Or( T scalar, const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __OR ) + return *this; + } + +#undef __OR + + // ------------------------------------------------------------------------- + +#define __OR_1( I ) \ + ImageVariant::Or( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __OR_2( I ) \ + image1.Or( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Or( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_REAL_2( image2, __OR_2 ) + } + +public: + + /*! + * Performs a bitwise OR (inclusive OR) operation between a subset of pixel + * samples in this image and the corresponding samples of the specified + * source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Or() + */ + ImageVariant& Or( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE_REAL( __OR_1 ) + return *this; + } + +#undef __OR_1 +#undef __OR_2 + + // ------------------------------------------------------------------------- + +#define __RAISE( I ) \ + static_cast( **this ).Raise( scalar, rect, firstChannel, lastChannel ) + + /*! + * Raises (exponentiation operator) a subset of pixel samples in this image + * to the specified \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Raise() + */ + template + ImageVariant& Raise( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __RAISE ) + return *this; + } + +#undef __RAISE + + /*! + * A synonym for Raise(). + */ + template + ImageVariant& Pow( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Raise( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __Qn( I ) \ + result = static_cast( **this ).Qn( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the Qn scale estimator of Rousseeuw and Croux for a subset of + * pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Qn() + */ + double Qn( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = false; + if ( *this ) + SOLVE_TEMPLATE( __Qn ) + return result; + } + +#undef __Qn + + // ------------------------------------------------------------------------- + +#define __RAISE_1( I ) \ + ImageVariant::Raise( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __RAISE_2( I ) \ + image1.Raise( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Raise( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __RAISE_2 ) + } + +public: + + /*! + * Raises (exponentiation operator) a subset of pixel samples in this image + * to samples from the specified source \a image. Returns a reference to + * this image. + * + * This member function is a generalized wrapper for GenericImage::Raise() + */ + ImageVariant& Raise( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __RAISE_1 ) + return *this; + } + +#undef __RAISE_1 +#undef __RAISE_2 + + /*! + * A synonym for Raise(). + */ + ImageVariant& Pow( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Raise( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __RAISED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Raised( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * raises it to a \a scalar. Returns the resulting image. + * + * This member function is a generalized wrapper for GenericImage::Raised() + */ + template + ImageVariant Raised( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __RAISED ) + return result; + } + +#undef __RAISED + + // ------------------------------------------------------------------------- + +#define __READ( I ) \ + static_cast( **this ).Read( file ) + + /*! + * Reads an image from a raw-storage stream. Returns a reference to this + * image. + * + * This member function is a generalized wrapper for GenericImage::Read() + */ + ImageVariant& Read( File& file ) + { + if ( *this ) + SOLVE_TEMPLATE( __READ ) + return *this; + } + +#undef __READ + + // ------------------------------------------------------------------------- + +#define __READ( I ) \ + static_cast( **this ).Read( filePath ) + + /*! + * Reads an image from a raw-storage file. Returns a reference to this + * image. + * + * This member function is a generalized wrapper for GenericImage::Read() + */ + ImageVariant& Read( const String& filePath ) + { + if ( *this ) + SOLVE_TEMPLATE( __READ ) + return *this; + } + +#undef __READ + + // ------------------------------------------------------------------------- + +#define __RESCALE( I ) \ + static_cast( **this ).Rescale( lowerBound, upperBound, rect, firstChannel, lastChannel ) + + /*! + * Rescales a subset of pixel samples to the specified range of values. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Rescale() + */ + template + ImageVariant& Rescale( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __RESCALE ) + return *this; + } + +#undef __RESCALE + + // ------------------------------------------------------------------------- + +#define __RESCALE( I ) \ + static_cast( **this ).Rescale( rect, firstChannel, lastChannel ) + + /*! + * Rescales a subset of pixel samples to the native range of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Rescale() + */ + ImageVariant& Rescale( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __RESCALE ) + return *this; + } + +#undef __RESCALE + + // ------------------------------------------------------------------------- + +#define __RESCALED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Rescaled( lowerBound, upperBound, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * rescaled to the specified range of values. + * + * This member function is a generalized wrapper for + * GenericImage::Rescaled() + */ + template + ImageVariant Rescaled( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __RESCALED ) + return result; + } + +#undef __RESCALED + + // ------------------------------------------------------------------------- + +#define __RESCALED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Rescaled( rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * rescaled to the native range of the image. + * + * This member function is a generalized wrapper for + * GenericImage::Rescaled() + */ + ImageVariant Rescaled( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE_REAL( __RESCALED ) + return result; + } + +#undef __RESCALED + + // ------------------------------------------------------------------------- + +#define __SET_ABSOLUTE_DIFFERENCE( I ) \ + static_cast( **this ).SetAbsoluteDifference( scalar, rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples in this image with the absolute + * values of their differences with the specified \a scalar. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetAbsoluteDifference() + */ + template + ImageVariant& SetAbsoluteDifference( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __SET_ABSOLUTE_DIFFERENCE ) + return *this; + } + +#undef __SET_ABSOLUTE_DIFFERENCE + + /*! + * A synonym for SetAbsoluteDifference(). + */ + template + ImageVariant& Dif( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetAbsoluteDifference( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SET_ABSOLUTE_DIFFERENCE_1( I ) \ + ImageVariant::SetAbsoluteDifference( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __SET_ABSOLUTE_DIFFERENCE_2( I ) \ + image1.SetAbsoluteDifference( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void SetAbsoluteDifference( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __SET_ABSOLUTE_DIFFERENCE_2 ) + } + +public: + + /*! + * Replaces a subset of pixel samples in this image with the absolute values + * of their differences with samples from the specified source \a image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetAbsoluteDifference() + */ + ImageVariant& SetAbsoluteDifference( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __SET_ABSOLUTE_DIFFERENCE_1 ) + return *this; + } + +#undef __SET_ABSOLUTE_DIFFERENCE_1 +#undef __SET_ABSOLUTE_DIFFERENCE_2 + + ImageVariant& Dif( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetAbsoluteDifference( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SET_ABSOLUTE_VALUE( I ) \ + static_cast( **this ).SetAbsoluteValue( rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples with their absolute values. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetAbsoluteValue() + */ + ImageVariant& SetAbsoluteValue( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __SET_ABSOLUTE_VALUE ) + return *this; + } + + ImageVariant& Abs( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetAbsoluteValue( rect, firstChannel, lastChannel ); + } + +#undef __SET_ABSOLUTE_VALUE + + // ------------------------------------------------------------------------- + +#define __SET_COLOR_SPACE( I ) \ + static_cast( **this ).SetColorSpace( colorSpace, maxProcessors ) + + /*! + * Converts the image to the specified color space. Returns a reference to + * this object. + * + * This member function is a generalized wrapper for + * GenericImage::SetColorSpace() + */ + ImageVariant& SetColorSpace( color_space colorSpace, int maxProcessors = 0 ) + { + if ( *this ) + SOLVE_TEMPLATE( __SET_COLOR_SPACE ) + return *this; + } + +#undef __SET_COLOR_SPACE + + // ------------------------------------------------------------------------- + +#define __SET_COLUMN( I ) \ + static_cast( **this ).SetColumn( buffer, x, channel ) + + /*! + * Sets a column of pixel samples from values in the specified array, with + * implicit data type conversion. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetColumn() + */ + template + ImageVariant& SetColumn( const T* buffer, int x, int channel = -1 ) + { + PCL_PRECONDITION( buffer != 0 ) + if ( *this ) + SOLVE_TEMPLATE( __SET_COLUMN ) + return *this; + } + +#undef __SET_COLUMN + + // ------------------------------------------------------------------------- + +#define __SET_LIGHTNESS_1( I ) \ + ImageVariant::SetLightness( static_cast( **this ), L, point, rect, maxProcessors ) + +#define __SET_LIGHTNESS_2( I ) \ + image.SetLightness( static_cast( *L ), point, rect, maxProcessors ) + +private: + + template static + void SetLightness( GenericImage

& image, const ImageVariant& L, + const Point& point, const Rect& rect, int maxProcessors ) + { + if ( !L.IsComplexSample() ) + SOLVE_TEMPLATE_REAL_2( L, __SET_LIGHTNESS_2 ) + } + +public: + + /*! + * Replaces the CIE L* component of a subset of pixel samples with data + * extracted from another image. + * + * This member function is a generalized wrapper for + * GenericImage::SetLightness() + */ + ImageVariant& SetLightness( const ImageVariant& L, + const Point& point = Point( int_max ), + const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) + { + if ( *this ) + if ( !IsComplexSample() ) + if ( L ) + SOLVE_TEMPLATE_REAL( __SET_LIGHTNESS_1 ) + return *this; + } + +#undef __SET_LIGHTNESS_1 +#undef __SET_LIGHTNESS_2 + + // ------------------------------------------------------------------------- + +#define __SET_LUMINANCE_1( I ) \ + ImageVariant::SetLuminance( static_cast( **this ), Y, point, rect, maxProcessors ) + +#define __SET_LUMINANCE_2( I ) \ + image.SetLuminance( static_cast( *Y ), point, rect, maxProcessors ) + +private: + + template static + void SetLuminance( GenericImage

& image, const ImageVariant& Y, + const Point& point, const Rect& rect, int maxProcessors ) + { + if ( !Y.IsComplexSample() ) + SOLVE_TEMPLATE_REAL_2( Y, __SET_LUMINANCE_2 ) + } + +public: + + /*! + * Replaces the CIE Y component of a subset of pixel samples with data + * extracted from another image. + * + * This member function is a generalized wrapper for + * GenericImage::SetLuminance() + */ + ImageVariant& SetLuminance( const ImageVariant& Y, + const Point& point = Point( int_max ), + const Rect& rect = Rect( 0 ), int maxProcessors = 0 ) + { + if ( *this ) + if ( !IsComplexSample() ) + if ( Y ) + SOLVE_TEMPLATE_REAL( __SET_LUMINANCE_1 ) + return *this; + } + +#undef __SET_LUMINANCE_1 +#undef __SET_LUMINANCE_2 + + // ------------------------------------------------------------------------- + +#define __SET_MAXIMUM( I ) \ + static_cast( **this ).SetMaximum( scalar, rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples in this image with the maximum of each + * sample and the specified \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetMaximum() + */ + template + ImageVariant& SetMaximum( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __SET_MAXIMUM ) + return *this; + } + +#undef __SET_MAXIMUM + + /*! + * A synonym for SetMaximum(). + */ + template + ImageVariant& Max( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMaximum( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SET_MAXIMUM_1( I ) \ + ImageVariant::SetMaximum( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __SET_MAXIMUM_2( I ) \ + image1.SetMaximum( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void SetMaximum( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __SET_MAXIMUM_2 ) + } + +public: + + /*! + * Replaces a subset of pixel samples in this image with the maximum of each + * target sample and the corresponding source sample of the specified + * \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetMaximum() + */ + ImageVariant& SetMaximum( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __SET_MAXIMUM_1 ) + return *this; + } + +#undef __SET_MAXIMUM_1 +#undef __SET_MAXIMUM_2 + + /*! + * A synonym for SetMaximum(). + */ + ImageVariant& Max( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMaximum( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SET_MINIMUM( I ) \ + static_cast( **this ).SetMinimum( scalar, rect, firstChannel, lastChannel ) + + /*! + * Replaces a subset of pixel samples in this image with the minimum of each + * sample and the specified \a scalar. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetMinimum() + */ + template + ImageVariant& SetMinimum( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __SET_MINIMUM ) + return *this; + } + +#undef __SET_MINIMUM + + /*! + * A synonym for SetMinimum(). + */ + template + ImageVariant& Min( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMinimum( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SET_MINIMUM_1( I ) \ + ImageVariant::SetMinimum( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __SET_MINIMUM_2( I ) \ + image1.SetMinimum( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void SetMinimum( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __SET_MINIMUM_2 ) + } + +public: + + /*! + * Replaces a subset of pixel samples in this image with the minimum of each + * target sample and the corresponding source sample of the specified + * \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetMinimum() + */ + ImageVariant& SetMinimum( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __SET_MINIMUM_1 ) + return *this; + } + +#undef __SET_MINIMUM_1 +#undef __SET_MINIMUM_2 + + /*! + * A synonym for SetMinimum(). + */ + ImageVariant& Min( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return SetMinimum( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __Sn( I ) \ + result = static_cast( **this ).Sn( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the Sn scale estimator of Rousseeuw and Croux for a subset of + * pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Sn() + */ + double Sn( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = false; + if ( *this ) + SOLVE_TEMPLATE( __Sn ) + return result; + } + +#undef __Sn + + // ------------------------------------------------------------------------- + +#define __SET_ROW( I ) \ + static_cast( **this ).SetRow( buffer, y, channel ) + + /*! + * Sets a row of pixel samples from values in the specified array, with + * implicit data type conversion. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::SetRow() + */ + template + ImageVariant& SetRow( const T* buffer, int y, int channel = -1 ) + { + PCL_PRECONDITION( buffer != 0 ) + if ( *this ) + SOLVE_TEMPLATE( __SET_ROW ) + return *this; + } + +#undef __SET_ROW + + // ------------------------------------------------------------------------- + +#define __ENSURE_UNIQUE_IMAGE( I ) \ + static_cast( **this ).EnsureUnique() + + /*! + * Ensures that the image transported by this %ImageVariant object uniquely + * references its pixel data, making a unique copy of its referenced pixel + * data if necessary. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::EnsureUnique() + */ + ImageVariant& EnsureUniqueImage() + { + if ( *this ) + SOLVE_TEMPLATE( __ENSURE_UNIQUE_IMAGE ) + return *this; + } + +#undef __ENSURE_UNIQUE_IMAGE + + // ------------------------------------------------------------------------- + +#define __ENSURE_LOCAL_IMAGE( I ) \ + static_cast( **this ).EnsureLocal() + + /*! + * Ensures that the image transported by this %ImageVariant object uses + * local pixel data storage. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::EnsureLocal() + */ + ImageVariant& EnsureLocalImage() + { + if ( *this ) + SOLVE_TEMPLATE( __ENSURE_LOCAL_IMAGE ) + return *this; + } + +#undef __ENSURE_LOCAL_IMAGE + + // ------------------------------------------------------------------------- + +#define __SHIFT( I ) \ + static_cast( **this ).Shift( fillValues ) + + /*! + * Shifts (translates) the image to its current anchor point selection. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Shift() + */ + template + ImageVariant& Shift( const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT ) + return *this; + } + +#undef __SHIFT + + // ------------------------------------------------------------------------- + +#define __SHIFT( I ) \ + static_cast( **this ).Shift() + + /*! + * Shifts (translates) the image to its current anchor point selection, + * filling extended regions with the minimum sample value in the native + * range of the image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Shift() + */ + ImageVariant& Shift() + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT ) + return *this; + } + +#undef __SHIFT + + // ------------------------------------------------------------------------- + +#define __SHIFT_BY( I ) \ + static_cast( **this ).ShiftBy( dx, dy, fillValues ) + + /*! + * Shifts (translates) this image by the specified increments in pixels. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::ShiftBy() + */ + template + ImageVariant& ShiftBy( int dx, int dy, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_BY ) + return *this; + } + +#undef __SHIFT_BY + + // ------------------------------------------------------------------------- + +#define __SHIFT_BY( I ) \ + static_cast( **this ).ShiftBy( dx, dy ) + + /*! + * Shifts (translates) this image by the specified increments in pixels, + * filling extended regions with the minimum sample value in the native + * range of the image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::ShiftBy() + */ + ImageVariant& ShiftBy( int dx, int dy ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_BY ) + return *this; + } + +#undef __SHIFT_BY + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO( I ) \ + static_cast( **this ).ShiftTo( x, y, fillValues ) + + /*! + * Shifts (translates) the image to the specified coordinates. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for GenericImage::ShiftTo() + */ + template + ImageVariant& ShiftTo( int x, int y, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO ) + return *this; + } + +#undef __SHIFT_TO + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO( I ) \ + static_cast( **this ).ShiftTo( x, y ) + + /*! + * Shifts (translates) the image to the specified coordinates, filling + * extended regions with the minimum sample value in the native range of the + * image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::ShiftTo() + */ + ImageVariant& ShiftTo( int x, int y ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO ) + return *this; + } + +#undef __SHIFT_TO + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO( I ) \ + static_cast( **this ).ShiftTo( p, fillValues ) + + /*! + * Shifts (translates) the image to the specified coordinates. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for GenericImage::ShiftTo() + */ + template + ImageVariant& ShiftTo( const Point& p, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO ) + return *this; + } + +#undef __SHIFT_TO + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO( I ) \ + static_cast( **this ).ShiftTo( p ) + + /*! + * Shifts (translates) the image to the specified coordinates, filling + * extended regions with the minimum sample value in the native range of the + * image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::ShiftTo() + */ + ImageVariant& ShiftTo( const Point& p ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO ) + return *this; + } + +#undef __SHIFT_TO + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_BOTTOM_LEFT( I ) \ + static_cast( **this ).ShiftToBottomLeft( width, height, fillValues ) + + /*! + * Extends or crops the image at its right and top sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToBottomLeft() + */ + template + ImageVariant& ShiftToBottomLeft( int width, int height, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_BOTTOM_LEFT ) + return *this; + } + +#undef __SHIFT_TO_BOTTOM_LEFT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_BOTTOM_LEFT( I ) \ + static_cast( **this ).ShiftToBottomLeft( width, height ) + + /*! + * Extends or crops the image at its right and top sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToBottomLeft() + */ + ImageVariant& ShiftToBottomLeft( int width, int height ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_BOTTOM_LEFT ) + return *this; + } + +#undef __SHIFT_TO_BOTTOM_LEFT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_BOTTOM_RIGHT( I ) \ + static_cast( **this ).ShiftToBottomRight( width, height, fillValues ) + + /*! + * Extends or crops the image at its left and top sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToBottomRight() + */ + template + ImageVariant& ShiftToBottomRight( int width, int height, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_BOTTOM_RIGHT ) + return *this; + } + +#undef __SHIFT_TO_BOTTOM_RIGHT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_BOTTOM_RIGHT( I ) \ + static_cast( **this ).ShiftToBottomRight( width, height ) + + /*! + * Extends or crops the image at its left and top sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToBottomRight() + */ + ImageVariant& ShiftToBottomRight( int width, int height ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_BOTTOM_RIGHT ) + return *this; + } + +#undef __SHIFT_TO_BOTTOM_RIGHT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_BOTTOM_CENTER( I ) \ + static_cast( **this ).ShiftToCenter( width, height, fillValues ) + + /*! + * Extends or crops the image centered within the specified \a width and + * \a height in pixels. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToCenter() + */ + template + ImageVariant& ShiftToCenter( int width, int height, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_BOTTOM_CENTER ) + return *this; + } + +#undef __SHIFT_TO_BOTTOM_CENTER + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_BOTTOM_CENTER( I ) \ + static_cast( **this ).ShiftToCenter( width, height ) + + /*! + * Extends or crops the image centered within the specified \a width and + * \a height in pixels, filling extended regions with the minimum sample + * value in the native range of the image. Returns a reference to this + * image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToCenter() + */ + ImageVariant& ShiftToCenter( int width, int height ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_BOTTOM_CENTER ) + return *this; + } + +#undef __SHIFT_TO_BOTTOM_CENTER + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_TOP_LEFT( I ) \ + static_cast( **this ).ShiftToTopLeft( width, height, fillValues ) + + /*! + * Extends or crops the image at its right and bottom sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToTopLeft() + */ + template + ImageVariant& ShiftToTopLeft( int width, int height, const GenericVector& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_TOP_LEFT ) + return *this; + } + +#undef __SHIFT_TO_TOP_LEFT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_TOP_LEFT( I ) \ + static_cast( **this ).ShiftToTopLeft( width, height ) + + /*! + * Extends or crops the image at its right and bottom sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToTopLeft() + */ + ImageVariant& ShiftToTopLeft( int width, int height ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_TOP_LEFT ) + return *this; + } + +#undef __SHIFT_TO_TOP_LEFT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_TOP_RIGHT( I ) \ + static_cast( **this ).ShiftToTopRight( width, height, fillValues ) + + /*! + * Extends or crops the image at its left and bottom sides to the specified + * \a width and \a height in pixels. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToTopRight() + */ + template + ImageVariant& ShiftToTopRight( int width, int height, const GenericVector< T >& fillValues ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_TOP_RIGHT ) + return *this; + } + +#undef __SHIFT_TO_TOP_RIGHT + + // ------------------------------------------------------------------------- + +#define __SHIFT_TO_TOP_RIGHT( I ) \ + static_cast( **this ).ShiftToTopRight( width, height ) + + /*! + * Extends or crops the image at its left and bottom sides to the specified + * \a width and \a height in pixels, filling extended regions with the + * minimum sample value in the native range of the image. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::ShiftToTopRight() + */ + ImageVariant& ShiftToTopRight( int width, int height ) + { + if ( *this ) + SOLVE_TEMPLATE( __SHIFT_TO_TOP_RIGHT ) + return *this; + } + +#undef __SHIFT_TO_TOP_RIGHT + + // ------------------------------------------------------------------------- + +#define __STD_DEV( I ) \ + result = static_cast( **this ).StdDev( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the standard deviation of a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::StdDev() + */ + double StdDev( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __STD_DEV ) + return result; + } + +#undef __STD_DEV + + // ------------------------------------------------------------------------- + +#define __SUBTRACT( I ) \ + static_cast( **this ).Subtract( scalar, rect, firstChannel, lastChannel ) + + /*! + * Subtracts the specified \a scalar from a subset of pixel samples in this + * image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Subtract() + */ + template + ImageVariant& Subtract( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE( __SUBTRACT ) + return *this; + } + +#undef __SUBTRACT + + /*! + * A synonym for Subtract(). + */ + template + ImageVariant& Sub( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Subtract( scalar, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SUBTRACT_1( I ) \ + ImageVariant::Subtract( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __SUBTRACT_2( I ) \ + image1.Subtract( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Subtract( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_2( image2, __SUBTRACT_2 ) + } + +public: + + /*! + * Subtracts pixel samples of the specified \a image from a subset of pixel + * samples in this image. Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Subtract() + */ + ImageVariant& Subtract( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __SUBTRACT_1 ) + return *this; + } + +#undef __SUBTRACT_1 +#undef __SUBTRACT_2 + + /*! + * A synonym for Subtract(). + */ + ImageVariant& Sub( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + return Subtract( image, point, channel, rect, firstChannel, lastChannel ); + } + + // ------------------------------------------------------------------------- + +#define __SUBTRACTED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Subtracted( scalar, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Creates a local image with a subset of pixel samples from this image, and + * subtracts a \a scalar. Returns the resulting image. + * + * This member function is a generalized wrapper for + * GenericImage::Subtracted() + */ + template + ImageVariant Subtracted( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __SUBTRACTED ) + return result; + } + +#undef __SUBTRACTED + + // ------------------------------------------------------------------------- + +#define __SUM_OF_SQUARES( I ) \ + result = static_cast( **this ).SumOfSquares( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the sum of the squares of a subset of pixel samples. + * + * This member function is a generalized wrapper for + * GenericImage::SumOfSquares() + */ + double SumOfSquares( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, + int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __SUM_OF_SQUARES ) + return result; + } + +#undef __SUM_OF_SQUARES + + // ------------------------------------------------------------------------- + +#define __TRANSFER_IMAGE_1( I ) \ + ImageVariant::TransferImage( static_cast( **this ), image ) + +#define __TRANSFER_IMAGE_2( I ) \ + image1.Transfer( static_cast( *image2 ) ) + +private: + + template static + void TransferImage( GenericImage

& image1, ImageVariant& image2 ) + { + SOLVE_TEMPLATE_2( image2, __TRANSFER_IMAGE_2 ) + } + +public: + + /*! + * Transfers pixel data to this image from another \a image, which is an + * instance of a different template instantiation of %GenericImage. Returns + * a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Transfer() + */ + ImageVariant& TransferImage( ImageVariant& image ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE( __TRANSFER_IMAGE_1 ) + return *this; + } + +#undef __TRANSFER_IMAGE_1 +#undef __TRANSFER_IMAGE_2 + + // ------------------------------------------------------------------------- + +#define __TRANSFORM( I ) \ + static_cast( **this ).Transform( transform, rect, firstChannel, lastChannel ) + + /*! + * Applies a \e direct image transformation to a subset of pixel samples. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Transform() + */ + void Transform( BidirectionalImageTransformation& transform, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + if ( *this ) + SOLVE_TEMPLATE( __TRANSFORM ) + } + +#undef __TRANSFORM + + // ------------------------------------------------------------------------- + +#define __TRUNCATE( I ) \ + static_cast( **this ).Truncate( lowerBound, upperBound, rect, firstChannel, lastChannel ) + + /*! + * Truncates a subset of pixel samples to the specified range of values. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Truncate() + */ + template + ImageVariant& Truncate( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __TRUNCATE ) + return *this; + } + +#undef __TRUNCATE + + // ------------------------------------------------------------------------- + +#define __TRUNCATE( I ) \ + static_cast( **this ).Truncate( rect, firstChannel, lastChannel ) + + /*! + * Truncates a subset of pixel samples to the native range of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for + * GenericImage::Truncate() + */ + ImageVariant& Truncate( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __TRUNCATE ) + return *this; + } + +#undef __TRUNCATE + + // ------------------------------------------------------------------------- + +#define __TRUNCATED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Truncated( lowerBound, upperBound, rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * truncated to the specified range of values. + * + * This member function is a generalized wrapper for + * GenericImage::Truncated() + */ + template + ImageVariant Truncated( T lowerBound, T upperBound, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __TRUNCATED ) + return result; + } + +#undef __TRUNCATED + + // ------------------------------------------------------------------------- + +#define __TRUNCATED( I ) \ + result.SetImage( *new pcl::I( static_cast( **this ).Truncated( rect, firstChannel, lastChannel ) ) ); \ + result.SetOwnership( true ) + + /*! + * Returns a local image with a subset of pixel samples from this image, + * truncated to the native range of the image. + * + * This member function is a generalized wrapper for + * GenericImage::Truncated() + */ + ImageVariant Truncated( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + ImageVariant result; + if ( *this ) + SOLVE_TEMPLATE( __TRUNCATED ) + return result; + } + +#undef __TRUNCATED + + // ------------------------------------------------------------------------- + +#define __VARIANCE( I ) \ + result = static_cast( **this ).Variance( rect, firstChannel, lastChannel, maxProcessors ) + + /*! + * Returns the variance from the mean of a subset of pixel samples. + * + * This member function is a generalized wrapper for GenericImage::Variance() + */ + double Variance( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1, int maxProcessors = 0 ) const + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __VARIANCE ) + return result; + } + +#undef __VARIANCE + + // ------------------------------------------------------------------------- + +#define __WHITE( I ) \ + static_cast( **this ).White( rect, firstChannel, lastChannel ) + + /*! + * Fills a subset of pixel samples with the maximum sample value in the + * native range of the image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::White() + */ + ImageVariant& White( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __WHITE ) + return *this; + } + +#undef __WHITE + + // ------------------------------------------------------------------------- + +#define __WRITE( I ) \ + static_cast( **this ).Write( file, rect, firstChannel, lastChannel ) + + /*! + * Writes a subset of pixel samples to a raw-storage output stream. Returns + * a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Write() + */ + ImageVariant& Write( File& file, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + if ( *this ) + SOLVE_TEMPLATE( __WRITE ) + return const_cast( *this ); + } + +#undef __WRITE + + // ------------------------------------------------------------------------- + +#define __WRITE( I ) \ + static_cast( **this ).Write( filePath, rect, firstChannel, lastChannel ) + + /*! + * Writes a subset of pixel samples to a raw-storage output stream. Returns + * a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Write() + */ + ImageVariant& Write( const String& filePath, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) const + { + if ( *this ) + SOLVE_TEMPLATE( __WRITE ) + return const_cast( *this ); + } + +#undef __WRITE + + // ------------------------------------------------------------------------- + +#define __XNOR( I ) \ + static_cast( **this ).Xnor( scalar, rect, firstChannel, lastChannel ) + + /*! + * Performs a bitwise XNOR (exclusive NOR) operation between a subset of + * pixel samples in this image and the specified \a scalar. Returns a + * reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Xnor() + */ + template + ImageVariant& Xnor( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __XNOR ) + return *this; + } + +#undef __XNOR + + // ------------------------------------------------------------------------- + +#define __XNOR_1( I ) \ + ImageVariant::Xnor( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __XNOR_2( I ) \ + image1.Xnor( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Xnor( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_REAL_2( image2, __XNOR_2 ) + } + +public: + + /*! + * Performs a bitwise XNOR (NOT exclusive OR) operation between a subset of + * pixel samples in this image and the corresponding samples of the + * specified source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Xnor() + */ + ImageVariant& Xnor( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE_REAL( __XNOR_1 ) + return *this; + } + +#undef __XNOR_1 +#undef __XNOR_2 + + // ------------------------------------------------------------------------- + +#define __XOR( I ) \ + static_cast( **this ).Xor( scalar, rect, firstChannel, lastChannel ) + + /*! + * Performs a bitwise XOR (exclusive OR) operation between a subset of pixel + * samples in this image and the specified \a scalar. Returns a reference to + * this image. + * + * This member function is a generalized wrapper for GenericImage::Xor() + */ + template + ImageVariant& Xor( T scalar, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __XOR ) + return *this; + } + +#undef __XOR + + // ------------------------------------------------------------------------- + +#define __XOR_1( I ) \ + ImageVariant::Xor( static_cast( **this ), image, point, channel, rect, firstChannel, lastChannel ) + +#define __XOR_2( I ) \ + image1.Xor( static_cast( *image2 ), point, channel, rect, firstChannel, lastChannel ) + +private: + + template static + void Xor( GenericImage

& image1, const ImageVariant& image2, + const Point& point, int channel, + const Rect& rect, int firstChannel, int lastChannel ) + { + SOLVE_TEMPLATE_REAL_2( image2, __XOR_2 ) + } + +public: + + /*! + * Performs a bitwise XOR (exclusive OR) operation between a subset of pixel + * samples in this image and the corresponding samples of the specified + * source \a image. Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Xor() + */ + ImageVariant& Xor( const ImageVariant& image, + const Point& point = Point( int_max ), int channel = -1, + const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + if ( image ) + SOLVE_TEMPLATE_REAL( __XOR_1 ) + return *this; + } + +#undef __XOR_1 +#undef __XOR_2 + + // ------------------------------------------------------------------------- + +#define __ZERO( I ) \ + static_cast( **this ).Zero( rect, firstChannel, lastChannel ) + + /*! + * Fills a subset of pixel samples with the constant value resulting from + * converting the scalar zero (0) to the sample data type of the image. + * Returns a reference to this image. + * + * This member function is a generalized wrapper for GenericImage::Zero() + */ + ImageVariant& Zero( const Rect& rect = Rect( 0 ), int firstChannel = -1, int lastChannel = -1 ) + { + if ( *this ) + SOLVE_TEMPLATE_REAL( __ZERO ) + return *this; + } + +#undef __ZERO + + // ------------------------------------------------------------------------- + +#define __COMPRESS( I ) \ + return static_cast( **this ).Compress( compressor, rect, channel, perf ) + + /*! + * Compression of pixel samples from the image transported by an + * %ImageVariant. Returns a list of compressed sub-blocks. + * + * If this %ImageVariant object does not transport an image, this function + * returns an empty array. + * + * This member function is a generalized wrapper for + * GenericImage::Compress(). + */ + Compression::subblock_list Compress( const Compression& compressor, + const Rect& rect = Rect( 0 ), int channel = -1, + Compression::Performance* perf = nullptr ) const + { + if ( *this ) + SOLVE_TEMPLATE( __COMPRESS ) + return Compression::subblock_list(); + } + +#undef __COMPRESS + + // ------------------------------------------------------------------------- + + /*! + * Returns true iff this %ImageVariant object transports an image that is an + * instance of the same template instantiation of the specified image. + */ + template + bool IsAs( const pcl::GenericImage

& ) const + { + return m_data->image && m_data->isFloatSample == P::IsFloatSample() && + m_data->isComplexSample == P::IsComplexSample() && + m_data->bitsPerSample == P::BitsPerSample(); + } + + /*! + * Assigns another instance of %ImageVariant to this object. Returns a + * reference to this object. + * + * If the previously transported image (if any) was owned by %ImageVariant, + * and there are no more ImageVariant references to it, then it is destroyed + * before assignment. + */ + ImageVariant& Assign( const ImageVariant& image ) + { + image.m_data->Attach(); + DetachFromData(); + m_data = image.m_data; + return *this; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * This operator calls Assign() with the specified source \a image. + */ + ImageVariant& operator =( const ImageVariant& image ) + { + return Assign( image ); + } + +#define TRANSFER_BODY() \ + if ( &image != this ) /* N.B.: Self-movement incompatible with server-side SharedImage */ \ + { \ + DetachFromData(); \ + m_data = image.m_data; \ + image.m_data = nullptr; \ + } \ + return *this + + /*! + * Transfers the image transported by other %ImageVariant to this object. + * Returns a reference to this object. + * + * If the previously transported image (if any) was owned by %ImageVariant, + * and there are no more ImageVariant references to it, then it is destroyed + * before assignment. + * + * After calling this function, the specified source \a image is left in an + * invalid state and should be destroyed immediately. + */ + ImageVariant& Transfer( ImageVariant& image ) + { + TRANSFER_BODY(); + } + + /*! + * Transfers the image transported by other %ImageVariant to this object. + * Returns a reference to this object. + * + * If the previously transported image (if any) was owned by %ImageVariant, + * and there are no more ImageVariant references to it, then it is destroyed + * before assignment. + * + * After calling this function, the specified source \a image is left in an + * invalid state and should be destroyed immediately. + */ + ImageVariant& Transfer( ImageVariant&& image ) + { + TRANSFER_BODY(); + } + +#undef TRANSFER_BODY + + /*! + * Move assignment operator. Returns a reference to this object. + * + * This operator calls Transfer() with the specified source \a image. + */ + ImageVariant& operator =( ImageVariant&& image ) + { + return Transfer( image ); + } + + /*! + * Releases the image transported by this object and forces another + * %ImageVariant instance to transport it. + * + * Unlike move assignment (or, equivalently, the Transfer() member + * function), this object will be in a valid empty state after calling this + * function. + */ + void ReleaseTo( ImageVariant& image ) + { + if ( &image != this ) // N.B.: Self-release incompatible with server-side SharedImage. + { + Data* newData = new Data; + image.DetachFromData(); + image.m_data = m_data; + m_data = newData; + } + } + + /*! + * Forces this instance of %ImageVariant to transport the specified image. + * Returns a reference to this object. + * + * If the previously transported image (if any) was owned by %ImageVariant, + * and there are no more %ImageVariant references to it, then it is + * destroyed before referencing the specified image. + */ + template + ImageVariant& SetImage( GenericImage

& image ) + { + if ( &image != m_data->image ) + { + Free(); + m_data->Update( &image ); + } + return *this; + } + + /*! + * Exchanges two %ImageVariant instances \a x1 and \a x2. + */ + friend void Swap( ImageVariant& x1, ImageVariant& x2 ) noexcept + { + pcl::Swap( x1.m_data, x2.m_data ); + } + + /*! + * Creates a new image with the specified sample data type. Returns a + * reference to this object. + * + * \param isFloat If true, floating-point real samples will be used. + * + * \param isComplex If true, complex pixel samples (implicitly + * floating-point) will be used. + * + * \param bitSize Number of bits per sample. The supported combinations + * are:\n + * \n + * \li For floating-point samples (real or complex): 32 or 64.\n + * \li For integer samples: 8, 16 or 32. + * + * If the previously transported image (if any) was owned by %ImageVariant, + * and there are no more %ImageVariant references to it, then it is + * destroyed before creating the new image. + * + * The newly created image will be empty. To allocate pixel data, you must + * call GenericImage::AllocateData() explicitly. + * + * The newly created image will be owned by %ImageVariant. + */ + ImageVariant& CreateImage( bool isFloat, bool isComplex, int bitSize ) + { + if ( isFloat ) + { + if ( isComplex ) + CreateComplexImage( bitSize ); + else + CreateFloatImage( bitSize ); + } + else + { + if ( !isComplex ) + CreateUIntImage( bitSize ); + /* + else + { + ### Yeah this is true, but everybody already knows so we don't want + to replicate this useless message everywhere! + throw Error( "Integer-valued complex images not supported by this PCL version." ); + } + */ + } + + return *this; + } + +#define CREATE_IMAGE( I ) m_data->Update( new pcl::I ) + + /*! + * Creates a new floating point real image with the specified sample size + * in bits. Returns a reference to this object. + * + * \param bitSize Sample size in bits for the newly created real image. + * Valid argument values are 32 and 64. The default value + * is 32. + * + * This function is a convenience shortcut for: + * + * \code CreateImage( true, false, bitSize ); \endcode + */ + ImageVariant& CreateFloatImage( int bitSize = 32 ) + { + PCL_PRECONDITION( bitSize == 32 || bitSize == 64 ) + Free(); + switch ( bitSize ) + { + case 32: CREATE_IMAGE( Image ); break; + case 64: CREATE_IMAGE( DImage ); break; + } + m_data->ownsImage = m_data->image != nullptr; + return *this; + } + + /*! + * Creates a new 32-bit floating point real image. Returns a reference to + * this object. + * + * This function is a convenience shortcut for: + * + * \code CreateFloatImage(); \endcode + */ + ImageVariant& CreateImage() + { + return CreateFloatImage(); + } + + /*! + * Creates a new floating point complex image with the specified sample + * size in bits. Returns a reference to this object. + * + * \param bitSize Sample size in bits for the newly created complex + * image. Valid argument values are 32 and 64. + * + * This function is a convenience shortcut for: + * + * \code CreateImage( true, true, bitSize ); \endcode + */ + ImageVariant& CreateComplexImage( int bitSize = 32 ) + { + PCL_PRECONDITION( bitSize == 32 || bitSize == 64 ) + Free(); + switch ( bitSize ) + { + case 32: CREATE_IMAGE( ComplexImage ); break; + case 64: CREATE_IMAGE( DComplexImage ); break; + } + m_data->ownsImage = m_data->image != nullptr; + return *this; + } + + /*! + * Creates a new unsigned integer image with the specified sample size in + * bits. Returns a reference to this object. + * + * \param bitSize Sample size in bits for the newly integer image. Valid + * argument values are 8, 16 and 32. + * + * This function is a convenience shortcut for: + * + * \code CreateImage( false, false, bitSize ); \endcode + */ + ImageVariant& CreateUIntImage( int bitSize = 16 ) + { + PCL_PRECONDITION( bitSize == 8 || bitSize == 16 || bitSize == 32 ) + Free(); + switch ( bitSize ) + { + case 8: CREATE_IMAGE( UInt8Image ); break; + case 16: CREATE_IMAGE( UInt16Image ); break; + case 32: CREATE_IMAGE( UInt32Image ); break; + } + m_data->ownsImage = m_data->image != nullptr; + return *this; + } + +#undef CREATE_IMAGE + + /*! + * Creates a new image with the same sample data type (template + * instantiation) as the specified image. Returns a reference to this + * object. + * + * \param image %Image to obtain sample data type parameters from. + * + * This function is a convenience shortcut for: + * + * \code + * CreateImage( P::IsFloatSample(), P::IsComplexSample(), P::BitsPerSample() ); + * \endcode + */ + template + ImageVariant& CreateImageAs( const pcl::GenericImage

& image ) + { + return CreateImage( P::IsFloatSample(), P::IsComplexSample(), P::BitsPerSample() ); + } + + /*! + * Creates a new image with the same sample data type (template + * instantiation) as the specified %ImageVariant object. Returns a reference + * to this object. + * + * \param image %ImageVariant to obtain sample data type parameters from. + * + * This function is a convenience shortcut for: + * + * \code + * CreateImage( image.IsFloatSample(), image.IsComplexSample(), image.BitsPerSample() ); + * \endcode + */ + ImageVariant& CreateImageAs( const ImageVariant& image ) + { + return CreateImage( image.IsFloatSample(), image.IsComplexSample(), image.BitsPerSample() ); + } + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + + /*! + * Creates a new shared image with the specified sample data type. Returns a + * reference to this object. + * + * \param isFloat If true, floating-point real pixels will be used. + * + * \param isComplex If true, complex pixels ( implicitly floating point ) + * will be used. + * + * \param bitSize Number of bits per sample. The supported combinations + * are:\n + * \n + * \li For floating-point samples ( real or complex ): 32 or 64.\n + * \li For integer samples: 8, 16 or 32. + * + * This member function works in an equivalent way to: + * + * \code CreateImage( bool isFloat, bool isComplex, int bitSize ); \endcode + * + * except that this function creates a shared image, while + * CreateImage() creates a local image. A shared image is an alias + * to an image that lives in the PixInsight core application, while a local + * image is a private object in the local heap of the calling module. + * + * Shared images are particularly useful for processes involving + * intermodule communication in the PixInsight platform. An example + * is the FileFormatInstance class, which can be used to perform file I/O + * operations by invoking any installed file format support module on the + * platform. %FileFormatInstance requires shared images to read/write images + * from/to disk files (you can actually pass a local image to + * %FileFormatInstance, but then PCL will generate and use a temporary + * \e shared working image on the fly, wasting memory unnecessarily). + */ + ImageVariant& CreateSharedImage( bool isFloat, bool isComplex, int bitSize ) + { + if ( isFloat ) + { + if ( isComplex ) + CreateSharedComplexImage( bitSize ); + else + CreateSharedFloatImage( bitSize ); + } + else + { + if ( !isComplex ) + CreateSharedUIntImage( bitSize ); + } + + return *this; + } + +#define CREATE_SHARED_IMAGE( I ) m_data->Update( new pcl::I( (void*)0, 0, 0 ) ) + + /*! + * Creates a new shared, floating point real image with the specified sample + * size in bits. Returns a reference to this object. + * + * \param bitSize Sample size in bits for the newly created real image. + * Valid argument values are 32 and 64. + * + * This function is a convenience shortcut for: + * + * \code CreateSharedImage( true, false, bitSize ); \endcode + * + * For an equivalent member function that creates a local image, see + * CreateFloatImage(). + */ + ImageVariant& CreateSharedFloatImage( int bitSize = 32 ) + { + PCL_PRECONDITION( bitSize == 32 || bitSize == 64 ) + Free(); + switch ( bitSize ) + { + case 32: CREATE_SHARED_IMAGE( Image ); break; + case 64: CREATE_SHARED_IMAGE( DImage ); break; + } + m_data->ownsImage = m_data->image != nullptr; + return *this; + } + + /*! + * Creates a new shared, 32-bit floating point real image. Returns a + * reference to this object. + * + * This function is a convenience shortcut for: + * + * \code CreateSharedFloatImage( 32 ); \endcode + * + * For an equivalent member function that creates a local image, see + * CreateImage(). + */ + ImageVariant& CreateSharedImage() + { + return CreateSharedFloatImage(); + } + + /*! + * Creates a new shared, floating point complex image with the specified + * sample size in bits. Returns a reference to this object. + * + * \param bitSize Sample size in bits for the newly created complex + * image. Valid argument values are 32 and 64. + * + * This function is a convenience shortcut for: + * + * \code CreateSharedImage( true, true, bitSize ); \endcode + * + * For an equivalent member function that creates a local image, see + * CreateComplexImage(). + */ + ImageVariant& CreateSharedComplexImage( int bitSize = 32 ) + { + PCL_PRECONDITION( bitSize == 32 || bitSize == 64 ) + Free(); + switch ( bitSize ) + { + case 32: CREATE_SHARED_IMAGE( ComplexImage ); break; + case 64: CREATE_SHARED_IMAGE( DComplexImage ); break; + } + m_data->ownsImage = m_data->image != nullptr; + return *this; + } + + /*! + * Creates a new shared, unsigned integer image with the specified sample + * size in bits. Returns a reference to this object. + * + * \param bitSize Sample size in bits for the newly integer image. Valid + * argument values are 8, 16 and 32. + * + * This function is a convenience shortcut for: + * + * \code CreateImage( false, false, bitSize ); \endcode + * + * For an equivalent member function that creates a local image, see + * CreateUIntImage(). + */ + ImageVariant& CreateSharedUIntImage( int bitSize = 16 ) + { + PCL_PRECONDITION( bitSize == 8 || bitSize == 16 || bitSize == 32 ) + Free(); + switch ( bitSize ) + { + case 8: CREATE_SHARED_IMAGE( UInt8Image ); break; + case 16: CREATE_SHARED_IMAGE( UInt16Image ); break; + case 32: CREATE_SHARED_IMAGE( UInt32Image ); break; + } + m_data->ownsImage = m_data->image != nullptr; + return *this; + } + +#undef CREATE_SHARED_IMAGE + + /*! + * Creates a new shared image with the same sample data type ( template + * instantiation ) as the specified image. Returns a reference to this + * object. + * + * \param image %Image to obtain sample data type parameters from. + * + * This function is a convenience shortcut for: + * + * \code + * CreateSharedImage( P::IsFloatSample(), P::IsComplexSample(), P::BitsPerSample() ); + * \endcode + * + * For an equivalent member function that creates a local image, see + * CreateImageAs( const pcl::GenericImage& ). + */ + template + ImageVariant& CreateSharedImageAs( const pcl::GenericImage

& image ) + { + return CreateSharedImage( P::IsFloatSample(), P::IsComplexSample(), P::BitsPerSample() ); + } + + /*! + * Creates a new shared image with the same sample data type ( template + * instantiation ) as the specified %ImageVariant object. Returns a + * reference to this object. + * + * \param image %ImageVariant to obtain sample data type parameters from. + * + * This function is a convenience shortcut for: + * + * \code + * CreateSharedImage( image.IsFloatSample(), image.IsComplexSample(), image.BitsPerSample() ); + * \endcode + * + * For an equivalent member function that creates a local image, see + * CreateImageAs( const ImageVariant& ). + */ + ImageVariant& CreateSharedImageAs( const ImageVariant& image ) + { + return CreateSharedImage( image.IsFloatSample(), image.IsComplexSample(), image.BitsPerSample() ); + } + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +#define ALLOCATE_IMAGE( I ) \ + static_cast( **this ).AllocateData( width, height, numberOfChannels, colorSpace ) + + /*! + * Allocates pixel data in the image transported by this %ImageVariant + * instance, with the specified geometry and color space. Returns a + * reference to this object. + * + * \param width Width of the newly created image in pixels. + * + * \param height Height of the newly created image in pixels. + * + * \param numberOfChannels Number of channels. Must be larger or equal to + * the number of nominal channels, as imposed by + * the specified color space. + * + * \param colorSpace Color space. See the ColorSpace namespace for + * symbolic constants. + * + * If this %ImageVariant object transports no image, a new one is created in + * 32-bit floating point format. %ImageVariant will own the newly created + * image in this case. + * + * This function is useful to allocate pixel data without having to resolve + * the template instantiation of the transported image. PCL allocates pixels + * of the appropriate sample data type transparently. + */ + ImageVariant& AllocateImage( int width, int height, int numberOfChannels, color_space colorSpace ) + { + if ( !*this ) + CreateImage(); + SOLVE_TEMPLATE( ALLOCATE_IMAGE ) + return *this; + } + +#undef ALLOCATE_IMAGE + +#define COPY_IMAGE( I ) static_cast( **this ).Assign( image ) + + /*! + * Assigns an image to the image transported by this %ImageVariant instance. + * Returns a reference to this object. + * + * \param image %Image to assign. + * + * The assigned image can be an instance of any supported template + * instantiation of GenericImage. If this %ImageVariant object transports no + * image, a new one is created as an instance of the same template + * instantiation as the specified source image. In this case, %ImageVariant + * will own the newly created image. + * + * This function is useful to assign an image without having to resolve the + * template instantiation of the transported image. PCL performs the + * assignment between different image types transparently. + */ + template + ImageVariant& CopyImage( const GenericImage

& image ) + { + if ( !*this ) + CreateImageAs( image ); + SOLVE_TEMPLATE( COPY_IMAGE ) + return *this; + } + +#undef COPY_IMAGE + +#define COPY_IMAGE( I ) CopyImage( static_cast( *image ) ) + + /*! + * Assigns an image transported by another %ImageVariant instance to the + * image transported by this object. Returns a reference to this object. + * + * \param image Source %ImageVariant instance whose transported image will + * be assigned. + * + * This function calls CopyImage( const I& ) after resolving the template + * instantiation of the transported image. See the documentation of that + * function for details. + */ + ImageVariant& CopyImage( const ImageVariant& image ) + { + if ( image ) + SOLVE_TEMPLATE_2( image, COPY_IMAGE ) + else + FreeImage(); + return *this; + } + +#undef COPY_IMAGE + +#define FREE_IMAGE( I ) static_cast( **this ).FreeData() + + /*! + * Destroys the existing pixel data in the image transported by this + * %ImageVariant instance. Returns a reference to this object. + * + * This function is useful to deallocate pixel data without having to + * resolve the template instantiation of the transported image. PCL + * deallocates pixel data of any supported pixel sample type transparently. + * + * If this %ImageVariant transports no image, this function has no effect. + * + * \note Unlike the Free() member function, this function cannot destroy + * the transported image, but only its pixel data. Note that this function + * destroys pixel data irrespective of whether %ImageVariant owns the + * transported image. + */ + ImageVariant& FreeImage() + { + if ( *this ) + SOLVE_TEMPLATE( FREE_IMAGE ) + return *this; + } + + /*! + * Returns a pointer to a dynamically allocated Compression object. The + * returned object implements the specified raw storage compression + * \a algorithm for compression of a contiguous sequence of elements with + * \a itemSize bytes each. + */ + static Compression* NewCompression( swap_compression algorithm, int itemSize = 1 ); + +#undef FREE_IMAGE + + /*! + * Writes the image transported by this %ImageVariant instance to a raw + * storage file. + * + * \param filePath A file path specification where the output raw + * storage file will be created. + * + * \param compression Compression algorithm. If specified, all stored + * pixel data will be compressed using this algorithm. + * Compression is disabled by default + * + * \param perf If non-null, pointer to a Compression::Performance + * structure where compression performance data will be + * provided if the raw file is compressed. + * + * \param processEvents If true, Module->ProcessEvents() will be called at + * regular intervals during the file write operation. + * This is useful to keep the graphical interface + * responsive during long disk operations. The default + * value is false. + * + * The generated file can be employed to construct a new image instance by + * calling the ReadSwapFile() member function with the same file path + * specification. + * + * This function is useful to write pixel data without having to resolve the + * template instantiation of the transported image. PCL writes pixel data of + * any supported sample type transparently. + */ + void WriteSwapFile( const String& filePath, + swap_compression compression = SwapCompression::None, + Compression::Performance* perf = nullptr, + bool processEvents = false ) const; + + /*! + * Writes the image transported by this %ImageVariant object to a set of + * raw storage files using parallel disk write operations. + * + * \param fileName Base file name for the raw storage files. + * + * \param directories A list of directories where the set of raw files + * will be created by this function. + * + * \param compression Compression algorithm. If specified, all stored + * pixel data will be compressed using this algorithm. + * Compression is disabled by default + * + * \param perf If non-null, pointer to a Compression::Performance + * structure where compression performance data will be + * provided if the raw files are compressed. Output + * performance values are the averages of the same + * values computed for all threads. + * + * \param processEvents If true, Module->ProcessEvents() will be called at + * regular intervals during the file write operation. + * This is useful to keep the graphical interface + * responsive during long disk operations. The default + * value is false. + * + * Each string in the \a directories string list must be a full path + * specification to an existing directory. On each directory, an output file + * will be created and an independent execution thread will write the + * corresponding section of the pixel data from the image transported by + * this %ImageVariant. To retrieve the data, call the ReadSwapFiles() member + * function with the same base file name and output directories. + * + * \warning This function is not thread-safe: it can only be called from the + * root thread. This function will throw an Error exception if it is called + * from a local thread. + */ + void WriteSwapFiles( const String& fileName, const StringList& directories, + swap_compression compression = SwapCompression::None, + Compression::Performance* perf = nullptr, + bool processEvents = false ) const; + /*! + * Reads the image transported by this %ImageVariant instance from a raw + * storage file. + * + * \param filePath A file path specification to an existing raw storage + * image file. + * + * \param perf If non-null, pointer to a Compression::Performance + * structure where compression performance data will be + * provided if the raw file is compressed. + * + * \param processEvents If true, Module->ProcessEvents() will be called at + * regular intervals during the file read operation. + * This is useful to keep the graphical interface + * responsive during long disk operations. The default + * value is false. + * + * If necessary, the transported image is re-created as an instance of a + * different template instantiation, to match the sample data type stored + * in the input file. + * + * In any case, if %ImageVariant owned the previously transported image ( if + * any ), it is destroyed before reading the new one. + * + * This function is useful to read pixel data without having to resolve + * template instantiation, neither of the input file nor of the transported + * image. PCL does all the necessary data reading, decompression, allocation + * and deallocation transparently. + */ + void ReadSwapFile( const String& filePath, + Compression::Performance* perf = nullptr, + bool processEvents = false ); + + /*! + * Reads an image from a set of raw storage files using parallel disk read + * operations. + * + * \param fileName Base file name for the raw storage files. + * + * \param directories A list of directories where the set of raw files + * have been created by a previous call to + * WriteSwapFiles( const String&, const StringList& ). + * + * \param perf If non-null, pointer to a Compression::Performance + * structure where compression performance data will be + * provided if the raw files are compressed. Output + * performance values are the averages of the same + * values computed for all threads. + * + * \param processEvents If true, Module->ProcessEvents() will be called at + * regular intervals during the file read operation. + * This is useful to keep the graphical interface + * responsive during long disk operations. The default + * value is false. + * + * The read image will be transported and owned by this %ImageVariant + * instance. If an image is already transported by this object before + * calling this function, it is removed by a call to Free() prior to the + * reading operation. + * + * If necessary, the transported image is re-created as an instance of a + * different template instantiation, to match the sample data type stored + * in the input file(s). + * + * \warning This function is not thread-safe: it can only be called from the + * root thread. This function will throw an Error exception if it is called + * from a local thread. + */ + void ReadSwapFiles( const String& fileName, const StringList& directories, + Compression::Performance* perf = nullptr, + bool processEvents = false ); + + /*! + * Merges the image transported by this object with pixel data read from a + * raw storage file, masking it with the image transported by another + * %ImageVariant instance. + * + * \param filePath A file path specification to an existing raw storage + * image file. + * + * \param mask A reference to an %ImageVariant instance whose + * transported image will act as a mask for the merge + * operation. + * + * \param invert If this argument is true, mask pixels will be + * inverted before carrying out the merge operation. + * + * \param processEvents If true, Module->ProcessEvents() will be called at + * regular intervals during the file read operation. + * This is useful to keep the graphical interface + * responsive during long disk operations. The default + * value is false. + * + * Given a pixel \b V of the image transported by this instance, a pixel + * \b S read from the input file, and a pixel \b M of the mask image, the + * original pixel \b V is replaced by the result \b V' of the following + * expression: + * + *

+    * if invert
+    *    M = 1 - M
+    * V' = V*( 1 - M ) + S*M
+    * 
+ * + * in the normalized real range [0,1], where \b 1 represents a saturated + * (usually white) pixel sample value. + */ + void MaskFromSwapFile( const String& filePath, const ImageVariant& mask, bool invert = false, + bool processEvents = false ); + + /*! + * Merges the image transported by this object with pixel data read from a + * set of raw storage files through parallel disk read operations, masking + * it with the image transported by another %ImageVariant instance. + * + * \param fileName Base file name for the raw storage files from which + * source pixels will be read to be merged with this + * image. + * + * \param directories A list of directories where the set of raw files + * have been created by a previous call to + * WriteSwapFiles( const String&, const StringList& ). + * + * \param mask A reference to an %ImageVariant instance whose + * transported image will act as a mask for the merge + * operation. + * + * \param invert If this argument is true, mask pixels will be + * inverted before carrying out the merge operation. + * + * \param processEvents If true, Module->ProcessEvents() will be called at + * regular intervals during the file read operation. + * This is useful to keep the graphical interface + * responsive during long disk operations. The default + * value is false. + * + * This routine produces exactly the same result as its single-threaded + * counterpart MaskFromSwapFile(). + * + * \warning This function is not thread-safe: it can only be called from the + * root thread. This function will throw an Error exception if it is called + * from a local thread. + */ + void MaskFromSwapFiles( const String& fileName, const StringList& directories, + const ImageVariant& mask, bool invert = false, + bool processEvents = false ); + + /*! + * Deletes all raw storage files previously created by a call to the + * WriteSwapFile() member function. + */ + static void DeleteSwapFile( const String& filePath ); + + /*! + * Deletes all raw storage files previously created by a call to the + * WriteSwapFiles() member function. + * + * \warning This function is not thread-safe: it can only be called from the + * root thread. This function will throw an Error exception if it is called + * from a local thread. + */ + static void DeleteSwapFiles( const String& fileName, const StringList& directories ); + + /*! + * Returns the total size in bytes occupied by a raw storage image file. + * + * \param filePath A file path specification to an existing raw storage + * image file. + * + * This function does not read any pixel data. All the required data to + * compute the returned file size is retrieved from existing file headers. + */ + static uint64 SwapFileSize( const String& filePath ); + + /*! + * Returns the total size in bytes occupied by a set of raw storage files. + * + * \param fileName Base file name for the raw storage files. + * + * \param directories A list of directories where the set of raw files + * have been created by a previous call to + * WriteSwapFiles( const String&, const StringList& ). + * + * This function does not read any pixel data. All the required data to + * compute the returned file size is retrieved from existing file headers. + */ + static uint64 SwapFilesSize( const String& fileName, const StringList& directories ); + + /*! + * Merges the image transported by this object with the image transported by + * another %ImageVariant instance, masking it with the image transported by + * a third %ImageVariant instance. + * + * \param src A reference to an %ImageVariant instance whose transported + * image will be the source of the merge operation. + * + * \param mask A reference to an %ImageVariant instance whose transported + * image will act as a mask for the merge operation. + * + * \param invert If this argument is true, mask pixels will be inverted + * before carrying out the merge operation. + * + * Given a pixel \b V of the image transported by this instance, a pixel + * \b S of the image transported by the source %ImageVariant instance, and a + * pixel \b M of the mask image, the original pixel \b V is replaced by the + * result \b V' of the following expression: + * + *
+    * if invert
+    *    M = 1 - M
+    * V' = V*( 1 - M ) + S*M
+    * 
+ * + * in the normalized real range [0,1], where \b 1 represents a saturated + * (usually white) pixel sample value. + */ + void MaskImage( const ImageVariant& src, const ImageVariant& mask, bool invert = false ); + + /*! + * Returns true iff %ImageVariant owns the image transported by this + * instance, if any. + */ + bool OwnsImage() const noexcept + { + return m_data->ownsImage; + } + + /*! + * Causes %ImageVariant to own the transported image, if any. Returns a + * reference to this object. + * + * \note If %ImageVariant owns a transported image, it is destroyed when all + * instances of %ImageVariant referencing that image are destroyed. It is + * very important to point out that ownership of transported images is a + * class-wide property of %ImageVariant, not a private property of + * any particular %ImageVariant instance. + */ + ImageVariant& SetOwnership( bool owner = true ) noexcept + { + m_data->ownsImage = owner && m_data->image; + return *this; + } + + /*! + * Removes the transported image, if there is one, from this %ImageVariant + * object. Returns a reference to this object. + * + * If the transported image is owned by %ImageVariant, and there are no more + * %ImageVariant references to it, then it is also destroyed. + */ + ImageVariant& Free() + { + if ( m_data->IsUnique() ) + m_data->Free(); + else + { + Data* newData = new Data; + DetachFromData(); + m_data = newData; + } + return *this; + } + + /*! + * Structure member selection operator. Returns a pointer to the constant + * image transported by this %ImageVariant object. + * + * \warning Do not call this member function if the %ImageVariant does not + * transport an image. + */ + const AbstractImage* operator ->() const noexcept + { + PCL_PRECONDITION( m_data->image != nullptr ) + return m_data->image; + } + + /*! + * Structure member selection operator. Returns a pointer to the image + * transported by this %ImageVariant object. + * + * \warning Do not call this member function if the %ImageVariant does not + * transport an image. + */ + AbstractImage* operator ->() noexcept + { + PCL_PRECONDITION( m_data->image != nullptr ) + return m_data->image; + } + + /*! + * Dereference operator. Returns a reference to the constant image + * transported by this %ImageVariant object. + * + * \warning Do not call this member function if the %ImageVariant does not + * transport an image. + */ + const AbstractImage& operator *() const noexcept + { + PCL_PRECONDITION( m_data->image != nullptr ) + return *m_data->image; + } + + /*! + * Dereference operator. Returns a reference to the image transported by + * this %ImageVariant object. + * + * \warning Do not call this member function if the %ImageVariant does not + * transport an image. + */ + AbstractImage& operator *() noexcept + { + PCL_PRECONDITION( m_data->image != nullptr ) + return *m_data->image; + } + + /*! + * Returns true iff this %ImageVariant instance transports an image. + */ + operator bool() const noexcept + { + return m_data->image != nullptr; + } + +#define __PIXEL_ACCESS_OPERATOR( I ) \ + pcl::I::pixel_traits::FromSample( result, *static_cast( **this ).PixelAddress( x, y, channel ) ) + + /*! + * Returns a pixel sample value, given by its pixel coordinates and channel + * index. + * + * \param x Horizontal coordinate (or column index) of the desired + * pixel, 0 ≤ \a x < \a w, where \a w is the width in + * pixels of this image. + * + * \param y Vertical coordinate (or row index) of the desired scan + * line, 0 ≤ \a y < \a h, where \a h is the height in + * pixels of this image. + * + * \param channel Channel index, 0 ≤ \a channel < \a n, where \a n is + * the number of channels in this image, including nominal + * and alpha channels. The default value is zero. + * + * This member function returns the requested pixel sample in the normalized + * range [0,1], irrespective of the sample data type of the image. This + * function conventionally returns zero if this object transports no image. + * + * \note For the sake of performance, this function does not check validity + * of coordinates and channel indexes. Specifying invalid coordinates may + * lead to unpredictable results, most likey raising an access violation + * signal or exception. + */ + double operator ()( int x, int y, int channel = 0 ) const noexcept + { + double result = 0; + if ( *this ) + SOLVE_TEMPLATE( __PIXEL_ACCESS_OPERATOR ) + return result; + } + +#undef __PIXEL_ACCESS_OPERATOR + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + + bool IsShared() const noexcept + { + return m_shared != nullptr; + } + + // Implemented in SharedImage.cpp + pi::SharedImage* GetSharedImage( bool rdOnly = false ) const; + pi::SharedImage* NewSharedImage( void* owner, bool rdOnly = false ); + +#endif + +private: + + struct Data : public ReferenceCounter + { + AbstractImage* image = nullptr; + bool isFloatSample = false; + bool isComplexSample = false; + uint8 bitsPerSample = 0; + bool ownsImage = false; + + Data() = default; + + ~Data() + { + Free(); + } + + template + void Update( GenericImage

* a_image ) noexcept + { + image = a_image; + isFloatSample = P::IsFloatSample(); + isComplexSample = P::IsComplexSample(); + bitsPerSample = uint8( P::BitsPerSample() ); + } + + void Free() + { + if ( ownsImage ) + delete image; + image = nullptr; + isFloatSample = isComplexSample = false; + bitsPerSample = 0; + //ownsImage = ownsImage; ### N.B.: Ownership must *not* change here + } + }; + + Data* m_data = nullptr; + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + // This is the server-side part of the image sharing mechanism + pi::SharedImage* m_shared = nullptr; +#else + const void* m_shared = nullptr; +#endif + + void DetachFromData() + { + if ( !m_data->Detach() ) + delete m_data; + } + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + // Server-side private ctor. used by View + template + ImageVariant( GenericImage

* image, int ) + { + m_data = new Data; + m_data->Update( image ); + m_data->ownsImage = true; + } +#endif + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION + friend class pi::SharedImage; +#else + friend class View; + friend class ImageView; +#endif +}; + +// ---------------------------------------------------------------------------- + +/* + * Implementation of member functions of GenericImage requiring a full + * declaration of ImageVariant. + */ + +template inline +void GenericImage

::GetLuminance( ImageVariant& Y, const Rect& rect, int maxProcessors ) const +{ + ImageVariant( const_cast*>( this ) ).GetLuminance( Y, rect, maxProcessors ); +} + +template inline +void GenericImage

::GetLightness( ImageVariant& L, const Rect& rect, int maxProcessors ) const +{ + ImageVariant( const_cast*>( this ) ).GetLightness( L, rect, maxProcessors ); +} + +template inline +void GenericImage

::GetIntensity( ImageVariant& I, const Rect& rect, int maxProcessors ) const +{ + ImageVariant( const_cast*>( this ) ).GetIntensity( I, rect, maxProcessors ); +} + +template inline +GenericImage

& GenericImage

::SetLuminance( const ImageVariant& Y, const Point& point, const Rect& rect, int maxProcessors ) +{ + (void)ImageVariant( this ).SetLuminance( Y, point, rect, maxProcessors ); + return *this; +} + +template inline +GenericImage

& GenericImage

::SetLightness( const ImageVariant& L, const Point& point, const Rect& rect, int maxProcessors ) +{ + (void)ImageVariant( this ).SetLightness( L, point, rect, maxProcessors ); + return *this; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ImageVariant_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageVariant.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageView.h b/3rdparty/include/pcl/ImageView.h new file mode 100644 index 0000000..6958794 --- /dev/null +++ b/3rdparty/include/pcl/ImageView.h @@ -0,0 +1,1459 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageView.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_ImageView_h +#define __PCL_ImageView_h + +/// \file pcl/ImageView.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageView + * \brief Client-side interface to a PixInsight %ImageView control. + * + * ### TODO: Write a detailed description for %ImageView. + * + * \sa ImageWindow + */ +class PCL_CLASS ImageView : public ScrollBox +{ +public: + + /*! + * Represents a GUI working mode. Valid modes are defined in the ImageMode + * namespace. + */ + typedef ImageMode::value_type gui_mode; + + /*! + * Represents a display image channel supported by the PixInsight core + * application. Valid display channels and components are defined in the + * DisplayChannel namespace. + */ + typedef DisplayChannel::value_type display_channel; + + /*! + * Represents a transparency background brush supported by the PixInsight + * core application. Valid transparency brushes are defined in the + * BackgroundBrush namespace. + */ + typedef BackgroundBrush::value_type background_brush; + + /*! + * Represents a transparency rendering mode supported by the PixInsight core + * application. Valid transparency rendering modes are defined in the + * TransparencyMode namespace. + */ + typedef TransparencyMode::value_type transparency_mode; + + /*! + * Creates a new %ImageView control with the specified image parameters. + * + * \param parent Parent control of the newly created %ImageView. + * + * \param width %Image width in pixels. Must be >= 0. There is no specific + * upper limit. If zero is specified, the %ImageView will + * contain an empty image. The default value is zero. + * + * \param height %Image width in pixels. Must be >= 0. There is no specific + * upper limit. If zero is specified, the %ImageView will + * contain an empty image. The default value is zero. + * + * \param numberOfChannels Number of channels in the image. Must be >= 0. + * There is no specific upper limit. If zero is specified, + * the %ImageView will contain an empty image. If a value > 0 + * is specified, it should not be less than the number of + * nominal channels: 1 for grayscale images, 3 for color + * images. Channels in excess of nominal channels are + * generated as alpha channels. The default value is one. + * + * \param bitsPerSample Number of bits per sample. Supported values are + * 8, 16 and 32 for integer images; 32 and 64 for floating + * point images. The default value is 32. + * + * \param floatSample True to create a floating point image; false to + * create an integer image. The default value is true. + * + * \param color True to create an RGB color image; false to create a + * grayscale image. The default value is false. + * + * If not empty, all nominal and alpha channels of the newly created image + * are initialized with zero pixel sample values (black pixels). + */ + ImageView( Control& parent = Control::Null(), + int width = 0, int height = 0, int numberOfChannels = 1, + int bitsPerSample = 32, bool floatSample = true, bool color = false ); + + /*! + * Destroys an %ImageView control. + */ + virtual ~ImageView() + { + } + + /*! + * Returns an ImageVariant instance that transports the image owned by this + * %ImageView control. + * + * The returned ImageVariant object transports a shared image. A + * shared image is a managed alias for an actual image living in the + * PixInsight core application. This is because a GUI control is also a + * managed object. + */ + ImageVariant Image() const; + + /*! + * Returns true iff this %ImageView control holds a color image, false if it + * is a grayscale image. + */ + bool IsColorImage() const; + + /*! + * Copies the width and height in pixels, and the number of channels of the + * image in this %ImageView control to the specified variables. + */ + void GetImageGeometry( int& width, int& height, int& numberOfChannels ) const; + + /*! + * Returns the width in pixels of the image in this %ImageView control. + */ + int ImageWidth() const + { + int w, dum; GetImageGeometry( w, dum, dum ); return w; + } + + /*! + * Returns the height in pixels of the image in this %ImageView control. + */ + int ImageHeight() const + { + int dum, h; GetImageGeometry( dum, h, dum ); return h; + } + + /*! + * Returns the bounding rectangle of the image in this %ImageView control. + * The upper left corner of the returned rectangle (x0, y0) is always (0,0). + * The lower right corner coordinates (x1, y1) correspond to the width and + * height of the image. + */ + Rect ImageBounds() const + { + int w, h, dum; GetImageGeometry( w, h, dum ); return Rect( w, h ); + } + + /*! + * Retrieves the pixel sample data format used by the image owned by this + * %ImageView control. + * + * \param[out] bitsPerSample On output, will be equal to the number of bits + * per sample used by the image. Can be 8, 16 or + * 32 for an integer image; 32 or 64 for a + * floating point image. + * + * \param[out] floatSample On output, will be true if the image uses + * floating point samples; false if it uses + * integer samples. + */ + void GetSampleFormat( int& bitsPerSample, bool& floatSample ) const; + + /*! + * Converts the image owned by this %ImageView control to the specified + * sample data format. + * + * \param bitsPerSample Number of bits per sample. Can be 8, 16 or 32 + * for an integer image; 32 or 64 for a floating + * point image. + * + * \param floatSample True to transform the image to a floating + * point data format; false to transform the + * image to an integer data format. + * + * This function does nothing if the image in this control already has the + * specified sample data format. + */ + void SetSampleFormat( int bitsPerSample, bool floatSample ); + + /*! + * Obtains a copy of the RGB working space (RGBWS) associated with the + * image owned by this %ImageView control. + * + * \param[out] rgbws Reference to an object where the parameters of the + * current RGBWS will be copied. + */ + void GetRGBWS( RGBColorSystem& rgbws ) const; + + /*! + * Sets the RGB working space (RGBWS) for the image owned by this %ImageView + * control. + * + * \param rgbws Reference to a RGBWS that will be associated with + * the image owned by this object. + */ + void SetRGBWS( const RGBColorSystem& rgbws ); + + /*! + * Returns true iff color management is active for the image in this + * %ImageView control. + */ + bool IsColorManagementEnabled() const; + + /*! + * Enables color management for the image in this %ImageView control. + * + * Color management uses ICC profiles for the image in this control (either + * a profile associated with the image or a global profile) and the monitor + * device to control how the image is rendered on the screen. Color + * management transformations are applied to yield a visual representation + * that takes into account the actual meaning of numerical pixel sample + * values, considering the chromatic responses of the screen and of the + * devices and color spaces that have originated the image. + * + * If color management is disabled for an image, its pixel sample values are + * sent directly to the screen, avoiding ICC profile transformations. This + * improves output performance, but may give a false representation of the + * image on the screen. + * + * If this control is visible, its screen rendition is updated immediately + * after calling this function. + */ + void EnableColorManagement( bool = true ); + + /*! + * Disables color management for the image in this %ImageView control. + * + * See the documentation for EnableColorManagement() for additional + * information on color management in PixInsight. + * + * If this control is visible, its screen rendition is updated immediately + * after calling this function. + */ + void DisableColorManagement( bool disable = true ) + { + EnableColorManagement( !disable ); + } + + /*! + * Returns true iff soft-proofing is currently enabled for the image + * in this %ImageView control. + */ + bool IsProofingEnabled() const; + + /*! + * Enables soft-proofing for the image in this %ImageView control. + * + * Color proofing is used to emulate an output device (usually a printer) on + * the screen. Proofing requires three ICC profiles: the image profile + * (either an embedded profile or the default profile), the monitor profile, + * and a proofing profile that describes the emulated device. Color + * proofing is useful to preview the final printed result without rendering + * images to physical media. + * + * If this control is visible and has color management enabled, its screen + * rendition is updated immediately after calling this function. + */ + void EnableProofing( bool = true ); + + /*! + * Disables soft-proofing for the image in this %ImageView control. + * + * See the documentation for EnableProofing() for additional information on + * color proofing. + * + * If this control is visible and has color management enabled, its screen + * rendition is updated immediately after calling this function. + */ + void DisableProofing( bool disable = true ) + { + EnableProofing( !disable ); + } + + /*! + * Returns true iff the gamut check soft-proofing feature is + * currently enabled for the image in this %ImageView control. + */ + bool IsGamutCheckEnabled() const; + + /*! + * Enables the gamut check proofing feature for the image in this + * %ImageView control. + * + * The gamut check feature represents out-of-gamut colors (i.e., + * colors that are not defined in the color space of the image) with a + * special color (selectable via global color management preferences) for + * quick visual detection. + * + * If this control is visible, has color management enabled, and has soft + * proofing enabled, its screen rendition is updated immediately after + * calling this function. If color proofing is disabled, calling this + * function has no effect. + */ + void EnableGamutCheck( bool = true ); + + /*! + * Disables the gamut check proofing feature for the image in this + * %ImageView control. + * + * See the documentation for EnableGamutCheck() for additional information + * on the gamut check color proofing feature. + * + * If this control is visible, has color management enabled, and has soft + * proofing enabled, its screen rendition is updated immediately after + * calling this function. If color proofing is disabled, calling this + * function has no effect. + */ + void DisableGamutCheck( bool disable = true ) + { + EnableGamutCheck( !disable ); + } + + /*! + * Allows enabling or disabling all color management features at once for + * this %ImageView control. + * + * \param cmEnabled Enables (if true) or disables (if false) color + * management for the image in this control. + * + * \param proofing Enables (if true) or disables (if false) + * soft-proofing for the image in this control. + * + * \param gamutCheck Enables (if true) or disables (if false) the + * gamut check proofing feature. The state of this + * argument has no meaning if the \a proofing parameter + * is false. + * + * If this control is visible, its screen rendition is updated immediately + * after calling this function. + */ + void SetColorManagementFeatures( bool cmEnabled, bool proofing, bool gamutCheck ); + + /*! + * Obtains a copy of the current ICC profile associated with the image in + * this %ImageView control. + * + * \param[out] icc Reference to an object where a copy of the current ICC + * profile will be stored. + */ + bool GetICCProfile( ICCProfile& icc ) const; + + /*! + * Sets the current ICC profile for the image in this %ImageView control as + * a copy of an existing ICC profile. + * + * \param icc Reference to an object that will be used to set the current + * ICC profile. + * + * If this control is visible and has color management enabled, its screen + * rendition is updated immediately after calling this function. + */ + void SetICCProfile( const ICCProfile& icc ); + + /*! + * Sets the current ICC profile for the image in this %ImageView control as + * a copy of an ICC profile loaded from a disk file. + * + * \param filePath A file path specification to an ICC profile that will + * be loaded and copied to the ICC profile of the image. + * + * If this control is visible and has color management enabled, its screen + * rendition is updated immediately after calling this function. + */ + void SetICCProfile( const String& filePath ); + + /*! + * Causes the image in this %ImageView control to be associated with the + * default ICC profile globally defined in the PixInsight core application. + * + * If this control has its own associated ICC profile, this funtion destroys + * it and frees its allocated space. + * + * If this control is visible and has color management enabled, its screen + * rendition is updated immediately after calling this function. + */ + void DeleteICCProfile(); + + /*! + * Returns the current GUI working mode for this %ImageView control. + * + * The returned value can be identified with the symbolic constants defined + * in the ImageMode namespace. + */ + gui_mode CurrentMode() const; + + /*! + * Sets the current GUI working mode for this %ImageView control. + * + * \param mode Specifies the new GUI mode. Supported modes are identified + * through symbolic constants defined in the ImageMode + * namespace. + * + * Preview edition and dynamic modes are not valid for %ImageView. The only + * valid GUI working modes are: + * + * ImageMode::Readout \n + * ImageMode::ZoomIn \n + * ImageMode::ZoomOut \n + * ImageMode::Pan \n + * ImageMode::Center + */ + void SelectMode( gui_mode mode ); + + /*! + * Returns the current display channel for this %ImageView control. + * + * The returned value can be identified with the symbolic constants defined + * int the DisplayChannel namespace. + */ + display_channel CurrentChannel() const; + + /*! + * Returns true iff the current display channel for this %ImageView control + * corresponds to an alpha channel of the image. + */ + bool IsAlphaChannelDisplayed() const + { + return CurrentChannel() >= DisplayChannel::Alpha; + } + + /*! + * Returns the alpha channel index displayed for the image in this + * %ImageView control. If the current display channel does not correspond to + * an alpha channel, a negative integer value is returned. + * + * Alpha channel indices are relative to the first alpha channel in an + * image. For example, the first alpha channel is always indexed as alpha + * channel #0, and so on. + */ + int CurrentAlphaChannel() const + { + return CurrentChannel() - DisplayChannel::Alpha; + } + + /*! + * Selects the current display channel for this %ImageView control. + * + * \param channel Specifies the new display channel. Supported display + * channels are enumerated in the DisplayChannel + * namespace. + * + * Not all display channels are valid for all images in all contexts. For + * example, if the image in the current view is a grayscale image, the only + * valid display channels are the combined RGB/K channel + * (DisplayChannel::RGBK) and, if the image has \a n alpha channels, values + * in the range DisplayChannel::Alpha to DisplayChannel::Alpha+n-1. If an + * invalid display channel is specified, this function is simply ignored. + */ + void SelectChannel( display_channel channel ); + + /*! + * Returns the current transparency rendering mode for this %ImageView + * control. + * + * Supported transparency modes are defined in the TransparencyMode + * namespace. + */ + transparency_mode TransparencyMode() const; + + /*! + * Returns the color used in this %ImageView control to render transparent + * image regions, when the transparency mode is TransparencyMode::Color. + * + * The returned color is an AARRGGBB value. The alpha value is always 0xff, + * since the transparency background cannot be transparent. + */ + RGBA TransparencyColor() const; + + /*! + * Returns true iff transparent image areas are currently visible for this + * %ImageView control. + * + * Transparencies are visible if the current rendering mode is not + * TransparencyMode::Hide. + */ + bool IsTransparencyVisible() const + { + return TransparencyMode() != pcl::TransparencyMode::Hide; + } + + /*! + * Sets the current transparency rendering mode for this %ImageView control. + * + * \param mode Specifies the new mode that will be used to render + * transparent regions of images. Supported transparency + * modes are identified through symbolic constants defined in + * the TransparencyMode namespace. + * + * \param color New color that will be used when the transparency mode is + * TransparencyMode::Color. If zero is specified (the default + * value), the current color will not be changed. + */ + void SetTransparencyMode( transparency_mode mode, RGBA color = 0 ); + + /*! + * Disables transparency renditions for this %ImageView control. + * + * Calling this function is equivalent to: + * + * \code SetTransparencyMode( pcl::TransparencyMode::Hide ); \endcode + */ + void HideTransparency() + { + SetTransparencyMode( pcl::TransparencyMode::Hide ); + } + + /*! + * Sets new viewport central location coordinates and zoom factor for this + * %ImageView control. + * + * \param cx,cy Position (horizontal, vertical) of the new central + * viewport location in image coordinates. + * + * \param zoom New viewport zoom factor. Positive zoom factors are + * interpreted as magnifying factors; negative zoom factors + * are reduction factors: + * + *

+    * Zoom Factor    Screen Zoom (screen pixels : image pixels)
+    * ===========    ==========================================
+    *      0               Current zoom factor (no change)
+    *   1 or -1            1:1 (actual pixels)
+    *      2               2:1 (x2 magnification)
+    *      3               3:1 (x3 magnification)
+    *     ...
+    *     -2               1:2 (1/2 reduction)
+    *     -3               1:3 (1/3 reduction)
+    *     ...
+    * 
+ * + * A zoom factor of -1 should not be used explicitly; it is a + * reserved value for internal use, and there is no guarantee + * that future versions of PCL continue accepting it. + * + * If the specified viewport location cannot correspond to the viewport + * central position with the specified zoom factor, the nearest image + * coordinates are always selected automatically. For example, if you + * pass image coordinates \a cx=0 and \a cy=0 as arguments to this function, + * the GUI will set the viewport center to the necessary image location in + * order to display the upper left corner of the image just at the upper + * left corner of the viewport. + * + * If the \a zoom argument is not specified, the current zoom factor is not + * changed since the default value of this parameter is zero; see the table + * above. + * + * If this control is visible, calling this function causes an immediate + * regeneration of the screen rendition for the visible viewport region. + */ + void SetViewport( double cx, double cy, int zoom = 0 ); + + /*! + * Sets new viewport central location and zoom factor for this %ImageView + * control. + * + * Calling this function is equivalent to: + * + * \code SetViewport( center.x, center.y, int ); \endcode + * + * See the documentation for SetViewport( double, double, int ). + */ + void SetViewport( const DPoint& center, int zoom = 0 ) + { + SetViewport( center.x, center.y, zoom ); + } + + /*! + * Returns the current zoom factor in the viewport of this %ImageView + * control. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + int ZoomFactor() const; + + /*! + * Sets the zoom factor for the viewport of this %ImageView control to the + * specified value \a z. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + void SetZoomFactor( int z ); + + /*! + * Increments the current zoom factor for the viewport of this %ImageView + * control. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + void ZoomIn() + { + int z = ZoomFactor() + 1; + SetZoomFactor( (z > 0) ? z : +1 ); + } + + /*! + * Decrements the current zoom factor for the viewport of this %ImageView + * control. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + void ZoomOut() + { + int z = ZoomFactor() - 1; + SetZoomFactor( (z > 0 || z < -1) ? z : -2 ); + } + + /*! + * Gets the current sizes of the viewport in this %ImageView control. + * + * \param[out] width Reference to a variable where the viewport width in + * pixels will be stored. + * + * \param[out] height Reference to a variable where the viewport height in + * pixels will be stored. + * + * The provided sizes represent the entire image in this control, as + * represented on its viewport after applying the current zoom factor. + * Viewport sizes can also be thought of as the available navigation ranges + * in an %ImageView control. + */ + void GetViewportSize( int& width, int& height ) const; + + /*! + * Gets the current width of the viewport in this %ImageView control. + */ + int ViewportWidth() const + { + int w, dum; + GetViewportSize( w, dum ); + return w; + } + + /*! + * Gets the current height of the viewport in this %ImageView control. + */ + int ViewportHeight() const + { + int dum, h; + GetViewportSize( dum, h ); + return h; + } + + /*! + * Returns the current viewport position in this %ImageView control. + * + * The viewport position corresponds to the viewport coordinates of the + * upper left corner of the visible viewport region. These + * coordinates can be negative if the represented image is smaller than the + * size of the viewport control, that is, when the extended viewport + * space is visible around the screen rendition of the image. + */ + Point ViewportPosition() const; + + /*! + * Sets the viewport position in this %ImageView control to the specified + * \a x and \a y viewport coordinates. + * + * If this control is visible, calling this function causes an immediate + * regeneration of the screen rendition for the visible viewport region. + */ + void SetViewportPosition( int x, int y ); + + /*! + * Sets the viewport position in this %ImageView control to the specified + * position \a p in viewport coordinates. + * + * Calling this function is equivalent to: + * + * \code SetViewportPosition( p.x, p.y ); \endcode + */ + void SetViewportPosition( const Point& p ) + { + SetViewportPosition( p.x, p.y ); + } + + /*! + * Gets the current visible viewport region in this %ImageView control. + * + * The returned rectangle corresponds to the visible region of the image in + * viewport coordinates. It depends on the current viewport zoom factor and + * on the positions of the viewport's scroll bars, if they are visible. + */ + Rect VisibleViewportRect() const; + + /*! + * Returns the width in pixels of the current visible viewport region in + * this %ImageView control. + */ + int VisibleViewportWidth() const + { + return VisibleViewportRect().Width(); + } + + /*! + * Returns the height in pixels of the current visible viewport region in + * this %ImageView control. + */ + int VisibleViewportHeight() const + { + return VisibleViewportRect().Height(); + } + + /*! + * Converts the specified \a x and \a y integer coordinates from the + * viewport coordinate system to the image coordinate system. + * + * The converted image coordinates are rounded to the nearest integers. + */ + void ViewportToImage( int& x, int& y ) const; + + /*! + * Converts the specified \a x and \a y real floating point coordinates from + * the viewport coordinate system to the image coordinate system. + */ + void ViewportToImage( double& x, double& y ) const; + + /*! + * Converts a point \a p in the viewport coordinate system to the image + * coordinate system. Returns a point with the resulting floating point real + * image coordinates. + */ + template + DPoint ViewportToImage( const GenericPoint& p ) const + { + DPoint p1 = p; + ViewportToImage( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the viewport coordinate system to the image + * coordinate system. Returns a rectangle with the resulting floating point + * real image coordinates. + */ + template + DRect ViewportToImage( const GenericRectangle& r ) const + { + DRect r1 = r; + ViewportToImage( r1.x0, r1.y0 ); + ViewportToImage( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Converts a set of integer points from the viewport coordinate system to + * the image coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from viewport coordinates to image coordinates. + * + * \param n Number of points in the \a p array. + * + * Converted point image coordinates are rounded to the nearest integers. + */ + void ViewportToImage( Point* p, size_type n ) const; + + /*! + * Converts a set of real floating-point points from the viewport + * coordinate system to the image coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from viewport coordinates to image coordinates. + * + * \param n Number of points in the \a p array. + */ + void ViewportToImage( DPoint* p, size_type n ) const; + + /*! + * Converts a set of points in a dynamic array from the viewport coordinate + * system to the image coordinate system. + * + * \param a Reference to a dynamic array of points that will be converted + * from viewport coordinates to image coordinates. + */ + template + void ViewportToImage( Array >& a ) const + { + ViewportToImage( a.Begin(), a.Length() ); + } + + /*! + * Converts a set of integer scalars from the viewport coordinate system to + * the image coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from viewport coordinates to image + * coordinates. + * + * \param n Number of scalars in the \a p array. + * + * Converted scalars in image coordinates are rounded to the nearest + * integers. + */ + void ViewportScalarToImage( int* d, size_type n ) const; + + /*! + * Converts a set of real floating-point scalars from the viewport + * coordinate system to the image coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from viewport coordinates to image + * coordinates. + * + * \param n Number of scalars in the \a p array. + */ + void ViewportScalarToImage( double* d, size_type n ) const; + + /*! + * Converts a scalar \a d in the viewport coordinate system to the image + * coordinate system. Returns the resulting floating point real scalar in + * image coordinates. + */ + double ViewportScalarToImage( double d ) const; + + /*! + * Converts a scalar \a d in the viewport coordinate system to the image + * coordinate system. Returns the resulting floating point real scalar in + * image coordinates. + */ + template + double ViewportScalarToImage( T d ) const + { + return ViewportScalarToImage( double( d ) ); + } + + /*! + * Converts the specified \a x and \a y integer coordinates from the image + * coordinate system to the viewport coordinate system. + * + * The converted viewport coordinates are rounded to the nearest integers. + */ + void ImageToViewport( int& x, int& y ) const; + + /*! + * Converts the specified \a x and \a y real floating-point coordinates from + * the image coordinate system to the viewport coordinate system. + */ + void ImageToViewport( double& x, double& y ) const; + + /*! + * Converts a point \a p in the image coordinate system to the viewport + * coordinate system. Returns a point with the resulting viewport + * coordinates. + * + * If the template argument T corresponds to an integer type, the converted + * viewport coordinates in the resulting point are rounded to the nearest + * integers. + */ + template + GenericPoint ImageToViewport( const GenericPoint& p ) const + { + GenericPoint p1 = p; + ImageToViewport( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the image coordinate system to the viewport + * coordinate system. Returns a rectangle with the resulting viewport + * coordinates. + * + * If the template argument T corresponds to an integer type, the converted + * viewport coordinates in the resulting rectangle are rounded to the + * nearest integers. + */ + template + GenericRectangle ImageToViewport( const GenericRectangle& r ) const + { + GenericRectangle r1 = r; + ImageToViewport( r1.x0, r1.y0 ); + ImageToViewport( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Converts a set of integer points from the image coordinate system to + * the viewport coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from image coordinates to viewport coordinates. + * + * \param n Number of points in the \a p array. + * + * Converted point viewport coordinates are rounded to the nearest integers. + */ + void ImageToViewport( Point* p, size_type n ) const; + + /*! + * Converts a set of real floating-point points from the image coordinate + * system to the viewport coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from image coordinates to viewport coordinates. + * + * \param n Number of points in the \a p array. + */ + void ImageToViewport( DPoint* p, size_type n ) const; + + /*! + * Converts a set of points in a dynamic array from the image coordinate + * system to the viewport coordinate system. + * + * \param a Reference to a dynamic array of points that will be converted + * from image coordinates to viewport coordinates. + */ + template + void ImageToViewport( Array >& a ) const + { + ImageToViewport( a.Begin(), a.Length() ); + } + + /*! + * Converts a set of integer scalars from the image coordinate system to + * the viewport coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from image coordinates to viewport + * coordinates. + * + * \param n Number of scalars in the \a p array. + * + * Converted scalars in viewport coordinates are rounded to the nearest + * integers. + */ + void ImageScalarToViewport( int* d, size_type n ) const; + + /*! + * Converts a set of real floating-point scalars from the image coordinate + * system to the viewport coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from image coordinates to viewport + * coordinates. + * + * \param n Number of scalars in the \a p array. + */ + void ImageScalarToViewport( double* d, size_type n ) const; + + /*! + * Converts an integer scalar \a d in the image coordinate system to the + * viewport coordinate system. Returns the resulting scalar in viewport + * coordinates. + * + * The resulting scalar in viewport coordinates is rounded to the nearest + * integer. + */ + int ImageScalarToViewport( int ) const; + + /*! + * Converts a real floating-point scalar \a d in the image coordinate system + * to the viewport coordinate system. Returns the resulting scalar in + * viewport coordinates. + */ + double ImageScalarToViewport( double ) const; + + /*! + * Converts the specified \a x and \a y integer coordinates from the + * viewport coordinate system to the global coordinate system. + * + * The converted global coordinates are rounded to the nearest integers. + */ + void ViewportToGlobal( int& x, int& y ) const; + + /*! + * Converts a point \a p in the viewport coordinate system to the global + * coordinate system. Returns a point with the resulting global coordinates. + */ + Point ViewportToGlobal( const Point& p ) const + { + Point p1 = p; + ViewportToGlobal( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the viewport coordinate system to the global + * coordinate system. Returns a rectangle with the resulting global + * coordinates. + */ + Rect ViewportToGlobal( const Rect& r ) const + { + Rect r1 = r; + ViewportToGlobal( r1.x0, r1.y0 ); + ViewportToGlobal( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Converts the specified \a x and \a y integer coordinates from the global + * coordinate system to the viewport coordinate system. + * + * The converted viewport coordinates are rounded to the nearest integers. + */ + void GlobalToViewport( int& x, int& y ) const; + + /*! + * Converts a point \a p in the global coordinate system to the viewport + * coordinate system. Returns a point with the resulting viewport + * coordinates. + */ + Point GlobalToViewport( const Point& p ) const + { + Point p1 = p; + GlobalToViewport( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the global coordinate system to the viewport + * coordinate system. Returns a rectangle with the resulting viewport + * coordinates. + */ + Rect GlobalToViewport( const Rect& r ) const + { + Rect r1 = r; + GlobalToViewport( r1.x0, r1.y0 ); + GlobalToViewport( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Causes a complete regeneration of the whole viewport and its associated + * UI resources. + * + * Calling this function may be necessary to force a regeneration after + * changing the geometry of the image owned by this %ImageView control. + */ + void Reset() + { + SetZoomFactor( ZoomFactor() ); + } + + /*! + * Regenerates the screen rendition for the visible viewport region in this + * %ImageView control. + */ + void Regenerate(); + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in viewport coordinates. + * + * Calling this function is equivalent to: + * + * \code RegenerateViewportRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void RegenerateViewportRect( const Rect& r ) + { + RegenerateViewportRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in viewport coordinates. + * + * \param x0,y0 %Viewport coordinates (horizontal, vertical) of the upper + * left corner of the regenerated region. + * + * \param x1,y1 %Viewport coordinates (horizontal, vertical) of the lower + * right corner of the regenerated region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be regenerated and updated, that is, + * its intersection with the visible viewport region. + */ + void RegenerateViewportRect( int x0, int y0, int x1, int y1 ); + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in image coordinates. + * + * Calling this function is equivalent to: + * + * \code RegenerateImageRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void RegenerateImageRect( const pcl::DRect& r ) + { + RegenerateImageRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in image coordinates. + * + * \param x0,y0 %Image coordinates (horizontal, vertical) of the upper + * left corner of the regenerated region. + * + * \param x1,y1 %Image coordinates (horizontal, vertical) of the lower + * right corner of the regenerated region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be regenerated and updated, that is, + * its intersection with the visible viewport region. + */ + void RegenerateImageRect( double x0, double y0, double x1, double y1 ); + + /*! + * Requests a screen update for the entire visible viewport region in this + * %ImageView control. + */ + void UpdateViewport(); + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in viewport coordinates. + * + * Calling this function is equivalent to: + * + * \code UpdateViewportRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void UpdateViewportRect( const Rect& r ) + { + UpdateViewportRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in viewport coordinates. + * + * \param x0,y0 %Viewport coordinates (horizontal, vertical) of the upper + * left corner of the update region. + * + * \param x1,y1 %Viewport coordinates (horizontal, vertical) of the lower + * right corner of the update region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be updated, that is, its + * intersection with the visible viewport region. + */ + void UpdateViewportRect( int x0, int y0, int x1, int y1 ); + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in image coordinates. + * + * Calling this function is equivalent to: + * + * \code UpdateImageRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void UpdateImageRect( const pcl::DRect& r ) + { + UpdateImageRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in image coordinates. + * + * \param x0,y0 %Image coordinates (horizontal, vertical) of the upper + * left corner of the update region. + * + * \param x1,y1 %Image coordinates (horizontal, vertical) of the lower + * right corner of the update region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be updated, that is, its + * intersection with the visible viewport region in the image coordinate + * system. + */ + void UpdateImageRect( double x0, double y0, double x1, double y1 ); + + /*! + * Returns true iff there are pending viewport updates for this %ImageView + * control. + */ + bool HasPendingUpdates() const; + + /*! + * Executes all pending viewport update requests for this %ImageView + * control. + * + * Viewport update requests are not executed immediately by the core + * PixInsight application. For the sake of performance, The GUI tries to + * optimize screen updates by performing the minimum possible redrawing + * work. + * + * This means that update requests are placed on a queue, waiting while the + * main GUI thread is busy or until a sufficiently large update region + * becomes available. + * + * With this function, an interface can force the immediate screen update + * for all pending update viewport regions. If multiple update regions are + * pending, the core application will still minimize the required drawing + * work by grouping all of them into the minimum possible amount of larger + * regions. + */ + void CommitPendingUpdates(); + + /*! + * Returns a rectangle in viewport coordinates that includes all pending + * viewport update regions for this %ImageView control. + */ + Rect ViewportUpdateRect() const; + + /*! + * Returns a RGBA bitmap with a screen rendition of a viewport region of + * this %ImageView control. + * + * Calling this function is equivalent to: + * + * \code ViewportBitmap( r.x0, r.y0, r.x1, r.y1, flags ); \endcode + */ + Bitmap ViewportBitmap( const Rect& r, uint32 flags = 0 ) const + { + return ViewportBitmap( r.x0, r.y0, r.x1, r.y1, flags ); + } + + /*! + * Returns a RGBA bitmap with a screen rendition of a viewport region of + * this %ImageView control. + * + * \param x0,y0 %Viewport coordinates (horizontal, vertical) of the upper + * left corner of the source viewport region. + * + * \param x1,y1 %Viewport coordinates (horizontal, vertical) of the lower + * right corner of the source viewport region. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + * + * The returned bitmap will contain a screen rendition for the specified + * source region of the image in this %ImageView control. It will be + * magnified or reduced according to the current zoom factor. + */ + Bitmap ViewportBitmap( int x0, int y0, int x1, int y1, uint32 flags = 0 ) const; + + /*! + * Begins a new interactive rectangular selection procedure on the viewport + * of this %ImageView control. + * + * Calling this function is equivalent to: + * + * \code BeginSelection( p.x, p.y, flags ); \endcode + */ + void BeginSelection( const Point& p, uint32 flags = 0 ) + { + BeginSelection( p.x, p.y, flags ); + } + + /*! + * Starts a new interactive rectangular selection procedure on the viewport + * of this %ImageView control. + * + * \param x,y %Image coordinates of the starting point of a new + * rectangular selection. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + * + * Interfaces typically use BeginSelection() in response to an OnMousePress + * event to start a rectangular selection. ModifySelection() is then called + * from an OnMouseMove event handler, and the final selection coordinates + * are obtained by calling SelectionRect() from an OnMouseRelease event + * handler. + */ + void BeginSelection( int x, int y, uint32 flags = 0 ); + + /*! + * Updates an ongoing interactive rectangular selection procedure on the + * viewport of this %ImageView control. + * + * Calling this function is equivalent to: + * + * \code ModifySelection( p.x, p.y, flags ); \endcode + */ + void ModifySelection( const Point& p, uint32 flags = 0 ) + { + ModifySelection( p.x, p.y, flags ); + } + + /*! + * Updates an ongoing interactive rectangular selection procedure on the + * viewport of this %ImageView control. + * + * \param x,y %Image coordinates to update the current rectangular + * selection. The selection rectangle is defined by this + * position and the starting position defined in the call to + * BeginSelection() that originated the current selection + * procedure. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + */ + void ModifySelection( int x, int y, uint32 flags = 0 ); + + /*! + * Requests a screen viewport update for the current rectangular selection. + */ + void UpdateSelection(); + + /*! + * Aborts the current interactive selection procedure. + */ + void CancelSelection(); + + /*! + * Terminates the current interactive selection procedure. + */ + void EndSelection(); + + /*! + * Returns the current rectangular selection in image coordinates. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + * + * Before calling this function, a rectangular selection procedure should + * have been started with BeginSelection(). + */ + Rect SelectionRect( uint32* flags = 0 ) const; + + /*! + * Returns true iff an interactive selection procedure is currently active on + * the viewport of this %ImageView control. + */ + bool IsSelection() const; + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnScrollViewport( ImageView& sender, int dx, int dy ); + + /*! + * \defgroup image_view_event_handlers ImageView Event Handlers + */ + + /*! + * Defines the prototype of a scroll event handler. + * + * A scroll event is generated when the viewport in this %ImageView control + * has been moved with respect to the control's origin, e.g. when the values + * of one or both scroll bars have been changed. The event is generated just + * \e before updating the viewport, so this event handler can be implemented + * for optimization purposes. + * + * \param sender The control that sends a scroll event. + * + * \param dx Horizontal scroll distance in viewport pixels. Positive + * values mean scrolling in the rightward direction. + * + * \param dy Vertical scroll distance in viewport pixels. Positive + * values mean scrolling in the downward direction. + * + * \ingroup image_view_event_handlers + */ + typedef void (Control::*scroll_event_handler)( ImageView& sender, int dx, int dy ); + + /*! + * Sets the scroll event handler for this %ImageView control. + * + * \param handler The scroll event handler. Must be a member function of + * the receiver object's class. + * + * \param receiver The control that will receive scroll events from this + * %ImageView object. + * + * \ingroup image_view_event_handlers + */ + void OnScrollViewport( scroll_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + scroll_event_handler onScrollViewport = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + +protected: + + /*! + * \internal + */ + ImageView( void* ); + + /*! + * \internal + */ + ImageView( void*, void* ); + + friend class ImageViewEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ImageView_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageView.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ImageWindow.h b/3rdparty/include/pcl/ImageWindow.h new file mode 100644 index 0000000..d930df9 --- /dev/null +++ b/3rdparty/include/pcl/ImageWindow.h @@ -0,0 +1,3025 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ImageWindow.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_ImageWindow_h +#define __PCL_ImageWindow_h + +/// \file pcl/ImageWindow.h + +#include + +#include +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include +#include +#include +#include +#include + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class RGBColorSystem; +class ICCProfile; +class ProcessInterface; + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ImageMode + * \brief GUI operation modes. + * + * + * + * + * + * + * + * + * + * + * + * + *
ImageMode::Invalid Represents an invalid or unsupported mode.
ImageMode::Readout Default mode, click to get real-time readouts.
ImageMode::ZoomIn Click to zoom in the current view.
ImageMode::ZoomOut Click to zoom out the current view.
ImageMode::Pan Click and drag to pan the current view.
ImageMode::Center Click to center the view at the mouse position.
ImageMode::NewPreview Click and drag to define a new preview.
ImageMode::EditPreview Click and drag to change an existing preview.
ImageMode::DynamicOperation Module-defined dynamic operation.
ImageMode::Default Identifies the default GUI operation mode in the PixInsight core application (ImageMode::Readout).
+ */ +namespace ImageMode +{ + enum value_type + { + Invalid = -1, // Represents an invalid or unsupported mode + Readout = 0, // Default mode, click to get real-time readouts + ZoomIn, // Click to zoom in the current view + ZoomOut, // Click to zoom out the current view + Pan, // Click and drag to pan the current view + Center, // Click to center the view at the mouse position + NewPreview, // Click and drag to define a new preview + EditPreview, // Click and drag to change an existing preview + DynamicOperation, // Module-defined dynamic operation + + NumberOfModes, + + Default = Readout + }; + + /*! + * Returns true iff the specified mode is a valid GUI mode when the active + * view is a preview. + */ + inline bool IsValidPreviewMode( value_type m ) + { + return m != NewPreview && m != EditPreview; + } + + /*! + * Returns true iff the specified mode is a valid GUI mode when the active + * view is a main view. + */ + inline bool IsValidMainViewMode( value_type m ) + { + return !IsValidPreviewMode( m ); + } +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::BackgroundBrush + * \brief Transparency background brushes. + * + * + * + * + * + * + * + * + * + * + * + * + * + *
BackgroundBrush::Small Small chessboard pattern
BackgroundBrush::Medium Medium chessboard pattern
BackgroundBrush::Large Large chessboard pattern
BackgroundBrush::SmallCrossPattern Small cross pattern
BackgroundBrush::MediumCrossPattern Medium cross pattern
BackgroundBrush::LargeCrossPattern Large cross pattern
BackgroundBrush::SmallDiagPattern Small diagonal pattern
BackgroundBrush::MediumDiagPattern Medium diagonal pattern
BackgroundBrush::LargeDiagPattern Large diagonal pattern
BackgroundBrush::Solid Solid brush with the foreground color
BackgroundBrush::Default Identifies the default transparency background brush used by the PixInsight core application. Currently this corresponds to BackgroundBrush::Small.
+ */ +namespace BackgroundBrush +{ + enum value_type + { + Small, // Small chessboard pattern + Medium, // Medium chessboard pattern + Large, // Large chessboard pattern + SmallCrossPattern, // Small cross pattern + MediumCrossPattern, // Medium cross pattern + LargeCrossPattern, // Large cross pattern + SmallDiagPattern, // Small diagonal pattern + MediumDiagPattern, // Medium diagonal pattern + LargeDiagPattern, // Large diagonal pattern + Solid, // Solid brush with the foreground color + + NumberOfBrushes, + + Default = Small + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::TransparencyMode + * \brief Transparency rendering modes + * + * + * + * + * + * + *
TransparencyMode::Hide Don't show transparencies (ignore alpha channels).
TransparencyMode::BackgroundBrush Use the transparency background brush.
TransparencyMode::Color Use an opaque background color.
TransparencyMode::Default Identifies the default transparency rendering mode used by the PixInsight core application. Currently this corresponds to TransparencyMode::BackgroundBrush.
+ */ +namespace TransparencyMode +{ + enum value_type + { + Hide, // Don't show transparencies + BackgroundBrush, // Use the transparency background brush + Color, // Use an opaque background color + + NumberOfModes, + + Default = BackgroundBrush + }; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::UndoFlag + * \brief History data item specifiers for ProcessImplementation::UndoMode(). + * + * Use %UndoFlag constants to make up return values for + * ProcessImplementation::UndoMode(). That member function specifies the data + * that the PixInsight core application must save to swap files before + * executing an instance of a given process. Saved undo data are used to + * retrieve a history state of an image, e.g. for undo and redo operations. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
UndoFlag::DefaultMode Save pixel data, astrometric solution and previews.
UndoFlag::PixelData Save pixel data.
UndoFlag::RGBWS Save RGB Working Space data.
UndoFlag::ICCProfile Save ICC profile.
UndoFlag::Keywords Save %FITS keywords.
UndoFlag::FormatData Save Format-specific data.
UndoFlag::ImageId Save image identifier.
UndoFlag::Resolution Save image resolution data.
UndoFlag::AstrometricSolution Save existing astrometric solution.
UndoFlag::All Save all data items.
UndoFlag::DeletePropertiesOnEntry Unconditionally destroy/delete non-permanent view properties before execution.
UndoFlag::DeletePropertiesOnExit Unconditionally destroy/delete non-permanent view properties after execution.
UndoFlag::ExcludePreviews Don't save state of previews.
UndoFlag::ExcludeMaskRelations Don't save masking dependencies.
+ */ +namespace UndoFlag +{ + /* + * ### TODO: PCL 2.x: Get rid of all project depencies on UndoFlags. + */ + enum mask_type + { + DefaultMode = 0x00000000, // Save pixel data, astrometric solution and previews + PixelData = 0x00000001, // Save pixel data + RGBWS = 0x00000002, // RGB Working Space data + ICCProfile = 0x00000004, // ICC profile + Keywords = 0x00000008, // %FITS keywords + //Metadata = 0x00000010, // ### DEPRECATED - Keep unused for now, for compatibility with existing projects + FormatData = 0x00000020, // Format-specific data + ImageId = 0x00000040, // %Image identifier + Resolution = 0x00000080, // %Image resolution + AstrometricSolution = 0x00000100, // Save the current astrometric solution + All = 0x000FFFFF, // Save all data items + DeletePropertiesOnEntry = 0x01000000, // Destroy/delete non-permanent view properties before execution + DeletePropertiesOnExit = 0x02000000, // Destroy/delete non-permanent view properties after execution + ExcludePreviews = 0x80000000, // Don't save state of previews + ExcludeMaskRelations = 0x40000000 // Don't save masking dependencies + }; +} + +/*! + * \class pcl::UndoFlags + * \brief A collection of history data item specifiers. + */ +typedef Flags UndoFlags; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class ImageWindow + * \brief High-level interface to an image window object in the PixInsight core + * application. + * + * ### TODO: Write a detailed description for %ImageWindow. + * + * \sa View + */ +class PCL_CLASS ImageWindow : public UIObject +{ +public: + + /*! + * Represents a GUI working mode. Valid modes are defined in the ImageMode + * namespace. + */ + typedef ImageMode::value_type gui_mode; + + /*! + * Represents a display image channel supported by the PixInsight core + * application. Valid display channels and components are defined in the + * DisplayChannel namespace. + */ + typedef DisplayChannel::value_type display_channel; + + /*! + * Represents a mask rendering mode supported by the PixInsight core + * application. Valid mask rendering modes are defined in the MaskMode + * namespace. + */ + typedef MaskMode::value_type mask_mode; + + /*! + * Represents a transparency background brush supported by the PixInsight + * core application. Valid transparency brushes are defined in the + * BackgroundBrush namespace. + */ + typedef BackgroundBrush::value_type background_brush; + + /*! + * Represents a transparency rendering mode supported by the PixInsight core + * application. Valid transparency rendering modes are defined in the + * TransparencyMode namespace. + */ + typedef TransparencyMode::value_type transparency_mode; + + /*! + * Constructs a null image window. A null %ImageWindow does not correspond + * to an existing image window in the PixInsight core application. + */ + ImageWindow() = default; + + /*! + * Creates a new image window with the specified image parameters. + * + * \param width %Image width in pixels. Must be >= 1. There is no specific + * upper limit. + * + * \param height %Image height in pixels. Must be >= 1. There is no + * specific upper limit. + * + * \param numberOfChannels Number of channels in the image. Should not be + * less than the number of nominal channels: 1 for grayscale + * images, 3 for color images. Channels in excess of nominal + * channels are generated as alpha channels. This parameter is + * one by default. + * + * \param bitsPerSample Number of bits per sample. Supported values are + * 8, 16 and 32 for integer images; 32 and 64 for floating point + * images. This parameter is 32 by default. + * + * \param floatSample True to create a floating point image; false to + * create an integer image. This parameter is true by default. + * + * \param color True to create a RGB color image; false to create a + * grayscale image. This parameter is false by default. + * + * \param initialProcessing True if the core application should assign a + * ProcessContainer instance to hold the initial processing for + * this image. The initial processing items will be + * automatically generated by the core application as a function + * of the current processing thread context. This parameter is + * true by default. + * + * \param id Identifier for the new image. If an empty string is + * specified, the core application will assign an automatically + * generated identifier. If the specified identifier is not + * unique, the core application will make it unique by appending + * an automatically generated suffix. This parameter is an empty + * string by default. + * + * The newly created image is initialized with zero pixel sample values + * (black pixels). This includes all nominal and alpha channels. + * + * The new image window will be hidden. To make it visible on the core + * application, you must call its Show() member function explicitly. + */ + ImageWindow( int width, int height, int numberOfChannels = 1, + int bitsPerSample = 32, bool floatSample = true, bool color = false, + bool initialProcessing = true, + const IsoString& id = IsoString() ); + + ImageWindow( int width, int height, int numberOfChannels, + int bitsPerSample, bool floatSample, bool color, + bool initialProcessing, + const IsoString::ustring_base& id ) + : ImageWindow( width, height, numberOfChannels, + bitsPerSample, floatSample, color, + initialProcessing, + IsoString( id ) ) + { + } + + /*! + * Copy constructor. Constructs an %ImageWindow object as an alias of an + * existing %ImageWindow object. + * + * It cannot be overemphasized that this constructor does not create a + * new image window in the PixInsight core application. It only creates + * an \e alias object for an existing image window in the calling + * module. In all respects, the alias and aliased objects are + * completely interchangeable; their behaviors are exactly identical since + * they refer to the same server-side object. + */ + ImageWindow( const ImageWindow& w ) + : UIObject( w ) + { + } + + /*! + * Move constructor. + */ + ImageWindow( ImageWindow&& x ) + : UIObject( std::move( x ) ) + { + } + + /*! + * Destroys this %ImageWindow object. + * + * This destructor does \e not destroy the actual image window object, which + * is part of the PixInsight core application. Only the managed alias object + * living in the calling module is destroyed. + */ + virtual ~ImageWindow() + { + } + + /*! + * Copy assignment operator. Detaches this object from its previously + * referenced server-side image window and makes it an alias of the + * specified \a window. Returns a reference to this object. + * + * When this operator is used, the calling object is detached from the + * previously referenced window. Note that an image window cannot be + * destroyed when it becomes unreferenced, as it is an internal UI object + * that belongs to the core application, not to the calling module, even if + * the window has been created by the calling module. + */ + ImageWindow& operator =( const ImageWindow& window ) + { + Assign( window ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ImageWindow& operator =( ImageWindow&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Returns a reference to a null %ImageWindow instance. A null %ImageWindow + * does not correspond to an existing image window in the PixInsight core + * application. + */ + static ImageWindow& Null(); + + /*! + * Opens an image file and loads one or more images into new image windows. + * + * \param url A path specification or URL that points to an image file to + * be loaded by the PixInsight core application. The file name + * \e must include a file extension, since it is the only way to + * select a file format, necessary to read and decode images. + * + * \param id Identifier for the new image(s). If an empty string is + * specified, the application will assign an automatically + * generated identifier. If the specified identifier is not + * unique, the application will make it unique by appending an + * automatically generated suffix. This parameter is an empty + * string by default. + * + * \param formatHints A string of format hints that will be sent to the + * file format instance created to load the image. Format hints + * are useful to modify the behavior of a file format suuport + * module lo load a specific image, overriding global + * preferences and format settings. See the + * FileFormatInstance::Open() member function for more + * information on format hints. This parameter is an empty + * string by default. + * + * \param asCopy True to open the images as \e copies. The %File > Save + * command (and all related menu items) is always disabled for + * images loaded as copies in the PixInsight core application. + * This means that the only way to write an image copy is the + * %File > Save As command. This is a security enhancement to + * avoid %File > Save accidents, e.g. by pressing Ctrl+S + * inattentively. The same applies to the \c save internal + * command-line command, which requires an explicit file path + * specification for image copies. This parameter is false by + * default. + * + * \param allowMessages True to allow the core application to show + * warning message boxes (e.g., to inform about inexact read + * operations) and color management dialog boxes (upon + * ICC profile mismatches or missing ICC profiles). If this + * parameter is false, no dialog box or warning message box will + * be shown, and default actions will be taken as appropriate + * for conflicting ICC profiles. However, all warning messages + * will be sent to the processing console when this parameter is + * false. Error messages will always be shown. This parameter is + * true by default. + * + * The PixInsight core application will find and select a file format to + * read the specified image file, among the installed file format modules. + * Format selection is exclusively a function of the specified file + * extension (e.g., .fit will select the %FITS format, .tif the %TIFF + * format, .jpg for %JPEG, and so on). + * + * %File and directory paths in the PixInsight environment employ UNIX + * directory separators (the slash character, '/') on all supported + * platforms. As an exception, on Windows PCL allows you to use also DOS + * separators (backslash, '\'), but their use is discouraged since its + * support might be discontinued in future PCL versions. + * + * URLs must be valid and conform to the URI specification from RFC 3986 + * (Uniform Resource Identifier: Generic Syntax). At least the file, HTTP, + * HTTPS, FTP and FTPS protocols are supported. More protocols may be + * available, depending on PixInsight core versions. + * + * Returns an array of %ImageWindow objects. Each object in the array + * corresponds to an image loaded into a new image window from the specified + * file. In general, the returned array will contain only one object, since + * most image file formats can store just a single image. For formats that + * can store multiple images, more than one %ImageWindow can be created as a + * result of opening a single file. + * + * Newly created image windows will be hidden. To make them visible on the + * core application's workspace, you must call their ImageWindow::Show() + * member function explicitly. + */ + static Array Open( const String& url, + const IsoString& id = IsoString(), + const IsoString& formatHints = IsoString(), + bool asCopy = false, + bool allowMessages = true ); + + template + static Array Open( const String& url, + const S1& id, + const S2& formatHints, + bool asCopy = false, + bool allowMessages = true ) + { + return Open( url, IsoString( id ), IsoString( formatHints ), asCopy, allowMessages ); + } + + /*! + * Returns true iff the image in this window has not been loaded from a disk + * file, but created as a new image in the core application (e.g., by the + * NewImage standard process). + */ + bool IsNew() const; + + /*! + * Returns true iff the image in this window has been loaded from a file + * as a copy. + * + * The %File > Save command (and all related menu items) is always disabled + * for images loaded as copies in the PixInsight core application. This + * means that the only way to write an image copy is the %File > Save As + * command. This is a security enhancement to avoid %File > Save accidents, + * e.g. by pressing Ctrl+S inattentively. The same applies to the \c save + * command-line internal command, which requires an explicit file path + * specification for image copies. + */ + bool IsACopy() const; + + /*! + * Returns the full file path to the image file loaded in this image + * window, or an empty string if this window holds is a \e new image. + * + * \note When an image has been loaded from a remote location (by specifying + * a valid URL in a call to ImageWindow::Open(), for example), the returned + * path corresponds to the file that has been downloaded to the local + * filesystem upon window creation, not to the original URL. + */ + String FilePath() const; + + /*! + * Returns the URL of the remote resource from which this image has been + * downloaded, or an empty string if this window has not been downloaded + * from a remote location. + */ + String FileURL() const; + + /*! + * Returns true iff this image has been downloaded from a remote location, in + * which case the source URL can be obtained by calling FileURL(). + */ + bool HasURL() const + { + return !FileURL().IsEmpty(); + } + + /*! + * Returns an ImageOptions structure with information about the image in + * this image window. + */ + ImageOptions FileInfo() const; + + /*! + * Returns the modification counter for this image window. The + * modification counter contains the amount of changes made to the image + * since it was created, loaded from a disk file, or saved to a disk file. + */ + size_type ModifyCount() const; + + /*! + * Returns true iff the image in this image window has been modified and is + * unsaved. An image is modified if its modification counter is not zero. + */ + bool IsModified() const + { + return ModifyCount() > 0; + } + + /*! + * Requests closing this image window. Returns true if the window was + * actually closed. + * + * When an image window is closed, its image and all of its numerous + * associated resources are destroyed. The close operation is irreversible + * in PixInsight. + * + * If the image in this window is not modified, the window will be closed + * and true will be returned. + * + * If the image in this window is modified and has not been saved to a disk + * file, the PixInsight core application will ask the user if it is ok to + * throw away the changes by closing this window. If the user answers + * affirmatively, the window will be closed and this function will return + * true. If the user says no, the window will not be closed and the + * function will return false. + * + * \sa ForceClose() + */ + bool Close(); + + /*! + * Closes this image window unconditionally. The window will be closed + * immediately without asking questions, irrespective of whether the image + * or its associated metadata have been modified. + * + * \sa Close() + */ + void ForceClose(); + + /*! + * Returns the main view of this image window. + * + * The main view holds the entire image of this window. There is only one + * main view in an image window. + */ + View MainView() const; + + /*! + * Returns the current view of this image window. + * + * The current view is the view currently selected for direct user + * interaction in the core application GUI for this image window. The + * current view receives cursor and pointing device (mouse) events. + */ + View CurrentView() const; + + /*! + * Selects the specified view as the current view in this image window. + */ + void SelectView( View& ); + + /*! + * Selects the main view as the current view in this image window. + */ + void SelectMainView() + { + View v( MainView() ); SelectView( v ); + } + + /*! + * Destroys all existing properties for all views in this image window. + */ + void PurgeProperties(); + + /*! + * Returns true iff the specified view is a view of this image window, that + * is, either the main view of this image window, or one of its previews. + */ + bool IsValidView( const View& ) const; + + /*! + * Returns the number of previews currently defined in this image window. + */ + int NumberOfPreviews() const; + + /*! + * Returns true iff there are one or more previews currently defined in this + * image window. + */ + bool HasPreviews() const + { + return NumberOfPreviews() > 0; + } + + /*! + * Returns a dynamic array of View objects corresponding to the previews + * currently defined in this image window. If this window has no previews, + * an empty array is returned. + */ + Array Previews() const; + + /*! + * Finds a preview by its identifier. If the specified \a previewId + * identifier corresponds to an existing preview in this image window, it + * is returned as a View object. If no preview in this image window has the + * specified \a previewId identifier, or if this window has no previews, + * this function returns an alias of View::Null(). + */ + View PreviewById( const IsoString& previewId ) const; + + View PreviewById( const IsoString::ustring_base& previewId ) const + { + return PreviewById( IsoString( previewId ) ); + } + + /*! + * Returns true if a preview with the specified \a previewId identifier is + * currently defined in this image window; false if no preview with such + * identifier exists in this window, or if this window has no previews. + */ + bool PreviewExists( const IsoString& previewId ) const + { + return !IsNull() && !PreviewById( previewId ).IsNull(); + } + + bool PreviewExists( const IsoString::ustring_base& previewId ) const + { + return PreviewExists( IsoString( previewId ) ); + } + + /*! + * Returns the currently selected preview, or an alias of View::Null() if + * no preview is currently selected in this image window. + * + * \note The selected preview in an image window has nothing to do + * with the current view in the same image window. The selected + * preview corresponds to a selection on the main view of the window, used + * to resize and move preview rectangles, and also to perform preview + * actions (undo/redo, reset, store, restore, etc) without needing to select + * a preview as the window's current view. + */ + View SelectedPreview() const; + + /*! + * Causes this window to select the specified view as its selected + * preview. Refer to the SelectedPreview() function for further + * information on the concept of selected preview. + */ + void SelectPreview( View& ); + + /*! + * Causes this window to select the view with the specified identifier as + * its current selected preview. Refer to the SelectedPreview() + * function for further information on the concept of selected preview. + */ + void SelectPreview( const IsoString& previewId ) + { + View v( PreviewById( previewId ) ), SelectPreview( v ); + } + + void SelectPreview( const IsoString::ustring_base& previewId ) + { + SelectPreview( IsoString( previewId ) ); + } + + /*! + * Creates a new preview in this image window. Returns the newly created + * preview as a View object. + * + * Calling this function is equivalent to: + * + * \code CreatePreview( r.x0, r.y0, r.x1, r.y1, previewId ); \endcode + */ + View CreatePreview( const Rect& r, const IsoString& previewId = IsoString() ) + { + return CreatePreview( r.x0, r.y0, r.x1, r.y1, previewId ); + } + + View CreatePreview( const Rect& r, const IsoString::ustring_base& previewId ) + { + return CreatePreview( r, IsoString( previewId ) ); + } + + /*! + * Creates a new preview in this image window. Returns the newly created + * preview as a View object. + * + * \param x0,y0 Position (horizontal, vertical) of the left-top corner of + * the preview rectangle in image coordinates. + * + * \param x1,y1 Position (horizontal, vertical) of the right-bottom corner + * of the preview rectangle in image coordinates. + * + * \param previewId Preview identifier. If an empty string is specified, + * the core application will generate an automatic identifier + * for the newly created preview. If the specified identifier is + * already in use, the core application will make it unique by + * appending an automatically generated suffix. + * + * The preview rectangle must define a non-empty rectangular area + * completely included in the boundaries of the image in this window. + */ + View CreatePreview( int x0, int y0, int x1, int y1, const IsoString& previewId = IsoString() ); + + View CreatePreview( int x0, int y0, int x1, int y1, const IsoString::ustring_base& previewId ) + { + return CreatePreview( x0, y0, x1, y1, IsoString( previewId ) ); + } + + /*! + * Modifies the identifier and rectangular area properties of an existing + * preview. + * + * Calling this function is equivalent to: + * + * \code ModifyPreview( previewId, r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void ModifyPreview( const IsoString& previewId, const Rect& r, const IsoString& newId = IsoString() ) + { + ModifyPreview( previewId, r.x0, r.y0, r.x1, r.y1, newId ); + } + + void ModifyPreview( const IsoString::ustring_base& previewId, const Rect& r ) + { + ModifyPreview( IsoString( previewId ), r ); + } + + void ModifyPreview( const IsoString::ustring_base& previewId, const Rect& r, const IsoString::ustring_base& newId ) + { + ModifyPreview( IsoString( previewId ), r, IsoString( newId ) ); + } + + /*! + * Modifies the identifier and rectangular area properties of an existing + * preview. + * + * \param previewId Identifier of a preview whose properties will be + * modified. + * + * \param x0,y0 Position (horizontal, vertical) of the left-top corner of + * the new preview rectangle in image coordinates. + * + * \param x1,y1 Position (horizontal, vertical) of the right-bottom corner + * of the new preview rectangle in image coordinates. + * + * \param newId New preview identifier. If an empty string is specified, + * this function will not modify the current preview identifier. + * If the specified identifier is already in use in this window, + * the core application will make it unique by appending an + * automatically generated suffix. + * + * The preview rectangle must define a rectangular area of at least one + * pixel, completely included in the boundaries of the image in this window. + */ + void ModifyPreview( const IsoString& previewId, int x0, int y0, int x1, int y1, + const IsoString& newId = IsoString() ); + + void ModifyPreview( const IsoString::ustring_base& previewId, int x0, int y0, int x1, int y1 ) + { + ModifyPreview( IsoString( previewId ), x0, y0, x1, y1 ); + } + + void ModifyPreview( const IsoString::ustring_base& previewId, int x0, int y0, int x1, int y1, + const IsoString::ustring_base& newId ) + { + ModifyPreview( IsoString( previewId ), x0, y0, x1, y1, IsoString( newId ) ); + } + + /*! + * Returns the rectangular area in image coordinates of a preview with the + * specified \a previewId identifier. + * + * If no preview is defined in this window with the specified identifier, + * this function returns an empty rectangle. + */ + Rect PreviewRect( const IsoString& previewId ) const; + + Rect PreviewRect( const IsoString::ustring_base& previewId ) const + { + return PreviewRect( IsoString( previewId ) ); + } + + /*! + * Destroys an existing preview in this window and frees all of its + * associated view resources. + * + * \param previewId Identifier of the preview that will be destroyed. + * + * The PixInsight core application might ask the user for permission before + * attempting to destroy a preview in an image window. + */ + void DeletePreview( const IsoString& previewId ); + + void DeletePreview( const IsoString::ustring_base& previewId ) + { + DeletePreview( IsoString( previewId ) ); + } + + /*! + * Destroys all previews in this image window. + * + * The PixInsight core application reserves the right to ask the user for + * permission before attempting to destroy all previews in an image window. + */ + void DeletePreviews(); + + /*! + * Retrieves the pixel sample data format used by the image in this window. + * + * \param[out] bitsPerSample On output, will be equal to the number of + * bits per sample in the image in this window. Can be 8, 16 or + * 32 for an integer image; 32 or 64 for a floating point image. + * + * \param[out] floatSample On output, will be true if the image in this + * window uses floating point samples; false if it uses integer + * samples. + */ + void GetSampleFormat( int& bitsPerSample, bool& floatSample ) const; + + /*! + * Converts the image in this window to the specified sample data format. + * + * \param bitsPerSample Number of bits per sample. Can be 8, 16 or 32 for + * an integer image; 32 or 64 for a floating point image. + * + * \param floatSample True to transform this image to a floating point + * data format; false to transform this image to an integer data + * format. + * + * This function does nothing if the image in this window already has the + * specified sample data format. + */ + void SetSampleFormat( int bitsPerSample, bool floatSample ); + + /*! + * Returns the image window that is currently acting as a mask for this + * window, or ImageWindow::Null() if this window has no assigned mask. + */ + ImageWindow Mask() const; + + /*! + * Selects an image as the current mask for this image window. + * + * \param w Reference to an image window whose image will be selected as + * a mask for this window. + * + * \param inverted True to activate mask inversion. + */ + void SetMask( ImageWindow& w, bool inverted = false ); + + /*! + * Removes the current mask selection of this image window. + */ + void RemoveMask() + { + SetMask( Null() ); + } + + /*! + * Returns true iff mask inversion is currently active for this image window. + */ + bool IsMaskInverted() const; + + /*! + * Activates or deactivates mask inversion for this image window. + */ + void InvertMask( bool invert = true ) + { + ImageWindow mask = Mask(); + SetMask( mask, invert ); + } + + /*! + * Returns true iff the mask is current enabled for this image window. + */ + bool IsMaskEnabled() const; + + /*! + * Enables the mask of this image window. + */ + void EnableMask( bool = true ); + + /*! + * Disables the mask of this image window. + */ + void DisableMask( bool disable = true ) + { + EnableMask( !disable ); + } + + /*! + * Returns true iff the mask is currently visible for this image window. + */ + bool IsMaskVisible() const; + + /*! + * Shows the mask of this image window, i.e. enables mask visibility. + */ + void ShowMask( bool = true ); + + /*! + * Hides the mask of this image window, i.e. disables mask visibility. + */ + void HideMask( bool hide = true ) + { + ShowMask( !hide ); + } + + /*! + * Returns true iff a specified image window could be selected as a mask for + * this image window. + * + * For a given image \a M to be a valid mask for an image \a I: + * + * \li Both \a I and \a M must have identical dimensions. + * \li If \a I is a RGB color image, \a M can be either a grayscale image + * or a RGB color image. + * \li If \a I is a grayscale image, \a M must be also a grayscale image. + */ + bool IsMaskCompatible( const ImageWindow& ); + + /*! + * Returns true iff this image window is acting as a mask for other image + * window(s). + */ + bool HasMaskReferences() const; + + /*! + * Removes all mask references for this image window. + * + * All images that were masked by this window will be unmasked after calling + * this function. Use it with great care, since removing masking relations + * without direct user intervention is potentially dangerous. + */ + void RemoveMaskReferences(); + + /*! + * Updates the screen renditions of all visible image windows that are + * currently masked by this window. This includes only masked image windows + * with enabled mask visibility. + */ + void UpdateMaskReferences(); + + /*! + * Obtains a copy of the RGB working space (RGBWS) associated with this + * image window. + * + * \param[out] rgbws Reference to an object where the parameters of the + * current RGBWS in this window will be copied. + */ + void GetRGBWS( RGBColorSystem& rgbws ) const; + + /*! + * Sets the RGB working space (RGBWS) for this image window. + * + * \param rgbws Reference to a RGBWS that will be associated with this + * image window. + */ + void SetRGBWS( const RGBColorSystem& rgbws ); + + /*! + * Returns true iff this image window is associated with the global RGB + * working space (RGBWS). + * + * See the documentation for GetGlobalRGBWS() for a description of the + * global RGBWS in PixInsight. + */ + bool UsingGlobalRGBWS() const; + + /*! + * Associates this image window with the global RGB working space. + * + * See the documentation for GetGlobalRGBWS() for a description of the + * global RGBWS in PixInsight. + */ + void UseGlobalRGBWS(); + + /*! + * Obtains a copy of the current global RGB working space (RGBWS) in the + * PixInsight core application. + * + * \param[out] rgbws Reference to an object where the parameters of the + * current global RGBWS will be copied. + * + * The global RGBWS is the default RGBWS that is associated with newly + * created image windows (both as new images and when images are loaded + * from disk files). Global RGBWS parameters can be modified by the user + * through the standard RGBWorkingSpace process in the core application. + */ + static void GetGlobalRGBWS( RGBColorSystem& rgbws ); + + /*! + * Sets the parameters of the global RGB working space (RGBWS) in the core + * PixInsight application. + * + * \param rgbws Reference to an object whose parameters will be copied to + * the global RGBWS. + * + * See the documentation for GetGlobalRGBWS() for a description of the + * global RGBWS in PixInsight. + */ + static void SetGlobalRGBWS( const RGBColorSystem& rgbws ); + + /*! + * Returns true iff color management is active for this image window. + */ + bool IsColorManagementEnabled() const; + + /*! + * Enables color management for this image window. + * + * Color management uses ICC profiles for this image (either a profile + * associated with this image or a global profile) and the monitor device to + * control how this image is rendered on the screen. Color management + * transformations are applied to yield a visual representation that takes + * into account the actual meaning of numerical pixel sample values, + * considering the chromatic responses of the screen and of the devices and + * color spaces that have originated this image. + * + * If color management is disabled for an image, its pixel sample values are + * sent directly to the screen, avoiding ICC profile transformations. This + * improves output performance, but may give a false representation of the + * image on the screen. + * + * If this image window is visible, its screen rendition is updated + * immediately after calling this function. + */ + void EnableColorManagement( bool = true ); + + /*! + * Disables color management for this image window. + * + * See the documentation for EnableColorManagement() for additional + * information on color management in PixInsight. + * + * If this image window is visible, its screen rendition is updated + * immediately after calling this function. + */ + void DisableColorManagement( bool disable = true ) + { + EnableColorManagement( !disable ); + } + + /*! + * Returns true iff soft-proofing is currently enabled for this + * image window. + */ + bool IsProofingEnabled() const; + + /*! + * Enables soft-proofing for this image window. + * + * Color proofing is used to emulate an output device (usually a printer) on + * the screen. Proofing requires three ICC profiles: the image profile + * (either an embedded profile or the default profile), the monitor profile, + * and a proofing profile that describes the emulated device. Color + * proofing is useful to preview the final printed result without rendering + * images to physical media. + * + * If this image window is visible and has color management enabled, its + * screen rendition is updated immediately after calling this function. + */ + void EnableProofing( bool = true ); + + /*! + * Disables soft-proofing for this image window. + * + * See the documentation for EnableProofing() for additional information on + * color proofing. + * + * If this image window is visible and has color management enabled, its + * screen rendition is updated immediately after calling this function. + */ + void DisableProofing( bool disable = true ) + { + EnableProofing( !disable ); + } + + /*! + * Returns true iff the gamut check soft-proofing feature is + * currently enabled for this image window. + */ + bool IsGamutCheckEnabled() const; + + /*! + * Enables the gamut check proofing feature for this image window. + * + * The gamut check feature represents out-of-gamut colors (i.e., + * colors that are not defined in the color space of the image) with a + * special color (selectable via global color management preferences) for + * quick visual detection. + * + * If this image window is visible, has color management enabled, and has + * proofing enabled, its screen rendition is updated immediately after + * calling this function. If color proofing is disabled, calling this + * function has no effect. + */ + void EnableGamutCheck( bool = true ); + + /*! + * Disables the gamut check proofing feature for this image window. + * + * See the documentation for EnableGamutCheck() for additional information + * on the gamut check color proofing feature. + * + * If this image window is visible, has color management enabled, and has + * proofing enabled, its screen rendition is updated immediately after + * calling this function. If color proofing is disabled, calling this + * function has no effect. + */ + void DisableGamutCheck( bool disable = true ) + { + EnableGamutCheck( !disable ); + } + + /*! + * Allows enabling or disabling all color management features at once. + * + * \param cmEnabled Enables (if true) or disables (if false) color + * management for this image window. + * + * \param proofing Enables (if true) or disables (if false) + * soft-proofing for this image window. + * + * \param gamutCheck Enables (if true) or disables (if false) the + * gamut check proofing feature for this image window. + * The state of this argument has no meaning if the + * \a proofing parameter is false. + * + * If this image window is visible, its screen rendition is updated + * immediately after calling this function. + */ + void SetColorManagementFeatures( bool cmEnabled, bool proofing, bool gamutCheck ); + + /*! + * Obtains a copy of the current ICC profile associated with this image. + * + * \param[out] icc Reference to an object where a copy of the current ICC + * profile in this image will be stored. + */ + bool GetICCProfile( ICCProfile& icc ) const; + + /*! + * Sets the current ICC profile for this image window as a copy of an + * existing ICC profile. + * + * \param icc Reference to an object that will be used to set the current + * ICC profile for this image. + * + * If this image window is visible and has color management enabled, its + * screen rendition is updated immediately after calling this function. + */ + void SetICCProfile( const ICCProfile& icc ); + + /*! + * Sets the current ICC profile for this image window as a copy of an + * ICC profile loaded from a disk file. + * + * \param filePath A file path specification to an ICC profile that will + * be loaded and copied to the ICC profile of this image window. + * + * If this image window is visible and has color management enabled, its + * screen rendition is updated immediately after calling this function. + */ + void SetICCProfile( const String& filePath ); + + /*! + * Causes this image window to be associated with the default ICC profile + * globally defined in the PixInsight core application. + * + * If this image window has its own associated ICC profile, this funtion + * destroys it and frees its allocated space. + * + * If this image window is visible and has color management enabled, its + * screen rendition is updated immediately after calling this function. + */ + void DeleteICCProfile(); + + /*! + * Returns a copy of the %FITS header keywords currently defined for the + * image in this window. Returns an empty array if this image has no %FITS + * keywords. + */ + FITSKeywordArray Keywords() const; + + /*! + * Obtains a copy of the %FITS header keywords currently defined for the + * image in this window. Returns true if this image has %FITS keywords. + * + * \param[out] keywords Reference to a container that will receive a copy of + * the %FITS keywords defined in this image. + * + * \deprecated This member function has been deprecated. It is left only to + * keep existing code working. Use Keywords() in newly produced code. + */ + bool GetKeywords( FITSKeywordArray& keywords ) const + { + keywords = Keywords(); + return !keywords.IsEmpty(); + } + + /*! + * Sets the %FITS header keywords for this image as a copy of the set of + * keywords in the specified container. + * + * \param keywords Reference to a %FITS keyword array whose contents will + * be copied to the list of %FITS keywords of this image. + * + * The previous set of %FITS keywords in this image, if any, is lost and + * replaced by the specified set. + */ + void SetKeywords( const FITSKeywordArray& keywords ); + + /*! + * Deletes all existing %FITS header keywords in this image window. + */ + void ResetKeywords(); + + /*! + * Returns true iff this image window has a valid astrometric solution. + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + bool HasAstrometricSolution() const; + + /*! + * Attempts to reconstruct the astrometric solution associated with this + * image from existing metadata and image properties. + * + * \param allowGUIMessages Whether to report possible error and warning + * messages through message boxes and other + * graphical resources that may block the core + * application's event loop. If this parameter is + * false, warning and error messages will only be + * shown on the process console. True by default. + * + * \param notify Whether to notify the platform on the property + * changes. This is true by default. + * + * Returns true iff a valid astrometric solution has been built for this + * image window. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + bool RegenerateAstrometricSolution( bool allowGUIMessages = true, bool notify = true ); + + /*! + * Removes an existing astrometric solution from this image window. + * + * \param notify Whether to notify the platform on the property changes. + * This is true by default. + * + * If the image has no valid astrometric solution, calling this member + * function has no effect. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + void ClearAstrometricSolution( bool notify = true ); + + /*! + * Updates the set of FITS header keywords and image properties of this + * image with metadata defining its current astrometric solution. + * + * \param notify Whether to notify the platform on the property changes. + * This is true by default. + * + * If the image has no valid astrometric solution, calling this member + * function has no effect. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + void UpdateAstrometryMetadata( bool notify = true ); + + /*! + * Converts the specified \a x and \a y coordinates from the image + * coordinate system to celestial equatorial coordinates. + * + * If the window has a valid astrometric solution and the image-to-celestial + * coordinate transformation succeeds, the values of the specified \a x and + * \a y variables are replaced with the corresponding right ascension and + * declination, respectively, and the function returns true. Right ascension + * and declination are provided expressed in degrees in the ranges [0,360) + * (if \a rawRA is false; see below) and [-90,+90], respectively. Note that + * both input image and output equatorial coordinates can legally be outside + * image bounds. Output equatorial coordinates will be referred to the + * reference system of the astrometric solution associated with this image + * window (ICRS or GCRS). + * + * If \a rawRA is true, the output right ascension is \e not constrained to + * the [0,360) range. This is useful for interpolation schemes where + * discontinuities caused by zero crossings in right ascension, i.e. abrupt + * changes from 360 to 0 degrees, are not admissible numerically. Right + * ascensions returned by this function when \a rawRA = true is specified + * can be larger than 360 degrees or less than zero, ensuring smooth + * transitions. + * + * If the window has no valid astrometric solution, or if the coordinate + * transformation cannot be performed, the \a x and \a y variables are not + * modified and the function returns false. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + bool ImageToCelestial( double& x, double& y, bool rawRA = false ) const; + + /*! + * Converts the specified point \a pI from the image coordinate system to + * celestial equatorial coordinates. + * + * If the conversion is successful, the computed right ascension and + * declination in degrees are stored in the \a pRD.x and \a pRD.y + * coordinates, respectively, and the function returns true. Otherwise the + * point \a pRD is not modified and the function returns false. + * + * See ImageToCelestial( double&, double&, bool ) const for complete + * information. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + template + bool ImageToCelestial( DPoint& pRD, const GenericPoint& pI, bool rawRA = false ) const + { + DPoint qI( double( pI.x ), double( pI.y ) ); + if ( ImageToCelestial( qI.x, qI.y, rawRA ) ) + { + pRD = qI; + return true; + } + return false; + } + + /*! + * Converts the specified \a ra and \a dec coordinates, expressed in + * degrees, from celestial equatorial coordinates to the image coordinate + * system. + * + * If the window has a valid astrometric solution and the celestial-to-image + * coordinate transformation succeeds, the values of the specified \a ra and + * \a dec variables are replaced with the corresponding \a x and \a y image + * coordinates, respectively, expressed in pixels. Note that both input + * equatorial and output image coordinates can legally be outside image + * bounds. Input equatorial coordinates are assumed to be referred to the + * reference system of the astrometric solution associated with this image + * window (ICRS or GCRS). + * + * If the window has no valid astrometric solution, or if the coordinate + * transformation cannot be performed, the \a ra and \a dec variables are + * not modified and the function returns false. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + bool CelestialToImage( double& ra, double& dec ) const; + + /*! + * Converts the specified point \a pRD from celestial equatorial coordinates + * in degrees to the image coordinate system. + * + * If the conversion is successful, the computed \a x and \a y image + * coordinates in pixels are stored in the \a pI.x and \a pI.y members, + * respectively, and the function returns true. Otherwise the point \a pI is + * not modified and the function returns false. + * + * See CelestialToImage( double&, double& ) const for detailed information. + * + * \ingroup astrometry_support + * \sa AstrometricMetadata + */ + bool CelestialToImage( DPoint& pI, const DPoint& pRD ) const + { + DPoint qI = pRD; + if ( CelestialToImage( qI.x, qI.y ) ) + { + pI = qI; + return true; + } + return false; + } + + /*! + * Gets the current image resolution parameters in this image window. + * + * \param[out] xRes Reference to a variable where the horizontal resolution + * will be stored. + * + * \param[out] yRes Reference to a variable where the vertical resolution + * will be stored. + * + * \param[out] metric Reference to a variable whose stored value will + * indicate the current resolution units in this image window. + * If this variable is true, resolution is expressed in pixels + * per centimeter; if it is false, resolution is expressed in + * pixels per inch. + * + * Resolution is expressed in pixels per resolution unit (centimeter if + * \a metric is true; inch if \a metric is false). + */ + void GetResolution( double& xRes, double& yRes, bool& metric ) const; + + /*! + * Sets image resolution parameters for this image window. + * + * \param xRes Horizontal resolution in pixels per resolution unit. + * Must be > 0. + * + * \param yRes Vertical resolution in pixels per resolution unit. + * Must be > 0. + * + * \param metric Indicates the resolution unit in which resolution is + * expressed for both axes. If this parameter is true, + * resolution is expressed in pixels per centimeter; if it is + * false, resolution is in pixels per inch. + */ + void SetResolution( double xRes, double yRes, bool metric = false ); + + /*! + * Sets equal image resolution parameters for both axes in this image + * window. + * + * \param r Resolution in pixels per resolution unit. This value is to be + * applied to both axes (horizontal, vertical) of the image in + * this window. + * + * \param metric Indicates the resolution unit in which resolution is + * expressed. If this parameter is true, resolution is expressed + * in pixels per centimeter; if it is false, resolution is in + * pixels per inch. + */ + void SetResolution( double r, bool metric = false ) + { + SetResolution( r, r, metric ); + } + + /*! + * Gets the current default image resolution parameters. + * + * \param[out] xRes Reference to a variable where the default horizontal + * resolution will be stored. + * + * \param[out] yRes Reference to a variable where the default vertical + * resolution will be stored. + * + * \param[out] metric Reference to a variable whose stored value will + * indicate the current default resolution units. If this + * variable is true, default resolution is expressed in pixels + * per centimeter; if it is false, resolution is expressed in + * pixels per inch. + * + * Resolution is expressed in pixels per resolution unit (centimeter if + * \a metric is true; inch if \a metric is false). + * + * Default resolution parameters are applied to all newly created images in + * the PixInsight core application. + */ + static void GetDefaultResolution( double& xRes, double& yRes, bool& metric ); + + /*! + * Returns true iff default ICC profile embedding is globally enabled for RGB + * images in the PixInsight core application. + * + * Modules implementing file format support may call this function to + * provide coherent default states for ICC profile embedding selectable + * options in their interfaces; e.g. "Embed ICC Profile" check boxes on + * format options dialogs presented to the user during file write + * operations. However, the PixInsight core application always provides + * coherent default states for all embedding flags to all modules, so this + * function is not frequently used. + */ + static bool IsDefaultICCProfileEmbeddingEnabledForRGBImages(); + + /*! + * Returns true iff default ICC profile embedding is globally enabled for + * grayscale images in the PixInsight core application. + * + * Modules implementing file format support may call this function to + * provide coherent default states for ICC profile embedding selectable + * options in their interfaces; e.g. "Embed ICC Profile" check boxes on + * format options dialogs presented to the user during file write + * operations. However, the PixInsight core application always provides + * coherent default states for all embedding flags to all modules, so this + * function is not frequently used. + */ + static bool IsDefaultICCProfileEmbeddingEnabledForGrayscaleImages(); + + /*! + * Returns true iff default thumbnail embedding is globally enabled in the + * PixInsight core application. + * + * Modules implementing file formats should call this function to provide + * coherent default states for thumbnail embedding selectable options in + * their interfaces; e.g. "Embed Thumbnail" check boxes on dialogs presented + * to the user to gather file and format-specific options during file write + * operations. + */ + static bool IsDefaultThumbnailEmbeddingEnabled(); + + /*! + * Returns true iff default properties embedding is globally enabled in the + * PixInsight core application. + * + * Modules implementing file formats should call this function to provide + * coherent default states for properties embedding selectable options in + * their interfaces; e.g. "Embed Properties" check boxes on dialogs + * presented to the user to gather file and format-specific options during + * file write operations. + */ + static bool IsDefaultPropertiesEmbeddingEnabled(); + + /*! + * Returns the current list of directories for storage of swap image files. + * + * Swap files are generated and maintained by the PixInsight core + * application to store temporary image data. By default, the returned list + * contains a single string with the system's temporary storage directory + * (usually the value of the TEMP or TMP environmental variables). + * + * When the returned list contains two or more directories, PixInsight uses + * parallel disk I/O operations to store and retrieve swap files on separate + * physical devices, which greatly improves performance of history traversal + * operations (as undo/redo operations). + */ + static StringList SwapDirectories(); + + /*! + * Attempts to set a new list of directories for storage of swap files. + * + * To be able to set a new list of directories for swap file storage, a + * module must have enough privileges to change global settings on the + * PixInsight platform. If the calling module has insufficient privileges, + * this function returns false and no changes are done. + * + * The specified list can contain zero or more path specifications to + * existing directories. If more than one directory is specified, all of + * them must be supported by different \e physical devices (usually hard + * disks) on the system. Read the documentation for the + * ImageVariant::WriteSwapFiles() member function for more information about + * parallel disk I/O operations and their associated risks. + * + * If the specified list is empty, the PixInsight platform will perform a + * reset of the swap directories list to its default settings. This usually + * means that all swap files will be generated and maintained on the + * system's temporary storage directory (the value of the TEMP or TMP + * environmental variables by default) using single-threaded disk I/O + * operations. + */ + static bool SetSwapDirectories( const StringList& directories ); + + /*! + * Returns the current cursor tolerance in viewport coordinates, as + * globally established in the PixInsight core application. + * + * This value is the threshold distance in pixels, in viewport coordinates, + * used to activate actions based on object proximity. + * + * For example, if an interface implements an interactive procedure for + * resizing a rectangle based on mouse movement events, when the mouse + * cursor gets closer to a given side of the rectangle by less than the + * current cursor tolerance, the cursor shape should be changed to give + * feedback to the user; e.g. to a double arrow shape corresponding to the + * side being resized. + */ + static int CursorTolerance(); + + /*! + * Returns the current GUI working mode in the PixInsight core application. + * + * The returned value can be identified with the symbolic constants defined + * in the ImageMode namespace. + */ + static gui_mode CurrentMode(); + + /*! + * Sets the current GUI working mode in the PixInsight core application. + * + * \param mode Specifies the new GUI mode. Supported modes are identified + * through symbolic constants defined in the ImageMode namespace. + * + * Not all GUI modes are valid in all contexts. For example, if the current + * view is a preview, the New Preview mode cannot be selected. If the + * specified mode is not currently valid, this function is simply ignored. + */ + static void SelectMode( gui_mode mode ); + + /*! + * Returns the current display channel in the core application's GUI. + * + * The returned value can be identified with the symbolic constants defined + * int the DisplayChannel namespace. + */ + display_channel CurrentChannel() const; + + /*! + * Returns true iff the current display channel (in the core application) + * corresponds to an alpha channel of the image in the current view. + */ + bool IsAlphaChannelDisplayed() const + { + return CurrentChannel() >= DisplayChannel::Alpha; + } + + /*! + * Returns the alpha channel index displayed for the image in the + * current view. If the current display channel does not correspond to an + * alpha channel, a negative integer value is returned. + * + * Alpha channel indices are relative to the first alpha channel in an + * image. For example, the first alpha channel is always indexed as alpha + * channel #0, and so on. + */ + int CurrentAlphaChannel() const + { + return CurrentChannel() - DisplayChannel::Alpha; + } + + /*! + * Selects the current display channel in the core application's GUI. + * + * \param c Specifies the new display channel. Supported display channels + * are identified through symbolic constants defined in the + * DisplayChannel namespace. + * + * Not all display channels are valid for all images in all contexts. For + * example, if the image in the current view is a grayscale image, the only + * valid display channels are the combined RGB/K channel + * (DisplayChannel::RGBK) and, if the image has \a n alpha channels, values + * in the range DisplayChannel::Alpha to DisplayChannel::Alpha+n-1. If an + * invalid display channel is specified, this function is simply ignored. + */ + void SelectChannel( display_channel c ); + + /*! + * Returns the current mask rendering mode for this image window. + * + * Supported mask rendering modes are defined in the MaskMode namespace. + */ + mask_mode MaskMode() const; + + /*! + * Sets the current mask rendering mode for this image window. + * + * \param mode Specifies the new mode that will be used to render + * masks. Supported mask rendition modes are identified + * through symbolic constants defined in the + * MaskMode namespace. + */ + void SetMaskMode( mask_mode mode ); + + /*! + * Returns the current transparency background brush and its foreground and + * background colors in the core application's GUI. + * + * \param[out] fgColor The foreground color of the background brush. + * \param[out] bgColor The background color of the background brush. + * + * The returned value can be identified with the symbolic constants defined + * int the BackgroundBrush namespace. + * + * The obtained colors are AARRGGBB values. The alpha values are always + * 0xff, since the background brush cannot be transparent. + * + * In PixInsight, pixel opacity is defined by the first alpha channel of the + * image: a pixel is opaque if the corresponding alpha channel value is + * white; a pixel is completely transparent if the corresponding alpha value + * is black. Intermediate alpha values define semitransparent pixels. + * + * The background brush is a two-color brush used to render transparent + * regions of images. It is a global object used for all images in the + * PixInsight core application. + */ + static background_brush GetBackgroundBrush( uint32& fgColor, uint32& bgColor ); + + /*! + * Sets the transparency background brush in the core application's GUI. + * + * \param brush Specifies the new background brush that will be used + * to render transparent regions of images. Supported + * background brushes are identified through symbolic + * constants defined in the BackgroundBrush namespace. + * + * \param fgColor New foreground color for the background brush. If zero is + * specified (the default value), the current foreground + * color will not be changed. + * + * \param bgColor New background color for the background brush. If zero is + * specified (the default value), the current background + * color will not be changed. + * + * For a definition of background brushes and their meaning in PixInsight, + * see the documentation of GetBackgroundBrush(). + * + * \note If no foreground and background colors are specified, this + * function will not change the current background brush colors. This is + * because the corresponding function arguments default to zero. + */ + static void SetBackgroundBrush( background_brush brush, uint32 fgColor = 0, uint32 bgColor = 0 ); + + /*! + * Returns the current transparency rendering mode for this image window. + * + * Supported transparency modes are defined in the TransparencyMode + * namespace. + */ + transparency_mode TransparencyMode() const; + + /*! + * Returns the color to be used in this image window to render transparent + * image regions, when the transparency mode is TransparencyMode::Color. + * + * The returned color is an AARRGGBB value. The alpha value is always 0xff, + * since the transparency background cannot be transparent. + */ + RGBA TransparencyColor() const; + + /*! + * Returns true iff transparent image areas are currently visible for this + * image window. + * + * Transparencies are visible if the current rendering mode is not + * TransparencyMode::Hide. + */ + bool IsTransparencyVisible() const + { + return TransparencyMode() != pcl::TransparencyMode::Hide; + } + + /*! + * Sets the current transparency rendering mode for this image window. + * + * \param mode Specifies the new mode that will be used to render + * transparent regions of images. Supported transparency + * modes are identified through symbolic constants defined in + * the TransparencyMode namespace. + * + * \param color New color that will be used when the transparency mode is + * TransparencyMode::Color. If zero is specified (the default + * value), the current color will not be changed. + */ + void SetTransparencyMode( transparency_mode mode, RGBA color = 0 ); + + /*! + * Disables transparency renditions for this image window. + * + * Calling this function is equivalent to: + * + * \code SetTransparencyMode( pcl::TransparencyMode::Hide ); \endcode + */ + void HideTransparency() + { + SetTransparencyMode( pcl::TransparencyMode::Hide ); + } + + /*! + * Sets new viewport central location coordinates and zoom factor for this + * image window. + * + * \param cx,cy Position (horizontal, vertical) of the new central + * viewport location in image coordinates. + * + * \param zoom New viewport zoom factor. Positive zoom factors are + * interpreted as magnifying factors; negative zoom factors + * are reduction factors: + * + *
+    * Zoom Factor    Screen Zoom (screen pixels : image pixels)
+    * ===========    ==========================================
+    *      0               Current zoom factor (no change)
+    *   1 or -1            1:1 (actual pixels)
+    *      2               2:1 (x2 magnification)
+    *      3               3:1 (x3 magnification)
+    *     ...
+    *     -2               1:2 (1/2 reduction)
+    *     -3               1:3 (1/3 reduction)
+    *     ...
+    * 
+ * + * A zoom factor of -1 should not be used explicitly; it is a + * reserved value for internal use, and there is no guarantee + * that future versions of PCL continue accepting it. + * + * If the specified viewport location cannot correspond to the viewport + * central position with the specified zoom factor, the nearest image + * coordinates are always selected automatically. For example, if you + * pass image coordinates \a cx=0 and \a cy=0 as arguments to this function, + * the GUI will set the viewport center to the necessary image location in + * order to display the upper left corner of the image just at the upper + * left corner of the viewport. + * + * If the \a zoom argument is not specified, the current zoom factor of the + * active view is not changed since the default value of this parameter is + * zero; see the table above. + * + * If this image window is visible, calling this function causes an + * immediate regeneration of the screen rendition for the visible viewport + * region. This includes regeneration of screen renditions depending on + * active dynamic interfaces. + */ + void SetViewport( double cx, double cy, int zoom = 0 ); + + /*! + * Sets new viewport central location and zoom factor for this image + * window. + * + * Calling this function is equivalent to: + * + * \code SetViewport( center.x, center.y, int ); \endcode + * + * See the documentation for SetViewport( double, double, int ). + */ + void SetViewport( const DPoint& center, int zoom = 0 ) + { + SetViewport( center.x, center.y, zoom ); + } + + /*! + * Adjusts this image window to the minimum size required to show the entire + * image at the current zoom factor or, if that cannot be achieved, to show + * the maximum possible portion of the image without exceeding the visible + * area of its parent workspace in the core application's GUI. + * + * This function will move the window on its parent workspace only if it is + * strictly necessary. + */ + void FitWindow(); + + /*! + * Selects the largest viewport zoom factor that allows showing the entire + * image in this image window, changing its size as necessary, but not its + * position on its parent workspace. + * + * \param optimalFit If true, the PixInsight core application will try to + * find an optimal zoom factor to fit the entire image + * window within the visible area of its parent + * workspace without causing too much obstruction of + * sibling windows and icons. This option is enabled by + * default. + * + * \param allowMagnification If false, this function will not select a zoom + * factor greater than one, even if doing so would be + * possible for this window without exceeding the + * visible area of its parent workspace. This option is + * true by default. + * + * \param allowAnimations If false, no graphical animation effects (such + * as fading effects) will be applied to the image + * window when resized, bypassing global preferences + * settings. Animations are enabled by default. + * + * \param noLimits If true, the window will be resized ignoring the + * current maximization limit set for its parent + * workspace, making possible to occupy the entire + * visible area of the workspace, just to the limits of + * the main application window. This option is disabled + * by default. + */ + void ZoomToFit( bool optimalFit = true, + bool allowMagnification = true, + bool allowAnimations = true, + bool noLimits = false ); + + /*! + * Returns the current zoom factor in the viewport of this image window. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + int ZoomFactor() const; + + /*! + * Sets the zoom factor for the viewport in this image window to the + * specified value \a z. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + void SetZoomFactor( int z ); + + /*! + * Increments the current zoom factor for the viewport in this image window. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + void ZoomIn() + { + int z = ZoomFactor() + 1; + SetZoomFactor( (z > 0) ? z : +1 ); + } + + /*! + * Decrements the current zoom factor for the viewport in this image window. + * + * To learn how zoom factors are interpreted in PixInsight, see the + * documentation for SetViewport( double, double, int ). + */ + void ZoomOut() + { + int z = ZoomFactor() - 1; + SetZoomFactor( (z > 0 || z < -1) ? z : -2 ); + } + + /*! + * Gets the current sizes of the viewport in this image window. + * + * \param[out] width Reference to a variable where the viewport width in + * pixels will be stored. + * + * \param[out] height Reference to a variable where the viewport height in + * pixels will be stored. + * + * The provided sizes represent the entire image in this image window, as + * represented on its viewport after applying the current zoom factor. + * Viewport sizes can also be thought of as the available navigation ranges + * in an image window. + */ + void GetViewportSize( int& width, int& height ) const; + + /*! + * Gets the current width of the viewport in this image window. + */ + int ViewportWidth() const + { + int w, dum; + GetViewportSize( w, dum ); + return w; + } + + /*! + * Gets the current height of the viewport in this image window. + */ + int ViewportHeight() const + { + int dum, h; + GetViewportSize( dum, h ); + return h; + } + + /*! + * Returns the current viewport position in this image window. + * + * The viewport position corresponds to the viewport coordinates of the + * upper left corner of the visible viewport region. These + * coordinates can be negative if the represented image is smaller than the + * size of the viewport control, that is, when the extended viewport + * space is visible around the screen rendition of the image. + */ + Point ViewportPosition() const; + + /*! + * Sets the viewport position in this image window to the specified \a x + * and \a y viewport coordinates. + * + * If this image window is visible, calling this function causes an + * immediate regeneration of the screen rendition for the visible viewport + * region. This includes regeneration of screen renditions depending on + * active dynamic interfaces. + */ + void SetViewportPosition( int x, int y ); + + /*! + * Sets the viewport position in this image window to the specified + * position \a p in viewport coordinates. + * + * Calling this function is equivalent to: + * + * \code SetViewportPosition( p.x, p.y ); \endcode + */ + void SetViewportPosition( const Point& p ) + { + SetViewportPosition( p.x, p.y ); + } + + /*! + * Gets the current visible viewport region in this image window. + * + * The returned rectangle corresponds to the visible region of the image in + * viewport coordinates. It depends on the current viewport zoom factor and + * on the positions of the viewport's scroll bars, if they are visible. + */ + Rect VisibleViewportRect() const; + + /*! + * Returns the width in pixels of the current visible viewport region in + * this image window. + */ + int VisibleViewportWidth() const + { + return VisibleViewportRect().Width(); + } + + /*! + * Returns the height in pixels of the current visible viewport region in + * this image window. + */ + int VisibleViewportHeight() const + { + return VisibleViewportRect().Height(); + } + + /*! + * Returns true iff this image window is currently visible. + */ + bool IsVisible() const; + + /*! + * Shows this image window on its parent workspace. + * + * \param fitWindow If true, this function will call ZoomToFit() with + * default parameters after showing the window on its + * parent workspace. This is useful to ensure that a + * newly created image window will be displayed + * optimally as soon as it is shown for the first time. + * This option is enabled by default. + * + * Image windows are normally visible in PixInsight. Under normal working + * conditions, an image window can only be hidden if it has never been shown + * since it was created, or if it has been hidden explicitly, which can only + * happen programmatically. + */ + void Show( bool fitWindow = true ); + + /*! + * Hides this image window if it is currently visible on its parent + * workspace. + */ + void Hide(); + + /*! + * Returns true iff this image window is iconic. + */ + bool IsIconic() const; + + /*! + * Iconizes this image window. + */ + void Iconize(); + + /*! + * Deiconizes this image window, if it was previously iconized. + */ + void Deiconize(); + + /*! + * Brings this image window to the top of the stack of image windows in its + * parent workspace of the PixInsight core application's GUI. + * + * Calling this function implicitly shows this image window, if it was + * previously hidden or iconized. If this window is a child of the current + * workspace, calling this function also activates it and gives it the + * keyboard focus. + */ + void BringToFront(); + + /*! + * Pushes this image window to the bottom of the stack of image windows in + * its parent workspace of the PixInsight core application's GUI. + * + * If this is the only visible image window in its parent workspace, calling + * this function has no effect. If there are more visible image windows in + * the parent workspace and it is the current workspace, calling this + * function implicitly deactivates this image window and gives the keyboard + * focus to the new topmost image window in the window stack. + */ + void SendToBack(); + + /*! + * Returns true iff a dynamic session is currently active in the core + * PixInsight application. + * + * A dynamic session is active if there is a processing interface working + * in dynamic mode, and one or more views have been selected by the active + * dynamic interface as dynamic targets. + */ + static bool IsDynamicSessionActive(); + + /*! + * Returns a pointer to the current active dynamic interface. + * + * The active dynamic interface is the interface that has been activated in + * dynamic mode. + * + * \warning Note that the returned pointer could point to an object that has + * not been created by the calling module; this is what we call a + * foreign object in the PixInsight/PCL framework. If a pointer to + * a foreign interface is returned by this function, the calling module + * cannot use that pointer to access the foreign object in any way, + * since direct intermodule communication is not supported in the current + * PixInsight/PCL framework. + */ + static ProcessInterface* ActiveDynamicInterface(); + + /*! + * Terminates the current dynamic session, if there is one active, and + * optionally closes the active dynamic interface. + * + * If the calling module is the owner of the active dynamic interface, the + * dynamic session is terminated immediately. + * + * If the calling module is not the owner of the active dynamic interface + * (i.e., if the active dynamic interface is a foreign object for + * the calling module), then the PixInsight core application will ask the + * user if it is ok to terminate the active dynamic session, providing + * complete information about the calling module. This is a security + * enforcement procedure. + */ + static bool TerminateDynamicSession( bool closeInterface = true ); + + /*! + * Sets the shape of the pointing device's cursor for the active dynamic + * session as an image in the XPM format. + * + * \param xpm Address of an image in the XPM format, which will be used + * as the new cursor shape in Dynamic Operation GUI mode. + * + * \param hx,hy Coordinates (horizontal, vertical) of the cursor hot spot + * relative to the upper left corner of the specified cursor + * shape image. + * + * See the documentation for SetDynamicCursor( const Bitmap&, int, int ) for + * more information on dynamic mode cursors. + * + * \deprecated This function has been deprecated and will be removed in a + * future version of PCL. Dynamic view cursors must always be specified as + * Bitmap objects in newly produced code. + */ + void SetDynamicCursor( const char** xpm, int hx = 0, int hy = 0 ); + + /*! + * Sets the shape of the pointing device's cursor for the active dynamic + * session as an image in the XPM format. + * + * Calling this function is equivalent to: + * + * \code SetDynamicCursor( xpm, p.x, p.y ); \endcode + * + * \deprecated This function has been deprecated and will be removed in a + * future version of PCL. Dynamic view cursors must always be specified as + * Bitmap objects in newly produced code. + */ + void SetDynamicCursor( const char** xpm, const Point& p ) + { + SetDynamicCursor( xpm, p.x, p.y ); + } + + /*! + * Sets the shape of the pointing device's cursor for the active dynamic + * session as an ARGB bitmap. + * + * \param bmp Reference to a bitmap that will be used as the new cursor + * shape for the Dynamic Operation GUI mode. + * + * \param hx,hy Coordinates (horizontal, vertical) of the cursor hot spot + * relative to the upper left corner of the specified cursor + * shape bitmap. + * + * If there is no active dynamic session, this function is ignored. + * + * Modules call this function to adapt the cursor shape to specific + * interactive operations during dynamic sessions. Custom cursor shapes + * must be used by dynamic interfaces to provide accurate and meaningful + * feedback to the user. + * + * The specified cursor shape will be used in the Dynamic Operation working + * GUI mode. It will not affect standard cursor shapes used by the GUI in + * other working modes (as Readout, Zoom In, etc). + */ + void SetDynamicCursor( const Bitmap& bmp, int hx = 0, int hy = 0 ); + + /*! + * Sets the shape of the pointing device's cursor for the active dynamic + * session as a RGBA bitmap. + * + * Calling this function is equivalent to: + * + * \code SetDynamicCursor( bmp, p.x, p.y ); \endcode + */ + void SetDynamicCursor( const Bitmap& bmp, const Point& p ) + { + SetDynamicCursor( bmp, p.x, p.y ); + } + + /*! + * Restores the default shape of the pointing device's cursor for the active + * dynamic session. + */ + void ResetDynamicCursor() + { + SetDynamicCursor( Bitmap::Null() ); + } + + /*! + * Returns a RGBA bitmap as a copy of the current shape of the pointing + * device's cursor for the active dynamic session. + */ + Bitmap DynamicCursorBitmap() const; + + /*! + * Returns the cursor hot spot position for the active dynamic session. + * + * Cursor hot spot coordinates are relative to the left-top corner of the + * cursor shape bitmap. + */ + Point DynamicCursorHotSpot() const; + + /*! + * Returns the ratio between physical screen pixels and device-independent + * coordinate units for this image window (actually, for the workspace that + * this window belongs to). + * + * The returned value is greater than or equal to one. Typical pixel ratios + * are 2.0 for high-dpi displays such as Retina monitors, or 1.0 for normal + * 96 dpi monitors. + * + * The display pixel ratio is never used by ImageWindow, since all viewport + * coordinates are always specified in physical display pixels. However, + * knowing this ratio is useful to properly scale interactive graphical + * contents generated by dynamic processes. For example, drawing vector + * graphics with one-pixel wide pens is fine for normal monitors, but may + * cause visibility problems on a 4K monitor, and is clearly inappropriate + * on a 5K monitor. + * + * The following example shows how to scale a Pen's width to adapt a drawing + * to the physical display where the window is being shown to the user: + * + * \code + * void MyStrokePolygon( VectorGraphics& G, + * const Array& points, RGBA color, + * const ImageWindow& window ) + * { + * G.StrokePolygon( points, Pen( color, window.DisplayPixelRatio() ) ); + * } + * \endcode + */ + double DisplayPixelRatio() const; + + /*! + * Converts the specified \a x and \a y integer coordinates from the + * viewport coordinate system to the image coordinate system. + * + * The converted image coordinates are rounded to the nearest integers. + */ + void ViewportToImage( int& x, int& y ) const; + + /*! + * Converts the specified \a x and \a y real floating point coordinates from + * the viewport coordinate system to the image coordinate system. + */ + void ViewportToImage( double& x, double& y ) const; + + /*! + * Converts a point \a p in the viewport coordinate system to the image + * coordinate system. Returns a point with the resulting floating point real + * image coordinates. + */ + template + DPoint ViewportToImage( const GenericPoint& p ) const + { + DPoint p1 = p; + ViewportToImage( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the viewport coordinate system to the image + * coordinate system. Returns a rectangle with the resulting floating point + * real image coordinates. + */ + template + DRect ViewportToImage( const GenericRectangle& r ) const + { + DRect r1 = r; + ViewportToImage( r1.x0, r1.y0 ); + ViewportToImage( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Converts a set of integer points from the viewport coordinate system to + * the image coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from viewport coordinates to image coordinates. + * + * \param n Number of points in the \a p array. + * + * Converted point image coordinates are rounded to the nearest integers. + */ + void ViewportToImage( Point* p, size_type n ) const; + + /*! + * Converts a set of real floating-point points from the viewport + * coordinate system to the image coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from viewport coordinates to image coordinates. + * + * \param n Number of points in the \a p array. + */ + void ViewportToImage( DPoint* p, size_type n ) const; + + /*! + * Converts a set of points in a dynamic array from the viewport coordinate + * system to the image coordinate system. + * + * \param a Reference to a dynamic array of points that will be converted + * from viewport coordinates to image coordinates. + */ + template + void ViewportToImage( Array >& a ) const + { + ViewportToImage( a.Begin(), a.Length() ); + } + + /*! + * Converts a set of integer scalars from the viewport coordinate system to + * the image coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from viewport coordinates to image + * coordinates. + * + * \param n Number of scalars in the \a p array. + * + * Converted scalars in image coordinates are rounded to the nearest + * integers. + */ + void ViewportScalarToImage( int* d, size_type n ) const; + + /*! + * Converts a set of real floating-point scalars from the viewport + * coordinate system to the image coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from viewport coordinates to image + * coordinates. + * + * \param n Number of scalars in the \a p array. + */ + void ViewportScalarToImage( double* d, size_type n ) const; + + /*! + * Converts a scalar \a d in the viewport coordinate system to the image + * coordinate system. Returns the resulting floating point real scalar in + * image coordinates. + */ + double ViewportScalarToImage( double d ) const; + + /*! + * Converts a scalar \a d in the viewport coordinate system to the image + * coordinate system. Returns the resulting floating point real scalar in + * image coordinates. + */ + template + double ViewportScalarToImage( T d ) const + { + return ViewportScalarToImage( double( d ) ); + } + + /*! + * Converts the specified \a x and \a y integer coordinates from the image + * coordinate system to the viewport coordinate system. + * + * The converted viewport coordinates are rounded to the nearest integers. + */ + void ImageToViewport( int& x, int& y ) const; + + /*! + * Converts the specified \a x and \a y real floating-point coordinates from + * the image coordinate system to the viewport coordinate system. + */ + void ImageToViewport( double& x, double& y ) const; + + /*! + * Converts a point \a p in the image coordinate system to the viewport + * coordinate system. Returns a point with the resulting viewport + * coordinates. + * + * If the template argument T corresponds to an integer type, the converted + * viewport coordinates in the resulting point are rounded to the nearest + * integers. + */ + template + GenericPoint ImageToViewport( const GenericPoint& p ) const + { + GenericPoint p1 = p; + ImageToViewport( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the image coordinate system to the viewport + * coordinate system. Returns a rectangle with the resulting viewport + * coordinates. + * + * If the template argument T corresponds to an integer type, the converted + * viewport coordinates in the resulting rectangle are rounded to the + * nearest integers. + */ + template + GenericRectangle ImageToViewport( const GenericRectangle& r ) const + { + GenericRectangle r1 = r; + ImageToViewport( r1.x0, r1.y0 ); + ImageToViewport( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Converts a set of integer points from the image coordinate system to + * the viewport coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from image coordinates to viewport coordinates. + * + * \param n Number of points in the \a p array. + * + * Converted point viewport coordinates are rounded to the nearest integers. + */ + void ImageToViewport( Point* p, size_type n ) const; + + /*! + * Converts a set of real floating-point points from the image coordinate + * system to the viewport coordinate system. + * + * \param p Pointer to the first point in the array of points that will + * be converted from image coordinates to viewport coordinates. + * + * \param n Number of points in the \a p array. + */ + void ImageToViewport( DPoint* p, size_type n ) const; + + /*! + * Converts a set of points in a dynamic array from the image coordinate + * system to the viewport coordinate system. + * + * \param a Reference to a dynamic array of points that will be converted + * from image coordinates to viewport coordinates. + */ + template + void ImageToViewport( Array >& a ) const + { + ImageToViewport( a.Begin(), a.Length() ); + } + + /*! + * Converts a set of integer scalars from the image coordinate system to + * the viewport coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from image coordinates to viewport + * coordinates. + * + * \param n Number of scalars in the \a p array. + * + * Converted scalars in viewport coordinates are rounded to the nearest + * integers. + */ + void ImageScalarToViewport( int* d, size_type n ) const; + + /*! + * Converts a set of real floating-point scalars from the image coordinate + * system to the viewport coordinate system. + * + * \param d Pointer to the first element in the array of scalars that + * will be converted from image coordinates to viewport + * coordinates. + * + * \param n Number of scalars in the \a p array. + */ + void ImageScalarToViewport( double* d, size_type n ) const; + + /*! + * Converts an integer scalar \a d in the image coordinate system to the + * viewport coordinate system. Returns the resulting scalar in viewport + * coordinates. + * + * The resulting scalar in viewport coordinates is rounded to the nearest + * integer. + */ + int ImageScalarToViewport( int ) const; + + /*! + * Converts a real floating-point scalar \a d in the image coordinate system + * to the viewport coordinate system. Returns the resulting scalar in + * viewport coordinates. + */ + double ImageScalarToViewport( double ) const; + + /*! + * Converts the specified \a x and \a y integer coordinates from the + * viewport coordinate system to the global coordinate system. + * + * The converted global coordinates are rounded to the nearest integers. + */ + void ViewportToGlobal( int& x, int& y ) const; + + /*! + * Converts a point \a p in the viewport coordinate system to the global + * coordinate system. Returns a point with the resulting global coordinates. + */ + Point ViewportToGlobal( const Point& p ) const + { + Point p1 = p; + ViewportToGlobal( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the viewport coordinate system to the global + * coordinate system. Returns a rectangle with the resulting global + * coordinates. + */ + Rect ViewportToGlobal( const Rect& r ) const + { + Rect r1 = r; + ViewportToGlobal( r1.x0, r1.y0 ); + ViewportToGlobal( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Converts the specified \a x and \a y integer coordinates from the global + * coordinate system to the viewport coordinate system. + * + * The converted viewport coordinates are rounded to the nearest integers. + */ + void GlobalToViewport( int& x, int& y ) const; + + /*! + * Converts a point \a p in the global coordinate system to the viewport + * coordinate system. Returns a point with the resulting viewport + * coordinates. + */ + Point GlobalToViewport( const Point& p ) const + { + Point p1 = p; + GlobalToViewport( p1.x, p1.y ); + return p1; + } + + /*! + * Converts a rectangle \a r in the global coordinate system to the viewport + * coordinate system. Returns a rectangle with the resulting viewport + * coordinates. + */ + Rect GlobalToViewport( const Rect& r ) const + { + Rect r1 = r; + GlobalToViewport( r1.x0, r1.y0 ); + GlobalToViewport( r1.x1, r1.y1 ); + return r1; + } + + /*! + * Causes a complete regeneration of the whole viewport and its associated + * UI resources. + * + * Calling this function may be necessary to force a regeneration after + * changing the geometry of the image in the current view of this image + * window. + */ + void Reset() + { + SetZoomFactor( ZoomFactor() ); + } + + /*! + * Regenerates the screen rendition for the visible viewport region in this + * image window. This includes regeneration of screen renditions depending + * on active dynamic interfaces. + */ + void Regenerate(); + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in viewport coordinates. + * + * Calling this function is equivalent to: + * + * \code RegenerateViewportRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void RegenerateViewportRect( const Rect& r ) + { + RegenerateViewportRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in viewport coordinates. + * + * \param x0,y0 %Viewport coordinates (horizontal, vertical) of the upper + * left corner of the regenerated region. + * + * \param x1,y1 %Viewport coordinates (horizontal, vertical) of the lower + * right corner of the regenerated region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be regenerated and updated, that is, + * its intersection with the visible viewport region. + */ + void RegenerateViewportRect( int x0, int y0, int x1, int y1 ); + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in image coordinates. + * + * Calling this function is equivalent to: + * + * \code RegenerateImageRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void RegenerateImageRect( const pcl::DRect& r ) + { + RegenerateImageRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Regenerates the screen rendition for a rectangular region of the + * viewport, specified in image coordinates. + * + * \param x0,y0 %Image coordinates (horizontal, vertical) of the upper + * left corner of the regenerated region. + * + * \param x1,y1 %Image coordinates (horizontal, vertical) of the lower + * right corner of the regenerated region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be regenerated and updated, that is, + * its intersection with the visible viewport region. + */ + void RegenerateImageRect( double x0, double y0, double x1, double y1 ); + + /*! + * Requests a screen update for the entire visible viewport region in this + * image window. + */ + void UpdateViewport(); + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in viewport coordinates. + * + * Calling this function is equivalent to: + * + * \code UpdateViewportRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void UpdateViewportRect( const Rect& r ) + { + UpdateViewportRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in viewport coordinates. + * + * \param x0,y0 %Viewport coordinates (horizontal, vertical) of the upper + * left corner of the update region. + * + * \param x1,y1 %Viewport coordinates (horizontal, vertical) of the lower + * right corner of the update region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be updated, that is, its + * intersection with the visible viewport region. + */ + void UpdateViewportRect( int x0, int y0, int x1, int y1 ); + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in image coordinates. + * + * Calling this function is equivalent to: + * + * \code UpdateImageRect( r.x0, r.y0, r.x1, r.y1 ); \endcode + */ + void UpdateImageRect( const pcl::DRect& r ) + { + UpdateImageRect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Requests a screen update for a rectangular region of the viewport, + * specified in image coordinates. + * + * \param x0,y0 %Image coordinates (horizontal, vertical) of the upper + * left corner of the update region. + * + * \param x1,y1 %Image coordinates (horizontal, vertical) of the lower + * right corner of the update region. + * + * The specified region will be updated on the screen. Only the visible + * portion of the specified region will be updated, that is, its + * intersection with the visible viewport region in the image coordinate + * system. + */ + void UpdateImageRect( double x0, double y0, double x1, double y1 ); + + /*! + * Returns true iff there are pending viewport updates for this image window. + */ + bool HasPendingUpdates() const; + + /*! + * Executes all pending viewport update requests for this image window. + * + * Viewport update requests are not executed immediately by the core + * PixInsight application. For the sake of performance, The GUI tries to + * optimize screen updates by performing the minimum possible redrawing + * work. + * + * This means that update requests are placed on a queue, waiting while the + * main GUI thread is busy or until a sufficiently large update region + * becomes available. + * + * With this function, an interface can force the immediate screen update + * for all pending update viewport regions. If multiple update regions are + * pending, the core application will still minimize the required drawing + * work by grouping all of them into the minimum possible amount of larger + * regions. + */ + void CommitPendingUpdates(); + + /*! + * Returns a rectangle in viewport coordinates that includes all pending + * viewport update regions for this image window. + */ + Rect ViewportUpdateRect() const; + + /*! + * Returns a RGBA bitmap with a screen rendition of a viewport region of + * this image window. + * + * Calling this function is equivalent to: + * + * \code ViewportBitmap( r.x0, r.y0, r.x1, r.y1, flags ); \endcode + */ + Bitmap ViewportBitmap( const Rect& r, uint32 flags = 0 ) const + { + return ViewportBitmap( r.x0, r.y0, r.x1, r.y1, flags ); + } + + /*! + * Returns a RGBA bitmap with a screen rendition of a viewport region of + * this image window. + * + * \param x0,y0 %Viewport coordinates (horizontal, vertical) of the upper + * left corner of the source viewport region. + * + * \param x1,y1 %Viewport coordinates (horizontal, vertical) of the lower + * right corner of the source viewport region. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + * + * The returned bitmap will contain a screen rendition for the specified + * source region of the image in the current view of this image window. It + * will be magnified or reduced according to the current zoom factor. It + * will not contain auxiliary vectorial elements (as preview rectangles), or + * other renditions of any kind that depend on active dynamic interfaces. + */ + Bitmap ViewportBitmap( int x0, int y0, int x1, int y1, uint32 flags = 0 ) const; + + /*! + * Begins a new interactive rectangular selection procedure on the viewport + * of this image window. + * + * Calling this function is equivalent to: + * + * \code BeginSelection( p.x, p.y, flags ); \endcode + */ + void BeginSelection( const Point& p, uint32 flags = 0 ) + { + BeginSelection( p.x, p.y, flags ); + } + + /*! + * Starts a new interactive rectangular selection procedure on the viewport + * of this image window. + * + * \param x,y %Image coordinates of the starting point of a new + * rectangular selection. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + * + * Dynamic interfaces use BeginSelection() in response to an OnMousePress + * event to start a rectangular selection. ModifySelection() is then called + * from an OnMouseMove event handler, and the final selection coordinates + * are obtained by calling SelectionRect() from an OnMouseRelease event + * handler. + */ + void BeginSelection( int x, int y, uint32 flags = 0 ); + + /*! + * Updates an ongoing interactive rectangular selection procedure on the + * viewport of this image window. + * + * Calling this function is equivalent to: + * + * \code ModifySelection( p.x, p.y, flags ); \endcode + */ + void ModifySelection( const Point& p, uint32 flags = 0 ) + { + ModifySelection( p.x, p.y, flags ); + } + + /*! + * Updates an ongoing interactive rectangular selection procedure on the + * viewport of this image window. + * + * \param x,y %Image coordinates to update the current rectangular + * selection. The selection rectangle is defined by this + * position and the starting position defined in the call to + * BeginSelection() that originated the current selection + * procedure. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to zero. + */ + void ModifySelection( int x, int y, uint32 flags = 0 ); + + /*! + * Requests a screen viewport update for the current rectangular selection. + */ + void UpdateSelection(); + + /*! + * Aborts the current interactive selection procedure. + */ + void CancelSelection(); + + /*! + * Terminates the current interactive selection procedure. + */ + void EndSelection(); + + /*! + * Returns the current rectangular selection in image coordinates. + * + * \param flags Currently not used; reserved for future extensions of PCL. + * Must be set to nullptr. + * + * Before calling this function, a rectangular selection procedure should + * have been started with BeginSelection(). + */ + Rect SelectionRect( uint32* flags = nullptr ) const; + + /*! + * Returns true iff an interactive selection procedure is currently active on + * the viewport of this image window. + */ + bool IsSelection() const; + + /*! + * Returns a image window with the specified image identifier. If no image + * exists with the specified identifier, this function returns + * ImageWindow::Null(). + */ + static ImageWindow WindowById( const IsoString& id ); + + static ImageWindow WindowById( const IsoString::ustring_base& id ) + { + return WindowById( IsoString( id ) ); + } + + /*! + * Returns the image window where the specified file path has been loaded. + * If no image has been loaded from the specified path, this function + * returns ImageWindow::Null(). + */ + static ImageWindow WindowByFilePath( const String& filePath ); + + /*! + * Returns the current active image window. Returns ImageWindow::Null() if + * there are no image windows, if all image windows are hidden, or if all + * image windows have been iconized. + * + * The active image window is the topmost image window of the stack of image + * windows in the current workspace. Most commands that apply to + * views, images and previews, are executed on the active image window by + * default, even if it doesn't have the keyboard focus. + */ + static ImageWindow ActiveWindow(); + + /*! + * Returns a container with all existing image windows, including visible + * and hidden windows, and optionally iconized windows. + * + * \param includeIconicWindows If this parameter is false, iconic image + * windows will not be included in the returned container. + */ + static Array AllWindows( bool includeIconicWindows = true ); + +private: + + ImageWindow( void* h ) : UIObject( h ) + { + } + + friend class View; + friend class ProcessInstance; // for IsMaskable() + friend class ProcessContextDispatcher; + friend class InternalWindowEnumerator; +}; + +// ---------------------------------------------------------------------------- + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_ImageWindow_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ImageWindow.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Indirect.h b/3rdparty/include/pcl/Indirect.h new file mode 100644 index 0000000..4fc4228 --- /dev/null +++ b/3rdparty/include/pcl/Indirect.h @@ -0,0 +1,323 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Indirect.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_Indirect_h +#define __PCL_Indirect_h + +/// \file pcl/Indirect.h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectUnaryFunction + * \brief A wrapper class that applies a unary function to pointers to objects. + * + * The UF template argument represents a unary function type of the form: + * + * void (*UF)( T ) + * + * The TPtr template argument represents a pointer to UF's argument type. TPtr + * is also the argument type of %IndirectUnaryFunction::operator ()(). + * + * %IndirectUnaryFunction can be used as UF, but acting on pointers to objects + * of type T. + */ +template +class PCL_CLASS IndirectUnaryFunction +{ +public: + + /*! + * Constructs an %IndirectUnaryFunction to wrap a unary m_function \a f. + */ + IndirectUnaryFunction( UF f ) + : m_function( f ) + { + } + + /*! + * Copy constructor. + */ + IndirectUnaryFunction( IndirectUnaryFunction& ) = default; + + /*! + * Function call operator. Applies the wrapped unary function to \a *ptr. + * + * If \a ptr is nullptr, the function is not invoked and calling this member + * function has no effect. + */ + void operator()( TPtr ptr ) const + { + if ( ptr != nullptr ) + m_function( *ptr ); + } + +private: + + UF m_function; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectBinaryFunction + * \brief A wrapper class that applies a binary function to pointers to objects. + * + * The BF template argument represents a binary function type of the form: + * + * void (*BF)( T1, T2 ) + * + * The T1Ptr and T2Ptr template arguments represent pointers to BF's first and + * second argument types, respectively. T1Ptr and T2Ptr are also the argument + * types of %IndirectBinaryFunction::operator ()(). + * + * %IndirectBinaryFunction can be used as BF, but acting on pointers to objects + * of the types T1 and T2. + */ +template +class PCL_CLASS IndirectBinaryFunction +{ +public: + + /*! + * Constructs an %IndirectBinaryFunction to wrap a binary function \a f. + */ + IndirectBinaryFunction( BF f ) + : m_function( f ) + { + } + + /*! + * Copy constructor. + */ + IndirectBinaryFunction( const IndirectBinaryFunction& ) = default; + + /*! + * Function call operator. Applies the wrapped binary function to \a *ptr1 + * and \a *ptr2. + * + * If either \a ptr1 or \a ptr2 is nullptr, the function is not invoked and + * calling this member function has no effect. + */ + void operator()( T1Ptr ptr1, T2Ptr ptr2 ) const + { + if ( ptr1 != nullptr ) + if ( ptr2 != nullptr ) + m_function( *ptr1, *ptr2 ); + } + +private: + + BF m_function; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectUnaryPredicate + * \brief A wrapper class that applies a unary predicate to pointers to objects. + * + * The UP template argument represents a unary predicate type of the form: + * + * bool (*UP)( T ) + * + * The TPtr template argument represents a pointer to UP's argument type. TPtr + * is also the argument type of %IndirectUnaryPredicate::operator ()(). + * + * %IndirectUnaryPredicate can be used as UP, but acting on pointers to objects + * of type T. + */ +template +class PCL_CLASS IndirectUnaryPredicate +{ +public: + + /*! + * Constructs an %IndirectUnaryFunction to wrap a unary predicate \a p. + */ + IndirectUnaryPredicate( UP p ) + : m_predicate( p ) + { + } + + /*! + * Copy constructor. + */ + IndirectUnaryPredicate( const IndirectUnaryPredicate& ) = default; + + /*! + * Function call operator. Applies the wrapped unary predicate to \a *ptr + * and returns its resulting value. + * + * If \a ptr is nullptr, the predicate is not invoked and false is returned. + */ + bool operator()( TPtr ptr ) const + { + return ptr != nullptr && m_predicate( *ptr ); + } + +private: + + UP m_predicate; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectBinaryPredicate + * \brief A wrapper class that applies a binary predicate to pointers to objects. + * + * The BP template argument represents a binary predicate type of the form: + * + * bool (*BP)( T1, T2 ) + * + * The T1Ptr and T2Ptr template arguments represent pointers to BP's first and + * second argument types, respectively. T1Ptr and T2Ptr are also the argument + * types of %IndirectBinaryPredicate::operator ()(). + * + * %IndirectBinaryPredicate can be used as BP, but acting on pointers to + * objects of the types T1 and T2. + */ +template +class PCL_CLASS IndirectBinaryPredicate +{ +public: + + /*! + * Constructs an %IndirectBinaryPredicate to wrap a binary predicate \a p. + */ + IndirectBinaryPredicate( BP p ) + : m_predicate( p ) + { + } + + /*! + * Copy constructor. + */ + IndirectBinaryPredicate( const IndirectBinaryPredicate& ) = default; + + /*! + * Function call operator. Applies the wrapped binary predicate to \a *ptr1 + * and \a *ptr2, and returns its resulting value. + * + * If either of \a ptr1 or \a ptr2 is nullptr, the predicate is not invoked + * and false is returned. + */ + bool operator()( T1Ptr ptr1, T2Ptr ptr2 ) const + { + return ptr1 != nullptr && ptr2 != nullptr && m_predicate( *ptr1, *ptr2 ); + } + +private: + + BP m_predicate; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectEqual + * \brief A functional class that tests two pointers for equality of the + * pointed objects. + */ +template +struct PCL_CLASS IndirectEqual +{ + /*! + * Function call operator. Returns true iff \a *ptr1 == \a *ptr2. + * + * If either of \a ptr1 or \a ptr2 is nullptr, no operation is performed on + * any pointed object and the return value is \a ptr1 == \a ptr2. + */ + bool operator ()( TPtr ptr1, TPtr ptr2 ) const + { + return (ptr1 != nullptr && ptr2 != nullptr) ? *ptr1 == *ptr2 : ptr1 == ptr2; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectLess + * \brief A functional class that applies the less than relational + * operator to the objects pointed to by two pointers. + */ +template +struct PCL_CLASS IndirectLess +{ + /*! + * Function call operator. Returns true iff \a *ptr1 < \a *ptr2. + * + * If either of \a ptr1 or \a ptr2 is nullptr, no operation is performed on + * any pointed object and the return value is \a ptr2 < \a ptr1. This + * ensures that when sorting lists of pointers indirectly, all null pointers + * will be packed at the bottom of the sorted list. + */ + bool operator ()( TPtr ptr1, TPtr ptr2 ) const + { + // When sorting a list, make sure all null pointers are packed at the bottom. + return ptr1 != nullptr && (ptr2 == nullptr || *ptr1 < *ptr2); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Indirect_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Indirect.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/IndirectArray.h b/3rdparty/include/pcl/IndirectArray.h new file mode 100644 index 0000000..2bfdf05 --- /dev/null +++ b/3rdparty/include/pcl/IndirectArray.h @@ -0,0 +1,2023 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/IndirectArray.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_IndirectArray_h +#define __PCL_IndirectArray_h + +/// \file pcl/IndirectArray.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectArray + * \brief Generic dynamic array of pointers to objects. + * + * %IndirectArray is a generic, finite ordered sequence of pointers to objects, + * implemented as a reference-counted, dynamic array of pointers to T + * instances. The type A provides dynamic allocation for contiguous sequences + * of void* (StandardAllocator is used by default). + * + * In the PixInsight/PCL platform, dynamic arrays of pointers to objects are + * powerful building blocks for the implementation of flexible data structures, + * including heterogeneous containers. + * + * Unlike ReferenceArray, %IndirectArray can contain null pointers because it + * does not require dereferencing pointers. Actually, %IndirectArray by itself + * does not need to know anything about the objects pointed to by its contained + * pointers, and precisely here lies its flexibility as a generic container. + * + * \sa IndirectSortedArray, ReferenceArray, ReferenceSortedArray, Array, + * SortedArray, ReferenceCounter + * \ingroup dynamic_arrays + */ +template +class PCL_CLASS IndirectArray : public IndirectContainer +{ +public: + + /*! # + */ + typedef A block_allocator; + + /*! # + */ + typedef pcl::Allocator allocator; + + /*! # + */ + typedef T** iterator; + + /*! # + */ + typedef T* const* const_iterator; + + /*! # + */ + typedef Array array_implementation; + + /*! # + */ + typedef typename array_implementation::iterator + array_iterator; + + /*! # + */ + typedef typename array_implementation::const_iterator + const_array_iterator; + + /*! # + */ + typedef ReverseRandomAccessIterator + reverse_iterator; + + /*! # + */ + typedef ReverseRandomAccessIterator + const_reverse_iterator; + + /*! # + */ + typedef IndirectEqual equal; + + /*! # + */ + typedef IndirectLess less; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty indirect array. + */ + IndirectArray() = default; + + /*! + * Constructs an indirect array of length \a n. All contained pointers are + * initialized to \c nullptr. + */ + explicit + IndirectArray( size_type n ) + { + m_array.Append( (void*)nullptr, n ); + } + + /*! + * Constructs an indirect array that stores \a n copies of a pointer \a p. + */ + IndirectArray( size_type n, const T* p ) + { + m_array.Append( (void*)p, n ); + } + + /*! + * Constructs an indirect array as a copy of the sequence of pointers + * defined by the range [i,j) of forward iterators. + */ + template + IndirectArray( FI i, FI j ) + : m_array( i, j ) + { + } + + /*! + * Copy constructor. + */ + IndirectArray( const IndirectArray& ) = default; + + /*! + * Move constructor. + */ + IndirectArray( IndirectArray&& ) = default; + + /*! + * Destroys an %IndirectArray object. + * + * Deallocates the internal array of pointers to objects, but does not + * destroy the pointed objects. To destroy them, you have to call Destroy() + * or Delete() explicitly. + */ + ~IndirectArray() + { + } + + /*! + * Returns true iff this indirect array uniquely references its contained + * array of pointers to objects. + */ + bool IsUnique() const + { + return m_array.IsUnique(); + } + + /*! + * Returns true iff this indirect array is an alias of the indirect array + * \a x. + * + * Two objects are aliases if both share the same data. Two indirect + * containers are aliases if they share a unique set of data pointers. + */ + bool IsAliasOf( const IndirectArray& x ) const + { + return m_array.IsAliasOf( x.m_array ); + } + + /*! + * Ensures that this indirect array uniquely references its contained data + * pointers. + * + * If necessary, this member function generates a duplicate of the array + * of pointers, references it, and then decrements the reference counter of + * the original pointer array. + */ + void EnsureUnique() + { + m_array.EnsureUnique(); + } + + /*! + * Returns the total number of bytes required to store the array of data + * pointers contained by this indirect array. + */ + size_type Size() const + { + return m_array.Size(); + } + + /*! + * Returns the length of this indirect array. + */ + size_type Length() const + { + return m_array.Length(); + } + + /*! + * Returns the capacity of this indirect array. The capacity is the maximum + * number of pointers to objects that this indirect array can contain + * without requiring a reallocation. + */ + size_type Capacity() const + { + return m_array.Capacity(); + } + + /*! + * Returns the length of the space available in this indirect array, or zero + * if this indirect array cannot contain more pointers. The available space + * is the number of pointers to objects that can be added to this indirect + * array without requiring a reallocation. It is equal to + * Capacity() - Length() by definition. + */ + size_type Available() const + { + return m_array.Available(); + } + + /*! + * Returns true only if this indirect array is valid. An indirect array is + * valid if it references an internal structure with an array of pointers, + * even if it is an empty array. + * + * In general, all %IndirectArray objects are valid with only two + * exceptions: + * + * \li Objects that have been move-copied or move-assigned to other arrays. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid array object cannot be used and should be destroyed + * immediately. Invalid arrays are always destroyed automatically during + * move construction and move assignment operations. + */ + bool IsValid() const + { + return m_array.IsValid(); + } + + /*! + * Returns true iff this indirect array is empty. + */ + bool IsEmpty() const + { + return m_array.IsEmpty(); + } + + /*! + * Returns the minimum legal index in this array (always zero). For empty + * arrays, this function returns a meaningless value. + */ + size_type LowerBound() const + { + return m_array.LowerBound(); + } + + /*! + * Returns the maximum legal index in this array. It is equal to Length()-1. + * For empty arrays, this function returns a meaningless value. + */ + size_type UpperBound() const + { + return m_array.UpperBound(); + } + + /*! + * Returns a reference to the allocator object used by this indirect array. + */ + const allocator& Allocator() const + { + return m_array.Allocator(); + } + + /*! + * Sets a new allocator object for this array. + */ + void SetAllocator( const allocator& a ) + { + m_array.SetAllocator( a ); + } + + /*! + * Returns an array iterator located at the specified index \a i. + */ + iterator At( size_type i ) + { + return iterator( m_array.At( i ) ); + } + + /*! + * Returns an immutable array iterator located at the specified index \a i. + */ + const_iterator At( size_type i ) const + { + return const_iterator( m_array.At( i ) ); + } + + /*! + * Returns a mutable iterator pointing to the same array element as the + * specified immutable iterator \a i. + * + * \warning As a side-effect of calling this function, the specified + * immutable iterator \a i may become invalid. This happens when this + * function is called for a shared array, since in this case getting a + * mutable iterator involves a deep copy of the array through an implicit + * call to EnsureUnique(). + */ + iterator MutableIterator( const_iterator i ) + { + return iterator( m_array.MutableIterator( (const_array_iterator)i ) ); + } + + /*! + * Returns a reference to the pointer stored at the specified index \a i. No + * bounds checking is performed. + */ + T*& operator []( size_type i ) + { + return (T*&)m_array[i]; + } + + /*! + * Returns a copy of the pointer to an unmodifiable object stored at the + * specified index \a i. No bounds checking is performed. + */ + const T* operator []( size_type i ) const + { + return (const T*)m_array[i]; + } + + /*! + * Returns a reference to the first pointer stored in this indirect array. + */ + T*& operator *() + { + return (T*&)*Begin(); + } + + /*! + * Returns a copy of the first pointer to an unmodifiable object stored in + * this indirect array. + */ + const T* operator *() const + { + return (T*)*Begin(); + } + + /*! + * Returns a mutable iterator located at the beginning of this array. + */ + iterator Begin() + { + return iterator( m_array.Begin() ); + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator Begin() const + { + return const_iterator( m_array.Begin() ); + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator ConstBegin() const + { + return const_iterator( m_array.ConstBegin() ); + } + + /*! + * Returns a mutable iterator located at the end of this array. + */ + iterator End() + { + return iterator( m_array.End() ); + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator End() const + { + return const_iterator( m_array.End() ); + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator ConstEnd() const + { + return const_iterator( m_array.ConstEnd() ); + } + + /*! + * Returns a mutable reverse iterator located at the reverse + * beginning of this indirect array. + * + * The reverse beginning corresponds to the last pointer in the array. + */ + reverse_iterator ReverseBegin() + { + return iterator( (array_iterator)m_array.ReverseBegin() ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this indirect array. + * + * The reverse beginning corresponds to the last pointer in the array. + */ + const_reverse_iterator ReverseBegin() const + { + return const_iterator( (const_array_iterator)m_array.ReverseBegin() ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this indirect array. + * + * The reverse beginning corresponds to the last pointer in the array. + */ + const_reverse_iterator ConstReverseBegin() const + { + return const_iterator( (const_array_iterator)m_array.ConstReverseBegin() ); + } + + /*! + * Returns a mutable reverse iterator located at the reverse end of + * this indirect array. + * + * The reverse end corresponds to a (nonexistent) pointer immediately before + * the first pointer in the array. + */ + reverse_iterator ReverseEnd() + { + return iterator( (array_iterator)m_array.ReverseEnd() ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this indirect array. + * + * The reverse end corresponds to a (nonexistent) pointer immediately before + * the first pointer in the array. + */ + const_reverse_iterator ReverseEnd() const + { + return const_iterator( (const_array_iterator)m_array.ReverseEnd() ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this indirect array. + * + * The reverse end corresponds to a (nonexistent) pointer immediately before + * the first pointer in the array. + */ + const_reverse_iterator ConstReverseEnd() const + { + return const_iterator( (const_array_iterator)m_array.ConstReverseEnd() ); + } + + /*! + * Returns a copy of the first pointer in this indirect array, or \c nullptr + * if this array is empty. + */ + T* First() + { + return IsEmpty() ? nullptr : *Begin(); + } + + /*! + * Returns a copy of the first pointer to an unmodifiable object in this + * indirect array, or \c nullptr if this array is empty. + */ + const T* First() const + { + return IsEmpty() ? nullptr : *Begin(); + } + + /*! + * Returns a copy of the last pointer in this indirect array, or \c nullptr + * if this array is empty. + */ + T* Last() + { + return IsEmpty() ? nullptr : *ReverseBegin(); + } + + /*! + * Returns a copy of the last pointer to an unmodifiable object in this + * indirect array, or \c nullptr if this array is empty. + */ + const T* Last() const + { + return IsEmpty() ? nullptr : *ReverseBegin(); + } + + /*! + * Ensures that the specified iterator points to a uniquely referenced + * pointer. If necessary, this function builds a new, uniquely referenced + * copy of this indirect array by calling EnsureUnique(). + * + * If the iterator \a i is changed, it is guaranteed to point to the pointer + * at the same array index it was pointing to before calling this function. + */ + void UniquifyIterator( iterator& i ) + { + m_array.UniquifyIterator( (array_iterator&)i ); + } + + /*! + * Ensures that the specified iterators point to uniquely referenced + * pointers. If necessary, this function builds a new, uniquely referenced + * copy of this indirect array by calling EnsureUnique(). + * + * If the iterators \a i and \a j are changed, they are guaranteed to point + * to the pointers at the same array indices they were pointing to before + * calling this function. + */ + void UniquifyIterators( iterator& i, iterator& j ) + { + m_array.UniquifyIterators( (array_iterator&)i, (array_iterator&)j ); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + iterator end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Copy assignment operator. + * + * Causes this indirect array to reference the same set of pointers as + * another array \a x. Returns a reference to this object. + */ + IndirectArray& operator =( const IndirectArray& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns an indirect array \a x to this indirect array. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Increments the reference counter of the source array's data and + * references it in this array. + */ + void Assign( const IndirectArray& x ) + { + m_array.Assign( x.m_array ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + IndirectArray& operator =( IndirectArray&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from another indirect array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( IndirectArray& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! + * Transfers data from another indirect array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( IndirectArray&& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! + * Replaces the contents of this indirect array with a sequence of \a n + * pointers equal to \a p. + */ + void Assign( const T* p, size_type n = 1 ) + { + m_array.Assign( (void*)p, n ); + } + + /*! + * Replaces the contents of this indirect array with a copy of the sequence + * of pointers defined by the range [i,j) of forward iterators. + * + * \note \a i and \a j must not be iterators into this array. + */ + template + void Assign( FI i, FI j ) + { + m_array.Assign( i, j ); + } + + /*! + * Replaces the contents of this indirect array with a set of pointers to + * newly created copies of the objects stored in the specified container + * \a x. This function works for both direct and indirect containers. + * + * Keep in mind that after calling this function (with a reference to a + * nonempty container) this array will store pointers to newly allocated + * objects. You should call Delete() or Destroy() to deallocate these + * objects before destructing this array, or copy the pointers somewhere, in + * order to avoid memory leaks. + */ + template + void CloneAssign( const C& x ) + { + PCL_ASSERT_CONTAINER( C, T ); + CloneObjects( x, (C*)nullptr ); + } + + /*! + * Causes this indirect array to store the sequence of pointers defined by + * the range [i,j) of indirect array iterators (pointers to pointers). The + * previously referenced data structure is dereferenced and deallocated if + * it becomes unreferenced. + */ + void Import( iterator i, iterator j ) + { + m_array.Import( (array_iterator)i, (array_iterator)j ); + } + + /*! + * Releases the set of pointers contained by this indirect array. + * + * This member function returns a pointer to the internal block of pointers + * stored in this object, after ensuring that it is uniquely referenced. + * If the array is empty, this function may return the null pointer. + * + * Before returning, this member function empties this array without + * deallocating its contained data. The caller is then responsible for + * deallocating the returned block when it is no longer required. + */ + iterator Release() + { + return iterator( m_array.Release() ); + } + + /*! + * Inserts a contiguous sequence of \a n null pointers at the specified + * location \a i in this indirect array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first newly created array element, or + * \a i if \a n is zero. + */ + iterator Grow( const_iterator i, size_type n = 1 ) + { + return iterator( m_array.Insert( (array_iterator)const_cast( i ), (void*)nullptr, n ) ); + } + + /*! + * Appends a contiguous sequence of \a n null pointers to this indirect + * array. This operation is equivalent to: + * + * \code Grow( End(), n ) \endcode + * + * Returns an iterator pointing to the first newly created array element, or + * End() if \a n is zero. + */ + iterator Expand( size_type n = 1 ) + { + return Grow( ConstEnd(), n ); + } + + /*! + * Removes a contiguous trailing sequence of \a n existing pointers from + * this indirect array. This operation is equivalent to: + * + * \code Truncate( End() - n ) \endcode + * + * If the specified count \a n is greater than or equal to the length of + * this array, this function calls Clear() to yield an empty array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Shrink( size_type n = 1 ) + { + if ( n < Length() ) + Truncate( ConstEnd() - n ); + else + Clear(); + } + + /*! + * Resizes this indirect array to the specified length \a n, either by + * appending null pointers, or by removing existing trailing pointers. + * This operation is equivalent to: + * + * \code + * if ( n > Length() ) + * Expand( n - Length() ); + * else + * Shrink( Length() - n ); + * \endcode + * + * When the array length is reduced, only pointers are removed by this + * function; the pointed objects are not affected in any way. + */ + void Resize( size_type n ) + { + size_type l = Length(); + if ( n > l ) + Expand( n - l ); + else + Shrink( l - n ); + } + + /*! + * Inserts a copy of the sequence of pointers contained by the indirect + * array \a x at the specified location \a i in this indirect array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. The source array \a x can + * safely be a reference to this array. + * + * Returns an iterator pointing to the first newly created array element, or + * \a i if \a x is empty. + */ + iterator Insert( const_iterator i, const IndirectArray& x ) + { + return iterator( m_array.Insert( (array_iterator)const_cast( i ), x.m_array ) ); + } + + /*! + * Inserts a contiguous sequence of \a n pointers equal to \a p at the + * specified location \a i. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first inserted array element, or \a i + * if \a n is zero. + */ + iterator Insert( const_iterator i, const T* p, size_type n = 1 ) + { + return iterator( m_array.Insert( (array_iterator)const_cast( i ), (void*)p, n ) ); + } + + /*! + * Inserts a copy of the sequence of pointers defined by the range [p,q) + * of forward iterators at the specified location \a i. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first inserted array element, or \a i + * if \a q <= \a p. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + iterator Insert( const_iterator i, FI p, FI q ) + { + return iterator( m_array.Insert( (array_iterator)const_cast( i ), p, q ) ); + } + + /*! + * Appends a copy of the sequence of pointers contained by the indirect + * array \a x to this indirect array. + */ + void Append( const IndirectArray& x ) + { + m_array.Append( x.m_array ); + } + + /*! + * Appends a contiguous sequence of \a n pointers equal to \a p to this + * indirect array. + */ + void Append( const T* p, size_type n = 1 ) + { + m_array.Append( (void*)p, n ); + } + + /*! + * Appends a copy of the sequence of pointers defined by the range [p,q) + * of forward iterators to this indirect array. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + void Append( FI p, FI q ) + { + m_array.Append( p, q ); + } + + /*! + * Inserts a copy of the sequence of pointers contained by the indirect + * array \a x at the beginning of this indirect array. + */ + void Prepend( const IndirectArray& x ) + { + m_array.Prepend( x.m_array ); + } + + /*! + * Inserts a contiguous sequence of \a n pointers equal to \a p at the + * beginning of this indirect array. + */ + void Prepend( const T* p, size_type n = 1 ) + { + m_array.Prepend( (void*)p, n ); + } + + /*! + * Inserts a copy of the sequence of pointers defined by the range [p,q) of + * forward iterators at the beginning of this indirect array. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + void Prepend( FI p, FI q ) + { + m_array.Prepend( p, q ); + } + + /*! + * A synonym for Append( const IndirectArray<>& ) + */ + void Add( const IndirectArray& x ) + { + Append( x ); + } + + /*! + * A synonym for Append( const T*, size_type ) + */ + void Add( const T* p, size_type n = 1 ) + { + Append( p, n ); + } + + /*! + * A synonym for Append( FI, FI ) + */ + template + void Add( FI i, FI j ) + { + Append( i, j ); + } + + /*! + * Removes a sequence of \a n contiguous pointers starting at the specified + * location \a i in this indirect array. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a n is zero, this function does nothing. Otherwise \a i is + * constrained to stay in the range [Begin(),End()) of existing array + * elements. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const_iterator i, size_type n = 1 ) + { + m_array.Remove( (array_iterator)const_cast( i ), n ); + } + + /*! + * Removes a sequence of contiguous pointers in the range [i,j) of this + * indirect array. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const_iterator i, const_iterator j ) + { + m_array.Remove( (array_iterator)const_cast( i ), + (array_iterator)const_cast( j ) ); + } + + /*! + * Removes a trailing sequence of contiguous pointers from the specified + * iterator of this array. This operation is equivalent to: + * + * \code Remove( i, End() ) \endcode + * + * If the specified iterator is located at or after the end of this array, + * this function does nothing. Otherwise the iterator is constrained to stay + * in the range [Begin(),End()) of existing array elements. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Truncate( const_iterator i ) + { + m_array.Truncate( (array_iterator)const_cast( i ) ); + } + + /*! + * Removes all existing non-null pointers whose pointed objects are equal to + * the specified value \a v in this indirect array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const T& v ) + { + array_implementation r; + for ( const_iterator i = ConstBegin(); i < ConstEnd(); ++i ) + if ( *i == nullptr || **i != v ) + r.Add( (void*)*i ); + if ( r.Length() < m_array.Length() ) + m_array.Transfer( r ); + } + + /*! + * Removes every non-null pointer x in this array such that the binary + * predicate p( *x, \a v ) is true. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + template + void Remove( const T& v, BP p ) + { + array_implementation r; + for ( const_iterator i = ConstBegin(); i < ConstEnd(); ++i ) + if ( *i == nullptr || !p( **i, v ) ) + r.Add( (void*)*i ); + if ( r.Length() < m_array.Length() ) + m_array.Transfer( r ); + } + + /*! + * Removes all contained pointers equal to \a p in this indirect array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const T* p ) + { + m_array.Remove( (void*)p ); + } + + /*! + * Removes all pointers contained by this object, yielding an empty indirect + * array. + * + * If this array is empty, then calling this member function has no effect. + * + * If this array uniquely references its internal array data structure, all + * pointers contained are deallocated; otherwise its reference counter is + * decremented. Then a new, empty array data structure is created and + * uniquely referenced. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Clear() + { + m_array.Clear(); + } + + /*! + * Destroys a sequence of \a n contiguous pointed objects, starting at the + * specified location \a i in this indirect array. Null pointers are + * ignored. + * + * This function destroys and deallocates the pointed objects, then replaces + * the corresponding pointers by \c nullptr in this array. The array length + * is not modified. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Delete( iterator i, size_type n = 1 ) + { + Delete( i, i+n ); + } + + /*! + * Destroys the objects pointed to by a range [i,j) of pointers in this + * indirect array. Null pointers are ignored. + * + * This function destroys and deallocates the pointed objects, then replaces + * the corresponding pointers by \c nullptr in this array. The array length + * is not modified. + * + * \warning This function can be useful but is potentially dangerous. If the + * array contains duplicate non-null pointers in the specified range of + * iterators, this function will lead to a crash as a result of multiple + * deletions. To minimize the risk of multiple deletions, this function + * ignores the normal data sharing mechanism so that all objects sharing the + * same array data structure will correctly 'see' the deleted pointers as + * null pointers. However, be aware of potential problems if other indirect + * containers store pointers to deleted objects in different data + * structures, which will be invalid after calling this function. + */ + void Delete( iterator i, iterator j ) + { + // NB: Copy-on-write must *not* happen in this function. + if ( i < ConstEnd() ) + { + i = pcl::Max( const_cast( ConstBegin() ), i ); + j = pcl::Min( j, const_cast( ConstEnd() ) ); + allocator a; + for ( ; i < j; ++i ) + if ( *i != nullptr ) + DeleteObject( i, a ); + } + } + + /*! + * Destroys all objects equal to \a v pointed to by non-null pointers + * contained by this array. + * + * This function destroys and deallocates the pointed objects, then replaces + * the corresponding pointers by \c nullptr in this array. The array length + * is not modified. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Delete( const T& v ) + { + // NB: Copy-on-write must *not* happen in this function. + allocator a; + for ( iterator i = const_cast( ConstBegin() ); i < ConstEnd(); ++i ) + if ( *i != nullptr && **i == v ) + DeleteObject( i, a ); + } + + /*! + * Destroys every object pointed to by a pointer x in this array such that + * the binary predicate p( *x, \a v ) is true. + * + * This function destroys and deallocates the pointed objects, then replaces + * the corresponding pointers by \c nullptr in this array. The array length + * is not modified. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + template + void Delete( const T& v, BP p ) + { + // NB: Copy-on-write must *not* happen in this function. + allocator a; + for ( iterator i = const_cast( ConstBegin() ); i < ConstEnd(); ++i ) + if ( *i != nullptr && p( **i, v ) ) + DeleteObject( i, a ); + } + + /*! + * Destroys all objects pointed to by non-null pointers in this indirect + * array. All pointers contained are set equal to \c nullptr, and the array + * length is not modified. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Delete() + { + // NB: Copy-on-write must *not* happen in this function. + allocator a; + for ( iterator i = const_cast( ConstBegin() ); i < ConstEnd(); ++i ) + if ( *i != nullptr ) + DeleteObject( i, a ); + } + + /*! + * Destroys and removes a sequence of \a n contiguous pointed objects, + * starting at the specified location \a i in this indirect array. Null + * pointers are ignored. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( iterator i, size_type n = 1 ) + { + Delete( i, n ); + Remove( i, n ); + } + + /*! + * Destroys and removes the objects pointed to by a range [i,j) of pointers + * in this indirect array. Null pointers are ignored. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( iterator i, iterator j ) + { + Delete( i, j ); + Remove( i, j ); + } + + /*! + * Destroys and removes all objects equal to \a v pointed to by non-null + * pointers contained by this array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( const T& v ) + { + array_implementation r; + allocator a; + for ( iterator i = const_cast( ConstBegin() ); i < ConstEnd(); ++i ) + if ( *i != nullptr && **i == v ) + DeleteObject( i, a ); + else + r.Add( (void*)*i ); + // NB: Copy-on-write must *not* happen before this point. + if ( r.Length() < m_array.Length() ) + m_array.Transfer( r ); + } + + /*! + * Destroys and removes every object pointed to by a pointer x in this array + * such that the binary predicate p( *x, \a v ) is true. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + template + void Destroy( const T& v, BP p ) + { + array_implementation r; + allocator a; + for ( iterator i = const_cast( ConstBegin() ); i < ConstEnd(); ++i ) + if ( *i != nullptr && p( **i, v ) ) + DeleteObject( i, a ); + else + r.Add( (void*)*i ); + // NB: Copy-on-write must *not* happen before this point. + if ( r.Length() < m_array.Length() ) + m_array.Transfer( r ); + } + + /*! + * Destroys all objects pointed to by non-null pointers in this indirect + * array, and removes all pointers, yielding an empty array. + * + * \warning See Delete( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy() + { + Delete(); + Clear(); + } + + /*! + * Removes all null pointers from this array. + */ + void Pack() + { + m_array.Remove( (void*)nullptr ); + } + + /*! + * Replaces a sequence of contiguous pointers defined by the range [i,j) of + * iterators in this array by the pointers stored in an indirect array \a x. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or \c nullptr if the resulting array is + * empty. + */ + iterator Replace( const_iterator i, const_iterator j, const IndirectArray& x ) + { + return iterator( m_array.Replace( (array_iterator)const_cast( i ), + (array_iterator)const_cast( j ), x.m_array ) ); + } + + /*! + * Replaces a sequence of contiguous pointers defined by the range [i,j) in + * this indirect array by \a n copies of the specified pointer \a p. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or \c nullptr if the resulting array is + * empty. + */ + iterator Replace( const_iterator i, const_iterator j, const T* p, size_type n = 1 ) + { + return iterator( m_array.Replace( (array_iterator)const_cast( i ), + (array_iterator)const_cast( j ), (void*)p, n ) ); + } + + /*! + * Replaces a sequence of contiguous pointers defined by the range [i,j) in + * this indirect array by the sequence of pointers in the range [p,q) of + * forward iterators. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or \c nullptr if the resulting array is + * empty. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + iterator Replace( const_iterator i, const_iterator j, FI p, FI q ) + { + return iterator( m_array.Replace( (array_iterator)const_cast( i ), + (array_iterator)const_cast( j ), p, q ) ); + } + + /*! + * Ensures that this indirect array has enough capacity to store \a n + * pointers. + * + * After calling this member function with \a n > 0, this object is + * guaranteed to uniquely reference its pointer array data. + */ + void Reserve( size_type n ) + { + m_array.Reserve( n ); + } + + /*! + * Causes this indirect array to allocate the exact required memory space to + * store its contained pointers. + * + * If the array has excess capacity, a new copy of its contained pointers is + * generated and stored in a newly allocated memory block that fits them + * exactly, then the previous memory block is deallocated. + * + * If the array is empty, calling this function is equivalent to Clear(). + * Note that in this case a previously allocated memory block (by a call to + * Reserve()) may also be deallocated. + */ + void Squeeze() + { + m_array.Squeeze(); + } + + /*! + * Sets all objects contained by this array equal to \a v. + */ + void Fill( const T& v ) + { + Apply( [v]( T* x ){ *x = v; } ); + } + + /*! + * Calls f( T& x ) for every object x pointed to by non-null pointers in + * this array, successively from the first contained pointer to the last. + */ + template + void Apply( F f ) + { + pcl::Apply( Begin(), End(), IndirectUnaryFunction( f ) ); + } + + /*! + * Calls f( const T& x ) for every object x pointed to by non-null pointers + * in this array, successively from the first contained pointer to the last. + */ + template + void Apply( F f ) const + { + pcl::Apply( Begin(), End(), IndirectUnaryFunction( f ) ); + } + + /*! + * Returns an iterator pointing to the first non-null pointer in this array + * that points to an object x such that f( const T& x ) is true. Returns + * End() if such pointer does not exist. + */ + template + iterator FirstThat( F f ) const + { + return const_cast( pcl::FirstThat( Begin(), End(), IndirectUnaryPredicate( f ) ) ); + } + + /*! + * Returns an iterator pointing to the last non-null pointer in this array + * that points to an object x such that f( const T& x ) is true. Returns + * End() if such pointer does not exist. + */ + template + iterator LastThat( F f ) const + { + return const_cast( pcl::LastThat( Begin(), End(), IndirectUnaryPredicate( f ) ) ); + } + + /*! + * Returns the number of objects equal to \a v pointed to by non-null + * pointers stored in this indirect array. + */ + size_type Count( const T& v ) const + { + return pcl::Count( Begin(), End(), &v, equal() ); + } + + /*! + * Returns the number of pointers equal to \a p stored in this indirect + * array. + */ + size_type Count( const T* p ) const + { + return m_array.Count( (void*)p ); + } + + /*! + * Returns the number of objects pointed to by non-null pointers stored in + * this indirect array such that for each counted pointer x the binary + * predicate p( *x, v ) returns true. + */ + template + size_type Count( const T& v, BP p ) const + { + return pcl::Count( Begin(), End(), &v, IndirectBinaryPredicate( p ) ); + } + + /*! + * Returns the number of objects pointed to by non-null pointers stored in + * this indirect array such that for each counted pointer x the unary + * predicate p( *x ) returns true. + */ + template + size_type CountIf( UP p ) const + { + return pcl::CountIf( Begin(), End(), IndirectUnaryPredicate( p ) ); + } + + /*! # + */ + iterator MinItem() const + { + return const_cast( pcl::MinItem( Begin(), End(), less() ) ); + } + + /*! # + */ + template + iterator MinItem( BP p ) const + { + return const_cast( pcl::MinItem( Begin(), End(), + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + iterator MaxItem() const + { + return const_cast( pcl::MaxItem( Begin(), End(), less() ) ); + } + + /*! # + */ + template + iterator MaxItem( BP p ) const + { + return const_cast( pcl::MaxItem( Begin(), End(), + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + void Reverse() + { + m_array.Reverse(); + } + + /*! # + */ + void Rotate( distance_type n ) + { + m_array.Rotate( n ); + } + + /*! # + */ + void ShiftLeft( const T* p, size_type n = 1 ) + { + m_array.ShiftLeft( (void*)p, n ); + } + + /*! # + */ + void ShiftRight( const T* p, size_type n = 1 ) + { + m_array.ShiftRight( (void*)p, n ); + } + + /*! # + */ + iterator Search( const T& v ) const + { + return const_cast( pcl::LinearSearch( Begin(), End(), &v, equal() ) ); + } + + /*! # + */ + iterator Search( const T* p ) const + { + return iterator( m_array.Search( (void*)p ) ); + } + + /*! # + */ + template + iterator Search( const T& v, BP p ) const + { + return const_cast( pcl::LinearSearch( Begin(), End(), &v, + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + iterator SearchLast( const T& v ) const + { + return const_cast( pcl::LinearSearchLast( Begin(), End(), &v, equal() ) ); + } + + /*! # + */ + iterator SearchLast( const T* p ) const + { + return iterator( m_array.SearchLast( (void*)p ) ); + } + + /*! # + */ + template + iterator SearchLast( const T& v, BP p ) const + { + return const_cast( pcl::LinearSearchLast( Begin(), End(), &v, + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + template + iterator SearchSubset( FI i, FI j ) const + { + return const_cast( pcl::Search( Begin(), End(), i, j, equal() ) ); + } + + /*! # + */ + template + iterator SearchSubset( FI i, FI j, BP p ) const + { + return const_cast( pcl::Search( Begin(), End(), i, j, + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + template + iterator SearchSubset( const C& c ) const + { + return const_cast( pcl::Search( Begin(), End(), c.Begin(), c.End(), equal() ) ); + } + + /*! # + */ + template + iterator SearchSubset( const C& c, BP p ) const + { + return const_cast( pcl::Search( Begin(), End(), c.Begin(), c.End(), + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( BI i, BI j ) const + { + return const_cast( pcl::SearchLast( Begin(), End(), i, j, equal() ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( BI i, BI j, BP p ) const + { + return const_cast( pcl::SearchLast( Begin(), End(), i, j, + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( const C& c ) const + { + return const_cast( pcl::SearchLast( Begin(), End(), c.Begin(), c.End(), equal() ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( const C& c, BP p ) const + { + return const_cast( pcl::SearchLast( Begin(), End(), c.Begin(), c.End(), + IndirectBinaryPredicate( p ) ) ); + } + + /*! # + */ + bool Contains( const T& v ) const + { + return Search( v ) != End(); + } + + /*! # + */ + bool Contains( const T* p ) const + { + return m_array.Contains( (void*)p ); + } + + /*! # + */ + template + bool Contains( const T& v, BP p ) const + { + return Search( v, p ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( FI i, FI j ) const + { + return SearchSubset( i, j ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( FI i, FI j, BP p ) const + { + return SearchSubset( i, j, p ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( const C& c ) const + { + return SearchSubset( c ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( const C& c, BP p ) const + { + return SearchSubset( c, p ) != End(); + } + + /*! # + */ + void Sort() + { + pcl::QuickSort( Begin(), End(), less() ); + } + + /*! # + */ + template + void Sort( BP p ) + { + pcl::QuickSort( Begin(), End(), IndirectBinaryPredicate( p ) ); + } + + /*! + * Exchanges two indirect arrays \a x1 and \a x2. + */ + friend void Swap( IndirectArray& x1, IndirectArray& x2 ) + { + pcl::Swap( x1.m_array, x2.m_array ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each non-null pointer in this indirect array, this function appends a + * string representation of the pointed object (known as a \e token) to the + * target string \a s. If the array contains more than one non-null pointer, + * successive tokens are separated with the specified \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform an array element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + const_iterator i = Begin(); + if ( i < End() ) + { + while ( *i == nullptr ) + if ( ++i == End() ) + return s; + s.Append( S( **i ) ); + if ( ++i < End() ) + do + if ( *i != nullptr ) + { + s.Append( separator ); + s.Append( S( **i ) ); + } + while ( ++i < End() ); + } + return s; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each non-null pointer p in this indirect array, this function appends + * a string representation of the pointed object (known as a \e token) to + * the target string \a s by calling the \a append function: + * + *\code append( s, S( *p ) ); \endcode + * + * If the array contains more than one non-null pointer, successive tokens + * are separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform an + * array element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably easier to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + const_iterator i = Begin(); + if ( i < End() ) + { + while ( *i == nullptr ) + if ( ++i == End() ) + return s; + append( s, S( **i ) ); + if ( ++i < End() ) + { + S p( separator ); + do + if ( *i != nullptr ) + { + append( s, p ); + append( s, S( **i ) ); + } + while ( ++i < End() ); + } + } + return s; + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return ToSeparated( s, ',' ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return ToSeparated( s, ' ' ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return ToSeparated( s, '\t' ); + } + + /*! + * Generates a newline-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\n' ); \endcode + */ + template + S& ToNewLineSeparated( S& s ) const + { + return ToSeparated( s, '\n' ); + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this indirect + * array. + * + * This function calls pcl::Hash64() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const + { + return m_array.Hash64( seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this indirect + * array. + * + * This function calls pcl::Hash32() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const + { + return m_array.Hash32( seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this indirect array. + * This function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const + { + return Hash64( seed ); + } + + // ------------------------------------------------------------------------- + +private: + + array_implementation m_array; + + void DeleteObject( iterator i, allocator& a ) + { + pcl::Destroy( *i ); + a.Deallocate( *i ); + *i = nullptr; + } + + template + void CloneObjects( const C& x, DirectContainer* ) + { + Clear(); + Reserve( x.Length() ); + Append( static_cast( nullptr ), x.Length() ); + iterator i = Begin(), j = End(); + typename C::const_iterator p = x.Begin(), q = x.End(); + for ( allocator a; i < j && p != q; ++i, ++p ) + { + *i = a.Allocate( 1 ); + pcl::Construct( *i, *p, a ); + } + } + + template + void CloneObjects( const C& x, IndirectContainer* ) + { + Clear(); + Reserve( x.Length() ); + Append( static_cast( nullptr ), x.Length() ); + iterator i = Begin(), j = End(); + typename C::const_iterator p = x.Begin(), q = x.End(); + for ( allocator a; i < j && p != q; ++i, ++p ) + if ( *p != nullptr ) + { + *i = a.Allocate( 1 ); + pcl::Construct( *i, **p, a ); + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * Returns true only if two indirect arrays \a x1 and \a x2 are equal. This + * operator compares the objects pointed to by the pointers stored in the + * indirect arrays. + * \ingroup array_relational_operators + */ +template inline +bool operator ==( const IndirectArray& x1, const IndirectArray& x2 ) +{ + return x1.Length() == x2.Length() && pcl::Equal( x1.Begin(), x2.Begin(), x2.End(), IndirectArray::equal() ); +} + +/*! + * Returns true only if an indirect array \a x1 precedes another indirect array + * \a x2. This operator compares the objects pointed to by the pointers stored + * in the indirect arrays. + * \ingroup array_relational_operators + */ +template inline +bool operator <( const IndirectArray& x1, const IndirectArray& x2 ) +{ + return pcl::Compare( x1.Begin(), x1.End(), x2.Begin(), x2.End(), IndirectArray::less() ) < 0; +} + +/*! + * Appends a pointer \a p to an indirect array \a x. Returns a reference to the + * left-hand indirect array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +IndirectArray& operator <<( IndirectArray& x, const V* p ) +{ + x.Append( static_cast( p ) ); + return x; +} + +/*! + * Appends a pointer \a p to a temporary indirect array \a x. Returns a + * reference to the left-hand indirect array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +IndirectArray& operator <<( IndirectArray&& x, const V* p ) +{ + x.Append( static_cast( p ) ); + return x; +} + +/*! + * Appends an indirect array \a x2 to an indirect array \a x1. Returns a + * reference to the left-hand indirect array. + * \ingroup array_insertion_operators + */ +template inline +IndirectArray& operator <<( IndirectArray& x1, const IndirectArray& x2 ) +{ + x1.Append( x2 ); + return x1; +} + +/*! + * Appends an indirect array \a y to a temporary indirect array \a x. Returns a + * reference to the left-hand indirect array. + * \ingroup array_insertion_operators + */ +template inline +IndirectArray& operator <<( IndirectArray&& x1, const IndirectArray& x2 ) +{ + x1.Append( x2 ); + return x1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_IndirectArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/IndirectArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/IndirectSortedArray.h b/3rdparty/include/pcl/IndirectSortedArray.h new file mode 100644 index 0000000..91f4cb9 --- /dev/null +++ b/3rdparty/include/pcl/IndirectSortedArray.h @@ -0,0 +1,1311 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/IndirectSortedArray.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_IndirectSortedArray_h +#define __PCL_IndirectSortedArray_h + +/// \file pcl/IndirectSortedArray.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class IndirectSortedArray + * \brief Generic dynamic sorted array of pointers to objects. + * + * %IndirectSortedArray is a generic, finite sorted sequence of pointers to + * objects, implemented as a reference-counted, dynamic array of T pointers + * with automatic sorting of inserted array elements. The type A provides + * dynamic allocation for contiguous sequences of void* elements + * (StandardAllocator is used by default). + * + * Ordering of array elements is implemented by indirection, that is, the + * pointed-to objects are compared for sorting, not the contained pointers. + * + * Unlike ReferenceArray and ReferenceSortedArray, %IndirectSortedArray can + * contain null pointers, which are ignored automatically in all internal + * operations controlling the implicit ordering of the (indirectly) contained + * elements. + * + * \sa IndirectArray, ReferenceArray, ReferenceSortedArray, Array, SortedArray, + * ReferenceCounter + * \ingroup dynamic_arrays + */ +template +class PCL_CLASS IndirectSortedArray : public IndirectSortedContainer +{ +public: + + /*! # + */ + typedef IndirectArray array_implementation; + + /*! # + */ + typedef typename array_implementation::block_allocator + block_allocator; + + /*! # + */ + typedef typename array_implementation::allocator + allocator; + + /*! # + */ + typedef typename array_implementation::iterator + iterator; + + /*! # + */ + typedef typename array_implementation::const_iterator + const_iterator; + + /*! # + */ + typedef typename array_implementation::reverse_iterator + reverse_iterator; + + /*! # + */ + typedef typename array_implementation::const_reverse_iterator + const_reverse_iterator; + + /*! # + */ + typedef typename array_implementation::equal + equal; + + /*! # + */ + typedef typename array_implementation::less + less; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty indirect sorted array. + */ + IndirectSortedArray() = default; + + /*! + * Constructs an indirect sorted array of length \a n. All contained + * pointers are initialized to \c nullptr. + */ + explicit + IndirectSortedArray( size_type n ) + : m_array( n ) + { + } + + /*! + * Constructs an indirect sorted array that stores \a n copies of a pointer + * \a p. + */ + IndirectSortedArray( size_type n, const T* p ) + : m_array( n, p ) + { + } + + /*! + * Constructs an indirect sorted array as a copy of the sequence of pointers + * defined by the range [i,j). The stored sequence of pointers is sorted by + * comparing the pointed objects. + */ + template + IndirectSortedArray( FI i, FI j ) + : m_array( i, j ) + { + Sort(); + } + + /*! + * Copy constructor. + */ + IndirectSortedArray( const IndirectSortedArray& ) = default; + + /*! + * Move constructor. + */ + IndirectSortedArray( IndirectSortedArray&& ) = default; + + /*! + * Destroys an %IndirectSortedArray object. + * + * Deallocates the internal array of pointers to objects, but does not + * destroy the pointed objects. To destroy them, you have to call Destroy() + * or Delete() explicitly. + */ + ~IndirectSortedArray() + { + } + + /*! + * Returns true iff this indirect sorted array uniquely references its + * contained array of data pointers. + */ + bool IsUnique() const + { + return m_array.IsUnique(); + } + + /*! + * Returns true iff this indirect sorted array is an alias of the indirect + * sorted array \a x. + * + * Two objects are aliases if both share the same data. Two indirect + * containers are aliases if they share a unique set of data pointers. + */ + bool IsAliasOf( const IndirectSortedArray& x ) const + { + return m_array.IsAliasOf( x.m_array ); + } + + /*! + * Ensures that this indirect array uniquely references its contained data + * pointers. + * + * If necessary, this member function generates a duplicate of the array + * of pointers, references it, and then decrements the reference counter of + * the original pointers array. + */ + void EnsureUnique() + { + m_array.EnsureUnique(); + } + + /*! + * Returns the total number of bytes required to store the array of data + * pointers in this indirect array. + */ + size_type Size() const + { + return m_array.Size(); + } + + /*! # + */ + size_type Length() const + { + return m_array.Length(); + } + + /*! # + */ + size_type Capacity() const + { + return m_array.Capacity(); + } + + /*! # + */ + size_type Available() const + { + return m_array.Available(); + } + + /*! # + */ + bool IsValid() const + { + return m_array.IsValid(); + } + + /*! # + */ + bool IsEmpty() const + { + return m_array.IsEmpty(); + } + + /*! # + */ + size_type LowerBound() const + { + return m_array.LowerBound(); + } + + /*! # + */ + size_type UpperBound() const + { + return m_array.UpperBound(); + } + + /*! # + */ + const allocator& Allocator() const + { + return m_array.Allocator(); + } + + /*! # + */ + void SetAllocator( const allocator& a ) + { + m_array.SetAllocator( a ); + } + + /*! # + */ + const_iterator At( size_type i ) const + { + return m_array.At( i ); + } + + /*! # + */ + iterator MutableAt( size_type i ) + { + return m_array.At( i ); + } + + /*! # + */ + iterator MutableIterator( const_iterator i ) + { + return m_array.MutableIterator( i ); + } + + /*! # + */ + const T* operator []( size_type i ) const + { + return m_array[i]; + } + + /*! # + */ + const T* operator *() const + { + return *Begin(); + } + + /*! # + */ + const_iterator Begin() const + { + return m_array.ConstBegin(); + } + + /*! # + */ + iterator MutableBegin() + { + return m_array.Begin(); + } + + /*! # + */ + const_iterator End() const + { + return m_array.ConstEnd(); + } + + /*! # + */ + iterator MutableEnd() + { + return m_array.End(); + } + + /*! # + */ + const_reverse_iterator ReverseBegin() const + { + return m_array.ConstReverseBegin(); + } + + /*! # + */ + reverse_iterator MutableReverseBegin() + { + return m_array.ReverseBegin(); + } + + /*! # + */ + const_reverse_iterator ReverseEnd() const + { + return m_array.ConstReverseEnd(); + } + + /*! # + */ + reverse_iterator MutableReverseEnd() + { + return m_array.ReverseEnd(); + } + + /*! # + */ + const T* First() const + { + return m_array.First(); + } + + /*! # + */ + T* MutableFirst() + { + return IsEmpty() ? nullptr : *MutableBegin(); + } + + /*! # + */ + const T* Last() const + { + return m_array.Last(); + } + + /*! # + */ + T* MutableLast() + { + return IsEmpty() ? nullptr : *MutableReverseBegin(); + } + + /*! + * Ensures that the specified iterator points to a uniquely referenced + * pointer. If necessary, this function builds a new, uniquely referenced + * copy of this indirect array by calling EnsureUnique(). + * + * If the iterator \a i is changed, it is guaranteed to point to the pointer + * at the same array index it was pointing to before calling this function. + */ + void UniquifyIterator( iterator& i ) + { + m_array.UniquifyIterator( i ); + } + + /*! + * Ensures that the specified iterators point to uniquely referenced + * pointers. If necessary, this function builds a new, uniquely referenced + * copy of this indirect array by calling EnsureUnique(). + * + * If the iterators \a i and \a j are changed, they are guaranteed to point + * to the pointers at the same array indices they were pointing to before + * calling this function. + */ + void UniquifyIterators( iterator& i, iterator& j ) + { + m_array.UniquifyIterators( i, j ); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Copy assignment operator. + * + * Causes this indirect array to reference the same set of pointers as + * another array \a x. Returns a reference to this object. + */ + IndirectSortedArray& operator =( const IndirectSortedArray& x ) + { + Assign( x ); + return *this; + } + + /*! # + */ + void Assign( const IndirectSortedArray& x ) + { + m_array.Assign( x.m_array ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + IndirectSortedArray& operator =( IndirectSortedArray&& x ) + { + Transfer( x ); + return *this; + } + + /*! # + */ + void Transfer( IndirectSortedArray& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! # + */ + void Transfer( IndirectSortedArray&& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! # + */ + IndirectSortedArray& operator =( const array_implementation& x ) + { + Assign( x ); + return *this; + } + + /*! # + */ + void Assign( const array_implementation& x ) + { + m_array.Assign( x ); + Sort(); + } + + /*! # + */ + IndirectSortedArray& operator =( array_implementation&& x ) + { + Transfer( x ); + return *this; + } + + /*! # + */ + void Transfer( array_implementation& x ) + { + m_array.Transfer( x ); + Sort(); + } + + /*! # + */ + void Transfer( array_implementation&& x ) + { + m_array.Transfer( x ); + Sort(); + } + + /*! # + */ + void Assign( const T* p, size_type n = 1 ) + { + m_array.Assign( p, n ); + } + + /*! # + */ + template + void Assign( FI i, FI j ) + { + m_array.Assign( i, j ); + Sort(); + } + + /*! # + */ + template + void CloneAssign( const C& x ) + { + m_array.CloneAssign( x ); + Sort(); + } + + /*! # + */ + void CloneAssign( SortedArray& x ) + { + m_array.CloneAssign( x ); + } + + /*! # + */ + void CloneAssign( IndirectSortedArray& x ) + { + m_array.CloneAssign( x ); + } + + /*! # + */ + void Import( iterator i, iterator j ) + { + m_array.Import( i, j ); + Sort(); + } + + /*! # + */ + iterator Release() + { + return m_array.Release(); + } + + /*! # + */ + void Add( const IndirectSortedArray& x ) + { + const_iterator p = x.m_array.Begin(), q = x.m_array.End(); + less cmp; + for ( iterator i = m_array.Begin(); i < m_array.End() && p < q; ++i ) + if ( cmp( *p, *i ) ) + i = m_array.Insert( i, *p++ ); + if ( p < q ) + m_array.Append( p, q ); + } + + /*! # + */ + void Add( const IndirectArray& x ) + { + Add( x.Begin(), x.End() ); + } + + /*! # + */ + const_iterator Add( const T* p, size_type n = 1 ) + { + return m_array.Insert( pcl::InsertionPoint( m_array.Begin(), m_array.End(), p, less() ), p, n ); + } + + /*! # + */ + template + void Add( FI i, FI j ) + { + if ( i != j ) + { + m_array.EnsureUnique(); + for ( const_iterator l = m_array.Begin(), r = m_array.End(); ; ) + { + FI h = i; + const_iterator m = m_array.Insert( pcl::InsertionPoint( l, r, *i, less() ), *i ); + + if ( ++i == j ) + break; + + if ( less()( *i, *h ) ) + { + l = m_array.Begin(); + r = m; + } + else + { + l = m+1; + r = m_array.End(); + } + } + } + } + + /*! # + */ + void Remove( const_iterator i, size_type n = 1 ) + { + m_array.Remove( i, n ); + } + + /*! # + */ + void Remove( const_iterator i, const_iterator j ) + { + m_array.Remove( i, j ); + } + + /*! + * Removes a trailing sequence of contiguous pointers from the specified + * iterator of this indirect array. This operation is equivalent to: + * + * \code Remove( i, End() ) \endcode + * + * If the specified iterator is located at or after the end of this array, + * this function does nothing. Otherwise the iterator is constrained to stay + * in the range [Begin(),End()) of existing array elements. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Truncate( const_iterator i ) + { + m_array.Truncate( i ); + } + + /*! + * Removes a contiguous trailing sequence of \a n existing pointers from + * this indirect array. This operation is equivalent to: + * + * \code Truncate( End() - n ) \endcode + * + * If the specified count \a n is greater than or equal to the length of + * this array, this function calls Clear() to yield an empty array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Shrink( size_type n = 1 ) + { + m_array.Shrink( n ); + } + + /*! # + */ + void Remove( const T& v ) + { + const_iterator i = pcl::BinarySearch( Begin(), End(), &v, less() ); + if ( i != End() ) + m_array.Remove( i, pcl::InsertionPoint( i+1, End(), &v, less() ) ); + } + + /*! # + */ + template + void Remove( const T& v, BP p ) + { + m_array.Remove( v, p ); + } + + /*! # + */ + void Remove( const T* p ) + { + m_array.Remove( p ); + } + + /*! # + */ + void Clear() + { + m_array.Clear(); + } + + /*! # + */ + void Delete( iterator i, size_type n = 1 ) + { + Delete( i, i+n ); + } + + /*! # + */ + void Delete( iterator i, iterator j ) + { + // NB: Copy-on-write must *not* happen in this function. + if ( i < End() ) + { + i = pcl::Max( const_cast( Begin() ), i ); + j = pcl::Min( j, const_cast( End() ) ); + m_array.Delete( i, j ); + if ( j < End() ) + pcl::Fill( pcl::Copy( i, j, const_cast( End() ) ), + const_cast( End() ), + static_cast( nullptr ) ); + } + } + + /*! # + */ + void Delete( const T& v ) + { + // NB: Copy-on-write must *not* happen in this function. + const_iterator i = pcl::BinarySearch( Begin(), End(), &v, less() ); + if ( i != End() ) + Delete( const_cast( i ), + const_cast( pcl::InsertionPoint( i+1, Begin(), &v, less() ) ) ); + } + + /*! # + */ + template + void Delete( const T& v, BP p ) + { + // NB: Copy-on-write must *not* happen in this function. + m_array.Delete( v, p ); + pcl::QuickSort( Begin(), End(), less() ); + } + + /*! # + */ + void Delete() + { + m_array.Delete(); + } + + /*! # + */ + void Destroy( iterator i, size_type n = 1 ) + { + m_array.Destroy( i, n ); + } + + /*! # + */ + void Destroy( iterator i, iterator j ) + { + m_array.Destroy( i, j ); + } + + /*! # + */ + void Destroy( const T& v ) + { + const_iterator i = pcl::BinarySearch( Begin(), End(), &v, less() ); + if ( i != End() ) + Destroy( const_cast( i ), + const_cast( pcl::InsertionPoint( i+1, End(), &v, less() ) ) ); + } + + /*! # + */ + template + void Destroy( const T& v, BP p ) + { + m_array.Destroy( v, p ); + pcl::QuickSort( Begin(), End(), less() ); + } + + /*! # + */ + void Destroy() + { + m_array.Destroy(); + } + + /*! # + */ + void Pack() + { + m_array.Pack(); + } + + /*! # + */ + void Reserve( size_type n ) + { + m_array.Reserve( n ); + } + + /*! # + */ + void Squeeze() + { + m_array.Squeeze(); + } + + /*! + * Sets all objects contained by this array equal to \a v. + */ + void Fill( const T& v ) + { + m_array.Fill( v ); + } + + /*! # + */ + template + void Apply( F f ) const + { + m_array.Apply( f ); + } + + /*! # + */ + template + const_iterator FirstThat( F f ) const + { + return m_array.FirstThat( f ); + } + + /*! # + */ + template + const_iterator LastThat( F f ) const + { + return m_array.LastThat( f ); + } + + /*! # + */ + size_type Count( const T& v ) const + { + const_iterator i = pcl::BinarySearch( Begin(), End(), &v, less() ); + return (i != End()) ? pcl::InsertionPoint( i+1, End(), &v, less() ) - i : 0; + } + + /*! # + */ + size_type Count( const T* p ) const + { + return m_array.Count( p ); + } + + /*! # + */ + template + size_type Count( const T& v, BP p ) const + { + return m_array.Count( v, p ); + } + + /*! # + */ + template + size_type CountIf( UP p ) const + { + return m_array.CountIf( p ); + } + + /*! # + */ + const_iterator MinItem() const + { + return Begin(); + } + + /*! # + */ + template + const_iterator MinItem( BP p ) const + { + return m_array.MinItem( p ); + } + + /*! # + */ + const_iterator MaxItem() const + { + return IsEmpty() ? End() : End()-1; + } + + /*! # + */ + template + const_iterator MaxItem( BP p ) const + { + return m_array.MaxItem( p ); + } + + /*! # + */ + const_iterator Search( const T& v ) const + { + return pcl::BinarySearch( Begin(), End(), &v, less() ); + } + + /*! # + */ + const_iterator Search( const T* p ) const + { + return m_array.Search( p ); + } + + /*! # + */ + template + const_iterator Search( const T& v, BP p ) const + { + return m_array.Search( v, p ); + } + + /*! # + */ + const_iterator SearchLast( const T& v ) const + { + return pcl::BinarySearchLast( Begin(), End(), &v, less() ); + } + + /*! # + */ + const_iterator SearchLast( const T* p ) const + { + return m_array.SearchLast( p ); + } + + /*! # + */ + template + const_iterator SearchLast( const T& v, BP p ) const + { + return m_array.SearchLast( v, p ); + } + + /*! # + */ + bool Contains( const T& v ) const + { + return Search( v ) != End(); + } + + /*! # + */ + bool Contains( const T* p ) const + { + return m_array.Contains( p ); + } + + /*! # + */ + template + bool Contains( const T& v, BP p ) const + { + return Search( v, p ) != End(); + } + + /*! # + */ + void Sort() + { + m_array.Sort(); + } + + /*! + * Exchanges two indirect sorted arrays \a x1 and \a x2. + */ + friend void Swap( IndirectSortedArray& x1, IndirectSortedArray& x2 ) + { + pcl::Swap( x1.m_array, x2.m_array ); + } + + /*! + * Returns true only if two indirect sorted arrays \a x1 and \a x2 are + * equal. + * \ingroup array_relational_operators + */ + friend bool operator ==( const IndirectSortedArray& x1, const IndirectSortedArray& x2 ) + { + return x1.m_array == x2.m_array; + } + + /*! + * Returns true only if an indirect sorted array \a x1 is equal to an + * indirect array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator ==( const IndirectSortedArray& x1, const array_implementation& x2 ) + { + return x1.m_array == x2; + } + + /*! + * Returns true only if an indirect array \a x1 is equal to an indirect + * sorted array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator ==( const array_implementation& x1, const IndirectSortedArray& x2 ) + { + return x1 == x2.m_array; + } + + /*! + * Returns true only if an indirect sorted array \a x1 precedes another + * indirect sorted array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const IndirectSortedArray& x1, const IndirectSortedArray& x2 ) + { + return x1.m_array < x2.m_array; + } + + /*! + * Returns true only if an indirect sorted array \a x1 precedes an indirect + * array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const IndirectSortedArray& x1, const array_implementation& x2 ) + { + return x1.m_array < x2; + } + + /*! + * Returns true only if an indirect array \a x1 precedes an indirect sorted + * array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const array_implementation& x1, const IndirectSortedArray& x2 ) + { + return x1 < x2.m_array; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each non-null pointer in this indirect array, this function appends a + * string representation of the pointed object (known as a \e token) to the + * target string \a s. If the array contains more than one non-null pointer, + * successive tokens are separated with the specified \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform an array element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + return m_array.ToSeparated( s, separator ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each non-null pointer p in this indirect array, this function appends + * a string representation of the pointed object (known as a \e token) to + * the target string \a s by calling the \a append function: + * + *\code append( s, S( *p ) ); \endcode + * + * If the array contains more than one non-null pointer, successive tokens + * are separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform an + * array element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably easier to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + return m_array.ToSeparated( s, separator, append ); + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return m_array.ToCommaSeparated( s ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return m_array.ToSpaceSeparated( s ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return m_array.ToTabSeparated( s ); + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this indirect + * array. + * + * This function calls pcl::Hash64() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const + { + return m_array.Hash64( seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this indirect + * array. + * + * This function calls pcl::Hash32() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const + { + return m_array.Hash32( seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this indirect array. + * This function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const + { + return Hash64( seed ); + } + + // ------------------------------------------------------------------------- + +private: + + array_implementation m_array; +}; + +// ---------------------------------------------------------------------------- + +/*! + * Adds a pointer \a p to an indirect sorted array \a x. Returns a reference to + * the left-hand indirect sorted array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +IndirectSortedArray& operator <<( IndirectSortedArray& x, const V* p ) +{ + x.Add( static_cast( p ) ); + return x; +} + +/*! + * Adds a pointer \a p to a temporary indirect sorted array \a x. Returns a + * reference to the left-hand indirect sorted array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +IndirectSortedArray& operator <<( IndirectSortedArray&& x, const V* p ) +{ + x.Add( static_cast( p ) ); + return x; +} + +/*! + * Adds an indirect sorted array \a x2 to an indirect sorted array \a x1. + * Returns a reference to the left-hand indirect sorted array. + * \ingroup array_insertion_operators + */ +template inline +IndirectSortedArray& operator <<( IndirectSortedArray& x1, const IndirectSortedArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds an indirect sorted array \a x2 to a temporary indirect sorted array + * \a x1. Returns a reference to the left-hand indirect sorted array. + * \ingroup array_insertion_operators + */ +template inline +IndirectSortedArray& operator <<( IndirectSortedArray&& x1, const IndirectSortedArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds an indirect array \a x2 to an indirect sorted array \a x1. Returns a + * reference to the left-hand indirect sorted array. + * \ingroup array_insertion_operators + */ +template inline +IndirectSortedArray& operator <<( IndirectSortedArray& x1, const IndirectArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds an indirect array \a x2 to a temporary indirect sorted array \a x1. + * Returns a reference to the left-hand indirect sorted array. + * \ingroup array_insertion_operators + */ +template inline +IndirectSortedArray& operator <<( IndirectSortedArray&& x1, const IndirectArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_IndirectSortedArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/IndirectSortedArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/IntegerResample.h b/3rdparty/include/pcl/IntegerResample.h new file mode 100644 index 0000000..f1a42eb --- /dev/null +++ b/3rdparty/include/pcl/IntegerResample.h @@ -0,0 +1,220 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/IntegerResample.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_IntegerResample_h +#define __PCL_IntegerResample_h + +/// \file pcl/IntegerResample.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::IntegerDownsampleMode + * \brief Downsampling operations for IntegerResample. + * + * + * + * + * + * + *
IntegerDownsampleMode::Average Downsample by averaging source pixels
IntegerDownsampleMode::Median Downsample by calculating the median of source pixels
IntegerDownsampleMode::Maximum Downsample by the maximum source pixel value
IntegerDownsampleMode::Minimum Downsample by the minimum source pixel value
+ */ +namespace IntegerDownsampleMode +{ + enum value_type + { + Average, + Median, + Maximum, + Minimum + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class IntegerResample + * \brief A geometric transformation to resample images by integer ratios. + * + * ### TODO: Write a detailed description for %IntegerResample. + */ +class PCL_CLASS IntegerResample : public GeometricTransformation +{ +public: + + /*! + * Represents a downsample operation. + */ + typedef IntegerDownsampleMode::value_type downsample_mode; + + /*! + * Constructs an %IntegerResample object with zoom factor \a z and + * downsampling mode \a m. + */ + IntegerResample( int zoom = 0, downsample_mode mode = IntegerDownsampleMode::Average ) + : m_zoomFactor( zoom ) + , m_downsampleMode( mode ) + { + } + + /*! + * Copy constructor. + */ + IntegerResample( const IntegerResample& ) = default; + + /*! + * Returns the current zoom factor of this %IntegerResample object. + */ + int ZoomFactor() const + { + return m_zoomFactor; + } + + /*! + * Sets the \a zoom factor for this %IntegerResample object. + * + * Positive zoom factors are interpreted as magnifying factors; negative + * zoom factors are reduction factors. For example: + * + * + * + * + * + * + * + * + *
Zoom Factor Resampling ratio (original pixels : resampled pixels)
-3 1:3 (1/3 reduction)
-2 1:2 (1/2 reduction)
1 1:1 (actual pixels)
2 2:1 (x2 magnification)
3 3:1 (x3 magnification)
+ * + * \note Zoom factors 0 and -1 should not be used explicitly; they are + * reserved for internal use, and there is no guarantee that future versions + * of PCL will continue accepting them. + */ + void SetZoomFactor( int zoom ) + { + m_zoomFactor = (zoom < -1 || zoom > +1) ? zoom : +1; + } + + /*! + * Returns the pixel scaling factor applied by this instance, or the + * equivalent image resampling ratio. See SetZoomFactor() for the + * correspondence between zoom factors and resampling ratios. + */ + double ScalingFactor() const + { + if ( m_zoomFactor == 0 ) + return 1; + return (m_zoomFactor < 0) ? 1.0/(-m_zoomFactor) : double( m_zoomFactor ); + } + + /*! + * Returns the current downsample mode of this %IntegerResample object. + */ + downsample_mode DownsampleMode() const + { + return m_downsampleMode; + } + + /*! + * Sets the downsample \e mode for this %IntegerResample object. + * + * The downsample mode defines an statistical operation that the integer + * resampling algorithms applies to the set of original pixels that produce + * each pixel in the subsampled image. The default mode is + * IntegerDownsampleMode::Average, which calculates the mean of source + * pixels. The Median, Minimum and Maximum modes turn the integer + * downsampling algorithm into a morphological downsampling + * operation with very interesting properties and applications. + */ + void SetDownsampleMode( downsample_mode mode ) + { + m_downsampleMode = mode; + } + + /*! + */ + void GetNewSizes( int& width, int& height ) const override; + +protected: + + /* + * Zoom factor: > 1 -> zoom in, < 1 -> zoom out, from -1 to +1 -> no change. + */ + int m_zoomFactor = 0; + + /* + * Downsample mode: average, median, maximum, minimum; see enumeration above. + */ + downsample_mode m_downsampleMode = IntegerDownsampleMode::Average; + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_IntegerResample_h + +// ---------------------------------------------------------------------------- +// EOF pcl/IntegerResample.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/IntegrationMetadata.h b/3rdparty/include/pcl/IntegrationMetadata.h new file mode 100644 index 0000000..3d41b51 --- /dev/null +++ b/3rdparty/include/pcl/IntegrationMetadata.h @@ -0,0 +1,426 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/IntegrationMetadata.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_IntegrationMetadata_h +#define __PCL_IntegrationMetadata_h + +/// \file pcl/IntegrationMetadata.h + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ConsistentlyDefined + * \brief An object that can be in consistently defined or undefined/inconsistent states. + * + * %ConsistentlyDefined is similar to Optional: it stores an instance of the + * template argument T, along with a defined state Boolean flag. In + * addition, this class includes a \e consistency state flag. A + * consistently defined object has been both defined and optionally + * ckecked for consistency against other objects or values. Two objects are + * considered consistent if an equality operator is true for them. + * + * As happens with %Optional, %ConsistentlyDefined objects update their defined + * and consistency states automatically as they are created, copied and + * assigned. + * + * \note This is a support utility class used internally by several modules, + * made public mainly for code organization purposes. We make this class public + * because it can be useful, but it still has not been fully developed as it + * should to fulfill standard PCL quality standards. + */ +template +class PCL_CLASS ConsistentlyDefined +{ +public: + + /*! + * Constructs an undefined, consistent %ConsistentlyDefined object. + * + * The value instance will be default-constructed implicitly, which means + * that the type T must provide valid default construction semantics. + */ + ConsistentlyDefined() + : m_value() // N.B: this initialization prevents warnings such as + { // 'ConsistentlyDefined<>::m_value may be used uninitialized...' + } + + /*! + * Copy constructor. + * + * The value instance will be copy-constructed implicitly, which means that + * the type T must provide valid copy construction semantics if this + * constructor is invoked. + */ + ConsistentlyDefined( const ConsistentlyDefined& ) = default; + + /* + * Move constructor. + */ + ConsistentlyDefined( ConsistentlyDefined&& ) = default; + + /*! + * Constructs a defined, consistent %ConsistentlyDefined object with the + * specified \a value. + */ + ConsistentlyDefined( const T& value ) + : m_value( value ) + , m_defined( true ) + { + } + + /*! + * Assigns the specified \a value to this object. Returns a reference to + * this object. After assigning a value, a %ConsistentlyDefined object will + * be in defined/consistent state. + */ + T& operator =( const T& value ) + { + m_value = value; + m_defined = m_consistent = true; + return m_value; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * If this object is inconsistent, then this function does nothing but + * returning a reference to this. + * + * If this object is consistent, then: + * + * - If \a other is defined and this is defined, then if the values of both + * objects are different, this object will be in defined/inconsistent state. + * + * - If \a other is defined and this is not defined, then the value of + * \a other will be assigned to this object, and this object will be in + * defined/consistent state. + * + * - If \a other is not defined and this is defined, then this object will + * be in defined/inconsistent state. + */ + ConsistentlyDefined& operator =( const ConsistentlyDefined& other ) + { + if ( m_consistent ) + if ( other.m_defined ) + { + if ( m_defined ) + { + if ( m_value != other.m_value ) + m_consistent = false; + } + else + { + m_value = other.m_value; + m_defined = true; + } + } + else + { + if ( m_defined ) + m_consistent = false; + } + + return *this; + } + + /*! + * Addition/assignment operator. Returns a reference to this object. + * + * If this object is inconsistent, then this function does nothing but + * returning a reference to this. + * + * If this object is consistent, then: + * + * - If \a other is defined and this is defined, then the value of \a other + * will be added to this object's value, and this object will remain in + * defined/consistent state. + * + * - If \a other is defined and this is not defined, then the value of + * \a other will be assigned to this object, and this object will be in + * defined/consistent state. + * + * - If \a other is not defined and this is defined, then this object will + * be in defined/inconsistent state. + */ + ConsistentlyDefined& operator +=( const ConsistentlyDefined& other ) + { + if ( m_consistent ) + if ( other.m_defined ) + { + if ( m_defined ) + m_value += other.m_value; + else + { + m_value = other.m_value; + m_defined = true; + } + } + else + { + if ( m_defined ) + m_consistent = false; + } + + return *this; + } + + /*! + * Addition/assignment operator. Returns a reference to this object. + * + * If this object is inconsistent, then this function does nothing but + * returning a reference to this. + * + * If this object is consistent, then: + * + * - If this object is defined, then \a otherValue will be added to this + * object's value, and this object will remain in defined/consistent state. + * + * - If this object is not defined, then \a otherValue will be assigned to + * this object, and this object will be in defined/consistent state. + */ + ConsistentlyDefined& operator +=( const T& otherValue ) + { + if ( m_consistent ) + if ( m_defined ) + m_value += otherValue; + else + { + m_value = otherValue; + m_defined = true; + } + + return *this; + } + + /*! + * Returns a reference to the value stored in this object. + * + * If this object is undefined, the returned value may be unpredictable, + * depending on construction semantics for the type T. + */ + const T& operator ()() const + { + return m_value; + } + + /*! + * Returns true iff this object has been defined, even if it's inconsistent. + */ + bool IsDefined() const + { + return m_defined; + } + + /*! + * Returns true iff this object is consistent, even if it has not been + * defined. + */ + bool IsConsistent() const + { + return m_consistent; + } + + /*! + * If this object is in defined/consistent state, then this function returns + * true. + * + * If this object is in undefined state, this function returns false. + * + * If this object is in defined/inconsistent state, this function returns + * false. In this case, if the \a what string is not empty, a warning + * message will be written to the core platform's console alerting about the + * inconsistent state. + */ + bool IsConsistentlyDefined( const String& what = String() ) const + { + if ( m_defined ) + { + if ( m_consistent ) + return true; + if ( !what.IsEmpty() ) + Console().WarningLn( "** Warning: Inconsistent " + what + " value(s) - metadata not generated." ); + } + return false; + } + + /*! + * Force this object to be in undefined state. + */ + void Undefine() + { + m_defined = false; + } + + /*! + * Force this object to be in inconsistent state. + */ + void SetInconsistent() + { + m_consistent = false; + } + + /*! + * Changes the value in this object in a forcible way, i.e. without checking + * for consistency. + */ + void ForceValue( const T& value ) + { + m_value = value; + } + + /*! + * Returns a String representation of the value in this object if it has + * been defined (even if it's inconsistent). Otherwise returns an empty + * string. + */ + String ToString() const + { + return m_defined ? String( m_value ) : String(); + } + +private: + + T m_value; + bool m_defined = false; + bool m_consistent = true; +}; + +// ---------------------------------------------------------------------------- + +#define __PCL_INTEGRATION_METADATA_VERSION "1.2" + +/* + * Optional, consistently defined metadata of an integrable image. + * + * ### N.B. Internal use - Not a public interface. + */ +class IntegrationMetadata +{ +public: + + String version = __PCL_INTEGRATION_METADATA_VERSION; + ConsistentlyDefined author; + ConsistentlyDefined observer; + ConsistentlyDefined instrumentName; + ConsistentlyDefined frameType; + ConsistentlyDefined filterName; + ConsistentlyDefined cfaPatternName; + ConsistentlyDefined cfaPattern; + ConsistentlyDefined cfaXOffset; // px + ConsistentlyDefined cfaYOffset; // px + ConsistentlyDefined pedestal; // DN + ConsistentlyDefined expTime; // s + ConsistentlyDefined sensorTemp; // C + ConsistentlyDefined xPixSize; // um + ConsistentlyDefined yPixSize; // um + ConsistentlyDefined cameraGain; + ConsistentlyDefined cameraISO; + ConsistentlyDefined xBinning; + ConsistentlyDefined yBinning; + ConsistentlyDefined xOrigin; // px + ConsistentlyDefined yOrigin; // px + ConsistentlyDefined telescopeName; + ConsistentlyDefined focalLength; // mm + ConsistentlyDefined aperture; // mm + ConsistentlyDefined apertureArea; // mm^2 + ConsistentlyDefined objectName; + ConsistentlyDefined startTime; // UTC + ConsistentlyDefined endTime; // UTC + ConsistentlyDefined ra; // deg (-180,+180] + ConsistentlyDefined dec; // deg [-90,+90] + ConsistentlyDefined celCrdSys; // ICRS, FK5 + ConsistentlyDefined equinox; // yr + ConsistentlyDefined longObs; // deg (-180,+180] + ConsistentlyDefined latObs; // deg [-90,+90] + ConsistentlyDefined altObs; // m + + IntegrationMetadata() = default; + IntegrationMetadata( const IntegrationMetadata& ) = default; + + IntegrationMetadata( const PropertyArray&, const FITSKeywordArray& ); + IntegrationMetadata( const String& serialization ); + + String Serialize() const; + + bool IsValid() const + { + return m_valid; + } + + void UpdatePropertiesAndKeywords( PropertyArray&, FITSKeywordArray& ) const; + + static IntegrationMetadata Summary( const Array& ); + +private: + + bool m_valid = false; + + // Block separators for text metadata serialization (UTF-16). + constexpr static char16_type ItemSeparator = char16_type( 0x2028 ); // Unicode Line Separator + constexpr static char16_type TokenSeparator = char16_type( 0x2029 ); // Unicode Paragraph Separator +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_IntegrationMetadata_h + +// ---------------------------------------------------------------------------- +// EOF pcl/IntegrationMetadata.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/InterlacedTransformation.h b/3rdparty/include/pcl/InterlacedTransformation.h new file mode 100644 index 0000000..779c390 --- /dev/null +++ b/3rdparty/include/pcl/InterlacedTransformation.h @@ -0,0 +1,181 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/InterlacedTransformation.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_InterlacedTransformation_h +#define __PCL_InterlacedTransformation_h + +/// \file pcl/InterlacedTransformation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class InterlacedTransformation + * \brief Interlaced image transformation in the spatial domain. + * + * %InterlacedTransformation represents an interlaced image + * transformation in PCL. An interlaced transformation can be applied to a + * subset of the pixels in a target image by acting exclusively on selected + * rows and columns of pixels, distributed at regular intervals. + * + * The distance between two consecutive rows or columns of transformed pixels + * is the interlacing distance that characterizes an interlaced + * transformation. Intermediate pixels falling between selected rows or columns + * are ignored during the transformation. + * + * In PCL, convolutions in the spatial domain and morphological transformations + * have been implemented as interlaced transformations. A good example of + * interlaced image transformation algorithm is the starlet transform (see the + * StarletTransform class), which uses interlaced convolutions to perform a + * multiscale decomposition. + */ +class PCL_CLASS InterlacedTransformation : public virtual ImageTransformation +{ +public: + + /*! + * Constructs an %InterlacedTransformation object with the specified + * interlacing distance \a n > 0 in pixels. + */ + InterlacedTransformation( int n = 1 ) + : m_distance( pcl::Max( 1, n ) ) + { + PCL_PRECONDITION( n > 0 ) + } + + /*! + * Copy constructor. + */ + InterlacedTransformation( const InterlacedTransformation& ) = default; + + /*! + * Destroys an %InterlacedTransformation object. + */ + virtual ~InterlacedTransformation() + { + } + + /*! + * Returns true iff this transformation is currently interlaced. + * + * The transformation is interlaced if the current interlacing distance is + * greater than one pixel. + * + * \sa InterlacingDistance() + */ + bool IsInterlaced() const + { + return m_distance > 1; + } + + /*! + * Returns the current interlacing distance of this transformation in + * pixels. + * + * \sa SetInterlacingDistance(), IsInterlaced() + */ + int InterlacingDistance() const + { + return m_distance; + } + + /*! + * Sets the current interlacing distance of this transformation to the + * specified value \a n > 0 in pixels. + * + * The interlacing distance is the distance in pixels between two + * consecutive rows or columns of transformed pixels. Intermediate pixels + * falling between selected rows or columns are ignored. + * + * \sa InterlacingDistance(), DisableInterlacing(), IsInterlaced() + */ + void SetInterlacingDistance( int n ) + { + PCL_PRECONDITION( n > 0 ) + m_distance = pcl::Max( 1, n ); + } + + /*! + * Disables interlacing for this transformation. + * + * This is a convenience function, equivalent to: + * + * \code SetInterlacingDistance( 1 ); \endcode + */ + void DisableInterlacing() + { + SetInterlacingDistance( 1 ); + } + +private: + + /* + * Interlacing distance in pixels + */ + int m_distance = 1; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_InterlacedTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/InterlacedTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Interpolation.h b/3rdparty/include/pcl/Interpolation.h new file mode 100644 index 0000000..b0ede84 --- /dev/null +++ b/3rdparty/include/pcl/Interpolation.h @@ -0,0 +1,112 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Interpolation.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_Interpolation_h +#define __PCL_Interpolation_h + +/// \file pcl/Interpolation.h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::InterpolationAlgorithm + * \brief Standard pixel interpolation algorithms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
InterpolationAlgorithm::NearestNeighbor Nearest neighbor interpolation
InterpolationAlgorithm::Bilinear Bilinear interpolation
InterpolationAlgorithm::BicubicSpline Bicubic spline interpolation (usually the default algorithm)
InterpolationAlgorithm::Bicubic A synonym for bicubic spline interpolation
InterpolationAlgorithm::BicubicBSpline Bicubic B-spline interpolation
InterpolationAlgorithm::Lanczos3 Lanczos-3 interpolation
InterpolationAlgorithm::Lanczos4 Lanczos-4 interpolation
InterpolationAlgorithm::Lanczos5 Lanczos-5 interpolation
InterpolationAlgorithm::MitchellNetravaliFilter Mitchell-Netravali cubic filter interpolation
InterpolationAlgorithm::CatmullRomSplineFilter Catmull-Rom spline filter interpolation
InterpolationAlgorithm::CubicBSplineFilter Cubic B-spline filter interpolation
InterpolationAlgorithm::Auto Used to indicate an automatic algorithm selection (often the default option)
InterpolationAlgorithm::Default Used to indicate a default interpolation algorithm (currently bicubic spline)
+ */ +namespace InterpolationAlgorithm +{ + enum value_type + { + Auto = -1, + NearestNeighbor = 0, + Bilinear, + BicubicSpline, + Bicubic = BicubicSpline, + BicubicBSpline, + Lanczos3, + Lanczos4, + Lanczos5, + MitchellNetravaliFilter, + CatmullRomSplineFilter, + CubicBSplineFilter, + NumberOfInterpolationAlgorithms, + Default = BicubicSpline + }; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Interpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Interpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Iterator.h b/3rdparty/include/pcl/Iterator.h new file mode 100644 index 0000000..be19791 --- /dev/null +++ b/3rdparty/include/pcl/Iterator.h @@ -0,0 +1,734 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Iterator.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_Iterator_h +#define __PCL_Iterator_h + +/// \file pcl/Iterator.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup iterator_classification Iterator Classification + */ + +/*! + * \class ForwardIterator + * \brief Forward iterator class. + * \ingroup iterator_classification + */ +class PCL_CLASS ForwardIterator +{ +}; + +/*! + * \class BidirectionalIterator + * \brief Bidirectional iterator class. + * \ingroup iterator_classification + */ +class PCL_CLASS BidirectionalIterator : public ForwardIterator +{ +}; + +/*! + * \class RandomAccessIterator + * \brief Random access iterator class. + * \ingroup iterator_classification + */ +class PCL_CLASS RandomAccessIterator : public BidirectionalIterator +{ +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Iterator + * \brief Generic container iterator. + */ +template +struct PCL_CLASS Iterator +{ + typedef C iterator_class; //!< Represents the iterator class + typedef T item_type; //!< Represents the item type +}; + +// ---------------------------------------------------------------------------- + +/*! + * Returns an instance of the iterator class corresponding to an instantiation + * of the %Iterator class. + */ +template inline +C IteratorClass( const Iterator& ) +{ + return C(); +} + +/*! + * Returns an instance of the iterator class for a pointer iterator, which is + * RandomAccessIterator. + */ +template inline +RandomAccessIterator IteratorClass( const T* ) +{ + return RandomAccessIterator(); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a pointer to the item type of an instantiation of the %Iterator + * class. The returned pointer has always a \c nullptr value. + */ +template inline +T* ItemType( const Iterator& ) +{ + return nullptr; +} + +/*! + * Returns a pointer to the item type of a pointer iterator, which is the same + * pointer. The returned pointer has always a \c nullptr value. + */ +template inline +T* ItemType( const T* ) +{ + return nullptr; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the existing distance in items from an iterator \a i to another + * iterator \a j. + */ +template inline +distance_type Distance( FI i, FI j ) +{ + return __pcl_distance__( i, j, IteratorClass( i ) ); +} + +template inline +distance_type __pcl_distance__( FI i, FI j, ForwardIterator ) +{ + distance_type d = 0; + for ( ; i != j; ++i, ++d ) {} + return d; +} + +template inline +distance_type __pcl_distance__( RI i, RI j, RandomAccessIterator ) +{ + return j - i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Advances an iterator \a i by the specified distance \a d. + */ +template inline +void Advance( FI& i, distance_type d ) +{ + __pcl_advance__( i, d, IteratorClass( i ) ); +} + +template inline +void __pcl_advance__( FI& i, distance_type d, ForwardIterator ) +{ + PCL_PRECONDITION( d >= 0 ) + for ( ; d > 0; --d, ++i ) {} +} + +template inline +void __pcl_advance__( BI& i, distance_type d, BidirectionalIterator ) +{ + if ( d > 0 ) + for ( ; ++i, --d > 0; ) {} + else + for ( ; d < 0; ++d, --i ) {} +} + +template inline +void __pcl_advance__( RI& i, distance_type d, RandomAccessIterator ) +{ + i += d; +} + +// ---------------------------------------------------------------------------- + +/*! + * Moves an iterator \a i forward by the specified number \a n of items. + */ +template inline +void MoveForward( FI& i, size_type n ) +{ + __pcl_move_forward__( i, n, IteratorClass( i ) ); +} + +template inline +void __pcl_move_forward__( FI& i, size_type n, ForwardIterator ) +{ + for ( ; n > 0; --n, ++i ) {} +} + +template inline +void __pcl_move_forward__( RI& i, size_type n, RandomAccessIterator ) +{ + i += n; +} + +// ---------------------------------------------------------------------------- + +/*! + * Moves an iterator \a i backward by the specified number \a n of items. + */ +template inline +void MoveBackward( BI& i, size_type n ) +{ + __pcl_move_backward__( i, n, IteratorClass( i ) ); +} + +template inline +void __pcl_move_backward__( BI& i, size_type n, BidirectionalIterator ) +{ + for ( ; n > 0; --n, --i ) {} +} + +template inline +void __pcl_move_backward__( RI& i, size_type n, RandomAccessIterator ) +{ + i -= n; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class ReverseIteratorBase + * \brief Base class of reverse iterators. + */ +template +class PCL_CLASS ReverseIteratorBase : public pcl::Iterator +{ +public: + + /*! + * Constructs a default %ReverseIteratorBase object. + */ + ReverseIteratorBase() = default; + + /*! + * Copy constructor. + */ + ReverseIteratorBase( const ReverseIteratorBase& i ) + : pcl::Iterator( i ) + , iterator( i.iterator ) + { + } + + /*! + * Constructs a %ReverseIteratorBase object as a duplicate of the specified + * bidirectional iterator \a i. + */ + ReverseIteratorBase( const BI& i ) + : iterator( i ) + { + } + + /*! + * Indirection operator. Returns a reference to the object pointed to by + * this reverse iterator. + */ + T& operator *() const + { + return (T&)*iterator; + } + + /*! + * Structure selection operator. Returns a copy of the bidirectional + * iterator contained by this reverse iterator. + */ + BI operator ->() const + { + return this->Iterator(); + } + + /*! + * Returns a bidirectional iterator that points to the object pointed by + * this %ReverseIteratorBase object. + */ + operator BI() const + { + return this->Iterator(); + } + + /*! + * A synonym for operator BI() const. + */ + BI Iterator() const + { + return iterator; + } + +protected: + + BI iterator; + + void PreIncrement() + { + --iterator; + } + + BI PostIncrement() + { + BI tmp = iterator; + --iterator; + return tmp; + } + + void PreDecrement() + { + ++iterator; + } + + BI PostDecrement() + { + BI tmp = iterator; + ++iterator; + return tmp; + } +}; + +/*! + * Returns true iff two reverse iterators \a i and \a j are equal. Two reverse + * iterators are equal if they point to the same item. + */ +template inline +bool operator ==( const ReverseIteratorBase& i, const ReverseIteratorBase& j ) +{ + return i.Iterator() == j.Iterator(); +} + +// ---------------------------------------------------------------------------- + +#define IMPLEMENT_INCDEC_OPERATORS \ + __I__& operator ++() { __R__::PreIncrement(); return *this; } \ + __I__ operator ++( int ) { return __I__( __R__::PostIncrement() ); } \ + __I__& operator --() { __R__::PreDecrement(); return *this; } \ + __I__ operator --( int ) { return __I__( __R__::PostDecrement() ); } + +/*! + * \class ReverseBidirectionalIterator + * \brief Reverse bidirectional iterator. + */ +template +class PCL_CLASS ReverseBidirectionalIterator : public ReverseIteratorBase +{ + typedef ReverseIteratorBase __R__; + typedef ReverseBidirectionalIterator __I__; + +public: + + /*! + * Constructs a %ReverseBidirectionalIterator object. + */ + ReverseBidirectionalIterator() = default; + + /*! + * Copy constructor. + */ + ReverseBidirectionalIterator( const ReverseBidirectionalIterator& i ) + : __R__( i ) + { + } + + /*! + * Constructs a %ReverseBidirectionalIterator object as a duplicate of the + * specified bidirectional iterator \a i. + */ + ReverseBidirectionalIterator( const BI& i ) + : __R__( i ) + { + } + + IMPLEMENT_INCDEC_OPERATORS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ReverseRandomAccessIterator + * \brief Reverse random access iterator. + */ +template +class PCL_CLASS ReverseRandomAccessIterator : public ReverseIteratorBase +{ + typedef ReverseIteratorBase __R__; + typedef ReverseRandomAccessIterator __I__; + +public: + + /*! + * Constructs a %ReverseRandomAccessIterator object. + */ + ReverseRandomAccessIterator() = default; + + /*! + * Copy constructor. + */ + ReverseRandomAccessIterator( const ReverseRandomAccessIterator& i ) + : __R__( i ) + { + } + + /*! + * Constructs a %ReverseRandomAccessIterator object as a duplicate of the + * specified random access iterator \a i. + */ + ReverseRandomAccessIterator( const RI& i ) + : __R__( i ) + { + } + + /*! + * Subscript operator. Returns a reference to the object at a distance \a d + * from the current iterator position. + */ + T& operator[]( size_type d ) const + { + return (T&)*(__R__::iterator - d); + } + + /*! + * Increments this interator by the specified distance \a d. Returns a + * reference to this object. + */ + ReverseRandomAccessIterator& operator +=( distance_type d ) + { + __R__::iterator -= d; + return *this; + } + + /*! + * Decrements this interator by the specified distance \a d. Returns a + * reference to this object. + */ + ReverseRandomAccessIterator& operator -=( distance_type d ) + { + __R__::iterator += d; + return *this; + } + + IMPLEMENT_INCDEC_OPERATORS +}; + +#undef IMPLEMENT_INCDEC_OPERATORS + +/*! # + */ +template inline +bool operator <( const ReverseRandomAccessIterator& i, const ReverseRandomAccessIterator& j ) +{ + return j.Iterator() < i.Iterator(); +} + +/*! # + */ +template inline +ReverseRandomAccessIterator operator +( const ReverseRandomAccessIterator& i, distance_type d ) +{ + RI r = i.Iterator(); + return r -= d; +} + +/*! # + */ +template inline +ReverseRandomAccessIterator operator +( distance_type d, const ReverseRandomAccessIterator& i ) +{ + return i + d; +} + +/*! # + */ +template inline +ReverseRandomAccessIterator operator -( const ReverseRandomAccessIterator& i, distance_type d ) +{ + RI r = i.Iterator(); + return r += d; +} + +/*! # + */ +template inline +distance_type operator -( const ReverseRandomAccessIterator& i, const ReverseRandomAccessIterator& j ) +{ + return j.Iterator() - i.Iterator(); +} + +// ---------------------------------------------------------------------------- + +/*! + * \class ReverseIterable + * \brief Reverse container adaptor + * + * A utility template class to facilitate the use of ranged-based for loops + * with reverse container iteration. Example of use: + * + * \code + * Array A{ 1, 2, 3, 4, 5 }; + * for ( auto a : A ) + * cout << a << ' '; + * cout << '\n'; + * for ( auto a : ReverseIterable( A ) ) + * cout << a << ' '; + * cout << '\n'; + * \endcode + * + * The output is: + * + * 1 2 3 4 5 \n + * 5 4 3 2 1 + * + * \note This class requires a compiler with C++14 support. In addition, the + * above example assumes a compiler with support for class template argument + * deduction, which is a C++17 feature. + */ +template +class PCL_CLASS ReverseIterable +{ +public: + + typedef C container; + + ReverseIterable( container& c ) + : m_container( c ) + { + } + + ReverseIterable( const ReverseIterable& ) = default; + + /*! + * Returns a mutable reverse iterator located at the reverse + * beginning of the iterated container. + * + * The reverse beginning corresponds to the last element in the container. + */ + auto Begin() + { + return m_container.ReverseBegin(); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of the iterated container. + * + * The reverse beginning corresponds to the last element in the container. + */ + auto Begin() const + { + return m_container.ReverseBegin(); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of the iterated container. + * + * The reverse beginning corresponds to the last element in the container. + */ + auto ConstBegin() const + { + return m_container.ConstReverseBegin(); + } + + /*! + * Returns a mutable reverse iterator located at the reverse end of + * the iterated container. + * + * The reverse end corresponds to a nonexistent element immediately before + * the first element in the container. + */ + auto End() + { + return m_container.ReverseEnd(); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of the iterated container. + * + * The reverse end corresponds to a nonexistent element immediately before + * the first element in the container. + */ + auto End() const + { + return m_container.ReverseEnd(); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of the iterated container. + * + * The reverse end corresponds to a nonexistent element immediately before + * the first element in the container. + */ + auto ConstEnd() const + { + return m_container.ConstReverseEnd(); + } + + /*! + * Returns a mutable iterator located at the beginning of the iterated + * container. + */ + auto ReverseBegin() + { + return m_container.Begin(); + } + + /*! + * Returns an immutable iterator located at the beginning of the iterated + * container. + */ + auto ReverseBegin() const + { + return m_container.Begin(); + } + + /*! + * Returns an immutable iterator located at the beginning of the iterated + * container. + */ + auto ConstReverseBegin() const + { + return m_container.ConstBegin(); + } + + /*! + * Returns a mutable iterator located at the end of the iterated container. + */ + auto ReverseEnd() + { + return m_container.End(); + } + + /*! + * Returns an immutable iterator located at the end of the iterated + * container. + */ + auto ReverseEnd() const + { + return m_container.End(); + } + + /*! + * Returns an immutable iterator located at the end of the iterated + * container. + */ + auto ConstReverseEnd() const + { + return m_container.ConstEnd(); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + auto begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + auto begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + auto end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + auto end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + +private: + + container& m_container; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Iterator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Iterator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/JPLEphemeris.h b/3rdparty/include/pcl/JPLEphemeris.h new file mode 100644 index 0000000..13c0758 --- /dev/null +++ b/3rdparty/include/pcl/JPLEphemeris.h @@ -0,0 +1,611 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/JPLEphemeris.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_JPLEphemeris_h +#define __PCL_JPLEphemeris_h + +/// \file pcl/JPLEphemeris.h + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup solar_system_ephemerides Solar System Ephemerides + */ + +/*! + * \namespace pcl::JPLEphemerisItem + * \brief JPL planetary ephemeris items + * + * Defines symbolic constants for native and derived JPL planetary ephemeris + * items. All items defined by DE438t/LE438t are currently supported. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
JPLEphemerisItem::Unknown Unknown ephemeris item.
JPLEphemerisItem::Mercury
JPLEphemerisItem::Venus
JPLEphemerisItem::EarthMoonBarycenter
JPLEphemerisItem::Mars
JPLEphemerisItem::Jupiter
JPLEphemerisItem::Saturn
JPLEphemerisItem::Uranus
JPLEphemerisItem::Neptune
JPLEphemerisItem::Pluto
JPLEphemerisItem::Moon Geocentric Moon.
JPLEphemerisItem::Sun
JPLEphemerisItem::Nutations Nutation angles dpsi and deps.
JPLEphemerisItem::LunarLibration Lunar libration angles phi, theta and psi.
JPLEphemerisItem::LunarMantleVelocity Lunar mantle velocity components omega_x, omega_y and omega_z.
JPLEphemerisItem::TT_TDB Difference TT-TDB at the geocenter in seconds
JPLEphemerisItem::NumberOfNativeItems Number of items directly available in JPL DE/LE ASCII files.
JPLEphemerisItem::NumberOfRequiredItems Number of required items in a valid JPL DE/LE ASCII file.
JPLEphemerisItem::Earth Geocenter relative to the solar system barycenter, synthesized from Earth-Moon barycenter and geocentric Moon.
JPLEphemerisItem::SSBMoon Moon relative to the solar system barycenter, synthesized from Earth-Moon barycenter and geocentric Moon.
+ * + * \ingroup solar_system_ephemerides + */ +namespace JPLEphemerisItem +{ + enum value_type + { + Unknown = -1, + + // Native JPL DE/LE items, as of 438t + Mercury = 0, + Venus, + EarthMoonBarycenter, + Mars, + Jupiter, + Saturn, + Uranus, + Neptune, + Pluto, + Moon, + Sun, + Nutations, + LunarLibration, + LunarMantleVelocity, + TT_TDB, + + NumberOfNativeItems, + NumberOfRequiredItems = Sun + 1, + + // Special items synthesized from EMB and Moon + Earth = 100, // Geocenter with respect to solar system barycenter + SSBMoon = 101 // Moon with respect to solar system barycenter + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class JPLEphemeris + * \brief JPL planetary ephemeris + * + * This class implements JPL DE/LE planetary ephemerides computed from original + * files in ASCII format. On the PixInsight/PCL platform, this is a utility + * class used to generate truncated binary ephemeris files in XEPH format by + * reinterpolation with Chebyshev polynomials from the original ephemeris data. + * + * Source JPL ephemeris ASCII files, documentation, and original test and + * utility programs and examples, are available at: + * + * ftp://ssd.jpl.nasa.gov/pub/eph/planets/ + * + * \ingroup solar_system_ephemerides + * + * \sa EphemerisFile + */ +class JPLEphemeris +{ +public: + + /*! + * Represents an ephemeris item. See the JPLEphemerisItem namespace for a + * list of the available items. + */ + typedef JPLEphemerisItem::value_type item_index; + + /*! + * Represents a numerical integration ephemeris constant defined by its + * name and value. + */ + typedef EphemerisConstant constant; + + /*! + * Represents a list of integration ephemeris constants. + */ + typedef EphemerisConstantList constant_list; + + /*! + * Constructs a &JPLEphemeris instance initialized from the specified DE/LE + * ephemeris header file in ASCII format. + * + * In the event of errors or invalid header data, this constructor throws + * the appropriate Error exceptions. + */ + JPLEphemeris( const String& filePath ); + + /*! + * Adds new ephemeris Chebyshev coefficients from the specified JPL DE/LE + * ephemeris data file in ASCII format. + * + * If this is not the first call to this member function for this object, + * the specified data file must cover a time span contiguous to the existing + * coefficients, that is, you must call this function successively with a + * list of consecutive ephemeris data files. For example, for DE/LE 432, you + * can call this function in sequence for the following file names: + * + * ascp01550.432, ascp01650.432, ascp01750.432, ..., ascp02550.432 + * + * to cover the entire ephemeris time span from JDE 2287184.5 to 2688976.5. + * You can also call this function to load a smaller time span; for example, + * calling it with the two file names: + * + * ascp02050.432, ascp02150.432 + * + * will cover a limited range from JDE 2469776.5 to 2542864.5. + */ + void AddData( const String& filePath ); + +#ifndef __PCL_NO_JPL_EPHEMERIS_TEST_ROUTINES + + /*! + * Verifies validity of the calculated ephemerides for a standard JPL DE/LE + * test file in ASCII format. Returns true iff the test was performed and it + * was successful. + * + * A test is successful if the computed coordinates and components do not + * differ from the values provided by the test file by more than 1e-13 in + * absolute value. If this member function returns true, you can be + * confident that the ephemerides being calculated with this object are + * correct. + * + * The specified file must be a standard "testpo" JPL ephemeris file + * corresponding to the DE/LE ephemeris loaded by this object. For example, + * for DE/LE 432, the required test file is "testpo.432". + * + * The test is only performed within the time span covered by this object, + * and unavailable target and center items are ignored. See the AddData() + * member function for more information. + * + * If the \a verbose argument is \c true, the function will output + * diagnostics information to stdout. + */ + bool Test( const String& filePath, bool verbose = true ) const; + +#endif // !__PCL_NO_JPL_EPHEMERIS_TEST_ROUTINES + + /*! + * Returns the DE (Development Ephemeris) number for the data loaded by this + * object. The returned number is the value of the "DENUM" integration + * constant. + */ + int DENumber() const + { + return TruncInt( ConstantValue( "DENUM" ) ); + } + + /*! + * Returns the LE (Lunar Ephemeris) number for the data loaded by this + * object. The returned number is the value of the "LENUM" integration + * constant. + */ + int LENumber() const + { + return TruncInt( ConstantValue( "LENUM" ) ); + } + + /*! + * Returns a Julian date corresponding to the first date covered by the JPL + * ephemeris for which this object has been initialized. + * + * The value returned by this function is for informative purposes only. + * Note that the ephemeris time span does not have to be the same as the + * effective time span covered by the data loaded in this object. See the + * AddData() member function for more information on ephemeris data. + */ + double EphemerisStartJD() const + { + return m_ephStartJD; + } + + /*! + * Returns a Julian date corresponding to the last date covered by the JPL + * ephemeris for which this object has been initialized. + * + * The value returned by this function is for informative purposes only. + * Note that the ephemeris time span does not have to be the same as the + * effective time span covered by the data loaded in this object. See the + * AddData() member function for more information on ephemeris data. + */ + double EphemerisEndJD() const + { + return m_ephEndJD; + } + + /*! + * Returns a Julian date corresponding to the first date covered by the + * ephemeris data loaded in this object. + * + * The value returned by this function is the smallest time point for which + * this object can compute ephemerides. The effective ephemeris time span is + * defined by the data loaded in successive calls to AddData(). + */ + double StartJD() const + { + return m_startJD; + } + + /*! + * Returns a Julian date corresponding to the last date covered by the + * ephemeris data loaded in this object. + * + * The value returned by this function is the largest time point for which + * this object can compute ephemerides. The effective ephemeris time span is + * defined by the data loaded in successive calls to AddData(). + */ + double EndJD() const + { + return m_endJD; + } + + /*! + * Returns a reference to the list of numerical integration constants used + * by this DE/LE ephemeris. The integration constants are loaded from an + * ASCII header file by the class constructor. + * + * The returned list is sorted by constant name in ascending order. + */ + const constant_list& Constants() const + { + return m_constants; + } + + /*! + * Returns the value of an integration constant given by its \a name. + * + * If no integration constant is available with the specified \a name + * (case-insensitive), this function throws an Error exception. + */ + double ConstantValue( const IsoString& name ) const + { + constant_list::const_iterator i = + BinarySearch( m_constants.Begin(), m_constants.End(), EphemerisConstant( name ) ); + if ( i == m_constants.End() ) + throw Error( "Undefined integration constant '" + name + '\'' ); + return i->value; + } + + /*! + * Returns true if the specified ephemeris item is available in the data + * loaded by this object. See the JPLEphemerisItem namespace for information + * on ephemeris items. + */ + bool IsItemAvailable( int i ) const + { + if ( i == JPLEphemerisItem::Earth || i == JPLEphemerisItem::SSBMoon ) + return IsItemAvailable( JPLEphemerisItem::EarthMoonBarycenter ) && IsItemAvailable( JPLEphemerisItem::Moon ); + return i >= 0 && i < JPLEphemerisItem::NumberOfNativeItems && m_blockIndex[i].subblocks > 0; + } + + /*! + * Returns the number of components calculated for the specified ephemeris + * item: + * + * 3 for the position and velocity of all major solar system bodies: Sun, + * Mercury to Pluto, and Moon. + * + * 2 for nutation angles. + * + * 3 for lunar libration angles and lunar mantle velocity. + * + * 1 for the difference TT-TDB. + */ + static int ComponentsForItem( int i ) + { + return (i == JPLEphemerisItem::Nutations) ? 2 : (i == JPLEphemerisItem::TT_TDB ? 1 : 3); + } + + /*! + * Computes a state vector. + * + * \param[out] r Reference to a vector where the components of the + * computed state will be stored. + * + * \param jd1,jd2 The requested time point in the TDB time scale, equal + * to jd1+jd2. + * + * \param i Index of the requested ephemeris item. + * + * Rectangular position coordinates are provided in au, except for the + * geocentric Moon, whose position is provided in km. + * + * Angles are provided in radians. + * + * TT-TDB differences are provided in seconds. + */ + void ComputeState( Vector& r, double jd1, double jd2, item_index i ) const + { + if ( i == JPLEphemerisItem::Earth ) + { + Vector rm( 3 ); + Interpolate( r.Begin(), nullptr, jd1, jd2, JPLEphemerisItem::EarthMoonBarycenter ); + Interpolate( rm.Begin(), nullptr, jd1, jd2, JPLEphemerisItem::Moon ); + rm *= m_emb2Earth; + r -= rm; + } + else if ( i == JPLEphemerisItem::SSBMoon ) + { + Vector re( 3 ); + Interpolate( re.Begin(), nullptr, jd1, jd2, JPLEphemerisItem::EarthMoonBarycenter ); + Interpolate( r.Begin(), nullptr, jd1, jd2, JPLEphemerisItem::Moon ); + r += re - m_emb2Earth*r; + } + else + Interpolate( r.Begin(), nullptr, jd1, jd2, i ); + + if ( i != JPLEphemerisItem::Moon ) + if ( i != JPLEphemerisItem::LunarLibration ) + if ( i != JPLEphemerisItem::Nutations ) + r *= m_km2au; + } + + /*! + * Computes a state vector and its first derivative. + * + * \param[out] r Reference to a vector where the components of the + * computed state will be stored. + * + * \param[out] v Reference to a vector where the components of the + * computed first derivative will be stored. + * + * \param jd1,jd2 The requested time point in the TDB time scale, equal + * to jd1+jd2. + * + * \param i Index of the requested ephemeris item. + * + * Rectangular position and velocity coordinates are provided in au and + * au/day, respectively, except for the geocentric Moon, whose position and + * velocity are provided in km and km/day, respectively. + * + * Angles and their variations are provided in radians and radians/day. + * + * TT-TDB differences and their variations are provided in seconds and + * seconds/day. + */ + void ComputeState( Vector& r, Vector& v, double jd1, double jd2, item_index i ) const + { + if ( i == JPLEphemerisItem::Earth ) + { + Vector rm( 3 ), vm( 3 ); + Interpolate( r.Begin(), v.Begin(), jd1, jd2, JPLEphemerisItem::EarthMoonBarycenter ); + Interpolate( rm.Begin(), vm.Begin(), jd1, jd2, JPLEphemerisItem::Moon ); + rm *= m_emb2Earth; + vm *= m_emb2Earth; + r -= rm; + v -= vm; + } + else if ( i == JPLEphemerisItem::SSBMoon ) + { + Vector re( 3 ), ve( 3 ); + Interpolate( re.Begin(), ve.Begin(), jd1, jd2, JPLEphemerisItem::EarthMoonBarycenter ); + Interpolate( r.Begin(), v.Begin(), jd1, jd2, JPLEphemerisItem::Moon ); + r += re - m_emb2Earth*r; + v += ve - m_emb2Earth*v; + } + else + Interpolate( r.Begin(), v.Begin(), jd1, jd2, i ); + + if ( i != JPLEphemerisItem::Moon ) + if ( i != JPLEphemerisItem::LunarLibration ) + if ( i != JPLEphemerisItem::Nutations ) + { + r *= m_km2au; + v *= m_km2au; + } + } + + /*! + * Computes a state vector for the specified time coordinate \a t. + * + * Calling this member function is equivalent to: + * + * \code ComputeState( r, t.JDI(), t.JDF(), i ); \endcode + */ + void ComputeState( Vector& r, TimePoint t, item_index i ) const + { + ComputeState( r, t.JDI(), t.JDF(), i ); + } + + /*! + * Computes a state vector and its first derivative for the specified time + * coordinate \a t. + * + * Calling this member function is equivalent to: + * + * \code ComputeState( r, v, t.JDI(), t.JDF(), i ); \endcode + */ + void ComputeState( Vector& r, Vector& v, TimePoint t, item_index i ) const + { + ComputeState( r, v, t.JDI(), t.JDF(), i ); + } + + /*! + * Generates a summary of the ephemeris loaded by this object, giving + * information on general ephemeris properties and a list of integration + * constants. + * + * The generated information is organized as a sequence of text lines + * terminated with UNIX end-of-line characters. + */ + IsoString Summary() const; + +private: + + struct block_index_item + { + int offset = 0; // offset of this ephemeris item in a block + int coefficients = 0; // number of coefficients per subblock + int subblocks = 0; // number of subblocks + }; + + typedef Array block_index; + + typedef MultiVector block_list; + + double m_ephStartJD = 0; // ephemeris start time + double m_ephEndJD = 0; // ephemeris end time + int m_blockDelta = 0; // block time span in days + constant_list m_constants; // integration constants + block_index m_blockIndex; // coefficients block index + block_list m_blocks; // coefficients blocks + double m_startJD = 0; // start time of the first coefficients block + double m_endJD = 0; // end time of the last coefficients block + double m_km2au = 0; // astronomical unit in kilometers + double m_emb2Earth = 0; // scale factor for translation Earth-Moon barycenter -> Earth + + /*! + * \internal + * Chebyshev polynomial evaluation. Special function adapted to work + * directly with JPL DE/LE ephemeris data. + */ + void Interpolate( double* r, double* v, double jd1, double jd2, item_index n ) const + { + // block index + int ix = TruncInt( ((jd1 - m_startJD) + jd2)/m_blockDelta ); + if ( ix < 0 || ix > int( m_blocks.Length() ) ) + throw Error( String().Format( "Time point out of range: %.15g", jd1+jd2 ) ); + if ( ix == int( m_blocks.Length() ) ) + --ix; + + // block coefficients + const double* block = m_blocks[ix].Begin(); + + // block index item + const block_index_item& index = m_blockIndex[n]; + + // block starting time + double jd0 = *block; + + // number of components + int nv = ComponentsForItem( n ); + + // number of coefficients per subblock + int nk = index.coefficients; + + // subblock time span in days + int dx = m_blockDelta/index.subblocks; + + // subblock index + ix = ((jd1 - jd0) + jd2)/dx; + if ( ix == index.subblocks ) + --ix; + + // subblock coefficients + const double* k = block + index.offset + ix*nv*nk; + + // compute state variables + Vector pc( nk ); + pc[0] = 1; + pc[1] = (2*((jd1 - (jd0 + ix*dx)) + jd2) - dx)/dx; + double y2 = 2*pc[1]; + for ( int i = 2; i < nk; ++i ) + pc[i] = y2*pc[i-1] - pc[i-2]; + for ( int i = 0; i < nv; ++i ) + { + r[i] = 0; + for ( int j = 0; j < nk; ++j ) + r[i] += pc[j] * *k++; + } + + // if requested, compute first derivatives. + if ( v != nullptr ) + { + double vf = 2.0*index.subblocks/m_blockDelta; + Vector vc( nk ); + vc[0] = 0; + vc[1] = 1; + vc[2] = 2*y2; + for ( int i = 3; i < nk; ++i ) + vc[i] = y2*vc[i-1] + 2*pc[i-1] - vc[i-2]; + for ( int i = nv; --i >= 0; ) + { + v[i] = 0; + for ( int j = nk; --j >= 0; ) + v[i] += vc[j] * *--k; + v[i] *= vf; + } + } + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_JPLEphemeris_h + +// ---------------------------------------------------------------------------- +// EOF pcl/JPLEphemeris.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/KDTree.h b/3rdparty/include/pcl/KDTree.h new file mode 100644 index 0000000..b4171a8 --- /dev/null +++ b/3rdparty/include/pcl/KDTree.h @@ -0,0 +1,607 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/KDTree.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_KDTree_h +#define __PCL_KDTree_h + +/// \file pcl/KDTree.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class KDTree + * \brief Bucket PR K-d tree for point data in arbitrary dimensions. + * + * An n-dimensional K-d tree is a specialized binary tree for partitioning of + * a set of points in an n-dimensional space. K-d trees have important + * applications in computational geometry problems requiring efficient + * rectangular range searching. + * + * This class implements a bucket point region K-d tree structure + * (see Reference 2). + * + * The template type argument T represents the type of a \e point object stored + * in a %KDTree structure. The type T must have the following properties: + * + * \li The standard default and copy constructors are required:\n + * \n + * T::T() \n + * T::T( const T& ) + * + * \li The \c T::component subtype must be defined. It represents a component + * of an object of type T. For example, if T is a vector type, T::component + * must be the type of a vector component. + * + * \li The array subscript operator must be defined as follows:\n + * \n + * component T::operator []( int i ) const \n + * \n + * This operator must return the value of the i-th component of an object being + * stored in the K-d tree, such that 0 <= i < N, where N > 0 is the dimension + * of the point space. + * + * \note We use this implementation of K-d trees in some essential PixInsight + * tools with success (e.g., StarAlignment), and hopefully it will be also + * useful for you, but we don't claim it to be complete. This is a practical + * and relatively simple implementation, where only the construction, + * destruction and range search operations are available. In particular, this + * implementation does not include point addition, deletion and iteration + * operations. Future versions of PCL will include more complete + * implementations of this fundamental data structure. + * + * \b References + * + * \li 1. Mark de Berg et al., Computational Geometry: Algorithms and + * Applications Third Edition, Springer, 2010, Section 5.2. + * + * \li 2. Hanan Samet, Foundations of Multidimensional and Metric Data + * Structures, Morgan Kaufmann, 2006, Section 1.5. + * + * \sa QuadTree + */ +template +class PCL_CLASS KDTree +{ +public: + + /*! + * Represents an N-dimensional point stored in this K-d tree. + */ + typedef T point; + + /*! + * Represents a point component. + */ + typedef typename point::component component; + + /*! + * A vector of point components. Used internally for tree build and range + * search operations. + */ + typedef GenericVector component_vector; + + /*! + * A list of points. Used for tree build and search operations. + */ + typedef Array point_list; + + /*! + * Constructs an empty K-d tree. + */ + KDTree() = default; + + /*! + * Constructs a K-d tree and builds it for the specified list of \a points. + * + * \param points A list of points that will be stored in this + * K-d tree. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be >= 1. The default value is 16. + * + * The dimension of the point space is taken as the length of the first + * point in the list (by calling points[0].Length()), and must be > 0. All + * points in the \a points list must be able to provide at least + * \a dimension components through a zero-based array subscript operator. + * + * If the specified list of \a points is empty, this constructor yields an + * empty K-d tree. If the dimension of the point space is less than one, an + * Error exception is thrown. + */ + KDTree( const point_list& points, int bucketCapacity = 16 ) + { + Build( points, bucketCapacity ); + } + + /*! + * Constructs a K-d tree of the specified \a dimension and builds it for a + * list of \a points. + * + * \param points A list of points that will be stored in this + * K-d tree. + * + * \param dimension The dimension of the point space. Must be > 0. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be >= 1. + * + * All points in the \a points list must be able to provide at least + * \a dimension components through a zero-based array subscript operator. + * + * If the specified list of \a points is empty, this constructor yields an + * empty K-d tree. If the dimension of the point space is less than one, an + * Error exception is thrown. + */ + KDTree( const point_list& points, int dimension, int bucketCapacity ) + { + Build( points, dimension, bucketCapacity ); + } + + /*! + * Copy constructor. Copy construction is disabled because this class uses + * internal data structures that cannot be copy-constructed. However, + * %KDTree implements move construction and move assignment. + */ + KDTree( const KDTree& ) = delete; + + /*! + * Copy assignment operator. Copy assignment is disabled because this class + * uses internal data structures that cannot be copy-assigned. However, + * %KDTree implements move assignment and move construction. + */ + KDTree& operator =( const KDTree& ) = delete; + + /*! + * Move constructor. + */ + KDTree( KDTree&& x ) + : m_root( x.m_root ) + , m_dimension( x.m_dimension ) + , m_bucketCapacity( x.m_bucketCapacity ) + , m_length( x.m_length ) + { + x.m_root = nullptr; + x.m_length = 0; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + KDTree& operator =( KDTree&& x ) + { + if ( &x != this ) + { + DestroyTree( m_root ); + m_root = x.m_root; + m_dimension = x.m_dimension; + m_bucketCapacity = x.m_bucketCapacity; + m_length = x.m_length; + x.m_root = nullptr; + x.m_length = 0; + } + return *this; + } + + /*! + * Destroys a K-d tree. All the stored point objects are deleted. + */ + ~KDTree() + { + Clear(); + } + + /*! + * Removes all the stored point objects, yielding an empty K-d tree. + */ + void Clear() + { + DestroyTree( m_root ); + m_root = nullptr; + m_length = 0; + } + + /*! + * Builds a new K-d tree for the specified list of \a points. + * + * \param points A list of points that will be stored in this + * K-d tree. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be >= 1. The default value is 16. + * + * The dimension of the point space is taken as the length of the first + * point in the list (by calling points[0].Length()), and must be > 0. All + * points in the \a points list must be able to provide at least + * \a dimension components through a zero-based array subscript operator. + * + * If the tree stores point objects before calling this function, they are + * destroyed and removed before building a new tree. + * + * If the specified list of \a points is empty, this member function yields + * an empty K-d tree. If the dimension of the point space is less than one, + * an Error exception is thrown. + */ + void Build( const point_list& points, int bucketCapacity = 16 ) + { + Clear(); + m_bucketCapacity = Max( 1, bucketCapacity ); + if ( !points.IsEmpty() ) + { + m_dimension = points[0].Length(); + if ( m_dimension < 1 ) + throw Error( "KDTree::Build(): Invalid point space dimension." ); + m_root = BuildTree( points, 0 ); + } + } + + /*! + * Builds a new K-d tree of the specified \a dimension for a list of + * \a points. + * + * \param points A list of points that will be stored in this + * K-d tree. + * + * \param dimension The dimension of the point space. Must be > 0. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be >= 1. + * + * All points in the \a points list must be able to provide at least + * \a dimension components through a zero-based array subscript operator. + * + * If the tree stores point objects before calling this function, they are + * destroyed and removed before building a new tree. + * + * If the specified list of \a points is empty, this member function yields + * an empty K-d tree. If the dimension of the point space is less than one, + * an Error exception is thrown. + */ + void Build( const point_list& points, int dimension, int bucketCapacity ) + { + Clear(); + m_bucketCapacity = Max( 1, bucketCapacity ); + if ( (m_dimension = dimension) < 1 ) + throw Error( "KDTree::Build(): Invalid point space dimension." ); + m_root = BuildTree( points, 0 ); + } + + /*! + * Performs a range search in this K-d tree. + * + * \param pt Reference to the point being searched for. The coordinates + * of this point define the center of the hyper-rectangular + * search range in the N-dimensional point space. + * + * \param epsilon Search tolerance, or half-side of the search + * hyperrectangle. + * + * Returns a (possibly empty) list with all the points found in the tree + * within the search range. In two dimensions, the search range would be the + * rectangle defined by the points: + * + * (pt[0] - epsilon, pt[1] - epsilon) and \n + * (pt[0] + epsilon, pt[1] + epsilon) + * + * with an obvious extension to higher dimensions. If \a epsilon is zero, + * the search can only return the set of stored points that are identical to + * the specified search point. + */ + point_list Search( const point& pt, component epsilon ) const + { + component_vector p0( m_dimension ); + component_vector p1( m_dimension ); + for ( int i = 0; i < m_dimension; ++i ) + { + p0[i] = pt[i] - epsilon; + p1[i] = pt[i] + epsilon; + } + point_list found; + SearchTree( found, p0, p1, m_root, 0 ); + return found; + } + + /*! + * Performs a range search in this K-d tree. + * + * \param pt Reference to the point being searched for. The + * coordinates of this point define the center of the + * hyper-rectangular search range in the N-dimensional + * point space. + * + * \param epsilon Search tolerance, or half-side of the search + * hyperrectangle. + * + * \param callback Callback functional. + * + * \param data Callback data. + * + * The callback function prototype should be: + * + * \code void callback( const point& pt, void* data ) \endcode + * + * The callback function will be called once for each point found in the + * tree within the specified search range. In two dimensions, the search + * range would be the rectangle defined by the points: + * + * (pt[0] - epsilon, pt[1] - epsilon) and \n + * (pt[0] + epsilon, pt[1] + epsilon) + * + * with an obvious extension to higher dimensions. If \a epsilon is zero, + * the search can only return the set of stored points that are identical to + * the specified search point. + */ + template + void Search( const point& pt, component epsilon, F callback, void* data ) const + { + component_vector p0( m_dimension ); + component_vector p1( m_dimension ); + for ( int i = 0; i < m_dimension; ++i ) + { + p0[i] = pt[i] - epsilon; + p1[i] = pt[i] + epsilon; + } + SearchTree( p0, p1, callback, data, m_root, 0 ); + } + + /*! + * Returns the dimension of this K-d tree. This is the number of components + * in a point stored in the tree. + */ + int Dimension() const + { + return m_dimension; + } + + /*! + * Returns the total number of points stored in this K-d tree. + */ + size_type Length() const + { + return m_length; + } + + /*! + * Returns true iff this K-d tree is empty. + */ + bool IsEmpty() + { + return m_root == nullptr; + } + + /*! + * Exchanges two %KDTree objects \a x1 and \a x2. + */ + friend void Swap( KDTree& x1, KDTree& x2 ) + { + pcl::Swap( x1.m_root, x2.m_root ); + pcl::Swap( x1.m_dimension, x2.m_dimension ); + pcl::Swap( x1.m_bucketCapacity, x2.m_bucketCapacity ); + pcl::Swap( x1.m_length, x2.m_length ); + } + +private: + + struct Node + { + double split = 0; // position of this node's splitting hyperplane + Node* left = nullptr; // child points at coordinates <= split + Node* right = nullptr; // child points at coordinates > split + + Node( double s = 0 ) + : split( s ) + { + } + + bool IsLeaf() const + { + return left == nullptr && right == nullptr; + } + }; + + struct LeafNode : public Node + { + point_list points; + + LeafNode( const point_list& p ) + : points( p ) + { + } + }; + + Node* m_root = nullptr; + int m_dimension = 0; + int m_bucketCapacity = 0; + size_type m_length = 0; + + LeafNode* NewLeafNode( const point_list& points ) + { + m_length += points.Length(); + return new LeafNode( points ); + } + + Node* BuildTree( const point_list& points, int depth ) + { + if ( points.IsEmpty() ) + return nullptr; + + if ( points.Length() <= size_type( m_bucketCapacity ) ) + return NewLeafNode( points ); + + int index = depth % m_dimension; + + Node* node = new Node( SplitValue( points, index ) ); + + point_list left, right; + for ( const point& p : points ) + if ( p[index] <= node->split ) + left.Add( p ); + else + right.Add( p ); + + // If we are about to build a degenerate subtree, abort this branch of + // recursion right now. + if ( left.IsEmpty() || right.IsEmpty() ) + { + delete node; + return NewLeafNode( points ); + } + + node->left = BuildTree( left, depth+1 ); + node->right = BuildTree( right, depth+1 ); + + // Further degeneracies cannot happen in theory, but let's prevent them + // for extra safety. + if ( node->IsLeaf() ) + { + delete node; + return NewLeafNode( points ); + } + + return node; + } + + void SearchTree( point_list& found, const component_vector& p0, const component_vector& p1, const Node* node, int depth ) const + { + if ( node != nullptr ) + if ( node->IsLeaf() ) + { + const LeafNode* leaf = static_cast( node ); + for ( const point& p : leaf->points ) + for ( int j = 0; ; ) + { + component x = p[j]; + if ( x < p0[j] || p1[j] < x ) + break; + if ( ++j == m_dimension ) + { + found.Add( p ); + break; + } + } + } + else + { + int index = depth % m_dimension; + if ( p0[index] <= node->split ) + SearchTree( found, p0, p1, node->left, depth+1 ); + if ( p1[index] > node->split ) + SearchTree( found, p0, p1, node->right, depth+1 ); + } + } + + template + void SearchTree( const component_vector& p0, const component_vector& p1, F callback, void* data, const Node* node, int depth ) const + { + if ( node != nullptr ) + if ( node->IsLeaf() ) + { + const LeafNode* leaf = static_cast( node ); + for ( const point& p : leaf->points ) + for ( int j = 0; ; ) + { + component x = p[j]; + if ( x < p0[j] || p1[j] < x ) + break; + if ( ++j == m_dimension ) + { + callback( p, data ); + break; + } + } + } + else + { + int index = depth % m_dimension; + if ( p0[index] <= node->split ) + SearchTree( p0, p1, callback, data, node->left, depth+1 ); + if ( p1[index] > node->split ) + SearchTree( p0, p1, callback, data, node->right, depth+1 ); + } + } + + void DestroyTree( Node* node ) + { + if ( node != nullptr ) + if ( node->IsLeaf() ) + delete static_cast( node ); + else + { + DestroyTree( node->left ); + DestroyTree( node->right ); + delete node; + } + } + + double SplitValue( const point_list& points, int index ) + { + component_vector v( points.Length() ); + for ( int i = 0; i < v.Length(); ++i ) + v[i] = points[i][index]; + return v.Median(); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_KDTree_h + +// ---------------------------------------------------------------------------- +// EOF pcl/KDTree.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/KernelFilter.h b/3rdparty/include/pcl/KernelFilter.h new file mode 100644 index 0000000..f35a51a --- /dev/null +++ b/3rdparty/include/pcl/KernelFilter.h @@ -0,0 +1,583 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/KernelFilter.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_KernelFilter_h +#define __PCL_KernelFilter_h + +/// \file pcl/KernelFilter.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE 1.0e-06F + +/*! + * \class KernelFilter + * \brief Kernel filter in two dimensions. + * + * %KernelFilter stores a square matrix of floating point filter coefficients + * and an optional filter name. This class provides automatic allocation and + * deallocation of coefficients, implicit data sharing, thread-safe access and + * a number of utility functions for filter management. + * + * %KernelFilter can be used along with a variety of PCL classes, such as + * Convolution and ATrousWaveletTransform. + * + * For separable filters and convolutions, see the SeparableFilter and + * SeparableConvolution PCL classes. + * + * \sa GaussianFilter, VariableShapeFilter, Convolution, ATrousWaveletTransform + */ +class PCL_CLASS KernelFilter +{ +public: + + /*! + * Represents a filter coefficient. + */ + typedef float coefficient; + + /*! + * Represents a filter coefficient matrix. + */ + typedef GenericMatrix coefficient_matrix; + + /*! + * Constructs an empty %KernelFilter object with optional \a name. + */ + KernelFilter( const String& name = String() ) + : filterName( name ) + { + } + + /*! + * Constructs a %KernelFilter object with the specified size \a n and + * optional \a name. Filter elements are not initialized, so they will + * contain unpredictable values. + * + * A %KernelFilter object must be initialized with either a zero size + * (which yields an empty filter), or an odd size >= 3. + */ + KernelFilter( int n, const String& name = String() ) + : coefficients( PCL_VALID_KERNEL_SIZE( n ), PCL_VALID_KERNEL_SIZE( n ) ) + , filterName( name ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + } + + /*! + * Constructs a %KernelFilter object with the specified size \a n, initial + * element value \a x, and optional \a name. + */ + template + KernelFilter( int n, const T& x, const String& name = String() ) + : coefficients( x, PCL_VALID_KERNEL_SIZE( n ), PCL_VALID_KERNEL_SIZE( n ) ) + , filterName( name ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + } + + /*! + * Constructs a %KernelFilter object with the specified filter coefficient + * matrix \a F and optional \a name. + */ + KernelFilter( const coefficient_matrix& F, const String& name = String() ) + : filterName( name ) + { + if ( !F.IsEmpty() && (F.Rows() != F.Cols() || (F.Rows() & 1) == 0) ) + throw Error( "KernelFilter: Invalid coefficient matrix in constructor." ); + coefficients = F; + } + + /*! + * Constructs a %KernelFilter object with the specified size \a n and + * optional \a name. Copies \a nxn filter coefficients from the specified + * static array \a k. + */ + template + KernelFilter( const T* k, int n, const String& name = String() ) + : coefficients( k, PCL_VALID_KERNEL_SIZE( n ), PCL_VALID_KERNEL_SIZE( n ) ) + , filterName( name ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + } + + /*! + * Copy constructor. + */ + KernelFilter( const KernelFilter& ) = default; + + /*! + * Move constructor. + */ + KernelFilter( KernelFilter&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~KernelFilter() + { + } + + /*! + * Returns a pointer to a dynamically allocated duplicate of this kernel + * filter. + * + * \note All derived classes from %KernelFilter must reimplement this + * virtual member function. + */ + virtual KernelFilter* Clone() const + { + return new KernelFilter( *this ); + } + + /*! + * Returns a separable filter equivalent to this kernel filter matrix. + * + * The default implementation computes the singular value decomposition of + * the filter matrix, which yields the separable filter as a couple of row + * and column vectors. Filter separability is then verified by computing the + * resulting filter by matrix multiplication of the separable filter + * components. If the resulting filter differs by more than the specified + * \a tolerance from the original, then the filter is non-separable and an + * empty SeparableFilter object is returned. + * + * For known separable filters, this member function must be reimplemented + * in derived classes to bypass the default (and expensive) separability + * tests. For example, Gaussian filters are separable, so this function is + * conveniently reimplemented by the GaussianFilter class to return a + * separable filter consisting of the central row and column vectors of the + * Gaussian filter matrix representation. + */ + virtual SeparableFilter AsSeparableFilter( float tolerance = __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE ) const; + + /*! + * Returns true iff this filter is separable, + * + * A two-dimensional filter matrix is separable if it can be expressed as + * the product of two vectors. The default implementation of this function + * tries to compute a separable filter by calling AsSeparable(). Then it + * returns true if the computed separable filter is nonempty. + * + * For known separable (and non-separable) filters, this member function + * must be reimplemented in derived classes to bypass the above, expensive + * procedure. + */ + virtual bool IsSeparable() const + { + return !AsSeparableFilter().IsEmpty(); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + KernelFilter& operator =( const KernelFilter& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + KernelFilter& operator =( KernelFilter&& ) = default; + + /*! + * Assigns the specified filter coefficient matrix \a F to this object. + * Returns a reference to this object. + * + * The specified matrix \a F must be either an empty matrix or a square + * matrix of odd size. If these conditions are not met, this member + * function throws an Error exception. + */ + KernelFilter& operator =( const coefficient_matrix& F ) + { + if ( !F.IsEmpty() && (F.Rows() != F.Cols() || (F.Rows() & 1) == 0) ) + throw Error( "KernelFilter: Invalid coefficient matrix assignment." ); + coefficients = F; + flipped = false; + return *this; + } + + /*! + * Assigns the specified scalar \a x to all filter coefficients. Returns a + * reference to this object. + */ + KernelFilter& operator =( const coefficient& x ) + { + coefficients = x; + flipped = false; + return *this; + } + + /*! + * Returns true iff this %KernelFilter object is equal to another instance + * \a f. Two %KernelFilter instances are equal if their name and filter + * coefficients are equal. + */ + bool operator ==( const KernelFilter& f ) const + { + return Name() == f.Name() && SameCoefficients( f ); + } + + /*! + * Returns the name of this %KernelFilter object. + */ + String Name() const + { + return filterName; + } + + /*! + * Sets the name of this %KernelFilter object. + */ + virtual void Rename( const String& newName ) + { + filterName = newName.Trimmed(); + } + + /*! + * Returns the size of this filter kernel. + */ + int Size() const + { + return coefficients.Rows(); // coefficients *must* be a square matrix + } + + /*! + * Sets the size of this filter kernel. Previous filter contents are lost; + * the internal matrix of filter coefficients will contain unpredictable + * values after calling this function. + */ + virtual void Resize( int n ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + if ( n == 0 ) + coefficients = coefficient_matrix(); + else + { + n = PCL_VALID_KERNEL_SIZE( n ); + coefficients = coefficient_matrix( n, n ); + } + flipped = false; + } + + /*! + * Returns true iff this is an empty filter, that is, if it has no filter + * coefficients. + */ + bool IsEmpty() const + { + return coefficients.IsEmpty(); + } + + /*! + * Returns true iff this is a non-empty filter. Equivalent to !IsEmpty(). + */ + operator bool() const + { + return !IsEmpty(); + } + + /*! + * Returns the total number of filter coefficients, or Size()*Size(). + */ + int NumberOfCoefficients() const + { + return coefficients.Rows()*coefficients.Cols(); + } + + /*! + * Returns a copy of the internal matrix of filter coefficients. + */ + coefficient_matrix Coefficients() const + { + return coefficients; + } + + /*! + * Returns a pointer to the beginning of the internal matrix of (immutable) + * filter coefficients. + * + * All filter coefficients are guaranteed to be stored at consecutive + * locations addressable from the pointer returned by this function. Filter + * coefficients are stored in row order (all coefficients of row 0 + * followed by all coefficients of row 1, and so on). + */ + const coefficient* Begin() const + { + return coefficients.Begin(); + } + + /*! + * Returns a pointer to the end of the internal matrix of (immutable) filter + * coefficients. + * + * All filter coefficients are guaranteed to be stored at consecutive + * locations in reverse order, addressable from the pointer returned by this + * function minus one. Filter coefficients are stored in + * row order (all coefficients of row 0 followed by all + * coefficients of row 1, etc.). + */ + const coefficient* End() const + { + return coefficients.End(); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const coefficient* begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const coefficient* end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Subscript operator. Returns a pointer to the first (immutable) filter + * coefficient of the specified \a row in this filter. \a row must be a + * valid vertical index: it must be 0 <= \a row < Size(). + */ + const coefficient* operator[]( int row ) const + { + return coefficients[row]; + } + + /*! + * Returns the \e weight of this kernel filter. The weight is equal to the + * sum of all filter coefficients. + */ + double Weight() const + { + return coefficients.Sum(); + } + + /*! + * Returns the sum of the absolute values of all filter coefficients. + */ + double Modulus() const + { + return coefficients.Modulus(); + } + + /*! + * Normalizes filter coefficients. Divides each filter coefficient by the + * result of the Modulus() member function. If Modulus() is zero or + * insignificant this function does nothing. + */ + void Normalize() + { + double m = Modulus(); + if ( 1 + m != 1 ) + coefficients /= m; + } + + /*! + * Returns the normalization of this kernel filter. This member function + * creates a new %KernelFilter instance as a copy of this object, normalizes + * it, and returns it. + */ + KernelFilter Normalized() const + { + KernelFilter f( *this ); + f.Normalize(); + return f; + } + + /*! + * Flips this kernel filter. Flipping a filter consists of rotating its + * coefficients by 180 degrees. + */ + void Flip() + { + coefficients.Flip(); + flipped = !flipped; + } + + /*! + * Returns a flipped copy of this filter. Flipping a filter consists of + * rotating its coefficients by 180 degrees. + */ + KernelFilter Flipped() const + { + KernelFilter f( *this ); + f.Flip(); + return f; + } + + /*! + * Returns true iff this kernel filter has been flipped (rotated by 180 + * degrees). Note that after an even number of successive flippings (which + * is a no-op) this member function will return false. + */ + bool IsFlipped() const + { + return flipped; + } + + /*! + * Returns true if this is a high-pass kernel filter; false if this is a + * low-pass kernel filter. + * + * A high-pass kernel filter has one or more negative coefficients. A + * low-pass kernel filter is either empty or all of its coefficients are + * positive or zero. + */ + bool IsHighPassFilter() const + { + const coefficient* a = coefficients.Begin(); + const coefficient* b = coefficients.End(); + //while ( a < b ) + // if ( *a++ < 0 || *--b < 0 ) + // The above loop is better for nonsymmetrical filters, which are seldom used. + while ( a < b ) + if ( *a++ < 0 ) + return true; + return false; + } + + /*! + * Returns true iff this %KernelFilter object has the same coefficients as + * other instance \a f. + */ + bool SameCoefficients( const KernelFilter& f ) const + { + return coefficients.SameElements( f.coefficients ); + } + + /*! + * Deallocates filter coefficients and yields an empy %KernelFilter object. + * Note that this member function does not change the current filter name. + */ + virtual void Clear() + { + coefficients = coefficient_matrix(); + flipped = false; + } + +#ifndef __PCL_NO_MATRIX_IMAGE_RENDERING + + /*! + * Renders this filter as an image. The contents of the specified target + * \a image will be replaced with a grayscale rendition of this filter, + * where each image pixel has a value proportional to its corresponding + * filter coefficient counterpart. + * + * Note that if this filter has out-of-range values for the pixel sample + * type of the target image, pixel saturation will occur at either the white + * or black points, or at both. This only happens when the target image is + * of an integer type and this filter contains floating point values outside + * the normalized [0,1] range. + * + * If the target image is of a floating-point type (either real or complex), + * it may require a rescaling or normalization operation to constrain all + * pixel values to the normalized [0,1] range after calling this function. + */ + template + void ToImage( GenericImage

& image ) const + { + coefficients.ToImage( image ); + } + + /*! + * Renders this filter as an image. The contents of the image transported by + * the specified %ImageVariant object \a v will be replaced with a grayscale + * rendition of this filter, where each image pixel has a value proportional + * to its corresponding filter coefficient counterpart. + * + * If the %ImageVariant object \a v does not transport an image, a new one + * is created in 32-bit floating point format. + * + * Also take into account the information given for + * ToImage( GenericImage

& ), relative to out-of-range values, which is + * entirely applicable to this member function. + */ + void ToImage( ImageVariant& v ) const + { + coefficients.ToImage( v ); + } + +#endif // !__PCL_NO_MATRIX_IMAGE_RENDERING + +protected: + + coefficient_matrix coefficients; // filter coefficients, size*size elements + String filterName; // identifying name + bool flipped = false; // flag true when filter rotated +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_KernelFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/KernelFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/KeyCodes.h b/3rdparty/include/pcl/KeyCodes.h new file mode 100644 index 0000000..6576c64 --- /dev/null +++ b/3rdparty/include/pcl/KeyCodes.h @@ -0,0 +1,481 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/KeyCodes.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_KeyCodes_h +#define __PCL_KeyCodes_h + +/// \file pcl/KeyCodes.h + +#include + +#ifndef __PCL_NO_KEY_QUERY_UTILITIES +# ifdef __PCL_WINDOWS +# include // for virtual key codes +# endif +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::KeyCode + * \brief Defines PCL key codes. + * + * The %KeyCode namespace defines platform-independent keyboard key identifiers + * on the PixInsight/PCL framework. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
KeyCode::Backspace 0x00000008
KeyCode::Tab 0x00000009
KeyCode::Clear 0x0000000c
KeyCode::Return 0x0000000d
KeyCode::Enter 0x0000000d
KeyCode::Escape 0x0000001b
KeyCode::Shift 0x70000001
KeyCode::Control 0x70000002
KeyCode::Alt 0x70000003
KeyCode::Meta 0x70000004
KeyCode::CapsLock 0x70000010
KeyCode::NumLock 0x70000020
KeyCode::ScrollLock 0x70000030
KeyCode::Pause 0x70000100
KeyCode::Print 0x70000200
KeyCode::Help 0x70000300
KeyCode::SysReq 0x70000400
KeyCode::Left 0x10000001
KeyCode::Up 0x10000002
KeyCode::Right 0x10000003
KeyCode::Down 0x10000004
KeyCode::Insert 0x10000010
KeyCode::Delete 0x10000020
KeyCode::Home 0x10000100
KeyCode::End 0x10000200
KeyCode::PageUp 0x10000300
KeyCode::PageDown 0x10000400
KeyCode::F1 0x08000001
KeyCode::F2 0x08000002
KeyCode::F3 0x08000003
KeyCode::F4 0x08000004
KeyCode::F5 0x08000005
KeyCode::F6 0x08000006
KeyCode::F7 0x08000007
KeyCode::F8 0x08000008
KeyCode::F9 0x08000009
KeyCode::F10 0x0800000a
KeyCode::F11 0x0800000b
KeyCode::F12 0x0800000c
KeyCode::F13 0x0800000d
KeyCode::F14 0x0800000e
KeyCode::F15 0x0800000f
KeyCode::F16 0x08000010
KeyCode::F17 0x08000020
KeyCode::F18 0x08000030
KeyCode::F19 0x08000040
KeyCode::F20 0x08000050
KeyCode::F21 0x08000060
KeyCode::F22 0x08000070
KeyCode::F23 0x08000080
KeyCode::F24 0x08000090
KeyCode::Space 0x00000020
KeyCode::Exclamation 0x00000021
KeyCode::DoubleQuote 0x00000022
KeyCode::NumberSign 0x00000023
KeyCode::Dollar 0x00000024
KeyCode::Percent 0x00000025
KeyCode::Ampersand 0x00000026
KeyCode::Apostrophe 0x00000027
KeyCode::LeftParenthesis 0x00000028
KeyCode::RightParenthesis 0x00000029
KeyCode::Asterisk 0x0000002a
KeyCode::Plus 0x0000002b
KeyCode::Comma 0x0000002c
KeyCode::Minus 0x0000002d
KeyCode::Period 0x0000002e
KeyCode::Slash 0x0000002f
KeyCode::Zero 0x00000030
KeyCode::One 0x00000031
KeyCode::Two 0x00000032
KeyCode::Three 0x00000033
KeyCode::Four 0x00000034
KeyCode::Five 0x00000035
KeyCode::Six 0x00000036
KeyCode::Seven 0x00000037
KeyCode::Eight 0x00000038
KeyCode::Nine 0x00000039
KeyCode::Colon 0x0000003a
KeyCode::Semicolon 0x0000003b
KeyCode::Less 0x0000003c
KeyCode::Equal 0x0000003d
KeyCode::Greater 0x0000003e
KeyCode::Question 0x0000003f
KeyCode::At 0x00000040
KeyCode::A 0x00000041
KeyCode::B 0x00000042
KeyCode::C 0x00000043
KeyCode::D 0x00000044
KeyCode::E 0x00000045
KeyCode::F 0x00000046
KeyCode::G 0x00000047
KeyCode::H 0x00000048
KeyCode::I 0x00000049
KeyCode::J 0x0000004a
KeyCode::K 0x0000004b
KeyCode::L 0x0000004c
KeyCode::M 0x0000004d
KeyCode::N 0x0000004e
KeyCode::O 0x0000004f
KeyCode::P 0x00000050
KeyCode::Q 0x00000051
KeyCode::R 0x00000052
KeyCode::S 0x00000053
KeyCode::T 0x00000054
KeyCode::U 0x00000055
KeyCode::V 0x00000056
KeyCode::W 0x00000057
KeyCode::X 0x00000058
KeyCode::Y 0x00000059
KeyCode::Z 0x0000005a
KeyCode::LeftBracket 0x0000005b
KeyCode::Backslash 0x0000005c
KeyCode::RightBracket 0x0000005d
KeyCode::Circumflex 0x0000005e
KeyCode::Underscore 0x0000005f
KeyCode::LeftQuote 0x00000060
KeyCode::LeftBrace 0x0000007b
KeyCode::Bar 0x0000007c
KeyCode::RightBrace 0x0000007d
KeyCode::Tilde 0x0000007e
KeyCode::Unknown 0x7fffffff
+ */ +namespace KeyCode +{ + enum value_type + { + Backspace = 0x00000008, + Tab = 0x00000009, + Clear = 0x0000000c, + Return = 0x0000000d, + Enter = 0x0000000d, + Escape = 0x0000001b, + Shift = 0x70000001, + Control = 0x70000002, + Alt = 0x70000003, + Meta = 0x70000004, + CapsLock = 0x70000010, + NumLock = 0x70000020, + ScrollLock = 0x70000030, + Pause = 0x70000100, + Print = 0x70000200, + Help = 0x70000300, + SysReq = 0x70000400, + Left = 0x10000001, + Up = 0x10000002, + Right = 0x10000003, + Down = 0x10000004, + Insert = 0x10000010, + Delete = 0x10000020, + Home = 0x10000100, + End = 0x10000200, + PageUp = 0x10000300, + PageDown = 0x10000400, + F1 = 0x08000001, + F2 = 0x08000002, + F3 = 0x08000003, + F4 = 0x08000004, + F5 = 0x08000005, + F6 = 0x08000006, + F7 = 0x08000007, + F8 = 0x08000008, + F9 = 0x08000009, + F10 = 0x0800000a, + F11 = 0x0800000b, + F12 = 0x0800000c, + F13 = 0x0800000d, + F14 = 0x0800000e, + F15 = 0x0800000f, + F16 = 0x08000010, + F17 = 0x08000020, + F18 = 0x08000030, + F19 = 0x08000040, + F20 = 0x08000050, + F21 = 0x08000060, + F22 = 0x08000070, + F23 = 0x08000080, + F24 = 0x08000090, + Space = 0x00000020, + Exclamation = 0x00000021, + DoubleQuote = 0x00000022, + NumberSign = 0x00000023, + Dollar = 0x00000024, + Percent = 0x00000025, + Ampersand = 0x00000026, + Apostrophe = 0x00000027, + LeftParenthesis = 0x00000028, + RightParenthesis = 0x00000029, + Asterisk = 0x0000002a, + Plus = 0x0000002b, + Comma = 0x0000002c, + Minus = 0x0000002d, + Period = 0x0000002e, + Slash = 0x0000002f, + Zero = 0x00000030, + One = 0x00000031, + Two = 0x00000032, + Three = 0x00000033, + Four = 0x00000034, + Five = 0x00000035, + Six = 0x00000036, + Seven = 0x00000037, + Eight = 0x00000038, + Nine = 0x00000039, + Colon = 0x0000003a, + Semicolon = 0x0000003b, + Less = 0x0000003c, + Equal = 0x0000003d, + Greater = 0x0000003e, + Question = 0x0000003f, + At = 0x00000040, + A = 0x00000041, + B = 0x00000042, + C = 0x00000043, + D = 0x00000044, + E = 0x00000045, + F = 0x00000046, + G = 0x00000047, + H = 0x00000048, + I = 0x00000049, + J = 0x0000004a, + K = 0x0000004b, + L = 0x0000004c, + M = 0x0000004d, + N = 0x0000004e, + O = 0x0000004f, + P = 0x00000050, + Q = 0x00000051, + R = 0x00000052, + S = 0x00000053, + T = 0x00000054, + U = 0x00000055, + V = 0x00000056, + W = 0x00000057, + X = 0x00000058, + Y = 0x00000059, + Z = 0x0000005a, + LeftBracket = 0x0000005b, + Backslash = 0x0000005c, + RightBracket = 0x0000005d, + Circumflex = 0x0000005e, + Underscore = 0x0000005f, + LeftQuote = 0x00000060, + LeftBrace = 0x0000007b, + Bar = 0x0000007c, + RightBrace = 0x0000007d, + Tilde = 0x0000007e, + + Unknown = 0x7fffffff + }; +} + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +/*! + * \defgroup keyboard_utilities Keyboard Utilities + */ + +/*! + * Returns true iff the specified keyboard key is currently pressed. + * + * The \a key1 and (optional) \a key2 parameters are platform-dependent + * keyboard scan codes or virtual key identifiers. + * + * \ingroup keyboard_utilities + */ +bool IsKeyPressed( int key1, int key2 = 0 ); // implemented in pcl/Keyboard.cpp + +#ifndef __PCL_NO_KEY_QUERY_UTILITIES + +/*! + * Returns true iff the Space Bar key is currently pressed. + * \ingroup keyboard_utilities + */ +inline bool IsSpaceBarPressed() +{ + return IsKeyPressed( +#if defined( __PCL_X11 ) + 65 +#endif +#if defined( __PCL_MACOSX ) + 0x31 // kVK_Space +#endif +#if defined( __PCL_WINDOWS ) + VK_SPACE +#endif + ); +} + +/*! + * Returns true iff a Control key (also known as Meta key on Mac OS X) is + * currently pressed. + * \ingroup keyboard_utilities + */ +inline bool IsControlPressed() +{ + return IsKeyPressed( +#if defined( __PCL_X11 ) + 37, 109 +#endif +#if defined( __PCL_MACOSX ) + 0x3B // kVK_Control +#endif +#if defined( __PCL_WINDOWS ) + VK_CONTROL +#endif + ); +} + +/*! + * Returns true iff a Shift key is currently pressed. + * \ingroup keyboard_utilities + */ +inline bool IsShiftPressed() +{ + return IsKeyPressed( +#if defined( __PCL_X11 ) + 50, 62 +#endif +#if defined( __PCL_MACOSX ) + 0x38 // kVK_Shift +#endif +#if defined( __PCL_WINDOWS ) + VK_SHIFT +#endif + ); +} + +/*! + * Returns true iff an Alt key (also known as Option key on Mac OS X) is + * currently pressed. + * \ingroup keyboard_utilities + */ +inline bool IsAltPressed() +{ + return IsKeyPressed( +#if defined( __PCL_X11 ) + 64, 113 +#endif +#if defined( __PCL_MACOSX ) + 0x3A // kVK_Option +#endif +#if defined( __PCL_WINDOWS ) + VK_MENU +#endif + ); +} + +#if defined( __PCL_MACOSX ) + +/*! + * Returns true iff the Command key (Mac keyboard only) is currently pressed. + * + * \note This function is only defined on Mac OS X. + * \ingroup keyboard_utilities + */ +inline bool IsCmdPressed() +{ + return IsKeyPressed( 0x37 ); // kVK_Command +} + +/*! + * Returns true iff the Meta key is currently pressed on the Mac keyboard. + * + * This function is a convenient alias for IsControlPressed(), only available + * on Mac OS X. + * + * \ingroup keyboard_utilities + */ +inline bool IsMetaPressed() +{ + return IsControlPressed(); +} + +#endif // __PCL_MACOSX + +/*! + * On UNIX, Linux and Windows platforms, returns true iff a Control key is + * currently pressed. On macOS, returns true iff the Command key is currently + * pressed. + * + * \ingroup keyboard_utilities + */ +inline bool IsControlOrCmdPressed() +{ +#if defined( __PCL_MACOSX ) + return IsCmdPressed(); +#else + return IsControlPressed(); +#endif +} + +#endif // !__PCL_NO_KEY_QUERY_UTILITIES + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_KeyCodes_h + +// ---------------------------------------------------------------------------- +// EOF pcl/KeyCodes.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/KeyValue.h b/3rdparty/include/pcl/KeyValue.h new file mode 100644 index 0000000..ae220bc --- /dev/null +++ b/3rdparty/include/pcl/KeyValue.h @@ -0,0 +1,184 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/KeyValue.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_KeyValue_h +#define __PCL_KeyValue_h + +/// \file pcl/KeyValue.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class KeyValue + * \brief Generic key-value association. + */ +template +class PCL_CLASS KeyValue +{ +public: + + T1 key; //!< The key member of this key-value association + T2 value; //!< The value member of this key-value association + + /*! + * Constructs a key-value association with default key and value members. + */ + KeyValue() + : key() + , value() + { + } + + /*! + * Constructs a key-value association with the specified key and value. + */ + KeyValue( const T1& k, const T2& v ) + : key( k ) + , value( v ) + { + } + + /*! + * Constructs a key-value association with the specified key and a + * default-constructed value. + */ + KeyValue( const T1& k ) + : key( k ) + , value() + { + } + + /*! + * Copy constructor. + */ + KeyValue( const KeyValue& ) = default; + + /*! + * Move constructor. + */ + KeyValue( KeyValue&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + KeyValue& operator =( const KeyValue& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + KeyValue& operator =( KeyValue&& ) = default; + + /*! + * Returns true iff this key-value association is equal to another object + * \a x. key-value associations are equal if their respective key and value + * members are equal. + */ + bool operator ==( const KeyValue& x ) const + { + return key == x.key && value == x.value; + } + + /*! + * Returns true iff this key-value association precedes another object \a x. + * In key-value comparisons, key members have precedence over value members. + * The comparison algorithm is as follows: + * + * \code + * if ( this->key != x.key ) + * return this->key < x.key; + * else + * return this->value < x.value; + * \endcode + * + * The implementation of this operator only requires less than + * semantics for the two types T1 and T2; it doesn't use equality operators. + */ + bool operator <( const KeyValue& x ) const + { + return (key < x.key) ? true : ((x.key < key) ? false : value < x.value); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup string_key_value_associations String Key-Value Associations + */ + +/*! + * \class pcl::StringKeyValue + * \ingroup string_key_value_associations + * \brief Key-value association of two Unicode (UTF-16) strings. + */ +typedef KeyValue StringKeyValue; + +/*! + * \class pcl::IsoStringKeyValue + * \ingroup string_key_value_associations + * \brief Key-value association of two 8-bit strings. + */ +typedef KeyValue IsoStringKeyValue; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_KeyValue_h + +// ---------------------------------------------------------------------------- +// EOF pcl/KeyValue.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Label.h b/3rdparty/include/pcl/Label.h new file mode 100644 index 0000000..0a9d6da --- /dev/null +++ b/3rdparty/include/pcl/Label.h @@ -0,0 +1,170 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Label.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_Label_h +#define __PCL_Label_h + +/// \file pcl/Label.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Label + * \brief Client-side interface to a PixInsight %Label control. + * + * ### TODO: Write a detailed description for %Label. + */ +class PCL_CLASS Label : public Frame +{ +public: + + /*! + * Constructs a %Label object with the specified \a text, as a child control + * of \a parent. + */ + Label( const String& text = String(), Control& parent = Control::Null() ); + + /*! + * Destroys a %Label object. + */ + virtual ~Label() + { + } + + /*! # + */ + String Text() const; + + /*! # + */ + void SetText( const String& ); + + /*! # + */ + void Clear() + { + SetText( String() ); + } + + /*! # + */ + int Margin() const; + + /*! # + */ + void SetMargin( int ); + + /*! # + */ + void ClearMargin() + { + SetMargin( 0 ); + } + + /*! # + */ + int TextAlignment() const; + + /*! # + */ + void SetTextAlignment( int ); + + /*! # + */ + bool IsWordWrappingEnabled() const; + + /*! # + */ + void EnableWordWrapping( bool = true ); + + /*! # + */ + void DisableWordWrapping( bool disable = true ) + { + EnableWordWrapping( !disable ); + } + + /*! # + */ + bool IsRichTextEnabled() const; + + /*! # + */ + void EnableRichText( bool = true ); + + /*! # + */ + void DisableRichText( bool disable = true ) + { + EnableRichText( !disable ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Label_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Label.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/LanczosInterpolation.h b/3rdparty/include/pcl/LanczosInterpolation.h new file mode 100644 index 0000000..6fd1a18 --- /dev/null +++ b/3rdparty/include/pcl/LanczosInterpolation.h @@ -0,0 +1,976 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/LanczosInterpolation.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_LanczosInterpolation_h +#define __PCL_LanczosInterpolation_h + +/// \file pcl/LanczosInterpolation.h + +#include +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_width this->m_width +#define m_height this->m_height +#define m_fillBorder this->m_fillBorder +#define m_fillValue this->m_fillValue +#define m_data this->m_data + +// ---------------------------------------------------------------------------- + +/* + * Default clamping threshold for Lanczos interpolation. This value has been + * selected as the best trade-off for a large set of test linear images. + */ +#ifndef __PCL_LANCZOS_CLAMPING_THRESHOLD +#define __PCL_LANCZOS_CLAMPING_THRESHOLD 0.3F +#endif + +// ---------------------------------------------------------------------------- + +/* + * Floating point and integer LUT-based interpolations for 3rd, 4th and 5th + * order Lanczos functions. LUTs are initialized automatically on-demand by + * thread-safe internal routines. + * + * Real Lanczos LUTs are accurate to +/- 1e-7 DN + * Integer Lanczos LUTs are accurate to +/- 1 16-bit DN + */ +#define __PCL_LANCZOS_LUT_REAL_RESOLUTION 4096 +const double** PCL_FUNC PCL_InitializeLanczosRealLUT( int ); +#define __PCL_LANCZOS_LUT_INT_RESOLUTION 65535 +const float* PCL_FUNC PCL_InitializeLanczosIntLUT( int ); + +// ---------------------------------------------------------------------------- + +#define PCL_LANCZOS_ACC() \ + if ( s < 0 ) \ + sn -= s, wn -= L; \ + else \ + sp += s, wp += L; + +/*! + * \class LanczosInterpolation + * \brief Two dimensional Lanczos interpolation algorithm. + * + * This class uses Lanczos filters to interpolate pixel values at arbitrary + * coordinates within a two-dimensional data matrix. A one-dimensional Lanczos + * filter of order \e n is defined by the following equations: + * + *

+ * L(x;n) = sinc(x)*sinc(x/n)    for |x| < n
+ * L(x;n) = 0                    for |x| >= n
+ * 
+ * + * where sinc() is the normalized sinc function: + * + *
+ * sinc(x;n) = 1                 for x = 0
+ * sinc(x;n) = sin(pi*x)/(pi*x)  for x != 0
+ * 
+ * + * The Lanczos function has alternating positive and negative lobes toward + * positive and negative infinity. The order \e n defines the number of lobes + * preserved in the interpolation filter function: n=1 only includes the + * central, positive lobe; n=2 includes the first two lobes (one positive and + * one negative), and so on. The default filter order is three. + * + * Lanczos interpolation has excellent detail preservation performance with + * minimal generation of aliasing patterns for noisy data. Its main drawback is + * generation of strong undershoot (aka ringing) artifacts when negative + * function lobes fall over bright pixels and edges. This usually happens with + * linear data. In the current PCL implementation we have included a clamping + * mechanism that prevents negative interpolated values and ringing problems + * for most images. + * + * \sa BidimensionalInterpolation, NearestNeighborInterpolation, + * BilinearInterpolation, BicubicSplineInterpolation, + * BicubicBSplineInterpolation, BicubicFilterInterpolation, + * Lanczos3LUTInterpolation, Lanczos4LUTInterpolation, Lanczos5LUTInterpolation + */ +template +class PCL_CLASS LanczosInterpolation : public BidimensionalInterpolation +{ +private: + + struct Default + { + template static bool UseLUT( _T* ) { return false; } + static bool UseLUT( uint8* ) { return true; } + static bool UseLUT( int8* ) { return true; } + static bool UseLUT( uint16* ) { return true; } + static bool UseLUT( int16* ) { return true; } + static bool UseLUT( float* ) { return true; } + }; + +public: + + /*! + * Constructs a %LanczosInterpolation instance. + * + * \param n Filter order (n >= 1). The Lanczos filter interpolates + * from the nearest (2*n)^2 mapped source pixels for each + * interpolation point. The default filter order is 3, so the + * interpolation uses a neighborhood of 36 pixels by default. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggressive deringing effect is + * achieved. A negative threshold value disables the clamping + * feature. The default value is 0.3. For more information, + * refer to the documentation for the + * SetClampingThreshold( float ) member function. + * + * \param useLUT If true, the interpolation will use a precomputed LUT of + * function values at discrete intervals. This greatly + * improves performance, increasing execution speed by about + * a factor of 2. In current PCL versions, the Lanczos + * functions are sampled at 0.00025 px resolution, which + * provides an interpolation accuracy of about 1.0e-07. This + * is valid for interpolation of 32-bit floating point data, + * but can be insufficient for 32-bit integers and double + * precision, depending on the application. If this parameter + * is false, the interpolation will compute actual function + * values for each interpolation point. This parameter is + * true by default for the uint8, int8, uint16, int16, and + * float template specializations; false by default for other + * types. + */ + LanczosInterpolation( int n = 3, float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD, bool useLUT = Default::UseLUT( (T*)0 ) ) + : m_n( Max( 1, n ) ) + , m_lut( useLUT ? PCL_InitializeLanczosRealLUT( m_n ) : nullptr ) + , m_Lx( 2*m_n ) + , m_clampTh( Range( clamp, 0.0F, 1.0F ) ) + , m_clampThInv( 1 - m_clampTh ) + , m_clamp( clamp >= 0 ) + { + PCL_PRECONDITION( n >= 1 ) + PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + LanczosInterpolation( const LanczosInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~LanczosInterpolation() + { + } + + /*! + * Interpolated value at \a {x,y} location. + * + * \param x,y %Coordinates of the interpolation point (horizontal, + * vertical). + */ + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + PCL_PRECONDITION( x >= 0 && x < m_width ) + PCL_PRECONDITION( y >= 0 && y < m_height ) + PCL_CHECK( m_n >= 1 ) + + // Central grid coordinates + int x0 = Range( TruncInt( x ), 0, m_width-1 ); + int y0 = Range( TruncInt( y ), 0, m_height-1 ); + + double sp = 0; // positive filter values + double sn = 0; // negative filter values + double wp = 0; // positive filter weight + double wn = 0; // negative filter weight + int i; // row index + + if ( m_lut != nullptr ) + { + // Discrete interpolation increments + int dx = TruncInt( __PCL_LANCZOS_LUT_REAL_RESOLUTION*(x - x0) ); + int dy = TruncInt( __PCL_LANCZOS_LUT_REAL_RESOLUTION*(y - y0) ); + + // Precalculate horizontal filter values + for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + m_Lx[k] = m_lut[k][dx]; + + int k; // LUT node index + + // Clipped rows at top + for ( i = -m_n + 1, k = 0; i <= m_n; ++i, ++k ) + { + int y = y0 + i; + if ( y >= 0 ) + break; + if ( m_fillBorder ) + FillRow( sp, sn, wp, wn, m_lut[k][dy] ); + else + InterpolateRow( sp, sn, wp, wn, m_data - 2*int64( y )*m_width, x0, m_lut[k][dy] ); + } + + // Unclipped rows + for ( ; i <= m_n; ++i, ++k ) + { + int y = y0 + i; + if ( y == m_height ) + break; + InterpolateRow( sp, sn, wp, wn, m_data + int64( y )*m_width, x0, m_lut[k][dy] ); + } + + // Clipped rows at bottom + for ( ; i <= m_n; ++i, ++k ) + { + if ( m_fillBorder ) + FillRow( sp, sn, wp, wn, m_lut[k][dy] ); + else + InterpolateRow( sp, sn, wp, wn, m_data + int64( 2*m_height - 2 - y0 - i )*m_width, x0, m_lut[k][dy] ); + } + } + else + { + // Interpolation increments + double dx = x - x0; + double dy = y - y0; + + // Precalculate horizontal filter values + for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + m_Lx[k] = Lanczos( j - dx ); + + // Clipped rows at top + for ( i = -m_n + 1; i <= m_n; ++i ) + { + int y = y0 + i; + if ( y >= 0 ) + break; + if ( m_fillBorder ) + FillRow( sp, sn, wp, wn, Lanczos( i - dy ) ); + else + InterpolateRow( sp, sn, wp, wn, m_data - 2*int64( y )*m_width, x0, Lanczos( i - dy ) ); + } + + // Unclipped rows + for ( ; i <= m_n; ++i ) + { + int y = y0 + i; + if ( y == m_height ) + break; + InterpolateRow( sp, sn, wp, wn, m_data + int64( y )*m_width, x0, Lanczos( i - dy ) ); + } + + // Clipped rows at bottom + for ( ; i <= m_n; ++i ) + { + if ( m_fillBorder ) + FillRow( sp, sn, wp, wn, Lanczos( i - dy ) ); + else + InterpolateRow( sp, sn, wp, wn, m_data + int64( 2*m_height - 2 - y0 - i )*m_width, x0, Lanczos( i - dy ) ); + } + } + + // Clamping + if ( m_clamp ) + { + // Empty data? + if ( sp == 0 ) + return 0; + + // Clamping ratio: s-/s+ + double r = sn/sp; + + // Clamp for s- >= s+ + if ( r >= 1 ) + return sp/wp; + + // Clamp for c < s- < s+ + if ( r > m_clampTh ) + { + r = (r - m_clampTh)/m_clampThInv; + double c = 1 - r*r; + sn *= c, wn *= c; + } + } + + // Weighted convolution + return (sp - sn)/(wp - wn); + } + + /*! + * Returns true iff the interpolation clamping feature has been enabled for + * this object. + * + * \sa EnableClamping(), ClampingThreshold() + */ + bool IsClampingEnabled() const noexcept + { + return m_clamp; + } + + /*! + * Enables (or disables) the interpolation clamping feature. + * + * \sa IsClampingEnabled(), DisableClamping(), SetClampingThreshold() + */ + void EnableClamping( bool enable = true ) noexcept + { + m_clamp = enable; + } + + /*! + * Disables (or enables) the interpolation clamping feature. + * + * \sa IsClampingEnabled(), EnableClamping(), SetClampingThreshold() + */ + void DisableClamping( bool disable = true ) noexcept + { + EnableClamping( !disable ); + } + + /*! + * Returns the current clamping threshold for this object. + * + * See the documentation for SetClampingThreshold( float ) for a detailed + * description of the clamping mechanism. + * + * \sa SetClampingThreshold(), IsClampingEnabled(), EnableClamping() + */ + float ClampingThreshold() const noexcept + { + return m_clampTh; + } + + /*! + * Defines a threshold to trigger interpolation \e clamping. + * + * Lanczos interpolation generates strong undershoot (aka ringing) artifacts + * when the negative lobes of the interpolation function fall over bright + * isolated pixels or edges. The clamping mechanism acts by limiting the + * high-pass component of the interpolation filter selectively to fix these + * problems. + * + * The specified clamping threshold \e clamp must be in the [0,1] range. + * Lower values cause a more aggressive deringing effect. Too strong of a + * clamping threshold can degrade performance of the Lanczos filter to some + * degree, since it tends to block its high-pass behavior. + * + * \note The interpolation clamping feature must be enabled for this + * threshold to have any effect. See the constructor for this class and the + * documentation for IsClampingEnabled(). + * + * \sa ClampingThreshold(), IsClampingEnabled(), EnableClamping() + */ + void SetClampingThreshold( float clamp ) noexcept + { + PCL_PRECONDITION( 0 <= clamp && clamp <= 1 ) + m_clampTh = Range( clamp, 0.0F, 1.0F ); + } + +private: + + int m_n; // filter order + const double** m_lut; // precomputed function values + mutable DVector m_Lx; // precalculated row of function values + double m_clampTh; // clamping threshold in [0,1] + double m_clampThInv; // 1 - m_clampTh + bool m_clamp; // clamping enabled ? + + /* + * Sinc function for x > 0 + */ + static double Sinc( double x ) noexcept + { + x *= Const::pi(); + return (x > 1.0e-07) ? Sin( x )/x : 1.0; + } + + /* + * Evaluate Lanczos function at x. + */ + double Lanczos( double x ) const noexcept + { + if ( x < 0 ) + x = -x; + if ( x < m_n ) + return Sinc( x ) * Sinc( x/m_n ); + return 0; + } + + /* + * Interpolate a row of pixels. + * Can be either an unclipped row or a mirrored border row. + */ + void InterpolateRow( double& sp, double& sn, double& wp, double& wn, const T* f, int x0, double Ly ) const noexcept + { + int j, k; + + // Clipped pixels at the left border + for ( j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + { + int x = x0 + j; + if ( x >= 0 ) + break; + double L = m_Lx[k] * Ly; + double s = (m_fillBorder ? m_fillValue : double( f[-x] )) * L; + PCL_LANCZOS_ACC() + } + + // Unclipped pixels + for ( ; j <= m_n; ++j, ++k ) + { + int x = x0 + j; + if ( x == m_width ) + break; + double L = m_Lx[k] * Ly; + double s = f[x] * L; + PCL_LANCZOS_ACC() + } + + // Clipped pixels at the right border + for ( ; j <= m_n; ++j, ++k ) + { + int x = x0 + j; + double L = m_Lx[k] * Ly; + double s = (m_fillBorder ? m_fillValue : double( f[2*m_width - 2 - x] )) * L; + PCL_LANCZOS_ACC() + } + } + + /* + * Interpolate a clipped pixel row with border filling. + */ + void FillRow( double& sp, double& sn, double& wp, double& wn, double Ly ) const noexcept + { + for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + { + double L = m_Lx[k] * Ly; + double s = m_fillValue * L; + PCL_LANCZOS_ACC() + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \internal + * \class LanczosLUTInterpolationBase + * \brief Base class of two dimensional LUT-based Lanczos interpolation algorithms. + * + * This is the base class for fixed-order Lanczos interpolation algorithms + * implemented through precalculated look-up tables (LUTs). The filter order + * \a n is specified as the second template class argument. For a description + * of the Lanczos algorithm and information on its performance and features, + * refer to the documentation for the LanczosInterpolation class. + * + * LUT-based Lanczos interpolations are about three times faster than the + * corresponding function evaluation interpolations. Interpolation from the + * implemented LUTs provides a maximum error of +/- 1/2^16, so this class and + * its derived classes are fully accurate for 8-bit and 16-bit integer images. + * + * \sa BidimensionalInterpolation, LanczosInterpolation, + * Lanczos3LUTInterpolation, Lanczos4LUTInterpolation, Lanczos5LUTInterpolation + */ +template +class PCL_CLASS LanczosLUTInterpolationBase : public BidimensionalInterpolation +{ +public: + + /*! + * Constructs a %LanczosLUTInterpolationBase instance. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggressive deringing effect is + * achieved. A negative threshold value disables the clamping + * feature. The default value is 0.3. For more information, + * refer to the documentation for the + * SetClampingThreshold( float ) member function. + */ + LanczosLUTInterpolationBase( float clamp ) + : m_lut( PCL_InitializeLanczosIntLUT( m_n ) ) + , m_Lx( 2*m_n ) + , m_Ly( 2*m_n ) + , m_clampTh( Range( clamp, 0.0F, 1.0F ) ) + , m_clampThInv( 1 - m_clampTh ) + , m_clamp( clamp >= 0 ) + { + PCL_PRECONDITION( m_n >= 1 ) + PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 ) + PCL_CHECK( m_lut != nullptr ) + } + + /*! + * Copy constructor. + */ + LanczosLUTInterpolationBase( const LanczosLUTInterpolationBase& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~LanczosLUTInterpolationBase() + { + } + + /*! + * Interpolated value at \a {x,y} location. + * + * \param x,y %Coordinates of the interpolation point (horizontal, + * vertical). + */ + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + PCL_PRECONDITION( x >= 0 && x < m_width ) + PCL_PRECONDITION( y >= 0 && y < m_height ) + + // Central grid coordinates + int x0 = Range( TruncInt( x ), 0, m_width-1 ); + int y0 = Range( TruncInt( y ), 0, m_height-1 ); + + // Precalculate function values + int dx = RoundInt( (x - x0)*__PCL_LANCZOS_LUT_INT_RESOLUTION ); + int dy = RoundInt( (y - y0)*__PCL_LANCZOS_LUT_INT_RESOLUTION ); + for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + { + int d0 = j*__PCL_LANCZOS_LUT_INT_RESOLUTION; + m_Lx[k] = m_lut[Abs( d0 - dx )]; + m_Ly[k] = m_lut[Abs( d0 - dy )]; + } + + double sp = 0; // positive filter values + double sn = 0; // negative filter values + double wp = 0; // positive filter weight + double wn = 0; // negative filter weight + int i, k; // row and coefficient indices + + // Clipped rows at top + for ( i = -m_n + 1, k = 0; i <= m_n; ++i, ++k ) + { + int y = y0 + i; + if ( y >= 0 ) + break; + if ( m_fillBorder ) + FillRow( sp, sn, wp, wn, m_Ly[k] ); + else + InterpolateRow( sp, sn, wp, wn, m_data - 2*int64( y )*m_width, x0, m_Ly[k] ); + } + + // Unclipped rows + for ( ; i <= m_n; ++i, ++k ) + { + int y = y0 + i; + if ( y == m_height ) + break; + InterpolateRow( sp, sn, wp, wn, m_data + int64( y )*m_width, x0, m_Ly[k] ); + } + + // Clipped rows at bottom + for ( ; i <= m_n; ++i, ++k ) + { + if ( m_fillBorder ) + FillRow( sp, sn, wp, wn, m_Ly[k] ); + else + InterpolateRow( sp, sn, wp, wn, m_data + int64( 2*m_height - 2 - y0 - i )*m_width, x0, m_Ly[k] ); + } + + // Clamping + if ( m_clamp ) + { + // Empty data? + if ( sp == 0 ) + return 0; + + // Clamping ratio: s-/s+ + double r = sn/sp; + + // Clamp for s- >= s+ + if ( r >= 1 ) + return sp/wp; + + // Clamp for c < s- < s+ + if ( r > m_clampTh ) + { + r = (r - m_clampTh)/m_clampThInv; + double c = 1 - r*r; + sn *= c, wn *= c; + } + } + + // Weighted convolution + return (sp - sn)/(wp - wn); + } + + /*! + * Returns true iff the interpolation clamping feature has been enabled for + * this object. + * + * \sa EnableClamping(), ClampingThreshold() + */ + bool IsClampingEnabled() const noexcept + { + return m_clamp; + } + + /*! + * Enables (or disables) the interpolation clamping feature. + * + * \sa IsClampingEnabled(), DisableClamping(), SetClampingThreshold() + */ + void EnableClamping( bool enable = true ) noexcept + { + m_clamp = enable; + } + + /*! + * Disables (or enables) the interpolation clamping feature. + * + * \sa IsClampingEnabled(), EnableClamping(), SetClampingThreshold() + */ + void DisableClamping( bool disable = true ) noexcept + { + EnableClamping( !disable ); + } + + /*! + * Returns the current clamping threshold for this object. + * + * See the documentation for SetClampingThreshold( float ) for a detailed + * description of the clamping mechanism. + * + * \sa SetClampingThreshold(), IsClampingEnabled(), EnableClamping() + */ + float ClampingThreshold() const noexcept + { + return m_clampTh; + } + + /*! + * Defines a threshold to trigger interpolation \e clamping. + * + * Lanczos interpolation generates strong undershoot (aka ringing) artifacts + * when the negative lobes of the interpolation function fall over bright + * isolated pixels or edges. The clamping mechanism acts by limiting the + * high-pass component of the interpolation filter selectively to fix these + * problems. + * + * The specified clamping threshold \e clamp must be in the [0,1] range. + * Lower values cause a more aggressive deringing effect. Too strong of a + * clamping threshold can degrade performance of the Lanczos filter to some + * degree, since it tends to block its high-pass behavior. + * + * \note The interpolation clamping feature must be enabled for this + * threshold to have any effect. See the constructor for this class and the + * documentation for IsClampingEnabled(). + * + * \sa ClampingThreshold(), IsClampingEnabled(), EnableClamping() + */ + void SetClampingThreshold( float clamp ) noexcept + { + PCL_PRECONDITION( 0 <= clamp && clamp <= 1 ) + m_clampTh = Range( clamp, 0.0F, 1.0F ); + } + +private: + + const float* m_lut; // filter LUT + mutable FVector m_Lx, m_Ly; // precalculated function values + double m_clampTh; // clamping threshold in [0,1] + double m_clampThInv; // 1 - m_clampTh + bool m_clamp; // clamping enabled ? + + /* + * Interpolate a row of pixels. + * Can be either an unclipped row or a mirrored border row. + */ + void InterpolateRow( double& sp, double& sn, double& wp, double& wn, const T* f, int x0, float Ly ) const noexcept + { + int j, k; + + // Clipped pixels at the left border + for ( j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + { + int x = x0 + j; + if ( x >= 0 ) + break; + double L = m_Lx[k] * Ly; + double s = (m_fillBorder ? m_fillValue : double( f[-x] )) * L; + PCL_LANCZOS_ACC() + } + + // Unclipped pixels + for ( ; j <= m_n; ++j, ++k ) + { + int x = x0 + j; + if ( x == m_width ) + break; + double L = m_Lx[k] * Ly; + double s = f[x] * L; + PCL_LANCZOS_ACC() + } + + // Clipped pixels at the right border + for ( ; j <= m_n; ++j, ++k ) + { + int x = x0 + j; + double L = m_Lx[k] * Ly; + double s = (m_fillBorder ? m_fillValue : double( f[2*m_width - 2 - x] )) * L; + PCL_LANCZOS_ACC() + } + } + + /* + * Interpolate a clipped pixel row with border filling. + */ + void FillRow( double& sp, double& sn, double& wp, double& wn, float Ly ) const noexcept + { + for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k ) + { + double L = m_Lx[k] * Ly; + double s = m_fillValue * L; + PCL_LANCZOS_ACC() + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Lanczos3LUTInterpolation + * \brief Two dimensional LUT-based 3rd-order Lanczos interpolation algorithm. + * + * This class implements 3rd-order Lanczos interpolation through precalculated + * look-up tables. For a description of the Lanczos algorithm and information + * on its performance and features, refer to the documentation for the + * LanczosInterpolation class. + * + * LUT-based Lanczos interpolations are about three times faster than the + * corresponding function evaluation interpolations. Interpolation from the + * implemented LUTs provides a maximum error of +/- 1/2^16, so this class is + * fully accurate for 8-bit and 16-bit integer images. + * + * \sa LanczosInterpolation, LanczosLUTInterpolationBase, + * Lanczos4LUTInterpolation, Lanczos5LUTInterpolation + */ +template +class PCL_CLASS Lanczos3LUTInterpolation : public LanczosLUTInterpolationBase +{ +public: + + /*! + * Constructs a %Lanczos3LUTInterpolation instance. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggressive deringing effect is + * achieved. A negative threshold value disables the clamping + * feature. The default value is 0.3. For more information, + * refer to the documentation for the + * SetClampingThreshold( float ) member function. + */ + Lanczos3LUTInterpolation( float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD ) + : LanczosLUTInterpolationBase( clamp ) + { + PCL_PRECONDITION( 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + Lanczos3LUTInterpolation( const Lanczos3LUTInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~Lanczos3LUTInterpolation() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Lanczos4LUTInterpolation + * \brief Two dimensional LUT-based 4th-order Lanczos interpolation algorithm. + * + * This class implements 4th-order Lanczos interpolation through precalculated + * look-up tables. For a description of the Lanczos algorithm and information + * on its performance and features, refer to the documentation for the + * LanczosInterpolation class. + * + * LUT-based Lanczos interpolations are about three times faster than the + * corresponding function evaluation interpolations. Interpolation from the + * implemented LUTs provides a maximum error of +/- 1/2^16, so this class is + * fully accurate for 8-bit and 16-bit integer images. + * + * \sa LanczosInterpolation, LanczosLUTInterpolationBase, + * Lanczos3LUTInterpolation, Lanczos5LUTInterpolation + */ +template +class PCL_CLASS Lanczos4LUTInterpolation : public LanczosLUTInterpolationBase +{ +public: + + /*! + * Constructs a %Lanczos4LUTInterpolation instance. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggressive deringing effect is + * achieved. A negative threshold value disables the clamping + * feature. The default value is 0.3. For more information, + * refer to the documentation for the + * SetClampingThreshold( float ) member function. + */ + Lanczos4LUTInterpolation( float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD ) + : LanczosLUTInterpolationBase( clamp ) + { + PCL_PRECONDITION( 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + Lanczos4LUTInterpolation( const Lanczos4LUTInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~Lanczos4LUTInterpolation() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Lanczos5LUTInterpolation + * \brief Two dimensional LUT-based 5th-order Lanczos interpolation algorithm. + * + * This class implements 5th-order Lanczos interpolation through precalculated + * look-up tables. For a description of the Lanczos algorithm and information + * on its performance and features, refer to the documentation for the + * LanczosInterpolation class. + * + * LUT-based Lanczos interpolations are about three times faster than the + * corresponding function evaluation interpolations. Interpolation from the + * implemented LUTs provides a maximum error of +/- 1/2^16, so this class is + * fully accurate for 8-bit and 16-bit integer images. + * + * \sa LanczosInterpolation, LanczosLUTInterpolationBase, + * Lanczos3LUTInterpolation, Lanczos4LUTInterpolation + */ +template +class PCL_CLASS Lanczos5LUTInterpolation : public LanczosLUTInterpolationBase +{ +public: + + /*! + * Constructs a %Lanczos5LUTInterpolation instance. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggressive deringing effect is + * achieved. A negative threshold value disables the clamping + * feature. The default value is 0.3. For more information, + * refer to the documentation for the + * SetClampingThreshold( float ) member function. + */ + Lanczos5LUTInterpolation( float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD ) + : LanczosLUTInterpolationBase( clamp ) + { + PCL_PRECONDITION( 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + Lanczos5LUTInterpolation( const Lanczos5LUTInterpolation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~Lanczos5LUTInterpolation() + { + } +}; + +// ---------------------------------------------------------------------------- + +#undef PCL_LANCZOS_ACC + +#undef m_width +#undef m_height +#undef m_fillBorder +#undef m_fillValue +#undef m_data + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_LanczosInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/LanczosInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/LinearFilter.h b/3rdparty/include/pcl/LinearFilter.h new file mode 100644 index 0000000..bdbb0ea --- /dev/null +++ b/3rdparty/include/pcl/LinearFilter.h @@ -0,0 +1,203 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/LinearFilter.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_LinearFilter_h +#define __PCL_LinearFilter_h + +/// \file pcl/LinearFilter.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class LinearFilter + * \brief A kernel filter that follows a discrete linear distribution with + * radial symmetry in two dimensions. + * + * A %LinearFilter object is a KernelFilter whose elements are calculated + * following a radial linear gradient function controlled by the following + * parameters: + * + * + * + * + * + *
\e size Odd filter size in pixels (size >= 3).
\e centralValue Value of the central filter element.
\e outerValue Value of outer (radial) elements.
+ * + * \sa KernelFilter, GaussianFilter, MoffatFilter, VariableShapeFilter + */ +class PCL_CLASS LinearFilter : public KernelFilter +{ +public: + + /*! + * Constructs an empty %LinearFilter object with default functional + * parameters: size=5, centralValue=1, outerValue=0.01. + */ + LinearFilter() = default; + + /*! + * Constructs a %LinearFilter object given the odd filter size \a n >= 3, + * central value \a v0, and outer value \a v1. Assigns an optional \a name + * to the new filter object. + */ + LinearFilter( int n, float v0 = 1.0F, float v1 = 0.01F, const String& name = String() ) + : KernelFilter( n, name ) + { + Initialize( v0, v1 ); + } + + /*! + * Copy constructor. + */ + LinearFilter( const LinearFilter& ) = default; + + /*! + * Move constructor. + */ + LinearFilter( LinearFilter&& ) = default; + + /*! + */ + KernelFilter* Clone() const override + { + return new LinearFilter( *this ); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + LinearFilter& operator =( const LinearFilter& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + LinearFilter& operator =( LinearFilter&& ) = default; + + /*! + * Returns the central filter coefficient value. + */ + float CentralValue() const + { + return m_centralValue; + } + + /*! + * Returns the outer filter coefficient value. + */ + float OuterValue() const + { + return m_outerValue; + } + + /*! + * Recalculates filter coefficients for the specified central and outer + * coefficient values, \a v0 and \a v1, respectively. + */ + void Set( float v0, float v1 ) + { + Initialize( v0, v1 ); + } + + /*! + * Recalculates filter coefficients for the specified outer coefficient + * value \a v1. The current central coefficient value is not varied. + */ + void Set( float v1 ) + { + Initialize( m_centralValue, v1 ); + } + + /*! + * Recalculates filter coefficients for the given kernel size \a n >= 3. The + * current central and outer coefficient values are not varied. + */ + void Resize( int n ) override + { + KernelFilter::Resize( n ); + Initialize( m_centralValue, m_outerValue ); + } + +private: + + float m_centralValue = 1.0F; + float m_outerValue = 0.01F; + + void Initialize( float v0, float v1 ) + { + m_centralValue = v0; + m_outerValue = v1; + float* h = *coefficients; + if ( h != nullptr ) + { + int n2 = Size() >> 1; + float dvn2 = (v1 - v0)/n2; + for ( int y = -n2; y <= n2; ++y ) + for ( int x = -n2; x <= n2; ++x ) + *h++ = v0 + Sqrt( float( x*x + y*y ) ) * dvn2; + } + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_LinearFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/LinearFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/LinearFit.h b/3rdparty/include/pcl/LinearFit.h new file mode 100644 index 0000000..9cae1c3 --- /dev/null +++ b/3rdparty/include/pcl/LinearFit.h @@ -0,0 +1,251 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/LinearFit.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_LinearFit_h +#define __PCL_LinearFit_h + +/// \file pcl/LinearFit.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS StatusMonitor; + +/*! + * \class LinearFit + * \brief Robust straight line fitting by minimization of mean absolute + * deviation + * + * Given a set of N data points {xi,yi} for i = {0,...,N-1}, %LinearFit finds + * the parameters a,b of the linear function: + * + *
y = L(x) := a + b*x
+ * + * that minimizes mean absolute deviation for all the data points. The \e a + * parameter of L() is the ordinate of its intersection with the Y axis. The + * \e b parameter is the slope of the fitted straight line. + */ +class PCL_CLASS LinearFit +{ +public: + + /*! + * The \e a parameter of the fitted straight line: + * + *
y = a + b*x
+ * + * is the ordinate of its intersection with the Y axis. It represents a + * constant additive pedestal present in the whole dataset. + */ + double a = 0; + + /*! + * The \e b parameter is the slope of the fitted straight line: + * + *
y = a + b*x
+ * + * If the fitted line passes through two points {x1,y1} and {x2,y2}, then + * its slope is equal to (y2 - y1)/(x2 - x1). + */ + double b = 0; + + /*! + * Mean absolute deviation of the linear fit. This is the mean absolute + * deviation computed for all data points with respect to the fitted + * straight line function. + */ + double adev = 0; + + /*! + * Returns true iff the fitted straight line model is valid. The model + * function is valid if the slope parameter is finite, i.e., if the fitted + * line is not vertical. + */ + bool IsValid() const + { + return IsFinite( b ); + } + + /*! + * Evaluates the fitted line function for the specified abscissa \a x. + */ + double operator ()( double x ) const + { + return a + b*x; + } + + /*! + * Constructs a default %LinearFit object. The resulting object corresponds + * to a horizontal line crossing at the origin, i.e. the X axis. + */ + LinearFit() = default; + + /*! + * Copy constructor. + */ + LinearFit( const LinearFit& ) = default; + + /*! + * Constructs a %LinearFit object representing the straight line that passes + * through two points {x1,y1} and {x2,y2}. + * + * \warning Do not specify a vertical line, that is, make sure that + * x1 != x2 w.r.t. the machine epsilon, or this constructor will perform a + * division by zero. + */ + template + LinearFit( T x1, T y1, T x2, T y2 ) + { + b = double( y2 - y1 )/double( x2 - x1 ); + a = (y2 - b*x2 + y1 - b*x1)/2; + adev = 0; + } + + /*! + * Constructs a %LinearFit object to fit a straight line for the specified + * set of data points. + * + * \param x %Array of abscissae values. + * + * \param y %Array of ordinate values. + * + * \param n Number of data points. Must be >= 2. + * + * \param status If nonzero, pointer to a StatusMonitor object that will be + * updated during the fitting process. The linear fit process + * is \e unbounded, i.e., the total number of monitoring + * steps cannot be known in advance. The default value is + * zero (no monitoring). + * + * When n >= 3, this constructor fits the straight line that minimizes mean + * absolute deviation for all the source data points. When n == 2, this + * function finds the straight line that passes through the two data points. + * When n < 2, this constructor throws an Error exception. + */ + template + LinearFit( const T* x, const T* y, size_type n, StatusMonitor* status = nullptr ) + { + if ( n < 2 ) + throw Error( "LinearFit::LinearFit(): Less than two data points specified." ); + + if ( n == 2 ) + { + b = double( y[1] - y[0] )/double( x[1] - x[0] ); + a = (y[1] - b*x[1] + y[0] - b*x[0])/2; + adev = 0; + } + else + Fit( a, b, adev, x, y, n, status ); + } + + /*! + * Constructs a %LinearFit object to fit a straight line for the specified + * data containers. + * + * \param x %Container of abscissae values. + * + * \param y %Container of ordinate values. + * + * \param status If nonzero, pointer to a StatusMonitor object that will be + * updated during the fitting process. The linear fit process + * is \e unbounded, i.e., the total number of monitoring + * steps cannot be known in advance. The default value is + * zero (no monitoring). + * + * The number \a n of data points is the minimum container length, i.e.: + * + *
n = Min( x.Length(), y.Length() )
+ * + * When n >= 3, this constructor fits the straight line that minimizes mean + * absolute deviation for all the source data points. When n == 2, this + * function finds the straight line that passes through the two data points. + * When n < 2, this constructor throws an Error exception. + */ + template + LinearFit( const C& x, const C& y, StatusMonitor* status = nullptr ) + { + size_type n = Min( x.Length(), y.Length() ); + if ( n < 2 ) + throw Error( "LinearFit::LinearFit(): Less than two data points specified." ); + + if ( n == 2 ) + { + b = double( y[1] - y[0] )/double( x[1] - x[0] ); + a = (y[1] - b*x[1] + y[0] - b*x[0])/2; + adev = 0; + } + else + Fit( a, b, adev, x.Begin(), y.Begin(), n, status ); + } + +private: + + static void Fit( double& a, double& b, double& adev, + const float* fx, const float* fy, size_type n, StatusMonitor* status ); + static void Fit( double& a, double& b, double& adev, + const double* fx, const double* fy, size_type n, StatusMonitor* status ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __LinearFit_h + +// ---------------------------------------------------------------------------- +// EOF pcl/LinearFit.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/LinearInterpolation.h b/3rdparty/include/pcl/LinearInterpolation.h new file mode 100644 index 0000000..be1fa0d --- /dev/null +++ b/3rdparty/include/pcl/LinearInterpolation.h @@ -0,0 +1,161 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/LinearInterpolation.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_LinearInterpolation_h +#define __PCL_LinearInterpolation_h + +/// \file pcl/LinearInterpolation.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class LinearInterpolation + * \brief Linear interpolation algorithm. + * + * The linear interpolation algorithm interpolates from two adjacent mapped + * source data items. It evaluates a linear function defined by the two + * adjacent points. + * + * \sa AkimaInterpolation, CubicSplineInterpolation + */ +template +class PCL_CLASS LinearInterpolation : public UnidimensionalInterpolation +{ +public: + + typedef typename UnidimensionalInterpolation::vector_type vector_type; + + /*! + * Constructs a %LinearInterpolation object. + */ + LinearInterpolation() = default; + + /*! + * Copy constructor. + */ + LinearInterpolation( const LinearInterpolation& ) = default; + + /*! + * Destroys a %LinearInterpolation object. + */ + virtual ~LinearInterpolation() + { + } + + /*! + * Returns true iff this interpolation is valid, i.e. if it has been + * correctly initialized and is ready to interpolate function values. + */ + bool IsValid() const override + { + return this->m_y.Length() > 1; + } + + /*! + * Interpolated value at \a x location. + */ + double operator()( double x ) const override + { + PCL_PRECONDITION( IsValid() ) + + if ( this->m_x ) + { + // Interpolation with monotonically increasing, explicit x[i]. + + PCL_CHECK( this->m_x.Length() >= this->m_y.Length() ) + int i0 = 0; + int i1 = this->m_x.Length() - 1; + while ( i1-i0 > 1 ) + { + int im = (i0 + i1) >> 1; + if ( x < this->m_x[im] ) + i1 = im; + else + i0 = im; + } + double x0( this->m_x[i0] ); + double y0( this->m_y[i0] ); + double dx = double( this->m_x[i1] ) - x0; + if ( 1 + dx != 1 ) // if no infinite slope (to within roundoff) + y0 += (x - x0)*(double( this->m_y[i1] ) - y0)/dx; + return y0; + } + else + { + // Interpolation with implicit x[i] = i for i = {0,1,...,n-1}. + + if ( x <= 0 ) + return this->m_y[0]; + if ( x >= this->m_y.Length()-1 ) + return this->m_y[this->m_y.Length()-1]; + int i0 = TruncInt( x ); + double y0( this->m_y[i0] ); + return y0 + (x - i0)*(double( this->m_y[i0+1] ) - y0); + } + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_LinearInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/LinearInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/LinearTransformation.h b/3rdparty/include/pcl/LinearTransformation.h new file mode 100644 index 0000000..af08548 --- /dev/null +++ b/3rdparty/include/pcl/LinearTransformation.h @@ -0,0 +1,287 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/LinearTransformation.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_LinearTransformation_h +#define __PCL_LinearTransformation_h + +/// \file pcl/LinearTransformation.h + +#include + +#include +#include +#include +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class LinearTransformation + * \brief A linear geometric transformation on the plane defined as a 2x3 + * matrix of 64-bit floating point scalars. + * + * %LinearTransformation is a simple structure where the six transformation + * coefficients are stored directly as \c double scalars. Since the third row + * of the transformation matrix is (0, 0, 1) implicitly, this class can only + * represent translations, rotations and scale changes. This class is primarily + * intended to support WCS coordinate transformations. + * + * \ingroup astrometry_support + */ +class LinearTransformation +{ +public: + + /*! + * Default constructor. Constructs a unit linear transformation. + */ + LinearTransformation() = default; + + /*! + * Copy constructor. + */ + LinearTransformation( const LinearTransformation& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + LinearTransformation& operator =( const LinearTransformation& ) = default; + + /*! + * Constructs a linear transformation with the specified matrix elements. + */ + LinearTransformation( double a00, double a01, double a02, double a10, double a11, double a12 ) + : m_a00( a00 ), m_a01( a01 ), m_a02( a02 ) + , m_a10( a10 ), m_a11( a11 ), m_a12( a12 ) + , m_det( a00*a11 - a01*a10 ) + { + } + + /*! + * Returns true if this transformation has been defined by a singular + * matrix. A singular matrix has zero or insignificant (with respect to the + * machine epsilon for \c double) determinant and hence cannot be inverted. + */ + bool IsSingularMatrix() const + { + return 1 + m_det == 1; + } + + /*! + * Returns the transformation of the specified point \a p. + */ + DPoint Transform( const DPoint& p ) const + { + return DPoint( m_a00*p.x + m_a01*p.y + m_a02, + m_a10*p.x + m_a11*p.y + m_a12 ); + } + + /*! + * Returns the transformation of the specified point \a p. This operator is + * equivalent to the Transform() member function. + */ + DPoint operator ()( const DPoint& p ) const + { + return Transform( p ); + } + + /*! + * Returns the inverse transformation of the specified point \a p. + * + * If the transformation matrix is singular, this member function throws an + * Error exception. + */ + DPoint TransformInverse( const DPoint& p ) const + { + if ( IsSingularMatrix() ) + throw Error( "Invalid call to LinearTransformation::TransformInverse(): Singular matrix" ); + return DPoint( ( m_a11*p.x - m_a01*p.y + m_a01*m_a12 - m_a02*m_a11)/m_det, + (-m_a10*p.x + m_a00*p.y + m_a02*m_a10 - m_a00*m_a12)/m_det ); + } + + /*! + * Returns the product of this transformation by a transformation \a T. + */ + LinearTransformation Multiply( const LinearTransformation& T ) const + { + return LinearTransformation( m_a00*T.m_a00 + m_a01*T.m_a10, + m_a00*T.m_a01 + m_a01*T.m_a11, + m_a00*T.m_a02 + m_a01*T.m_a12 + m_a02, + m_a10*T.m_a00 + m_a11*T.m_a10, + m_a10*T.m_a01 + m_a11*T.m_a11, + m_a10*T.m_a02 + m_a11*T.m_a12 + m_a12 ); + } + + /*! + * Returns the inverse of this transformation. + * + * If the transformation matrix is singular, this member function throws an + * Error exception. + */ + LinearTransformation Inverse() const + { + if ( IsSingularMatrix() ) + throw Error( "Invalid call to LinearTransformation::Inverse(): Singular matrix" ); + return LinearTransformation( m_a11/m_det, + -m_a01/m_det, + (m_a01*m_a12 - m_a02*m_a11)/m_det, + -m_a10/m_det, + m_a00/m_det, + (m_a02*m_a10 - m_a00*m_a12)/m_det ); + } + + /*! + * Returns the transformation coefficient at the first row, first column. + */ + double A00() const + { + return m_a00; + } + + /*! + * Returns the transformation coefficient at the first row, second column. + */ + double A01() const + { + return m_a01; + } + + /*! + * Returns the transformation coefficient at the first row, third column. + */ + double A02() const + { + return m_a02; + } + + /*! + * Returns the transformation coefficient at the second row, first column. + */ + double A10() const + { + return m_a10; + } + + /*! + * Returns the transformation coefficient at the second row, second column. + */ + double A11() const + { + return m_a11; + } + + /*! + * Returns the transformation coefficient at the third row, third column. + */ + double A12() const + { + return m_a12; + } + + /*! + * Returns a 3x3 matrix initialized with the transformation coefficients in + * this object. + */ + Matrix ToMatrix() const + { + return Matrix( m_a00, m_a01, m_a02, + m_a10, m_a11, m_a12, + 0.0, 0.0, 1.0 ); + } + + /*! + * Returns a six-component vector initialized with the transformation + * coefficients in this object. + */ + Vector ToVector() const + { + return Vector( { m_a00, m_a01, m_a02, m_a10, m_a11, m_a12 } ); + } + + /*! + * Returns a string representation of the transformation matrix. The + * representation consists of two text lines, each with \a indent leading + * spaces, separated by a newline character. + */ + String ToString( int indent = 0 ) const + { + String text; + if ( indent > 0 ) + text << String( ' ', indent ); + text.AppendFormat( "%+16.8e %+16.8e %+16.8e\n", m_a00, m_a01, m_a02 ); + if ( indent > 0 ) + text << String( ' ', indent ); + text.AppendFormat( "%+16.8e %+16.8e %+16.8e", m_a10, m_a11, m_a12 ); + return text; + } + +private: + + double m_a00 = 1, m_a01 = 0, m_a02 = 0, + m_a10 = 0, m_a11 = 1, m_a12 = 0; + double m_det = 1; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_LinearTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/LinearTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/LocalNormalizationData.h b/3rdparty/include/pcl/LocalNormalizationData.h new file mode 100644 index 0000000..7cfd9ae --- /dev/null +++ b/3rdparty/include/pcl/LocalNormalizationData.h @@ -0,0 +1,795 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ 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 + +#include +#include +#include +#include + +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 + matrix_interpolation; + + /*! + * Represents an array of local normalization interpolators. + */ + typedef Array 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 > 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 diff --git a/3rdparty/include/pcl/Math.h b/3rdparty/include/pcl/Math.h new file mode 100644 index 0000000..fb747fc --- /dev/null +++ b/3rdparty/include/pcl/Math.h @@ -0,0 +1,4996 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Math.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_Math_h +#define __PCL_Math_h + +/// \file pcl/Math.h + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef _MSC_VER +# include // for __cpuid() +#endif + +#if defined( __x86_64__ ) || defined( _M_X64 ) || defined( __PCL_MACOSX ) +# define __PCL_HAVE_SSE2 1 +# include +#endif + +/* + * sincos() is only available as a GNU extension: + * + * http://man7.org/linux/man-pages/man3/sincos.3.html + * + * Unfortunately, it is not part of the C++ standard library because of the + * anachronic dependency on errno. + */ +#if !defined( _MSC_VER ) && !defined( __clang__ ) && defined( __GNUC__ ) +# define __PCL_HAVE_SINCOS 1 +#endif + +#ifdef __PCL_QT_INTERFACE +# include +#endif + +/* + * Number of histogram bins used by fast histogram-based median calculation + * algorithm implementations. + */ +#define __PCL_MEDIAN_HISTOGRAM_LENGTH 8192 + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup hw_identification_functions Hardware Identification Routines + */ + +/*! + * Returns an integer representing the highest set of Streaming SIMD Extensions + * instructions (SSE) supported by the running processor. This function is a + * portable wrapper to the CPUID x86 instruction. + * + * The returned value can be one of: + * + *
+ *  0 : No SSE instructions supported
+ *  1 : SSE instructions set supported
+ *  2 : SSE2 instructions set supported
+ *  3 : SSE3 instructions set supported
+ * 41 : SSE4.1 instructions set supported
+ * 42 : SSE4.2 instructions set supported
+ * 
+ * + * \ingroup hw_identification_functions + */ +inline int MaxSSEInstructionSetSupported() noexcept +{ + int32 edxFlags = 0; + int32 ecxFlags = 0; + +#ifdef _MSC_VER + int cpuInfo[ 4 ]; + __cpuid( cpuInfo, 1 ); + edxFlags = cpuInfo[3]; + ecxFlags = cpuInfo[2]; +#else + asm volatile( "mov $0x00000001, %%eax\n\t" + "cpuid\n\t" + "mov %%edx, %0\n\t" + "mov %%ecx, %1\n" + : "=r" (edxFlags), "=r" (ecxFlags) // output operands + : // input operands + : "%eax", "%ebx", "%ecx", "%edx" ); // clobbered registers +#endif + + if ( ecxFlags & (1u << 20) ) // SSE4.2 + return 42; + if ( ecxFlags & (1u << 19) ) // SSE4.1 + return 41; + if ( ecxFlags & 1u ) // SSE3 + return 3; + if ( edxFlags & (1u << 26) ) // SSE2 + return 2; + if ( edxFlags & (1u << 25) ) // SSE + return 1; + return 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup fpclassification_functions Floating Point Number Classification + */ + +#define __PCL_FLOAT_SGNMASK 0x80000000 +#define __PCL_FLOAT_EXPMASK 0x7f800000 +#define __PCL_FLOAT_SIGMASK 0x007fffff + +/*! + * Returns true iff the specified 32-bit floating point number is \e finite. + * A number is finite if it is neither NaN (Not a Number) nor positive or + * negative infinity. + * + * \ingroup fpclassification_functions + * \sa IsNaN( float ), IsInfinity( float ) + */ +inline bool IsFinite( float x ) noexcept +{ + union { float f; uint32 u; } v = { x }; + return (v.u & __PCL_FLOAT_EXPMASK) != __PCL_FLOAT_EXPMASK; +} + +/*! + * Returns true iff the specified 32-bit floating point number is \e NaN. A NaN + * (Not A Number) is a special value in the IEEE 754 standard used to represent + * an undefined or unrepresentable value, such as the result of invalid + * operations like 0/0, or real operations with complex results as the square + * root of a negative number. + * + * \ingroup fpclassification_functions + * \sa IsFinite( float ), IsInfinity( float ) + */ +inline bool IsNaN( float x ) noexcept +{ + union { float f; uint32 u; } v = { x }; + return (v.u & __PCL_FLOAT_EXPMASK) == __PCL_FLOAT_EXPMASK && + (v.u & __PCL_FLOAT_SIGMASK) != 0; +} + +/*! + * Returns a nonzero integer value if the specified 32-bit floating point + * number is an \e infinity. + * + * This function returns: + * + *
+ * +1 if \a x is positive infinity.
+ * -1 if \a x is negative infinity.
+ *  0 if \a x is either NaN or a finite value.
+ * 
+ * + * \ingroup fpclassification_functions + * \sa IsFinite( float ), IsNaN( float ) + */ +inline int IsInfinity( float x ) noexcept +{ + union { float f; uint32 u; } v = { x }; + if ( (v.u & __PCL_FLOAT_EXPMASK) == __PCL_FLOAT_EXPMASK && + (v.u & __PCL_FLOAT_SIGMASK) == 0 ) + return ((v.u & __PCL_FLOAT_SGNMASK) == 0) ? +1 : -1; + return 0; +} + +/*! + * Returns true iff the specified 32-bit floating point number is a negative + * zero. + * + * \ingroup fpclassification_functions + */ +inline bool IsNegativeZero( float x ) noexcept +{ + union { float f; uint32 u; } v = { x }; + return v.u == __PCL_FLOAT_SGNMASK; +} + +#define __PCL_DOUBLE_SGNMASK 0x80000000 +#define __PCL_DOUBLE_EXPMASK 0x7ff00000 +#define __PCL_DOUBLE_SIGMASK 0x000fffff + +/*! + * Returns true iff the specified 64-bit floating point number is \e finite. + * A number is finite if it is neither NaN (Not a Number) nor positive or + * negative infinity. + * + * \ingroup fpclassification_functions + * \sa IsNaN( double ), IsInfinity( double ) + */ +inline bool IsFinite( double x ) noexcept +{ + union { double d; uint32 u[2]; } v = { x }; + return (v.u[1] & __PCL_DOUBLE_EXPMASK) != __PCL_DOUBLE_EXPMASK; +} + +/*! + * Returns true iff the specified 64-bit floating point number is \e NaN. A NaN + * (Not A Number) is a special value in the IEEE 754 standard used to represent + * an undefined or unrepresentable value, such as the result of invalid + * operations like 0/0, or real operations with complex results as the square + * root of a negative number. + * + * \ingroup fpclassification_functions + * \sa IsFinite( double ), IsInfinity( double ) + */ +inline bool IsNaN( double x ) noexcept +{ + union { double d; uint32 u[2]; } v = { x }; + return (v.u[1] & __PCL_DOUBLE_EXPMASK) == __PCL_DOUBLE_EXPMASK && + (v.u[0] != 0 || (v.u[1] & __PCL_DOUBLE_SIGMASK) != 0); +} + +/*! + * Returns a nonzero integer value if the specified 64-bit floating point + * number is an \e infinity. + * + * This function returns: + * + *
+ * +1 if \a x is positive infinity.
+ * -1 if \a x is negative infinity.
+ *  0 if \a x is either NaN or a finite value.
+ * 
+ * + * \ingroup fpclassification_functions + * \sa IsFinite( double ), IsNaN( double ) + */ +inline int IsInfinity( double x ) noexcept +{ + union { double d; uint32 u[2]; } v = { x }; + if ( v.u[0] == 0 && + (v.u[1] & __PCL_DOUBLE_SIGMASK) == 0 && + (v.u[1] & __PCL_DOUBLE_EXPMASK) == __PCL_DOUBLE_EXPMASK ) + return ((v.u[1] & __PCL_DOUBLE_SGNMASK) == 0) ? +1 : -1; + return 0; +} + +/*! + * Returns true iff the specified 64-bit floating point number is a negative + * zero. + * + * \ingroup fpclassification_functions + */ +inline bool IsNegativeZero( double x ) noexcept +{ + union { double d; uint32 u[2]; } v = { x }; + return v.u[1] == __PCL_DOUBLE_SGNMASK && + v.u[0] == 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup mathematical_functions Mathematical Functions + */ + +/*! + * Absolute value of \a x. + * \ingroup mathematical_functions + */ +inline float Abs( float x ) noexcept +{ + return std::fabs( x ); +} + +/*! + * \ingroup mathematical_functions + */ +inline double Abs( double x ) noexcept +{ + return std::fabs( x ); +} + +/*! + * \ingroup mathematical_functions + */ +inline long double Abs( long double x ) noexcept +{ + return std::fabs( x ); +} + +/*! + * \ingroup mathematical_functions + */ +inline signed int Abs( signed int x ) noexcept +{ + return ::abs( x ); +} + +/*! + * \ingroup mathematical_functions + */ +#if defined( __PCL_MACOSX ) && defined( __clang__ ) // turn off warning due to broken cstdlib in Xcode +_Pragma("clang diagnostic push") +_Pragma("clang diagnostic ignored \"-Wabsolute-value\"") +#endif +inline signed long Abs( signed long x ) noexcept +{ + return ::abs( x ); +} +#if defined( __PCL_MACOSX ) && defined( __clang__ ) +_Pragma("clang diagnostic pop") +#endif + +/*! + * \ingroup mathematical_functions + */ +#if defined( _MSC_VER ) +inline __int64 Abs( __int64 x ) noexcept +{ + return (x < 0) ? -x : +x; +} +#elif defined( __PCL_MACOSX ) && defined( __clang__ ) +inline constexpr signed long long Abs( signed long long x ) noexcept +{ + return (x < 0) ? -x : +x; +} +#else +inline signed long long Abs( signed long long x ) noexcept +{ + return ::abs( x ); +} +#endif + +/*! + * \ingroup mathematical_functions + */ +inline signed short Abs( signed short x ) noexcept +{ + return (signed short)::abs( int( x ) ); +} + +/*! + * \ingroup mathematical_functions + */ +inline signed char Abs( signed char x ) noexcept +{ + return (signed char)::abs( int( x ) ); +} + +/*! + * \ingroup mathematical_functions + */ +inline wchar_t Abs( wchar_t x ) noexcept +{ + return (wchar_t)::abs( int( x ) ); +} + +/*! + * \ingroup mathematical_functions + */ +inline constexpr unsigned int Abs( unsigned int x ) noexcept +{ + return x; +} + +/*! + * \ingroup mathematical_functions + */ +inline constexpr unsigned long Abs( unsigned long x ) noexcept +{ + return x; +} + +/*! + * \ingroup mathematical_functions + */ +#ifdef _MSC_VER +inline unsigned __int64 Abs( unsigned __int64 x ) noexcept +{ + return x; +} +#else +inline constexpr unsigned long long Abs( unsigned long long x ) noexcept +{ + return x; +} +#endif + +/*! + * \ingroup mathematical_functions + */ +inline constexpr unsigned short Abs( unsigned short x ) noexcept +{ + return x; +} + +/*! + * \ingroup mathematical_functions + */ +inline constexpr unsigned char Abs( unsigned char x ) noexcept +{ + return x; +} + +// ---------------------------------------------------------------------------- + +/*! + * The pi constant: 3.141592... + * \ingroup mathematical_functions + */ +inline constexpr long double Pi() noexcept +{ + return (long double)( 0.31415926535897932384626433832795029e+01L ); +} + +/*! + * Twice the pi constant: 0.6283185... + * \ingroup mathematical_functions + */ +inline constexpr long double TwoPi() noexcept +{ + return (long double)( 0.62831853071795864769252867665590058e+01L ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Merges a complex angle given by degrees and arcminutes into single degrees. + * \ingroup mathematical_functions + */ +template inline constexpr T Angle( int d, T m ) noexcept +{ + return d + m/60; +} + +/*! + * Merges a complex angle given by degrees, arcminutes and arcseconds into + * single degrees. + * \ingroup mathematical_functions + */ +template inline constexpr T Angle( int d, int m, T s ) noexcept +{ + return Angle( d, m + s/60 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse cosine function (arccosine). + * \ingroup mathematical_functions + */ +template inline constexpr T ArcCos( T x ) noexcept +{ + PCL_PRECONDITION( T( -1 ) <= x && x <= T( 1 ) ) + return std::acos( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse sine function (arcsine). + * \ingroup mathematical_functions + */ +template inline constexpr T ArcSin( T x ) noexcept +{ + PCL_PRECONDITION( T( -1 ) <= x && x <= T( 1 ) ) + return std::asin( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse tangent function (arctangent). + * \ingroup mathematical_functions + */ +template inline constexpr T ArcTan( T x ) noexcept +{ + return std::atan( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Arctangent of y/x, result in the proper quadrant. + * \ingroup mathematical_functions + */ +template inline constexpr T ArcTan( T y, T x ) noexcept +{ + return std::atan2( y, x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Arctangent of y/x, proper quadrant, result in the interval [0,2pi). + * \ingroup mathematical_functions + */ +template inline T ArcTan2Pi( T y, T x ) noexcept +{ + T r = ArcTan( y, x ); + if ( r < 0 ) + r = static_cast( r + TwoPi() ); + return r; +} + +// ---------------------------------------------------------------------------- + +/*! + * The ceil function: lowest integer >= x. + * \ingroup mathematical_functions + */ +template inline constexpr T Ceil( T x ) noexcept +{ + return std::ceil( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Cosine function. + * \ingroup mathematical_functions + */ +template inline constexpr T Cos( T x ) noexcept +{ + return std::cos( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Hyperbolic Cosine function. + * \ingroup mathematical_functions + */ +template inline constexpr T Cosh( T x ) noexcept +{ + return std::cosh( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Cotangent of x, equal to Cos(x)/Sin(x) or 1/Tan(x). + * \ingroup mathematical_functions + */ +template inline constexpr T Cotan( T x ) noexcept +{ + return T( 1 )/std::tan( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from radians to degrees. + * \ingroup mathematical_functions + */ +template inline constexpr T Deg( T x ) noexcept +{ + return static_cast( 0.572957795130823208767981548141051700441964e+02L * x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * The exponential function e**x. + * \ingroup mathematical_functions + */ +template inline constexpr T Exp( T x ) noexcept +{ + return std::exp( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * The floor function: highest integer <= x. + * \ingroup mathematical_functions + */ +template inline constexpr T Floor( T x ) noexcept +{ + return std::floor( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Fractional part of x. + * The returned value is within (-1,+1), and has the same sign as x. + * \ingroup mathematical_functions + */ +template inline constexpr T Frac( T x ) noexcept +{ + return std::modf( x, &x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Calculates base-2 mantissa and exponent. + * The arguments \a m and \a p receive the values of the base-2 mantissa and + * exponent, respectively, such that: 0.5 <= m < 1.0, x = m * 2**p + * \ingroup mathematical_functions + */ +template inline void Frexp( T x, T& m, int& p ) noexcept +{ + m = std::frexp( x, &p ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Haversine function: + * + * Hav( x ) = (1 - Cos( x ))/2 + * + * The haversine is useful to work with tiny angles. + * + * \ingroup mathematical_functions + */ +template inline constexpr T Hav( T x ) noexcept +{ + return (1 - Cos( x ))/2; +} + +// ---------------------------------------------------------------------------- + +/*! + * Calculates m * 2**p. + * \ingroup mathematical_functions + */ +template inline constexpr T Ldexp( T m, int p ) noexcept +{ + return std::ldexp( m, p ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Natural (base e) logarithm of \a x. + * \ingroup mathematical_functions + */ +template inline constexpr T Ln( T x ) noexcept +{ + PCL_PRECONDITION( x >= 0 ) + return std::log( x ); +} + +// ---------------------------------------------------------------------------- + +struct PCL_CLASS FactorialCache +{ + constexpr static int s_cacheSize = 127; + static const double s_lut[ s_cacheSize+1 ]; +}; + +/*! + * The factorial of \a n ≥ 0. + * + * A static lookup table is used to speed up for \a n <= 127. + * + * \ingroup mathematical_functions + */ +inline double Factorial( int n ) noexcept +{ + PCL_PRECONDITION( n >= 0 ) + if ( n <= FactorialCache::s_cacheSize ) + return FactorialCache::s_lut[n]; + double x = FactorialCache::s_lut[FactorialCache::s_cacheSize]; + for ( int m = FactorialCache::s_cacheSize; ++m <= n; ) + x *= m; + return x; +} + +/*! + * The natural logarithm of the factorial of \a n ≥ 0. + * + * For \a n <= 127 computes the natural logarithm of the factorial function + * directly. For \a n > 127 computes a series approximation, so that the + * function won't overflow even for very large arguments. + * + * \ingroup mathematical_functions + */ +inline double LnFactorial( int n ) noexcept +{ + PCL_PRECONDITION( n >= 0 ) + if ( n <= FactorialCache::s_cacheSize ) + return Ln( FactorialCache::s_lut[n] ); + double x = n + 1; +// return (x - 0.5)*Ln( x ) - x + 0.5*Ln( TwoPi() ) + 1/12/x - 1/(360*x*x*x); + return (x - 0.5)*Ln( x ) - x + 0.91893853320467267 + 1/12/x - 1/(360*x*x*x); +} + +/*! + * \class Fact + * \brief Factorial function. + * + * We use a static lookup table to speed up for \a n <= 127. + * + * Example of use: + * + * \code double factorialOfEight = Fact()( 8 ); // = 40320 \endcode + * + * The implementation of this class is thread-safe. + * + * \deprecated This class is deprecated and subject to removal in a future + * version of PCL. For newly produced code, use the pcl::Factorial() and + * pcl::LnFactorial() functions instead. + * + * \ingroup mathematical_functions + */ +template struct PCL_CLASS Fact : public FactorialCache +{ + /*! + * Returns the factorial of \a n ≥ 0. + */ + T operator()( int n ) const noexcept + { + PCL_PRECONDITION( n >= 0 ) + if ( n <= s_cacheSize ) + return T( s_lut[n] ); + double x = s_lut[s_cacheSize]; + for ( int m = s_cacheSize; ++m <= n; ) + x *= m; + return T( x ); + } + + /*! + * Returns the natural logarithm of the factorial of \a n ≥ 0. For + * \a n <= 127 computes the natural logarithm of the factorial function + * directly. For \a n > 127 computes a series approximation, so that the + * function won't overflow even for very large arguments. + */ + T Ln( int n ) const noexcept + { + PCL_PRECONDITION( n >= 0 ) + if ( n <= s_cacheSize ) + return T( pcl::Ln( s_lut[n] ) ); + double x = n + 1; +// return T( (x - 0.5)*pcl::Ln( x ) - x + 0.5*pcl::Ln( TwoPi() ) + 1/12/x - 1/(360*x*x*x) ); + return T( (x - 0.5)*pcl::Ln( x ) - x + 0.91893853320467267 + 1/12/x - 1/(360*x*x*x) ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * Natural (base e) logarithm of two. + * \ingroup mathematical_functions + */ +inline constexpr long double Ln2() noexcept +{ + return (long double)( 0.6931471805599453094172321214581766e+00L ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Base 10 Logarithm of x. + * \ingroup mathematical_functions + */ +template inline constexpr T Log( T x ) noexcept +{ + PCL_PRECONDITION( x >= 0 ) + return std::log10( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Base 10 Logarithm of two. + * \ingroup mathematical_functions + */ +inline constexpr long double Log2() noexcept +{ + // Use the relation: + // log10(2) = ln(2)/ln(10) + return (long double)( 0.3010299956639811952137388947244930416265e+00L ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Base 2 Logarithm of x. + * \ingroup mathematical_functions + */ +template inline constexpr T Log2( T x ) noexcept +{ + // Use the relation: + // log2(x) = ln(x)/ln(2) + PCL_PRECONDITION( x >= 0 ) + return std::log( x )/Ln2(); +} + +// ---------------------------------------------------------------------------- + +/*! + * Base 2 Logarithm of e. + * \ingroup mathematical_functions + */ +inline constexpr long double Log2e() noexcept +{ + // Use the relation: + // log2(e) = 1/ln(2) + return (long double)( 0.14426950408889634073599246810018920709799e+01L ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Base 2 Logarithm of ten. + * \ingroup mathematical_functions + */ +inline constexpr long double Log2T() noexcept +{ + // Use the relation: + // log2(10) = 1/log(2) + return (long double)( 0.33219280948873623478703194294893900118996e+01L ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Base \a n logarithm of \a x. + * \ingroup mathematical_functions + */ +template inline constexpr T LogN( T n, T x ) noexcept +{ + PCL_PRECONDITION( x >= 0 ) + return std::log( x )/std::log( n ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Remainder of x/y. + * \ingroup mathematical_functions + */ +template inline constexpr T Mod( T x, T y ) noexcept +{ + return std::fmod( x, y ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Horner's algorithm to evaluate the polynomial function with the specified + * array \a c of \a n + 1 coefficients: + * + *
+ * y = c[0] + c[1]*x + c[2]*x**2 + ... + c[n]*x**n
+ * 
+ * + * The array \a c of coefficients must provide contiguous storage for at least + * \a n + 1 values of type T. The degree \a n must be >= 0; otherwise this + * function invokes undefined behavior. + * + * \ingroup mathematical_functions + */ +template inline T Poly( T x, C c, int n ) noexcept +{ + PCL_PRECONDITION( n >= 0 ) + T y; + for ( c += n, y = *c; n > 0; --n ) + { + y *= x; + y += *--c; + } + return y; +} + +/*! + * Horner's algorithm to evaluate the polynomial function: + * + *
+ * y = c[0] + c[1]*x + c[2]*x**2 + ... + c[n]*x**n
+ * 
+ * + * The specified coefficients initializer list \a c must not be empty; + * otherwise this function invokes undefined behavior. + * + * \ingroup mathematical_functions + */ +template inline T Poly( T x, std::initializer_list c ) noexcept +{ + PCL_PRECONDITION( c.size() > 0 ) + return Poly( x, c.begin(), int( c.size() )-1 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Sign function: + * + *
+ * -1 if x ≤ 0
+ *  0 if x = 0
+ * +1 if x ≥ 0
+ * 
+ * + * \ingroup mathematical_functions + */ +template inline constexpr int Sign( T x ) noexcept +{ + return (x < 0) ? -1 : ((x > 0) ? +1 : 0); +} + +// ---------------------------------------------------------------------------- + +/*! + * Sign character: + * + *
+ * '-' if x ≤ 0
+ * ' ' if x = 0
+ * '+' if x ≥ 0
+ * 
+ * + * \ingroup mathematical_functions + */ +template inline constexpr char SignChar( T x ) noexcept +{ + return (x < 0) ? '-' : ((x > 0) ? '+' : ' '); +} + +// ---------------------------------------------------------------------------- + +/*! + * Sine function + * \ingroup mathematical_functions + */ +template inline constexpr T Sin( T x ) noexcept +{ + return std::sin( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Hyperbolic Sine function. + * \ingroup mathematical_functions + */ +template inline constexpr T Sinh( T x ) noexcept +{ + return std::sinh( x ); +} + +// ---------------------------------------------------------------------------- + +#ifdef __PCL_HAVE_SINCOS + +inline void __pcl_sincos__( float x, float& sx, float& cx ) noexcept +{ + ::sincosf( x, &sx, &cx ); +} + +inline void __pcl_sincos__( double x, double& sx, double& cx ) noexcept +{ + ::sincos( x, &sx, &cx ); +} + +inline void __pcl_sincos__( long double x, long double& sx, long double& cx ) noexcept +{ + ::sincosl( x, &sx, &cx ); +} + +#endif + +/*! + * Sine and cosine of \a x. + * + * The arguments \a sx and \a cx will receive, respectively, the values of the + * sine and cosine of x. + * + * If supported by the underlying standard math library, this function is + * roughly twice as fast as calling Sin() and Cos() separately. For code that + * spend a significant amount of time calculating sines and cosines, this + * optimization is critical. + * + * \ingroup mathematical_functions + */ +template inline void SinCos( T x, T& sx, T& cx ) noexcept +{ +#ifdef __PCL_HAVE_SINCOS + __pcl_sincos__( x, sx, cx ); +#else + sx = std::sin( x ); + cx = std::cos( x ); +#endif +} + +// ---------------------------------------------------------------------------- + +/*! + * Integer and fractional parts of \a x. + * + * The arguments \a i and \a f receive, respectively, the integer (truncated) + * part and the fractional part of \a x. It holds that \a x = \a i + \a f, i.e. + * both \a i and \a f have the same sign as \a x. + * + * \ingroup mathematical_functions + */ +template inline void Split( T x, T& i, T& f ) noexcept +{ + f = std::modf( x, &i ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Square root function. + * \ingroup mathematical_functions + */ +template inline constexpr T Sqrt( T x ) noexcept +{ + return sqrt( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Tangent function. + * \ingroup mathematical_functions + */ +template inline constexpr T Tan( T x ) noexcept +{ + return std::tan( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Hyperbolic Tangent function. + * \ingroup mathematical_functions + */ +template inline constexpr T Tanh( T x ) noexcept +{ + return std::tanh( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Truncated integer part of \a x. + * \ingroup mathematical_functions + */ +template inline T Trunc( T x ) noexcept +{ + (void)std::modf( x, &x ); + return x; +} + +// ---------------------------------------------------------------------------- + +#ifdef __PCL_HAVE_SSE2 + +inline int __pcl_trunci__( float x ) noexcept +{ + return _mm_cvtt_ss2si( _mm_load_ss( &x ) ); +} + +inline int __pcl_trunci__( double x ) noexcept +{ + return _mm_cvttsd_si32( _mm_load_sd( &x ) ); +} + +inline int __pcl_trunci__( long double x ) noexcept +{ + return int( x ); +} + +#endif + +/*! + * TruncInt function: Truncated integer part of \a x as a 32-bit signed + * integer. + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \ingroup mathematical_functions + */ +template inline int TruncInt( T x ) noexcept +{ + PCL_PRECONDITION( x >= int_min && x <= int_max ) +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + return int( x ); +#else +# ifdef __PCL_HAVE_SSE2 + return __pcl_trunci__( x ); +# else + return int( x ); +# endif +#endif +} + +/*! + * TruncI function: Truncated integer part of \a x as a 32-bit signed integer. + * to a 32-bit signed integer. + * + * \deprecated Use TruncInt() in newly produced code. + * + * \ingroup mathematical_functions + */ +template inline int TruncI( T x ) noexcept +{ + return TruncInt( x ); +} + +#define TruncInt32( x ) TruncInt( x ) +#define TruncI32( x ) TruncInt( x ) + +// ---------------------------------------------------------------------------- + +#ifdef __PCL_HAVE_SSE2 + +#if defined( __x86_64__ ) || defined( _M_X64 ) + +inline int64 __pcl_trunci64__( float x ) noexcept +{ + return _mm_cvttss_si64( _mm_load_ss( &x ) ); +} + +inline int64 __pcl_trunci64__( double x ) noexcept +{ + return _mm_cvttsd_si64( _mm_load_sd( &x ) ); +} + +#else + +inline int64 __pcl_trunci64__( float x ) noexcept +{ + return int64( _mm_cvtt_ss2si( _mm_load_ss( &x ) ) ); +} + +inline int64 __pcl_trunci64__( double x ) noexcept +{ + return int64( x ); +} + +#endif + +inline int64 __pcl_trunci64__( long double x ) noexcept +{ + return int64( x ); +} + +#endif // __PCL_HAVE_SSE2 + +/*! + * TruncInt64 function: Truncated integer part of \a x as a 64-bit signed + * integer. + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \ingroup mathematical_functions + */ +template inline int64 TruncInt64( T x ) noexcept +{ + PCL_PRECONDITION( x >= int64_min && x <= int64_max ) +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + return int64( Trunc( x ) ); +#else +# ifdef __PCL_HAVE_SSE2 + return __pcl_trunci64__( x ); +# else + return int64( Trunc( x ) ); +# endif +#endif +} + +/*! + * TruncI64 function: Truncated integer part of \a x as a 64-bit signed + * integer. + * + * \deprecated Use TruncInt64() in newly produced code. + * + * \ingroup mathematical_functions + */ +template inline int64 TruncI64( T x ) noexcept +{ + return TruncInt64( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * General power function: \a x raised to \a y. + * + * When you know some of the arguments in advance, faster alternatives are: + * + * \li Use Pow10I\()( y ) when x == 10 and y is an integer + * \li Use PowI( x, y ) when x != 10 and y is an integer + * \li Use Pow10( y ) when x == 10 and y is not an integer + * + * Otherwise, you can also use: Pow2( y*Log2( x ) ) + * + * \ingroup mathematical_functions + */ +template inline constexpr T Pow( T x, T y ) noexcept +{ + PCL_PRECONDITION( y < T( int_max ) ) + return std::pow( x, y ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Pow10I + * \brief Exponential function 10**n, \a n being a signed integer. + * + * Example of use: + * + * \code double x = Pow10I()( 5 ); // x = 10^5 \endcode + * + * \ingroup mathematical_functions + */ +template struct PCL_CLASS Pow10I +{ + T operator ()( int n ) const noexcept + { + // Use fast table lookups and squaring up to |n| <= 50. + static const T lut[] = + { +#define ___( x ) static_cast( x ) + ___( 1.0e+00 ), ___( 1.0e+01 ), ___( 1.0e+02 ), ___( 1.0e+03 ), ___( 1.0e+04 ), + ___( 1.0e+05 ), ___( 1.0e+06 ), ___( 1.0e+07 ), ___( 1.0e+08 ), ___( 1.0e+09 ), + ___( 1.0e+10 ), ___( 1.0e+11 ), ___( 1.0e+12 ), ___( 1.0e+13 ), ___( 1.0e+14 ), + ___( 1.0e+15 ), ___( 1.0e+16 ), ___( 1.0e+17 ), ___( 1.0e+18 ), ___( 1.0e+19 ), + ___( 1.0e+20 ), ___( 1.0e+21 ), ___( 1.0e+22 ), ___( 1.0e+23 ), ___( 1.0e+24 ), + ___( 1.0e+25 ), ___( 1.0e+26 ), ___( 1.0e+27 ), ___( 1.0e+28 ), ___( 1.0e+29 ), + ___( 1.0e+30 ), ___( 1.0e+31 ), ___( 1.0e+32 ), ___( 1.0e+33 ), ___( 1.0e+34 ), + ___( 1.0e+35 ), ___( 1.0e+36 ), ___( 1.0e+37 ), ___( 1.0e+38 ), ___( 1.0e+39 ), + ___( 1.0e+40 ), ___( 1.0e+41 ), ___( 1.0e+42 ), ___( 1.0e+43 ), ___( 1.0e+44 ), + ___( 1.0e+45 ), ___( 1.0e+46 ), ___( 1.0e+47 ), ___( 1.0e+48 ), ___( 1.0e+49 ) +#undef ___ + }; + static const int N = ItemsInArray( lut ); + int i = ::abs( n ); + double x; + if ( i < N ) + x = lut[i]; + else + { + x = lut[N-1]; + while ( (i -= N-1) >= N ) + x *= x; + if ( i != 0 ) + x *= lut[i]; + } + return T( (n >= 0) ? x : 1/x ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * The exponential function 10**x. + * \ingroup mathematical_functions + */ +template inline T Pow10( T x ) noexcept +{ + int i = TruncInt( x ); + return (i == x) ? Pow10I()( i ) : T( std::pow( 10, x ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Bitwise rotate left function: Rotates \a x to the left by \a n bits. + * + * The template argument T must be an unsigned arithmetic type (uint8, uint16, + * uint32 or uint64). The bit count \a n must be smaller than the number of + * bits required to store an instance of T; for example, if T is uint32, \a n + * must be in the range [0,31]. + * + * \ingroup mathematical_functions + */ +template inline T RotL( T x, uint32 n ) noexcept +{ + static_assert( std::is_unsigned::value, + "RotL() can only be used for unsigned integer scalar types" ); + const uint8 mask = 8*sizeof( x ) - 1; + const uint8 r = uint8( n & mask ); + return (x << r) | (x >> ((-r) & mask)); + // Or equivalently, but less optimized: + //return (x << r) | (x >> (1+mask-r)); +} + +/*! + * Bitwise rotate right function: Rotates \a x to the right by \a n bits. + * + * The template argument T must be an unsigned arithmetic type (uint8, uint16, + * uint32 or uint64). The bit count \a n must be smaller than the number of + * bits required to store an instance of T; for example, if T is uint32, \a n + * must be in the range [0,31]. + * + * \ingroup mathematical_functions + */ +template inline T RotR( T x, uint32 n ) noexcept +{ + static_assert( std::is_unsigned::value, + "RotR() can only be used for unsigned integer scalar types" ); + const uint8 mask = 8*sizeof( x ) - 1; + const uint8 r = uint8( n & mask ); + return (x >> r) | (x << ((-r) & mask)); + // Or equivalently, but less optimized: + //return (x >> r) | (x << (1+mask-r)); +} + +// ---------------------------------------------------------------------------- + +/*! + * Round function: x rounded to the nearest integer (double precision version). + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \ingroup mathematical_functions + */ +inline double Round( double x ) noexcept +{ +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + + return floor( x + 0.5 ); + +#else + +# ifdef _MSC_VER +# ifdef _M_X64 + return double( _mm_cvtsd_si64( _mm_load_sd( &x ) ) ); +# else + __asm fld x + __asm frndint +# endif +# else + double r; + asm volatile( "frndint\n": "=t" (r) : "0" (x) ); + return r; +# endif + +#endif +} + +/*! + * Round function: x rounded to the nearest integer (single precision version). + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \ingroup mathematical_functions + */ +inline float Round( float x ) noexcept +{ +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + + return floorf( x + 0.5F ); + +#else + +# ifdef _MSC_VER +# ifdef _M_X64 + return float( _mm_cvtss_si32( _mm_load_ss( &x ) ) ); +# else + __asm fld x + __asm frndint +# endif +# else + float r; + asm volatile( "frndint\n": "=t" (r) : "0" (x) ); + return r; +# endif + +#endif +} + +/*! + * Round function: x rounded to the nearest integer (long double version). + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \ingroup mathematical_functions + */ +inline long double Round( long double x ) noexcept +{ +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + + return floorl( x + 0.5L ); + +#else + +# ifdef _MSC_VER +# ifdef _M_X64 + double _x = x; + return (long double)_mm_cvtsd_si64( _mm_load_sd( &_x ) ); +# else + __asm fld x + __asm frndint +# endif +# else + long double r; + asm volatile( "frndint\n": "=t" (r) : "0" (x) ); + return r; +# endif + +#endif +} + +// ---------------------------------------------------------------------------- + +/*! + * RoundInt function: Rounds \a x to the nearest integer and converts the + * result to a 32-bit signed integer. + * + * This function follows the Banker's rounding rule: a perfect half is always + * rounded to the nearest even digit. Some examples: + * + *
+ * RoundInt( 0.5 ) -> 0
+ * RoundInt( 1.5 ) -> 2
+ * RoundInt( 2.5 ) -> 2
+ * RoundInt( 3.5 ) -> 4
+ * 
+ * + * By contrast, arithmetic rounding rounds a perfect half to the nearest digit, + * either odd or even. For example: + * + *
+ * RoundIntArithmetic( 0.5 ) -> 1
+ * RoundIntArithmetic( 1.5 ) -> 2
+ * RoundIntArithmetic( 2.5 ) -> 3
+ * RoundIntArithmetic( 3.5 ) -> 4
+ * 
+ * + * Banker's rounding (also known as Gaussian rounding) is statistically more + * accurate than the usual arithmetic rounding, but it causes aliasing problems + * in some specific algorithms that depend critically on uniform rounding, such + * as nearest neighbor upsampling. + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \sa RoundIntArithmetic(), RoundIntBanker() + * + * \ingroup mathematical_functions + */ +template inline int RoundInt( T x ) noexcept +{ + PCL_PRECONDITION( x >= int_min && x <= int_max ) + +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + + return int( Round( x ) ); + +#else + + volatile union { double d; int32 i; } v = { x + 6755399441055744.0 }; + return v.i; // ### NB: Assuming little-endian architecture. + +/* + ### Deprecated code - The above code based on magic numbers is faster and + more portable across platforms and compilers. + + // Default FPU rounding mode assumed to be nearest integer. + int r; + +# ifdef _MSC_VER + __asm fld x + __asm fistp dword ptr r +# else + asm volatile( "fistpl %0\n" : "=m" (r) : "t" (x) : "st" ); +# endif + + return r; +*/ + +#endif +} + +/*! + * RoundI function: Rounds \a x to the nearest integer and converts the result + * to a 32-bit signed integer. + * + * \deprecated Use RoundInt() in newly produced code. + * + * \ingroup mathematical_functions + */ +template inline int RoundI( T x ) noexcept +{ + return RoundInt( x ); +} + +/*! + * Rounds \a x to the nearest integer using the Banker's rounding rule, and + * converts the result to a 32-bit signed integer. + * + * This function is a convenience synonym for RoundInt(). + * + * \ingroup mathematical_functions + */ +template inline int RoundIntBanker( T x ) noexcept +{ + return RoundInt( x ); +} + +/*! + * Rounds \a x to the nearest integer using the arithmetic rounding rule, and + * converts the result to a 32-bit signed integer. + * + * Arithmetic rounding rounds a perfect half to the nearest digit, either odd + * or even. For example: + * + *
+ * RoundIntArithmetic( 0.5 ) -> 1
+ * RoundIntArithmetic( 1.5 ) -> 2
+ * RoundIntArithmetic( 2.5 ) -> 3
+ * RoundIntArithmetic( 3.5 ) -> 4
+ * 
+ * + * See the RoundInt() function for more information on rounding rules. + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \sa RoundInt(), RoundIntBanker() + * + * \ingroup mathematical_functions + */ +template inline int RoundIntArithmetic( T x ) noexcept +{ + PCL_PRECONDITION( x >= int_min && x <= int_max ) + + int i = TruncInt( x ); + if ( i < 0 ) + { + if ( x - i <= T( -0.5 ) ) + return i-1; + } + else + { + if ( x - i >= T( +0.5 ) ) + return i+1; + } + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * RoundInt64 function: Rounds \a x to the nearest integer and converts the + * result to a 64-bit signed integer. + * + * Since the default IEEE 754 rounding mode follows Banker's rounding rule, + * this is what you should expect when calling this function. See the + * documentation for RoundInt() for more information on rounding modes. + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \ingroup mathematical_functions + */ +inline int64 RoundInt64( double x ) noexcept +{ +#ifdef __PCL_NO_PERFORMANCE_CRITICAL_MATH_ROUTINES + + return int64( Round( x ) ); + +#else + + // ### N.B.: Default FPU rounding mode assumed to be nearest integer. + +# ifdef _MSC_VER +# ifdef _M_X64 + return _mm_cvtsd_si64( _mm_load_sd( &x ) ); +# else + int64 r; + __asm fld x + __asm fistp qword ptr r + return r; +# endif +# else + int64 r; + asm volatile( "fistpll %0\n" : "=m" (r) : "t" (x) : "st" ); + return r; +# endif + +#endif +} + +/*! + * RoundI64 function: Rounds \a x to the nearest integer and converts the + * result to a 64-bit signed integer. + * + * \deprecated Use RoundInt64() in newly produced code. + */ +inline int64 RoundI64( double x ) noexcept +{ + return RoundInt64( x ); +} + +/*! + * Rounds \a x to the nearest integer using the arithmetic rounding rule, and + * converts the result to a 64-bit signed integer. + * + * Arithmetic rounding rounds a perfect half to the nearest digit, either odd + * or even. For example: + * + *
+ * RoundIntArithmetic( 0.5 ) -> 1
+ * RoundIntArithmetic( 1.5 ) -> 2
+ * RoundIntArithmetic( 2.5 ) -> 3
+ * RoundIntArithmetic( 3.5 ) -> 4
+ * 
+ * + * See the RoundInt() function for more information on rounding rules. + * + * \note This is a performance-critical routine. It has been implemented using + * high-performance, low-level techniques that may include inline assembly code + * and/or compiler intrinsic functions. + * + * \sa RoundInt(), RoundIntBanker() + * + * \ingroup mathematical_functions + */ +inline int64 RoundInt64Arithmetic( double x ) noexcept +{ + int64 i = TruncInt64( x ); + if ( i < 0 ) + { + if ( x - i <= -0.5 ) + return i-1; + } + else + { + if ( x - i >= +0.5 ) + return i+1; + } + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * General rounding function: \a x rounded to \a n fractional digits. + * \ingroup mathematical_functions + */ +template inline T Round( T x, int n ) noexcept +{ + PCL_PRECONDITION( n >= 0 ) + T p = Pow10I()( n ); return Round( p*x )/p; +} + +// ---------------------------------------------------------------------------- + +/*! + * The exponential function 2**x. + * \ingroup mathematical_functions + */ +template inline constexpr T Pow2( T x ) noexcept +{ + // Use the relation: + // 2**x = e**(x*ln(2)) + return Exp( x*Ln2() ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Pow2I + * \brief Exponential function 2**n, \a n being a signed integer. + * + * Example of use: + * + * \code float x = Pow2I()( -2 ); // x = 1/4 \endcode + * + * \ingroup mathematical_functions + */ +template struct PCL_CLASS Pow2I +{ + T operator ()( int n ) const noexcept + { + // We shift left a single bit in 31-bit chunks. + int i = ::abs( n ), p; + double x = uint32( 1 ) << (p = Min( i, 31 )); + while ( (i -= p) != 0 ) + x *= uint32( 1 ) << (p = Min( i, 31 )); + return T( (n >= 0) ? x : 1/x ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * The exponential function x**n, where \a n is a signed integer. + * \ingroup mathematical_functions + */ +template inline T PowI( T x, int n ) noexcept +{ + if ( n == 0 ) + return T( 1 ); + + T r = x; + int i = ::abs( n ); + if ( i > 1 ) + { + do + r *= r; + while ( (i >>= 1) > 1 ); + if ( n & 1 ) + r *= x; + } + return (n > 0) ? r : T( 1/r ); +} + +/*! + * Returns \a x raised to the 4th power. + * \ingroup mathematical_functions + */ +template inline T PowI4( T x ) noexcept +{ + x *= x; return x*x; +} + +/*! + * Returns \a x raised to the 6th power. + * \ingroup mathematical_functions + */ +template inline T PowI6( T x ) noexcept +{ + x *= x*x; return x*x; +} + +/*! + * Returns \a x raised to the 8th power. + * \ingroup mathematical_functions + */ +template inline T PowI8( T x ) noexcept +{ + x *= x*x*x; return x*x; +} + +/*! + * Returns \a x raised to the 10th power. + * \ingroup mathematical_functions + */ +template inline T PowI10( T x ) noexcept +{ + x *= x*x*x*x; return x*x; +} + +/*! + * Returns \a x raised to the 12th power. + * \ingroup mathematical_functions + */ +template inline T PowI12( T x ) noexcept +{ + x *= x*x*x*x*x; return x*x; +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse hyperbolic sine function. + * + * ArcSinh( x ) = Ln( x + Sqrt( 1 + x**2 ) ) + * + * \ingroup mathematical_functions + */ +template inline constexpr T ArcSinh( T x ) noexcept +{ +#ifndef __PCL_NO_STD_INV_HYP_TRIG_FUNCTIONS + return std::asinh( x ); +#else + return Ln( x + Sqrt( 1 + x*x ) ); +#endif +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse hyperbolic cosine function. + * + * ArcCosh( x ) = 2*Ln( Sqrt( (x + 1)/2 ) + Sqrt( (x - 1)/2 ) ) + * + * \ingroup mathematical_functions + */ +template inline constexpr T ArcCosh( T x ) noexcept +{ +#ifndef __PCL_NO_STD_INV_HYP_TRIG_FUNCTIONS + return std::acosh( x ); +#else + return 2*Ln( Sqrt( (x + 1)/2 ) + Sqrt( (x - 1)/2 ) ); +#endif +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse hyperbolic tangent function. + * + * ArcTanh( x ) = (Ln( 1 + x ) - Ln( 1 - x ))/2 + * + * \ingroup mathematical_functions + */ +template inline constexpr T ArcTanh( T x ) noexcept +{ +#ifndef __PCL_NO_STD_INV_HYP_TRIG_FUNCTIONS + return std::atanh( x ); +#else + return (Ln( 1 + x ) - Ln( 1 - x ))/2; +#endif +} + +// ---------------------------------------------------------------------------- + +/*! + * Inverse haversine (archaversine) function: + * + * ArcHav( x ) = 2*ArcSin( Sqrt( x ) ) + * + * The haversine is useful to work with tiny angles. + * + * \ingroup mathematical_functions + */ +template inline constexpr T ArcHav( T x ) noexcept +{ + return 2*ArcSin( Sqrt( x ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from degrees to radians. + * \ingroup mathematical_functions + */ +template inline constexpr T Rad( T x ) noexcept +{ + return static_cast( 0.174532925199432957692369076848861272222e-01L * x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from radians to arcminutes. + * \ingroup mathematical_functions + */ +template inline constexpr T RadMin( T x ) noexcept +{ + return Deg( x )*60; +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from radians to arcseconds. + * \ingroup mathematical_functions + */ +template inline constexpr T RadSec( T x ) noexcept +{ + return Deg( x )*3600; +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from arcminutes to radians. + * \ingroup mathematical_functions + */ +template inline constexpr T MinRad( T x ) noexcept +{ + return Rad( x/60 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from arcseconds to radians. + * \ingroup mathematical_functions + */ +template inline constexpr T SecRad( T x ) noexcept +{ + return Rad( x/3600 ); +} + +/*! + * Conversion from arcseconds to radians (a synonym for SecRad()). + * \ingroup mathematical_functions + */ +template inline constexpr T AsRad( T x ) noexcept +{ + return SecRad( x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from milliarcseconds (mas) to radians. + * \ingroup mathematical_functions + */ +template inline constexpr T MasRad( T x ) noexcept +{ + return Rad( x/3600000 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion from microarcseconds (uas) to radians. + * \ingroup mathematical_functions + */ +template inline constexpr T UasRad( T x ) noexcept +{ + return Rad( x/3600000000 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * An angle in radians reduced to the [-pi,+pi] range. + * \ingroup mathematical_functions + */ +template inline constexpr T ModPi( T x ) noexcept +{ + x = Mod( x + static_cast( Pi() ), static_cast( TwoPi() ) ) - static_cast( Pi() ); + return (x < -static_cast( Pi() )) ? x + static_cast( TwoPi() ) : x; +} + +// ---------------------------------------------------------------------------- + +/*! + * An angle in radians reduced to the (-2pi,+2pi) range, that is, the remainder + * of x/(2*pi). + * \ingroup mathematical_functions + */ +template inline constexpr T Mod2Pi( T x ) noexcept +{ + return Mod( x, static_cast( TwoPi() ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * An angle in radians normalized to the [0,2pi) range. + * \ingroup mathematical_functions + */ +template inline constexpr T Norm2Pi( T x ) noexcept +{ + return ((x = Mod2Pi( x )) < 0) ? x + static_cast( TwoPi() ) : x; +} + +// ---------------------------------------------------------------------------- + +/*! + * Rotates a point on the plane. + * + * \param[out] x,y %Point coordinates. On output, these variables will + * receive the corresponding rotated coordinates. + * + * \param sa, ca Sine and cosine of the rotation angle. + * + * \param xc,yc Coordinates of the center of rotation. + * + * \ingroup mathematical_functions + */ +template +inline void Rotate( T& x, T& y, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept +{ + T1 dx = T1( x ) - T1( xc ); + T1 dy = T1( y ) - T1( yc ); + x = T( T1( xc ) + ca*dx - sa*dy ); + y = T( T1( yc ) + sa*dx + ca*dy ); +} + +/*! + * Rotates a point on the plane. + * + * This is a template instantiation of Rotate( T&, T&, T1, T1, T2, T2 ) for + * the \c int type. + * + * Rotated coordinates are rounded to the nearest integers. + * + * \ingroup mathematical_functions + */ +template +inline void Rotate( int& x, int& y, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept +{ + T1 dx = T1( x ) - T1( xc ); + T1 dy = T1( y ) - T1( yc ); + x = RoundInt( T1( xc ) + ca*dx - sa*dy ); + y = RoundInt( T1( yc ) + sa*dx + ca*dy ); +} + +/*! + * Rotates a point on the plane. + * + * This is a template instantiation of Rotate( T&, T&, T1, T1, T2, T2 ) for + * the \c long type. + * + * Rotated coordinates are rounded to the nearest integers. + * + * \ingroup mathematical_functions + */ +template +inline void Rotate( long& x, long& y, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept +{ + T1 dx = T1( x ) - T1( xc ); + T1 dy = T1( y ) - T1( yc ); + x = (long)RoundInt( T1( xc ) + ca*dx - sa*dy ); + y = (long)RoundInt( T1( yc ) + sa*dx + ca*dy ); +} + +/*! + * Rotates a point on the plane. + * + * This is a template instantiation of Rotate( T&, T&, T1, T1, T2, T2 ) for + * the \c int64 type. + * + * Rotated coordinates are rounded to the nearest integers. + * + * \ingroup mathematical_functions + */ +template +inline void Rotate( int64& x, int64& y, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept +{ + T1 dx = T1( x ) - T1( xc ); + T1 dy = T1( y ) - T1( yc ); + x = RoundInt64( T1( xc ) + ca*dx - sa*dy ); + y = RoundInt64( T1( yc ) + sa*dx + ca*dy ); +} + +/*! + * Rotates a point on the plane. + * + * \param[out] x,y %Point coordinates. On output, these variables will + * receive the corresponding rotated coordinates. + * + * \param a Rotation angle in radians. + * + * \param xc,yc Coordinates of the center of rotation. + * + * Instantiations for integer types round rotated coordinated to the nearest + * integers. + * + * \ingroup mathematical_functions + */ +template +inline void Rotate( T& x, T& y, T1 a, T2 xc, T2 yc ) noexcept +{ + T1 sa, ca; SinCos( a, sa, ca ); Rotate( x, y, sa, ca, xc, yc ); +} + +// ---------------------------------------------------------------------------- + +template inline +N __pcl_norm__( const T* i, const T* j, const P& p, N* ) noexcept +{ + PCL_PRECONDITION( p > P( 0 ) ) + N n = N( 0 ); + for ( ; i < j; ++i ) + n += Pow( Abs( N( *i ) ), N( p ) ); + return Pow( n, N( 1/p ) ); +} + +/*! + * Computes the norm of the elements in the sequence [i,j). For any real p > 0, + * the norm N is given by: + * + *
+ * N = sum( abs( x )^p )^(1/p)
+ * 
+ * + * for all x in [i,j). + * + * \ingroup mathematical_functions + * \sa L1Norm(), L2Norm() + */ +template inline T Norm( const T* i, const T* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (T*)( 0 ) ); +} + +template inline double Norm( const float* i, const float* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const int* i, const int* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const unsigned* i, const unsigned* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const int8* i, const int8* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const uint8* i, const uint8* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const int16* i, const int16* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const uint16* i, const uint16* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const int64* i, const int64* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} +template inline double Norm( const uint64* i, const uint64* j, const P& p ) noexcept +{ + return __pcl_norm__( i, j, p, (double*)( 0 ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +N __pcl_l1norm__( const T* i, const T* j, N* ) noexcept +{ + N n = N( 0 ); + for ( ; i < j; ++i ) + n += N( Abs( *i ) ); + return n; +} + +/*! + * Computes the L1 norm (or Manhattan norm) of the elements in the sequence + * [i,j). The L1 norm is the sum of the absolute values of the elements. + * + * \ingroup mathematical_functions + */ +template inline T L1Norm( const T* i, const T* j ) noexcept +{ + return __pcl_l1norm__( i, j, (T*)( 0 ) ); +} + +inline double L1Norm( const float* i, const float* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const int* i, const int* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const unsigned* i, const unsigned* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const int8* i, const int8* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const uint8* i, const uint8* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const int16* i, const int16* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const uint16* i, const uint16* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const int64* i, const int64* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} +inline double L1Norm( const uint64* i, const uint64* j ) noexcept +{ + return __pcl_l1norm__( i, j, (double*)( 0 ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +N __pcl_l2norm__( const T* i, const T* j, N* ) noexcept +{ + N n = N( 0 ); + for ( ; i < j; ++i ) + n += N( *i ) * N( *i ); + return Sqrt( n ); +} + +/*! + * Computes the L2 norm (or Euclidean norm) of the elements in the sequence + * [i,j). The L2 norm is the square root of the sum of squared elements. + * + * \ingroup mathematical_functions + */ +template inline T L2Norm( const T* i, const T* j ) noexcept +{ + return __pcl_l2norm__( i, j, (T*)( 0 ) ); +} + +inline double L2Norm( const float* i, const float* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const int* i, const int* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const unsigned* i, const unsigned* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const int8* i, const int8* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const uint8* i, const uint8* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const int16* i, const int16* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const uint16* i, const uint16* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const int64* i, const int64* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double L2Norm( const uint64* i, const uint64* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Computes the L2 norm (or Euclidean norm) of the elements in the sequence + * [i,j). This function is a synonym for L2Norm(). + * + * \ingroup mathematical_functions + */ +template inline T Norm( const T* i, const T* j ) noexcept +{ + return L2Norm( i, j ); +} + +inline double Norm( const float* i, const float* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const int* i, const int* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const unsigned* i, const unsigned* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const int8* i, const int8* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const uint8* i, const uint8* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const int16* i, const int16* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const uint16* i, const uint16* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const int64* i, const int64* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} +inline double Norm( const uint64* i, const uint64* j ) noexcept +{ + return __pcl_l2norm__( i, j, (double*)( 0 ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Computes the Julian date (JD) corresponding to a time point expressed as a + * date and a day fraction, providing the result by its separate integer and + * fractional parts. + * + * \param[out] jdi On output, the integer part of the resulting JD. + * + * \param[out] jdf On output, the fractional part of the resulting JD. + * + * \param year The year of the date. Positive and negative years are + * supported. Years are counted arithmetically: the year zero + * is the year before the year +1, that is, what historians + * call the year 1 B.C. + * + * \param month The month of the date. Usually in the [1,12] range but can + * be any integer number. + * + * \param day The day of the date. Usually in the [1,31] range but can + * be any integer number. + * + * \param dayf The day fraction. The default value is zero, which + * computes the JD at zero hours. Usually in the [0,1) range + * but can be any real number. + * + * This routine, as well as JDToCalendarTime(), implement modified versions of + * the original algorithms due to Jean Meeus. Our modifications allow for + * negative Julian dates, which extends the range of allowed dates to the past + * considerably. We developed these modifications in the context of large-scale + * solar system ephemeris calculations. + * + * The computed value is the JD corresponding to the specified date and day + * fraction, which is equal to the sum of the \a jdi and \a jdf variables. + * + * \b References + * + * Meeus, Jean (1991), Astronomical Algorithms, Willmann-Bell, Inc., + * chapter 7. + * + * \ingroup mathematical_functions + */ +void PCL_FUNC CalendarTimeToJD( int& jdi, double& jdf, int year, int month, int day, double dayf = 0 ) noexcept; + +/*! + * Computes the Julian date (JD) corresponding to a time point expressed as a + * date and a day fraction. + * + * \param year The year of the date. Positive and negative years are + * supported. Years are counted arithmetically: the year zero is + * the year before the year +1, that is, what historians call + * the year 1 B.C. + * + * \param month The month of the date. Usually in the [1,12] range but can be + * any integer number. + * + * \param day The day of the date. Usually in the [1,31] range but can be + * any integer number. + * + * \param dayf The day fraction. The default value is zero, which computes + * the JD at zero hours. Usually in the [0,1) range but can be + * any real number. + * + * This routine, as well as JDToCalendarTime(), implement modified versions of + * the original algorithms due to Jean Meeus. Our modifications allow for + * negative Julian dates, which extends the range of allowed dates to the past + * considerably. We developed these modifications in the context of large-scale + * solar system ephemeris calculations. + * + * The returned value is the JD corresponding to the specified date and day + * fraction. + * + * Because of the numerical precision of the double type (IEEE 64-bit floating + * point), this routine can return JD values accurate only to within one + * millisecond. + * + * \b References + * + * Meeus, Jean (1991), Astronomical Algorithms, Willmann-Bell, Inc., + * chapter 7. + * + * \ingroup mathematical_functions + */ +inline double CalendarTimeToJD( int year, int month, int day, double dayf = 0 ) noexcept +{ + int jdi; + double jdf; + CalendarTimeToJD( jdi, jdf, year, month, day, dayf ); + return jdi + jdf; +} + +/*! + * Computes the date and day fraction corresponding to a time point expressed + * as a Julian date (JD), specified by its separate integer and fractional + * parts. + * + * \param[out] year On output, this variable receives the year of the + * resulting date. + * + * \param[out] month On output, this variable receives the month of the + * resulting date in the range [1,12]. + * + * \param[out] day On output, this variable receives the day of the + * resulting date in the range [1,31]. Different month day + * counts and leap years are taken into account, so the + * returned day corresponds to an existing calendar date. + * + * \param[out] dayf On output, this variable receives the day fraction for the + * specified time point, in the [0,1) range. + * + * \param jdi The integer part of the input Julian date. + * + * \param jdf The fractional part of the input Julian date. + * + * The input time point must be equal to the sum of \a jdi and \a jdf. + * + * For more information about the implemented algorithms and references, see + * the documentation for CalendarTimeToJD(). + * + * \ingroup mathematical_functions + */ +void PCL_FUNC JDToCalendarTime( int& year, int& month, int& day, double& dayf, int jdi, double jdf ) noexcept; + +/*! + * Computes the date and day fraction corresponding to a time point expressed + * as a Julian date (JD). + * + * \param[out] year On output, this variable receives the year of the + * resulting date. + * + * \param[out] month On output, this variable receives the month of the + * resulting date in the range [1,12]. + * + * \param[out] day On output, this variable receives the day of the + * resulting date in the range [1,31]. Different month day + * counts and leap years are taken into account, so the + * returned day corresponds to an existing calendar date. + * + * \param[out] dayf On output, this variable receives the day fraction for the + * specified time point, in the [0,1) range. + * + * \param jd The input time point as a Julian date. + * + * Because of the numerical precision of the double type (IEEE 64-bit floating + * point), this routine can handle JD values accurate only to within one + * millisecond. + * + * For more information about the implemented algorithms and references, see + * the documentation for CalendarTimeToJD(). + * + * \ingroup mathematical_functions + */ +inline void JDToCalendarTime( int& year, int& month, int& day, double& dayf, double jd ) noexcept +{ + JDToCalendarTime( year, month, day, dayf, TruncInt( jd ), Frac( jd ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Conversion of a decimal scalar \a d to the equivalent sexagesimal decimal + * components \a sign, \a s1, \a s2 and \a s3, such that: + * + *
+ * d = sign * (s1 + (s2 + s3/60)/60)
+ * 
+ * + * with the following constraints: + * + *
+ * sign = -1 iff d < 0
+ * sign = +1 iff d ≥ 0
+ * 0 ≤ s1
+ * 0 ≤ s2 < 60
+ * 0 ≤ s3 < 60
+ * 
+ * + * \ingroup mathematical_functions + */ +template +inline void DecimalToSexagesimal( int& sign, S1& s1, S2& s2, S3& s3, const D& d ) noexcept +{ + double t1 = Abs( d ); + double t2 = Frac( t1 )*60; + double t3 = Frac( t2 )*60; + sign = (d < 0) ? -1 : +1; + s1 = S1( TruncInt( t1 ) ); + s2 = S2( TruncInt( t2 ) ); + s3 = S3( t3 ); +} + +/*! + * Conversion of the sexagesimal decimal components \a sign, \a s1, \a s2 and + * \a s3 to their equivalent decimal scalar. The returned value is equal to: + * + *
+ * ((sign < 0) ? -1 : +1)*(Abs( s1 ) + (s2 + s3/60)/60);
+ * 
+ * + * \ingroup mathematical_functions + */ +template +inline double SexagesimalToDecimal( int sign, const S1& s1, const S2& s2 = S2( 0 ), const S3& s3 = S3( 0 ) ) noexcept +{ + double d = Abs( s1 ) + (s2 + s3/60)/60; + return (sign < 0) ? -d : d; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup statistical_functions Statistical Functions + */ + +/*! + * Returns the sum of elements in a sequence [i,j). + * + * For empty sequences, this function returns zero. + * + * This is a straight implementation of a floating point sum, which is subject + * to severe roundoff errors if the number of summed elements is large. One way + * to improve on this problem is to sort the input set by decreasing order of + * absolute value \e before calling this function. A much better solution, but + * computationally expensive, is a compensated summation algorithm such as + * Kahan summation, which we have implemented in the StableSum() routine. + * + * \ingroup statistical_functions + */ +template inline double Sum( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + double sum = 0; + while ( i < j ) + sum += double( *i++ ); + return sum; +} + +/*! + * Computes the sum of elements in a sequence [i,j) using a numerically stable + * summation algorithm to minimize roundoff error. + * + * For empty sequences, this function returns zero. + * + * In the current PCL versions, this function implements the Kahan summation + * algorithm to reduce roundoff error to the machine's floating point error. + * + * \ingroup statistical_functions + */ +template inline double StableSum( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + double sum = 0; + double eps = 0; + while ( i < j ) + { + double y = double( *i++ ) - eps; + double t = sum + y; + eps = (t - sum) - y; + sum = t; + } + return sum; +} + +/*! + * Returns the sum of the absolute values of the elements in a sequence [i,j). + * + * For empty sequences, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableModulus() for a (slow) numerically stable version of + * this function. + * + * \ingroup statistical_functions + */ +template inline double Modulus( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + double S = 0; + while ( i < j ) + S += Abs( double( *i++ ) ); + return S; +} + +/*! + * Computes the sum of the absolute values of the elements in a sequence [i,j) + * using a numerically stable summation algorithm to minimize roundoff error. + * + * For empty sequences, this function returns zero. + * + * In the current PCL versions, this function implements the Kahan summation + * algorithm to reduce roundoff error to the machine's floating point error. + * + * \ingroup statistical_functions + */ +template inline double StableModulus( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + double sum = 0; + double eps = 0; + while ( i < j ) + { + double y = Abs( double( *i++ ) ) - eps; + double t = sum + y; + eps = (t - sum) - y; + sum = t; + } + return sum; +} + +/*! + * Returns the sum of the squares of the elements in a sequence [i,j). + * + * For empty sequences, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableSumOfSquares() for a (slow) numerically stable version + * of this function. + * + * \ingroup statistical_functions + */ +template inline double SumOfSquares( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + double Q = 0; + while ( i < j ) + { + double f = double( *i++ ); + Q += f*f; + } + return Q; +} + +/*! + * Computes the sum of the squares of the elements in a sequence [i,j) using a + * numerically stable summation algorithm to minimize roundoff error. + * + * For empty sequences, this function returns zero. + * + * In the current PCL versions, this function implements the Kahan summation + * algorithm to reduce roundoff error to the machine's floating point error. + * + * \ingroup statistical_functions + */ +template inline double StableSumOfSquares( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + double sum = 0; + double eps = 0; + while ( i < j ) + { + double f = double( *i++ ); + double y = f*f - eps; + double t = sum + y; + eps = (t - sum) - y; + sum = t; + } + return sum; +} + +/*! + * Returns the arithmetic mean of a sequence [i,j). + * + * For empty sequences, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableMean() for a (slow) numerically stable version of this + * function. + * + * \ingroup statistical_functions + */ +template inline double Mean( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + return Sum( i, j )/n; +} + +/*! + * Computes the arithmetic mean of a sequence [i,j) using a numerically stable + * summation algorithm to minimize roundoff error. + * + * For empty sequences, this function returns zero. + * + * In the current PCL versions, this function implements the Kahan summation + * algorithm to reduce roundoff error to the machine's floating point error. + * + * \ingroup statistical_functions + */ +template inline double StableMean( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + return StableSum( i, j )/n; +} + +/*! + * Returns the variance of a sequence [i,j) with respect to the specified + * \a center value. + * + * For sequences of less than two elements, this function returns zero. + * + * This implementation uses a two-pass compensated summation algorithm to + * minimize roundoff errors (see the references). + * + * \b References + * + * William H. Press et al., Numerical Recipes in C: The Art of Scientific + * Computing, Second Edition (1997 reprint) Cambridge University Press, + * page 613. + * + * \ingroup statistical_functions + */ +template inline double Variance( const T* __restrict__ i, const T* __restrict__ j, double center ) noexcept +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double var = 0, eps = 0; + do + { + double d = double( *i++ ) - center; + var += d*d; + eps += d; + } + while ( i < j ); + return (var - eps*eps/n)/(n - 1); +} + +/*! + * Returns the variance from the mean of a sequence [i,j). + * + * For sequences of less than two elements, this function returns zero. + * + * This implementation uses a two-pass compensated summation algorithm to + * minimize roundoff errors (see References). + * + * \b References + * + * William H. Press et al., Numerical Recipes in C: The Art of Scientific + * Computing, Second Edition (1997 reprint) Cambridge University Press, + * page 613. + * + * \ingroup statistical_functions + */ +template inline double Variance( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double m = 0; + for ( const T* f = i; f < j; ++f ) + m += double( *f ); + m /= n; + double var = 0, eps = 0; + do + { + double d = double( *i++ ) - m; + var += d*d; + eps += d; + } + while ( i < j ); + return (var - eps*eps/n)/(n - 1); +} + +/*! + * Returns the standard deviation of a sequence [i,j) with respect to the + * specified \a center value. + * + * For sequences of less than two elements, this function returns zero. + * + * \ingroup statistical_functions + */ +template inline double StdDev( const T* __restrict__ i, const T* __restrict__ j, double center ) noexcept +{ + return Sqrt( Variance( i, j, center ) ); +} + +/*! + * Returns the standard deviation from the mean of a sequence [i,j). + * + * For sequences of less than two elements, this function returns zero. + * + * \ingroup statistical_functions + */ +template inline double StdDev( const T* __restrict__ i, const T* __restrict__ j ) noexcept +{ + return Sqrt( Variance( i, j ) ); +} + +/*! + * Returns the median value of a sequence [i,j). + * + * For scalar data types the following algorithms are used: + * + * \li Hard-coded, fast selection networks for small sequences of 32 or less + * elements. + * + * \li A quick selection algorithm for sequences of up to about 2M elements. + * The actual limit has been determined empirically and can vary across PCL + * versions. This single-threaded algorithm can use up to 16 MiB of additional + * memory allocated dynamically (for 8-byte types such as \c double). + * + * \li A parallelized, fast histogram-based algorithm for sequences larger than + * the limit described above. This algorithm has negligible additional memory + * space requirements. + * + * For non-scalar data types, this function requires the following type + * conversion operator publicly defined for the type T: + * + * \code T::operator double() const; \endcode + * + * This operator will be used to generate a temporary dynamic array of + * \c double values with the length of the input sequence, which will be used + * to compute the median with the algorithms enumerated above. + * + * \b References (selection networks) + * + * \li Knuth, D. E., The Art of Computer Programming, volume 3: + * Sorting and Searching, Addison Wesley, 1973. + * + * \li Hillis, W. D., Co-evolving parasites improve simulated + * evolution as an optimization procedure. Langton, C. et al. (Eds.), + * Artificial Life II. Addison Wesley, 1992. + * + * \li Hugues Juille, Evolution of Non-Deterministic Incremental + * Algorithms as a New Approach for Search in State Spaces, 1995 + * + * \b References (quick select algorithm) + * + * \li William H. Press et al., Numerical Recipes 3rd Edition: The Art of + * Scientific Computing, Cambridge University Press, 2007, Section 8.5. + * + * \li Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, + * Addison-Wesley Professional, 2011, pp 345-347. + * + * \ingroup statistical_functions + */ +template inline double Median( const T* __restrict__ i, const T* __restrict__ j ) +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + if ( n == 1 ) + return double( *i ); + double* d = new double[ n ]; + double* __restrict__ t = d; + do + *t++ = double( *i++ ); + while ( i < j ); + double m = double( *pcl::Select( d, t, n >> 1 ) ); + if ( (n & 1) == 0 ) + m = (m + double( *pcl::Select( d, t, (n >> 1)-1 ) ))/2; + delete [] d; + return m; +} + +double PCL_FUNC Median( const unsigned char* __restrict__ i, const unsigned char* __restrict__ j ); +double PCL_FUNC Median( const signed char* __restrict__ i, const signed char* __restrict__ j ); +double PCL_FUNC Median( const wchar_t* __restrict__ i, const wchar_t* __restrict__ j ); +double PCL_FUNC Median( const unsigned short* __restrict__ i, const unsigned short* __restrict__ j ); +double PCL_FUNC Median( const signed short* __restrict__ i, const signed short* __restrict__ j ); +double PCL_FUNC Median( const unsigned int* __restrict__ i, const unsigned int* __restrict__ j ); +double PCL_FUNC Median( const signed int* __restrict__ i, const signed int* __restrict__ j ); +double PCL_FUNC Median( const unsigned long* __restrict__ i, const unsigned long* __restrict__ j ); +double PCL_FUNC Median( const signed long* __restrict__ i, const signed long* __restrict__ j ); +double PCL_FUNC Median( const unsigned long long* __restrict__ i, const unsigned long long* __restrict__ j ); +double PCL_FUNC Median( const signed long long* __restrict__ i, const signed long long* __restrict__ j ); +double PCL_FUNC Median( const float* __restrict__ i, const float* __restrict__ j ); +double PCL_FUNC Median( const double* __restrict__ i, const double* __restrict__ j ); +double PCL_FUNC Median( const long double* __restrict__ i, const long double* __restrict__ j ); + +#define CMPXCHG( a, b ) \ + if ( i[b] < i[a] ) pcl::Swap( i[a], i[b] ) + +#define MEAN( a, b ) \ + (double( a ) + double( b ))/2 + +/*! + * Returns the median value of a sequence [i,j), altering the existing order of + * elements in the input sequence. + * + * This function is intended for sequences of non-scalar objects where the + * order of elements is irrelevant, and hence generation of a working duplicate + * is unnecessary. The following type conversion operator must be publicly + * defined for the type T: + * + * \code T::operator double() const; \endcode + * + * The following algorithms are used: + * + * \li Hard-coded, fast selection networks for sequences of 9 or less elements. + * + * \li A quick selection algorithm for sequences larger than 9 elements. + * + * \note This is a \e destructive median calculation algorithm: it alters the + * existing order of items in the input [i,j) sequence. + * + * \b References (selection networks) + * + * \li Knuth, D. E., The Art of Computer Programming, volume 3: + * Sorting and Searching, Addison Wesley, 1973. + * + * \li Hillis, W. D., Co-evolving parasites improve simulated + * evolution as an optimization procedure. Langton, C. et al. (Eds.), + * Artificial Life II. Addison Wesley, 1992. + * + * \li Hugues Juille, Evolution of Non-Deterministic Incremental + * Algorithms as a New Approach for Search in State Spaces, 1995 + * + * \b References (quick select algorithm) + * + * \li William H. Press et al., Numerical Recipes 3rd Edition: The Art of + * Scientific Computing, Cambridge University Press, 2007, Section 8.5. + * + * \li Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, + * Addison-Wesley Professional, 2011, pp 345-347. + * + * \ingroup statistical_functions + */ +template inline double MedianDestructive( T* __restrict__ i, T* __restrict__ j ) noexcept +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + + switch ( n ) + { + case 1: // !? + return i[0]; + case 2: + return MEAN( i[0], i[1] ); + case 3: + CMPXCHG( 0, 1 ); CMPXCHG( 1, 2 ); + return pcl::Max( i[0], i[1] ); + case 4: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); + return MEAN( i[1], i[2] ); + case 5: + CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 0, 3 ); + CMPXCHG( 1, 4 ); CMPXCHG( 1, 2 ); CMPXCHG( 2, 3 ); + return pcl::Max( i[1], i[2] ); + case 6: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 1, 4 ); + CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 3, 4 ); + return MEAN( i[2], i[3] ); + case 7: + CMPXCHG( 0, 5 ); CMPXCHG( 0, 3 ); CMPXCHG( 1, 6 ); + CMPXCHG( 2, 4 ); CMPXCHG( 0, 1 ); CMPXCHG( 3, 5 ); + CMPXCHG( 2, 6 ); CMPXCHG( 2, 3 ); CMPXCHG( 3, 6 ); + CMPXCHG( 4, 5 ); CMPXCHG( 1, 4 ); CMPXCHG( 1, 3 ); + return pcl::Min( i[3], i[4] ); + case 8: + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); + CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); + CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 1, 4 ); + CMPXCHG( 3, 6 ); + return MEAN( i[3], i[4] ); + case 9: + CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 ); + CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 6, 7 ); + CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 ); + CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 ); CMPXCHG( 4, 7 ); + CMPXCHG( 3, 6 ); CMPXCHG( 1, 4 ); CMPXCHG( 2, 5 ); + CMPXCHG( 4, 7 ); CMPXCHG( 4, 2 ); CMPXCHG( 6, 4 ); + return pcl::Min( i[2], i[4] ); + default: + { + double m = double( *pcl::Select( i, j, n >> 1 ) ); + if ( n & 1 ) + return m; + return MEAN( m, double( *pcl::Select( i, j, (n >> 1)-1 ) ) ); + } + } +} + +#undef CMPXCHG + +#define CMPXCHG( a, b ) \ + if ( p( i[b], i[a] ) ) pcl::Swap( i[a], i[b] ) + +/*! + * Returns the median value of a sequence [i,j), altering the existing order of + * elements in the input sequence. + * + * Element comparison is given by a binary predicate \a p such that p( a, b ) + * is true for any pair a, b of elements such that a precedes b. + * + * We use fast, hard-coded selection networks for sequences of 9 or less + * elements, and a quick selection algorithm for larger sets. + * + * See the documentation of MedianDestructive( T*, T* ) for more information + * and references. + * + * \ingroup statistical_functions + */ +template inline double MedianDestructive( T* __restrict__ i, T* __restrict__ j, BP p ) noexcept +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + + switch ( n ) + { + case 1: // !? + return i[0]; + case 2: + return MEAN( i[0], i[1] ); + case 3: + CMPXCHG( 0, 1 ); CMPXCHG( 1, 2 ); + return pcl::Max( i[0], i[1] ); + case 4: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); + return MEAN( i[1], i[2] ); + case 5: + CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 0, 3 ); + CMPXCHG( 1, 4 ); CMPXCHG( 1, 2 ); CMPXCHG( 2, 3 ); + return pcl::Max( i[1], i[2] ); + case 6: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 1, 4 ); + CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 3, 4 ); + return MEAN( i[2], i[3] ); + case 7: + CMPXCHG( 0, 5 ); CMPXCHG( 0, 3 ); CMPXCHG( 1, 6 ); + CMPXCHG( 2, 4 ); CMPXCHG( 0, 1 ); CMPXCHG( 3, 5 ); + CMPXCHG( 2, 6 ); CMPXCHG( 2, 3 ); CMPXCHG( 3, 6 ); + CMPXCHG( 4, 5 ); CMPXCHG( 1, 4 ); CMPXCHG( 1, 3 ); + return pcl::Min( i[3], i[4] ); + case 8: + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); + CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); + CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 1, 4 ); + CMPXCHG( 3, 6 ); + return MEAN( i[3], i[4] ); + case 9: + CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 ); + CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 6, 7 ); + CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 ); + CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 ); CMPXCHG( 4, 7 ); + CMPXCHG( 3, 6 ); CMPXCHG( 1, 4 ); CMPXCHG( 2, 5 ); + CMPXCHG( 4, 7 ); CMPXCHG( 4, 2 ); CMPXCHG( 6, 4 ); + return pcl::Min( i[2], i[4] ); + default: + { + double m = double( *pcl::Select( i, j, n >> 1, p ) ); + if ( n & 1 ) + return m; + return MEAN( m, double( *pcl::Select( i, j, (n >> 1)-1, p ) ) ); + } + } +} + +#undef CMPXCHG +#undef MEAN + +/*! + * Returns the k-th order statistic of a sequence [i,j). + * + * For scalar data types the following algorithms are used: + * + * \li A quick selection algorithm for sequences of up to about 2M elements. + * The actual limit has been determined empirically and can vary across PCL + * versions. This single-threaded algorithm can use up to 16 MiB of additional + * memory allocated dynamically (for 8-byte types such as \c double). + * + * \li A parallelized, fast histogram-based algorithm for sequences larger than + * the limit described above. This algorithm has negligible additional memory + * space requirements. + * + * For non-scalar data types, this function requires the following type + * conversion operator publicly defined for the type T: + * + * \code T::operator double() const; \endcode + * + * This operator will be used to generate a temporary dynamic array of + * \c double values with the length of the input sequence, which will be used + * to compute the median with the quick selection algorithm. + * + * \b References (quick select algorithm) + * + * \li William H. Press et al., Numerical Recipes 3rd Edition: The Art of + * Scientific Computing, Cambridge University Press, 2007, Section 8.5. + * + * \li Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, + * Addison-Wesley Professional, 2011, pp 345-347. + * + * \ingroup statistical_functions + */ +template inline double OrderStatistic( const T* __restrict__ i, const T* __restrict__ j, distance_type k ) +{ + distance_type n = j - i; + if ( n < 1 || k < 0 || k >= n ) + return 0; + if ( n == 1 ) + return double( *i ); + double* d = new double[ n ]; + double* t = d; + do + *t++ = double( *i++ ); + while ( i < j ); + double s = *pcl::Select( d, t, k ); + delete [] d; + return s; +} + +double PCL_FUNC OrderStatistic( const unsigned char* __restrict__ i, const unsigned char* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const signed char* __restrict__ i, const signed char* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const wchar_t* __restrict__ i, const wchar_t* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const unsigned short* __restrict__ i, const unsigned short* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const signed short* __restrict__ i, const signed short* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const unsigned int* __restrict__ i, const unsigned int* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const signed int* __restrict__ i, const signed int* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const unsigned long* __restrict__ i, const unsigned long* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const signed long* __restrict__ i, const signed long* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const unsigned long long* __restrict__ i, const unsigned long long* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const signed long long* __restrict__ i, const signed long long* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const float* __restrict__ i, const float* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const double* __restrict__ i, const double* __restrict__ j, distance_type k ); +double PCL_FUNC OrderStatistic( const long double* __restrict__ i, const long double* __restrict__ j, distance_type k ); + +/*! + * Returns the k-th order statistic of a sequence [i,j), altering the existing + * order of elements in the input sequence. + * + * This function is intended for sequences of non-scalar objects where the + * order of elements is irrelevant, and hence generation of a working duplicate + * is unnecessary. The following type conversion operator must be publicly + * defined for the type T: + * + * <\code> T::operator double() const; \endcode + * + * The quick selection algorithm is used to find the k-th element in the + * ordered sequence. + * + * \note This is a \e destructive algorithm: it alters the existing order of + * items in the input [i,j) sequence. + * + * \b References (quick select algorithm) + * + * \li William H. Press et al., Numerical Recipes 3rd Edition: The Art of + * Scientific Computing, Cambridge University Press, 2007, Section 8.5. + * + * \li Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, + * Addison-Wesley Professional, 2011, pp 345-347. + * + * \ingroup statistical_functions + */ +template inline double OrderStatisticDestructive( T* __restrict__ i, T* __restrict__ j, distance_type k ) noexcept +{ + distance_type n = j - i; + if ( n < 1 || k < 0 || k >= n ) + return 0; + if ( n == 1 ) + return double( *i ); + return double( *pcl::Select( i, j, k ) ); +} + +/*! + * Returns the k-th order statistic of a sequence [i,j), altering the existing + * order of elements in the input sequence. + * + * Element comparison is given by a binary predicate \a p such that p( a, b ) + * is true for any pair a, b of elements such that a precedes b. + * + * See the documentation of OrderStatisticDestructive( T*, T*, distance_type ) + * for more information and references. + * + * \ingroup statistical_functions + */ +template inline double OrderStatisticDestructive( const T* __restrict__ i, const T* __restrict__ j, distance_type k, BP p ) noexcept +{ + distance_type n = j - i; + if ( n < 1 || k < 0 || k >= n ) + return 0; + if ( n == 1 ) + return double( *i ); + return double( *pcl::Select( i, j, k, p ) ); +} + +/*! + * Computes the two-sided, asymmetric trimmed mean of a sequence [i,j). + * + * The returned value is the arithmetic mean of a sequence [I+l,J-h-1], where + * [I,J) is the input sequence [i,j) sorted in ascending order. + * + * Let n = j-i be the length of the input sequence. For empty sequences + * (n ≤ 0) or completely truncated sequences (l+h >= n), this function + * returns zero. Otherwise the returned value is the arithmetic mean of the + * nonrejected n-l-h elements in the sorted sequence, as described above. + * + * \ingroup statistical_functions + */ +template inline double TrimmedMean( const T* __restrict__ i, const T* __restrict__ j, distance_type l = 1, distance_type h = 1 ) +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + if ( l+h < 1 ) + return Sum( i, j )/n; + if ( l+h >= n ) + return 0; + for ( double s = 0, + t0 = OrderStatistic( i, j, l ), + t1 = OrderStatistic( i, j, n-h-1 ); ; ) + { + double x = double( *i ); + if ( x >= t0 ) + if ( x <= t1 ) + s += x; + if ( ++i == j ) + return s/(n - l - h); + } +} + +/*! + * Computes the two-sided, asymmetric trimmed mean of a sequence [i,j), + * possibly altering the existing order of elements in the input sequence. + * + * The returned value is the arithmetic mean of a sequence [I+l,J-h-1], where + * [I,J) represents the input sequence [i,j) sorted in ascending order. + * + * Let n = j-i be the length of the input sequence. For empty sequences + * (n ≤ 0) or completely truncated sequences (l+h >= n), this function + * returns zero. Otherwise the returned value is the arithmetic mean of the + * nonrejected n-l-h elements in the sorted sequence, as described above. + * + * \note This is a \e destructive trimmed mean calculation algorithm: it may + * alter the existing order of items in the input [i,j) sequence. + * + * \ingroup statistical_functions + */ +template inline double TrimmedMeanDestructive( T* __restrict__ i, T* __restrict__ j, distance_type l = 1, distance_type h = 1 ) noexcept +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + if ( l+h < 1 ) + return Sum( i, j )/n; + if ( l+h >= n ) + return 0; + for ( double s = 0, + t0 = OrderStatisticDestructive( i, j, l ), + t1 = OrderStatisticDestructive( i, j, n-h-1 ); ; ) + { + double x = double( *i ); + if ( x >= t0 ) + if ( x <= t1 ) + s += x; + if ( ++i == j ) + return s/(n - l - h); + } +} + +/*! + * Computes the two-sided, asymmetric trimmed mean of squares of a sequence + * [i,j). + * + * The returned value is the arithmetic mean of squares of a sequence + * [I+l,J-h-1], where [I,J) represents the input sequence [i,j) sorted in + * ascending order. + * + * Let n = j-i be the length of the input sequence. For empty sequences + * (n ≤ 0) or completely truncated sequences (l+h >= n), this function + * returns zero. Otherwise the returned value is the arithmetic mean of the + * squared nonrejected n-l-h elements in the sorted sequence, as described + * above. + * + * \ingroup statistical_functions + */ +template inline double TrimmedMeanOfSquares( const T* __restrict__ i, const T* __restrict__ j, distance_type l = 1, distance_type h = 1 ) +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + if ( l+h < 1 ) + return Sum( i, j )/n; + if ( l+h >= n ) + return 0; + for ( double s = 0, + t0 = OrderStatistic( i, j, l ), + t1 = OrderStatistic( i, j, n-h-1 ); ; ) + { + double x = double( *i ); + if ( x >= t0 ) + if ( x <= t1 ) + s += x*x; + if ( ++i == j ) + return s/(n - l - h); + } +} + +/*! + * Computes the two-sided, asymmetric trimmed mean of squares of a sequence + * [i,j), possibly altering the existing order of elements in the input + * sequence. + * + * The returned value is the arithmetic mean of squares of a sequence + * [I+l,J-h-1], where [I,J) represents the input sequence [i,j) sorted in + * ascending order. + * + * Let n = j-i be the length of the input sequence. For empty sequences + * (n ≤ 0) or completely truncated sequences (l+h >= n), this function + * returns zero. Otherwise the returned value is the arithmetic mean of the + * squared nonrejected n-l-h elements in the sorted sequence, as described + * above. + * + * \note This is a \e destructive trimmed mean of squares calculation + * algorithm: it may alter the existing order of items in the input [i,j) + * sequence. + * + * \ingroup statistical_functions + */ +template inline double TrimmedMeanOfSquaresDestructive( T* __restrict__ i, T* __restrict__ j, distance_type l = 1, distance_type h = 1 ) noexcept +{ + distance_type n = j - i; + if ( n < 1 ) + return 0; + if ( l+h < 1 ) + return Sum( i, j )/n; + if ( l+h >= n ) + return 0; + for ( double s = 0, + t0 = OrderStatisticDestructive( i, j, l ), + t1 = OrderStatisticDestructive( i, j, n-h-1 ); ; ) + { + double x = double( *i ); + if ( x >= t0 ) + if ( x <= t1 ) + s += x*x; + if ( ++i == j ) + return s/(n - l - h); + } +} + +/*! + * Returns the average absolute deviation of the values in a sequence [i,j) + * with respect to the specified \a center value. + * + * When the median of the sequence is used as the center value, this function + * returns the average absolute deviation from the median, which is a + * well-known estimator of dispersion. + * + * For sequences of less than two elements, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableAvgDev() for a (slow) numerically stable version of + * this function. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \ingroup statistical_functions + */ +template inline double AvgDev( const T* __restrict__ i, const T* __restrict__ j, double center ) noexcept +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double d = 0; + do + d += Abs( double( *i++ ) - center ); + while ( i < j ); + return d/n; +} + +/*! + * Returns the average absolute deviation of the values in a sequence [i,j) + * with respect to the specified \a center value, using a numerically stable + * summation algorithm to minimize roundoff error. + * + * When the median of the sequence is used as the center value, this function + * returns the average absolute deviation from the median, which is a + * well-known estimator of dispersion. + * + * For sequences of less than two elements, this function returns zero. + * + * In the current PCL versions, this function implements the Kahan summation + * algorithm to reduce roundoff error to the machine's floating point error. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \ingroup statistical_functions + */ +template inline double StableAvgDev( const T* __restrict__ i, const T* __restrict__ j, double center ) noexcept +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double sum = 0; + double eps = 0; + do + { + double y = Abs( double( *i++ ) - center ) - eps; + double t = sum + y; + eps = (t - sum) - y; + sum = t; + } + while ( i < j ); + return sum/n; +} + +/*! + * Returns the average absolute deviation from the median of the values in a + * sequence [i,j). + * + * The average absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For sequences of less than two elements, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableAvgDev() for a (slow) numerically stable version of + * this function. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \ingroup statistical_functions + */ +template inline double AvgDev( const T* __restrict__ i, const T* __restrict__ j ) +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double m = Median( i, j ); + double d = 0; + do + d += Abs( double( *i++ ) - m ); + while ( i < j ); + return d/n; +} + +/*! + * Computes the average absolute deviation from the median of the values in a + * sequence [i,j) using a numerically stable summation algorithm to minimize + * roundoff error. + * + * The average absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For sequences of less than two elements, this function returns zero. + * + * In the current PCL versions, this function implements the Kahan summation + * algorithm to reduce roundoff error to the machine's floating point error. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \ingroup statistical_functions + */ +template inline double StableAvgDev( const T* __restrict__ i, const T* __restrict__ j ) +{ + return pcl::StableAvgDev( i, j, pcl::Median( i, j ) ); +} + +/*! + * \struct TwoSidedEstimate + * \brief Two-sided descriptive statistical estimate. + * + * This POD structure is returned by functions implementing two-sided scale + * estimators. Given a sample X = {x_0,...,x_n-1} and a reference center value + * m (typically, the median of X), a two-sided scale estimate is computed as + * two separate components: A low estimate for all x in X such that + * x ≤ m, and a high estimate for all x in X such that x > m. + * + * Two-sided scale estimates are important in normalization for accurate + * outlier rejection and sample distribution characterization, especially for + * skewed or asymmetric distributions. + * + * \ingroup statistical_functions + * \sa TwoSidedAvgDev(), TwoSidedMAD(), TwoSidedBiweightMidvariance() + */ +struct TwoSidedEstimate +{ + double low = 0; //!< Low estimate component. + double high = 0; //!< High estimate component. + + /*! + * Default constructor. Both components are initialized to zero. + */ + TwoSidedEstimate() = default; + + /*! + * Copy constructor. + */ + TwoSidedEstimate( const TwoSidedEstimate& ) = default; + + /*! + * Move constructor. + */ + TwoSidedEstimate( TwoSidedEstimate&& ) = default; + + /*! + * Copy assignment operator. + */ + TwoSidedEstimate& operator =( const TwoSidedEstimate& ) = default; + + /*! + * Move assignment operator. + */ + TwoSidedEstimate& operator =( TwoSidedEstimate&& ) = default; + + /*! + * Constructor from separate low and high components. + */ + template + TwoSidedEstimate( const T1& l, const T2& h ) + : low( double( l ) ) + , high( double( h ) ) + { + } + + /*! + * Constructor from a unique component value \a x, which is assigned to both + * the low and high estimate components. + */ + template + TwoSidedEstimate( const T& x ) + { + low = high = double( x ); + } + + /*! + * Returns true iff this two-sided scale estimate is valid. A two-sided + * scale estimate is valid if both the low and high components are finite, + * positive and nonzero with respect to the machine epsilon for the type + * \c double. + */ + bool IsValid() const noexcept + { + return IsFinite( low ) && low > std::numeric_limits::epsilon() + && IsFinite( high ) && high > std::numeric_limits::epsilon(); + } + + /*! + * Returns the sum of the low and high estimate components. + */ + double Total() const noexcept + { + return low + high; + } + + /*! + * Returns the arithmetic mean of the low and high estimate components if + * both are nonzero. Otherwise returns the maximum component. + */ + double Mean() const noexcept + { + if ( low != 0 ) + { + if ( high != 0 ) + return (low + high)/2; + return low; + } + return high; + } + + /*! + * Conversion to scalar. Equivalent to Mean(). + */ + explicit operator double() const noexcept + { + return Mean(); + } + + /*! + * Assignment-multiplication by a scalar. Returns a reference to this + * object. + */ + TwoSidedEstimate& operator *=( double x ) noexcept + { + low *= x; + high *= x; + return *this; + } + + /*! + * Assignment-division by a scalar. Returns a reference to this object. + */ + TwoSidedEstimate& operator /=( double x ) noexcept + { + low /= x; + high /= x; + return *this; + } + + /*! + * Assignment-division by a two-sided estimate. Returns a reference to this + * object. + */ + TwoSidedEstimate& operator /=( const TwoSidedEstimate& e ) noexcept + { + low /= e.low; + high /= e.high; + return *this; + } + + /*! + * Returns the result of multiplying this two-sided estimate by a scalar. + */ + TwoSidedEstimate operator *( double x ) const noexcept + { + return { low*x, high*x }; + } + + /*! + * Returns the result of dividing this two-sided estimate by a scalar. + */ + TwoSidedEstimate operator /( double x ) const noexcept + { + return { low/x, high/x }; + } + + /*! + * Returns the result of the component wise division of this two-sided + * estimate by another two-sided estimate. + */ + TwoSidedEstimate operator /( const TwoSidedEstimate& e ) const noexcept + { + return { low/e.low, high/e.high }; + } +}; + +/*! + * Returns the component wise square root of a two-sided estimate. + * \ingroup statistical_functions + */ +inline TwoSidedEstimate Sqrt( const TwoSidedEstimate& e ) noexcept +{ + return { Sqrt( e.low ), Sqrt( e.high ) }; +} + +/*! + * Returns the component wise exponent function of a two-sided estimate. + * \ingroup statistical_functions + */ +template inline TwoSidedEstimate Pow( const TwoSidedEstimate& e, T x ) noexcept +{ + double x_ = double( x ); + return { Pow( e.low, x_ ), Pow( e.high, x_ ) }; +} + +/*! + * Returns the two-sided average absolute deviation of the values in a sequence + * [i,j) with respect to the specified \a center value. + * + * When the median of the sequence is used as the center value, this function + * returns the average absolute deviation from the median, which is a + * well-known estimator of dispersion. + * + * For sequences of less than two elements, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableAvgDev() for a (slow) numerically stable version of + * this function. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \ingroup statistical_functions + */ +template inline TwoSidedEstimate TwoSidedAvgDev( const T* __restrict__ i, const T* __restrict__ j, double center ) noexcept +{ + double dl = 0, dh = 0; + distance_type nl = 0, nh = 0; + while ( i < j ) + { + double x = double( *i++ ); + if ( x <= center ) + { + dl += center - x; + ++nl; + } + else + { + dh += x - center; + ++nh; + } + } + return { (nl > 1) ? dl/nl : 0.0, + (nh > 1) ? dh/nh : 0.0 }; +} + +/*! + * Returns the two-sided average absolute deviation from the median of the + * values in a sequence [i,j). + * + * The average absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For sequences of less than two elements, this function returns zero. + * + * See the remarks made for the Sum() function, which are equally applicable in + * this case. See StableAvgDev() for a (slow) numerically stable version of + * this function. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + * + * \ingroup statistical_functions + */ +template inline TwoSidedEstimate TwoSidedAvgDev( const T* __restrict__ i, const T* __restrict__ j ) +{ + return pcl::TwoSidedAvgDev( i, j, pcl::Median( i, j ) ); +} + +/*! + * Returns the median absolute deviation (MAD) of the values in a sequence + * [i,j) with respect to the specified \a center value. + * + * The MAD is a well-known robust estimator of scale. + * + * For sequences of less than two elements, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, its result must be multiplied by the constant 1.4826. + * + * \ingroup statistical_functions + */ +template inline double MAD( const T* __restrict__ i, const T* __restrict__ j, double center ) +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double* d = new double[ n ]; + double* p = d; + do + *p++ = Abs( double( *i++ ) - center ); + while ( i < j ); + double m = pcl::Median( d, d+n ); + delete [] d; + return m; +} + +double PCL_FUNC MAD( const unsigned char* __restrict__ i, const unsigned char* __restrict__ j, double center ); +double PCL_FUNC MAD( const signed char* __restrict__ i, const signed char* __restrict__ j, double center ); +double PCL_FUNC MAD( const wchar_t* __restrict__ i, const wchar_t* __restrict__ j, double center ); +double PCL_FUNC MAD( const unsigned short* __restrict__ i, const unsigned short* __restrict__ j, double center ); +double PCL_FUNC MAD( const signed short* __restrict__ i, const signed short* __restrict__ j, double center ); +double PCL_FUNC MAD( const unsigned int* __restrict__ i, const unsigned int* __restrict__ j, double center ); +double PCL_FUNC MAD( const signed int* __restrict__ i, const signed int* __restrict__ j, double center ); +double PCL_FUNC MAD( const unsigned long* __restrict__ i, const unsigned long* __restrict__ j, double center ); +double PCL_FUNC MAD( const signed long* __restrict__ i, const signed long* __restrict__ j, double center ); +double PCL_FUNC MAD( const unsigned long long* __restrict__ i, const unsigned long long* __restrict__ j, double center ); +double PCL_FUNC MAD( const signed long long* __restrict__ i, const signed long long* __restrict__ j, double center ); +double PCL_FUNC MAD( const float* __restrict__ i, const float* __restrict__ j, double center ); +double PCL_FUNC MAD( const double* __restrict__ i, const double* __restrict__ j, double center ); +double PCL_FUNC MAD( const long double* __restrict__ i, const long double* __restrict__ j, double center ); + +/*! + * Returns the median absolute deviation from the median (MAD) for the values + * in a sequence [i,j). + * + * The MAD is a well-known robust estimator of scale. + * + * For sequences of less than two elements, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, its result must be multiplied by the constant 1.4826. + * + * \ingroup statistical_functions + */ +template inline double MAD( const T* __restrict__ i, const T* __restrict__ j ) +{ + return pcl::MAD( i, j, pcl::Median( i, j ) ); +} + +/*! + * Returns the two-sided median absolute deviation (MAD) of the values in a + * sequence [i,j) with respect to the specified \a center value. + * + * The MAD is a well-known robust estimator of scale. + * + * For sequences of less than two elements, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, its result must be multiplied by the constant 1.4826. + * + * \ingroup statistical_functions + */ +template inline TwoSidedEstimate TwoSidedMAD( const T* __restrict__ i, const T* __restrict__ j, double center ) +{ + distance_type n = j - i; + if ( n < 2 ) + return 0; + double* d = new double[ n ]; + double* __restrict__ p = d; + double* __restrict__ q = d + n; + do + { + double x = double( *i++ ); + if ( x <= center ) + *p++ = center - x; + else + *--q = x - center; + } + while( i < j ); + double l = pcl::Median( d, p ); + double h = pcl::Median( q, d+n ); + delete [] d; + return { l, h }; +} + +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const unsigned char* __restrict__ i, const unsigned char* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const signed char* __restrict__ i, const signed char* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const wchar_t* __restrict__ i, const wchar_t* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const unsigned short* __restrict__ i, const unsigned short* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const signed short* __restrict__ i, const signed short* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const unsigned int* __restrict__ i, const unsigned int* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const signed int* __restrict__ i, const signed int* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const unsigned long* __restrict__ i, const unsigned long* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const signed long* __restrict__ i, const signed long* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const unsigned long long* __restrict__ i, const unsigned long long* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const signed long long* __restrict__ i, const signed long long* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const float* __restrict__ i, const float* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const double* __restrict__ i, const double* __restrict__ j, double center ); +TwoSidedEstimate PCL_FUNC TwoSidedMAD( const long double* __restrict__ i, const long double* __restrict__ j, double center ); + +/*! + * Returns the two-sided median absolute deviation from the median (MAD) for + * the values in a sequence [i,j). + * + * The MAD is a well-known robust estimator of scale. + * + * For sequences of less than two elements, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, its result must be multiplied by the constant 1.4826. + * + * \ingroup statistical_functions + */ +template inline TwoSidedEstimate TwoSidedMAD( const T* __restrict__ i, const T* __restrict__ j ) +{ + return pcl::TwoSidedMAD( i, j, pcl::Median( i, j ) ); +} + +/*! + * Returns the Sn scale estimator of Rousseeuw and Croux for a sequence [x,xn): + * + *
+ * Sn = c * low_median( high_median( |x_i - x_j| ) )
+ * 
+ * + * where low_median() is the order statistic of rank (n + 1)/2, and + * high_median() is the order statistic of rank n/2 + 1. n >= 2 is the number + * of elements in the sequence: n = xn - x. + * + * This implementation is a direct C++ translation of the original FORTRAN + * code by the authors (see References). The algorithm has O(n*log_2(n)) time + * complexity and uses O(n) additional storage. + * + * The constant c = 1.1926 must be used to make the Sn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for + * consistency with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median Absolute + * Deviation, Journal of the American Statistical Association, Vol. 88, + * pp. 1273-1283. + * + * \note This is a \e destructive algorithm: it may alter the initial order of + * items in the specified [x,xn) sequence. + * + * \ingroup statistical_functions + */ +template double Sn( T* __restrict__ x, T* __restrict__ xn ) +{ + /* + * N.B.: In the code below, lines commented with an asterisk (*) have been + * modified with respect to the FORTRAN original to account for zero-based + * array indices. + */ + + distance_type n = xn - x; + if ( n < 2 ) + return 0; + + pcl::Sort( x, xn ); + + double* a2 = new double[ n ]; + a2[0] = double( x[n >> 1] ) - double( x[0] ); // * + + distance_type nh = (n + 1) >> 1; + + for ( distance_type i = 2; i <= nh; ++i ) + { + distance_type nA = i-1; + distance_type nB = n - i; + distance_type diff = nB - nA; + distance_type leftA = 1; + distance_type leftB = 1; + distance_type rightA = nB; + distance_type Amin = (diff >> 1) + 1; + distance_type Amax = (diff >> 1) + nA; + + while ( leftA < rightA ) + { + distance_type length = rightA - leftA + 1; + distance_type even = (length & 1) == 0; + distance_type half = (length - 1) >> 1; + distance_type tryA = leftA + half; + distance_type tryB = leftB + half; + + if ( tryA < Amin ) + leftA = tryA + even; + else + { + if ( tryA > Amax ) + { + rightA = tryA; + leftB = tryB + even; + } + else + { + double medA = double( x[i-1] ) - double( x[i-2 - tryA + Amin] ); // * + double medB = double( x[tryB + i-1] ) - double( x[i-1] ); // * + if ( medA >= medB ) + { + rightA = tryA; + leftB = tryB + even; + } + else + leftA = tryA + even; + } + } + } + + if ( leftA > Amax ) + a2[i-1] = double( x[leftB + i-1] ) - double( x[i-1] ); // * + else + { + double medA = double( x[i-1] ) - double( x[i-2 - leftA + Amin] ); // * + double medB = double( x[leftB + i-1] ) - double( x[i-1] ); + a2[i-1] = pcl::Min( medA, medB ); // * + } + } + + for ( distance_type i = nh + 1; i < n; ++i ) + { + distance_type nA = n - i; + distance_type nB = i - 1; + distance_type diff = nB - nA; + distance_type leftA = 1; + distance_type leftB = 1; + distance_type rightA = nB; + distance_type Amin = (diff >> 1) + 1; + distance_type Amax = (diff >> 1) + nA; + + while ( leftA < rightA ) + { + distance_type length = rightA - leftA + 1; + distance_type even = (length & 1) == 0; + distance_type half = (length - 1) >> 1; + distance_type tryA = leftA + half; + distance_type tryB = leftB + half; + + if ( tryA < Amin) + leftA = tryA + even; + else + { + if ( tryA > Amax ) + { + rightA = tryA; + leftB = tryB + even; + } + else + { + double medA = double( x[i + tryA - Amin] ) - double( x[i-1] ); // * + double medB = double( x[i-1] ) - double( x[i-1 - tryB] ); // * + if ( medA >= medB ) + { + rightA = tryA; + leftB = tryB + even; + } + else + leftA = tryA + even; + } + } + } + + if ( leftA > Amax ) + a2[i-1] = double( x[i-1] ) - double( x[i-1 - leftB] ); // * + else + { + double medA = double( x[i + leftA - Amin] ) - double( x[i-1] ); // * + double medB = double( x[i-1] ) - double( x[i-1 - leftB] ); // * + a2[i-1] = pcl::Min( medA, medB ); // * + } + } + + a2[n-1] = double( x[n-1] ) - double( x[nh-1] ); // * + + /* + * Correction for a finite sample + */ + double cn; + switch ( n ) + { + case 2: cn = 0.743; break; + case 3: cn = 1.851; break; + case 4: cn = 0.954; break; + case 5: cn = 1.351; break; + case 6: cn = 0.993; break; + case 7: cn = 1.198; break; + case 8: cn = 1.005; break; + case 9: cn = 1.131; break; + default: cn = (n & 1) ? n/(n - 0.9) : 1.0; break; + } + + double sn = cn * *pcl::Select( a2, a2+n, nh-1 ); + + delete [] a2; + return sn; +} + +/*! + * \internal + * Auxiliary routine for Qn(). + * + * Algorithm to compute the weighted high median in O(n) time. + * + * The weighted high median is defined as the smallest a[j] such that the sum + * of the weights of all a[i] <= a[j] is strictly greater than half of the + * total weight. + */ +inline double __pcl_whimed__( double* a, distance_type* iw, distance_type n, + double* acand, distance_type* iwcand ) +{ + distance_type wtotal = 0; + for ( distance_type i = 0; i < n; ++i ) + wtotal += iw[i]; + + for ( distance_type nn = n, wrest = 0; ; ) + { + double trial = *pcl::Select( a, a+nn, nn >> 1 ); // * + + distance_type wleft = 0; + distance_type wmid = 0; + distance_type wright = 0; + for ( distance_type i = 0; i < nn; ++i ) + if ( a[i] < trial ) + wleft += iw[i]; + else if ( a[i] > trial ) + wright += iw[i]; + else + wmid += iw[i]; + + if ( 2*(wrest + wleft) > wtotal ) + { + distance_type kcand = 0; + for ( distance_type i = 0; i < nn; ++i ) + if ( a[i] < trial ) + { + acand[kcand] = a[i]; + iwcand[kcand] = iw[i]; + ++kcand; + } + nn = kcand; + } + else + { + if ( 2*(wrest + wleft + wmid) > wtotal ) + return trial; + + distance_type kcand = 0; + for ( distance_type i = 0; i < nn; ++i ) + if ( a[i] > trial ) + { + acand[kcand] = a[i]; + iwcand[kcand] = iw[i]; + ++kcand; + } + nn = kcand; + wrest += wleft + wmid; + } + + for ( distance_type i = 0; i < nn; ++i ) + { + a[i] = acand[i]; + iw[i] = iwcand[i]; + } + } +} + +/*! + * Returns the Qn scale estimator of Rousseeuw and Croux for a sequence [x,xn): + * + *
+ * Qn = c * first_quartile( |x_i - x_j| : i < j )
+ * 
+ * + * where first_quartile() is the order statistic of rank (n + 1)/4. n >= 2 is + * the number of elements in the sequence: n = xn - x. + * + * This implementation is a C++ translation of the original FORTRAN code by the + * authors (see References). The algorithm has O(n*log_2(n)) time complexity + * and the implementation requires about O(9*n) additional storage. + * + * The constant c = 2.2219 must be used to make the Qn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for consistency + * with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median Absolute + * Deviation, Journal of the American Statistical Association, Vol. 88, + * pp. 1273-1283. + * + * \note This is a \e destructive algorithm: it may alter the initial order of + * items in the specified [x,xn) sequence. + * + * \ingroup statistical_functions + */ +template double Qn( T* __restrict__ x, T* __restrict__ xn ) +{ + distance_type n = xn - x; + if ( n < 2 ) + return 0; + + double* y = new double[ n ]; + double* work = new double[ n ]; + double* acand = new double[ n ]; + distance_type* iwcand = new distance_type[ n ]; + distance_type* left = new distance_type[ n ]; + distance_type* right = new distance_type[ n ]; + distance_type* P = new distance_type[ n ]; + distance_type* Q = new distance_type[ n ]; + distance_type* weight = new distance_type[ n ]; + + distance_type h = (n >> 1) + 1; + distance_type k = (h*(h - 1)) >> 1; + for ( distance_type i = 0; i < n; ++i ) + { + y[i] = double( x[i] ); + left[i] = n - i + 1; // * + right[i] = (i <= h) ? n : n - i + h; // N.B. The original code is "right[i] = n" + } + + pcl::Sort( y, y+n ); + + distance_type nL = (n*(n + 1)) >> 1; + distance_type nR = n*n; + distance_type knew = k + nL; + + bool found = false; + double qn; + + while ( nR-nL > n ) + { + distance_type j = 0; // * + for ( distance_type i = 1; i < n; ++i ) // * + if ( left[i] <= right[i] ) + { + weight[j] = right[i] - left[i] + 1; + work[j] = double( y[i] ) - y[n - left[i] - (weight[j] >> 1)]; + ++j; + } + qn = __pcl_whimed__( work, weight, j, acand, iwcand ); + + for ( distance_type i = n-1, j = 0; i >= 0; --i ) // * + { + while ( j < n && double( y[i] ) - y[n-j-1] < qn ) + ++j; + P[i] = j; + } + + for ( distance_type i = 0, j = n+1; i < n; ++i ) // * + { + while ( double( y[i] ) - y[n-j+1] > qn ) + --j; + Q[i] = j; + } + + double sumP = 0; + double sumQ = 0; + for ( distance_type i = 0; i < n; ++i ) + { + sumP += P[i]; + sumQ += Q[i] - 1; + } + + if ( knew <= sumP ) + { + for ( distance_type i = 0; i < n; ++i ) + right[i] = P[i]; + nR = sumP; + } + else if ( knew > sumQ ) + { + for ( distance_type i = 0; i < n; ++i ) + left[i] = Q[i]; + nL = sumQ; + } + else + { + found = true; + break; + } + } + + if ( !found ) + { + distance_type j = 0; + for ( distance_type i = 1; i < n; ++i ) + for ( distance_type jj = left[i]; jj <= right[i]; ++jj, ++j ) + work[j] = double( y[i] ) - y[n-jj]; // * + qn = *pcl::Select( work, work+j, knew-nL-1 ); // * + } + + /* + * Correction for a finite sample + */ + double dn; + switch ( n ) + { + case 2: dn = 0.399; break; + case 3: dn = 0.994; break; + case 4: dn = 0.512; break; + case 5: dn = 0.844; break; + case 6: dn = 0.611; break; + case 7: dn = 0.857; break; + case 8: dn = 0.669; break; + case 9: dn = 0.872; break; + default: dn = (n & 1) ? n/(n + 1.4) : n/(n + 3.8); break; + } + qn *= dn; + + delete [] y; + delete [] work; + delete [] acand; + delete [] iwcand; + delete [] left; + delete [] right; + delete [] P; + delete [] Q; + delete [] weight; + + return qn; +} + +/*! + * Returns a biweight midvariance (BWMV) for the elements in a sequence [x,xn). + * + * \param x, xn Define a sequence of sample data points for which the BWMV + * estimator will be calculated. + * + * \param center Reference center value. Normally, the median of the sample + * should be used. + * + * \param sigma A reference estimate of dispersion. Normally, the median + * absolute deviation from the median (MAD) of the sample should + * be used. + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param reducedLength If true, reduce the sample size to exclude rejected + * elements. This tends to approximate the true dispersion of + * the data more accurately for relatively small samples, or + * samples with large amounts of outliers. Note that this + * departs from the standard definition of biweight midvariance, + * where the total number of data items is used to scale the + * variance estimate. If false, use the full sample size, + * including rejected elements, which gives a standard biweight + * midvariance estimate. + * + * The square root of the biweight midvariance is a robust estimator of scale. + * It is an efficient estimator with respect to many statistical distributions + * (about 87% Gaussian efficiency), and appears to have a breakdown point close + * to 0.5 (the same as MAD). + * + * For sequences of less than two elements, this function returns zero. + * + * \note To make the BWMV estimator consistent with the standard deviation of + * a normal distribution, its square root must be multiplied by the constant + * 0.991. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and Hypothesis + * Testing, 4th Edition, Elsevier Inc., Section 3.12.1. + * + * \ingroup statistical_functions + */ +template +double BiweightMidvariance( const T* __restrict__ x, const T* __restrict__ xn, double center, + double sigma, int k = 9, bool reducedLength = false ) noexcept +{ + distance_type n = xn - x; + if ( n < 2 ) + return 0; + + double kd = k * sigma; + if ( kd < 0 || 1 + kd == 1 ) + return 0; + + double num = 0, den = 0; + distance_type nr = 0; + for ( ; x < xn; ++x ) + { + double xc = double( *x ) - center; + double y = xc/kd; + if ( Abs( y ) < 1 ) + { + double y2 = y*y; + double y21 = 1 - y2; + num += xc*xc * y21*y21*y21*y21; + den += y21 * (1 - 5*y2); + ++nr; + } + } + + den *= den; + return (1 + den != 1) ? (reducedLength ? nr : n)*num/den : 0.0; +} + +/*! + * Returns a two-sided biweight midvariance (BWMV) for the elements in a + * sequence [x,xn). + * + * \param x, xn Define a sequence of sample data points for which the + * two-sided BWMV estimator will be calculated. + * + * \param center Reference center value. Normally, the median of the sample + * should be used. + * + * \param sigma A reference two-sided estimate of dispersion. Normally, the + * two-sided median absolute deviation from the median (MAD) of + * the sample should be used. See the TwoSidedMAD() function. + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param reducedLength If true, reduce the sample size to exclude rejected + * elements. Size reduction is performed separately for the low + * and high halves of the data. This tends to approximate the + * true dispersion of the data more accurately for relatively + * small samples, or samples with large amounts of outliers. + * Note that this departs from the standard definition of + * biweight midvariance, where the total number of data items is + * used to scale the variance estimate. If false, use the full + * sample size, including rejected elements, which gives a + * standard biweight midvariance estimate. + * + * See BiweightMidvariance() for more information and references. + * + * \ingroup statistical_functions + */ +template +TwoSidedEstimate TwoSidedBiweightMidvariance( const T* __restrict__ x, const T* __restrict__ xn, double center, + const TwoSidedEstimate& sigma, int k = 9, bool reducedLength = false ) noexcept +{ + double kd0 = k * sigma.low; + double kd1 = k * sigma.high; + if ( kd0 < 0 || 1 + kd0 == 1 || kd1 < 0 || 1 + kd1 == 1 ) + return 0; + + double num0 = 0, den0 = 0, num1 = 0, den1 = 0; + size_type n0 = 0, n1 = 0, nr0 = 0, nr1 = 0; + for ( ; x < xn; ++x ) + { + double xc = double( *x ) - center; + bool low = xc <= 0; + if ( low ) + ++n0; + else + ++n1; + + double y = xc/(low ? kd0 : kd1); + if ( pcl::Abs( y ) < 1 ) + { + double y2 = y*y; + double y21 = 1 - y2; + double num = xc*xc * y21*y21*y21*y21; + double den = y21 * (1 - 5*y2); + if ( low ) + { + num0 += num; + den0 += den; + ++nr0; + } + else + { + num1 += num; + den1 += den; + ++nr1; + } + } + } + + den0 *= den0; + den1 *= den1; + return { (n0 >= 2 && 1 + den0 != 1) ? (reducedLength ? nr0 : n0)*num0/den0 : 0.0, + (n1 >= 2 && 1 + den1 != 1) ? (reducedLength ? nr1 : n1)*num1/den1 : 0.0 }; +} + +/*! + * Returns a percentage bend midvariance (PBMV) for the elements in a sequence + * [x,xn). + * + * \param x, xn Define a sequence of sample data points for which the PBWV + * estimator will be calculated. + * + * \param center Reference center value. Normally, the median of the sample + * should be used. + * + * \param beta Rejection parameter in the [0,0.5] range. Higher values + * improve robustness to outliers (i.e., increase the breakdown + * point of the estimator) at the expense of a lower efficiency. + * The default value is beta=0.2. + * + * The square root of the percentage bend midvariance is a robust estimator of + * scale. With the default beta=0.2, its Gaussian efficiency is 67%. With + * beta=0.1, its efficiency is 85% but its breakdown is only 0.1. + * + * For sequences of less than two elements, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2012), Introduction to Robust Estimation and Hypothesis + * Testing, 3rd Edition, Elsevier Inc., Section 3.12.3. + * + * \ingroup statistical_functions + */ +template +double BendMidvariance( const T* __restrict__ x, const T* __restrict__ xn, double center, double beta = 0.2 ) +{ + distance_type n = xn - x; + if ( n < 2 ) + return 0; + + beta = Range( beta, 0.0, 0.5 ); + distance_type m = Floor( (1 - beta)*n + 0.5 ); + + double* w = new double[ n ]; + for ( distance_type i = 0; i < n; ++i ) + w[i] = Abs( double( x[i] ) - center ); + double wb = *pcl::Select( w, w+n, m ); + delete [] w; + if ( 1 + wb == 1 ) + return 0; + + double num = 0; + distance_type den = 0; + for ( ; x < xn; ++x ) + { + double y = (double( *x ) - center)/wb; + double f = Max( -1.0, Min( 1.0, y ) ); + num += f*f; + if ( Abs( y ) < 1 ) + ++den; + } + + den *= den; + return (1 + den != 1) ? n*wb*wb*num/den : 0.0; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup special_functions Special Functions + */ + +/*! + * Evaluation of the regularized incomplete beta function I_x( a, b ). + * + * \param a,b The a and b parameters of the beta function being evaluated. + * + * \param x Function evaluation point. Must be in the range [0,1]. + * + * \param eps Relative accuracy of the returned function evaluation. The + * default value is 1.0e-8. + * + * This implementation is adapted from original code by Lewis Van Winkle, + * released under zlib license: + * + *
+ * https://codeplea.com/incomplete-beta-function-c
+ * https://github.com/codeplea/incbeta
+ * 
+ * + * Copyright (c) 2016, 2017 Lewis Van Winkle + * + * \ingroup special_functions + */ +inline double IncompleteBeta( double a, double b, double x, double eps = 1.0e-8 ) noexcept +{ + if ( x < 0 || x > 1 ) + return std::numeric_limits::infinity(); + + /* + * The continued fraction converges nicely for x < (a+1)/(a+b+2) + */ + if ( x > (a + 1)/(a + b + 2) ) + return 1 - IncompleteBeta( b, a, 1 - x ); // Use the fact that beta is symmetric + + /* + * Find the first part before the continued fraction. + */ + double lbeta_ab = lgamma( a ) + lgamma( b ) - lgamma( a + b ); + double front = Exp( Ln( x )*a + Ln( 1 - x )*b - lbeta_ab )/a; + + /* + * Use Lentz's algorithm to evaluate the continued fraction. + */ + const double tiny = 1.0e-30; + double f = 1, c = 1, d = 0; + for ( int i = 0; i <= 200; ++i ) + { + int m = i >> 1; + double numerator; + if ( i & 1 ) + numerator = -((a + m)*(a + b + m)*x)/((a + 2*m)*(a + 2*m + 1)); // Odd term + else if ( i > 0 ) + numerator = (m*(b - m)*x)/((a + 2*m - 1)*(a + 2*m)); // Even term + else + numerator = 1; // First numerator is 1.0 + + /* + * Do an iteration of Lentz's algorithm. + */ + d = 1 + numerator*d; + if ( Abs( d ) < tiny ) + d = tiny; + d = 1/d; + c = 1 + numerator/c; + if ( Abs( c ) < tiny ) + c = tiny; + double cd = c*d; + f *= cd; + if ( Abs( 1 - cd ) < eps ) + return front*(f - 1); + } + + // Needed more loops, did not converge. + return std::numeric_limits::infinity(); +} + +// ---------------------------------------------------------------------------- + +/*! + * The error function: erf( \a x ). + * \ingroup mathematical_functions + */ +template inline constexpr T Erf( T x ) noexcept +{ + return std::erf( x ); +} + +/*! + * The inverse error function: erf^-1( \a x ). + * + * Code adapted from erfinv implementation by Lakshay Garg: + * + * https://github.com/lakshayg/erfinv + * + * Copyright (c) 2017-2019 Lakshay Garg + * Licensed under MIT license. + * + * \ingroup mathematical_functions + */ +template inline constexpr T ErfInv( T x ) noexcept +{ + if ( x < -1 || x > 1 ) + return std::numeric_limits::quiet_NaN(); + if ( x == 1 ) + return std::numeric_limits::infinity(); + if ( x == -1 ) + return -std::numeric_limits::infinity(); + + const long double A0 = 1.1975323115670912564578e0L; + const long double A1 = 4.7072688112383978012285e1L; + const long double A2 = 6.9706266534389598238465e2L; + const long double A3 = 4.8548868893843886794648e3L; + const long double A4 = 1.6235862515167575384252e4L; + const long double A5 = 2.3782041382114385731252e4L; + const long double A6 = 1.1819493347062294404278e4L; + const long double A7 = 8.8709406962545514830200e2L; + + const long double B0 = 1.0000000000000000000e0L; + const long double B1 = 4.2313330701600911252e1L; + const long double B2 = 6.8718700749205790830e2L; + const long double B3 = 5.3941960214247511077e3L; + const long double B4 = 2.1213794301586595867e4L; + const long double B5 = 3.9307895800092710610e4L; + const long double B6 = 2.8729085735721942674e4L; + const long double B7 = 5.2264952788528545610e3L; + + const long double C0 = 1.42343711074968357734e0L; + const long double C1 = 4.63033784615654529590e0L; + const long double C2 = 5.76949722146069140550e0L; + const long double C3 = 3.64784832476320460504e0L; + const long double C4 = 1.27045825245236838258e0L; + const long double C5 = 2.41780725177450611770e-1L; + const long double C6 = 2.27238449892691845833e-2L; + const long double C7 = 7.74545014278341407640e-4L; + + const long double D0 = 1.4142135623730950488016887e0L; + const long double D1 = 2.9036514445419946173133295e0L; + const long double D2 = 2.3707661626024532365971225e0L; + const long double D3 = 9.7547832001787427186894837e-1L; + const long double D4 = 2.0945065210512749128288442e-1L; + const long double D5 = 2.1494160384252876777097297e-2L; + const long double D6 = 7.7441459065157709165577218e-4L; + const long double D7 = 1.4859850019840355905497876e-9L; + + const long double E0 = 6.65790464350110377720e0L; + const long double E1 = 5.46378491116411436990e0L; + const long double E2 = 1.78482653991729133580e0L; + const long double E3 = 2.96560571828504891230e-1L; + const long double E4 = 2.65321895265761230930e-2L; + const long double E5 = 1.24266094738807843860e-3L; + const long double E6 = 2.71155556874348757815e-5L; + const long double E7 = 2.01033439929228813265e-7L; + + const long double F0 = 1.414213562373095048801689e0L; + const long double F1 = 8.482908416595164588112026e-1L; + const long double F2 = 1.936480946950659106176712e-1L; + const long double F3 = 2.103693768272068968719679e-2L; + const long double F4 = 1.112800997078859844711555e-3L; + const long double F5 = 2.611088405080593625138020e-5L; + const long double F6 = 2.010321207683943062279931e-7L; + const long double F7 = 2.891024605872965461538222e-15L; + + long double abs_x = Abs( x ); + + if ( abs_x <= 0.85L ) + { + long double r = 0.180625L - 0.25L * x*x; + long double num = (((((((A7*r + A6)*r + A5)*r + A4)*r + A3)*r + A2)*r + A1)*r + A0); + long double den = (((((((B7*r + B6)*r + B5)*r + B4)*r + B3)*r + B2)*r + B1)*r + B0); + return T( x * num/den ); + } + + long double r = Sqrt( Ln2() - Ln( 1 - abs_x ) ); + long double num = 0, den = 0; + if ( r <= 5 ) + { + r = r - 1.6L; + num = (((((((C7*r + C6)*r + C5)*r + C4)*r + C3)*r + C2)*r + C1)*r + C0); + den = (((((((D7*r + D6)*r + D5)*r + D4)*r + D3)*r + D2)*r + D1)*r + D0); + } + else + { + r = r - 5.0L; + num = (((((((E7*r + E6)*r + E5)*r + E4)*r + E3)*r + E2)*r + E1)*r + E0); + den = (((((((F7*r + F6)*r + F5)*r + F4)*r + F3)*r + F2)*r + F1)*r + F0); + } + + return T( std::copysign( num/den, x ) ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup hash_functions Non-Cryptographic Hash Functions + */ + +/*! + * Computes a 64-bit non-cryptographic hash function. + * + * \param data Address of the first byte of the input data block. + * + * \param size Length in bytes of the input data block. + * + * \param seed Optional seed value for initialization of the hash function. + * If \a seed is zero or is not specified, the seed will be set + * equal to the length of the data block. + * + * Returns a 64-bit hash value computed from the input data block. + * + *
+ * Test vector: "The quick brown fox jumps over the lazy dog"
+ * Hash64 checksum = 9a11f5e9468d7425
+ *
+ * Test vector: "" (empty string)\n
+ * Hash64 checksum = ef46db3751d8e999
+ * 
+ * + * This function implements the xxHash algorithm by Yann Collet. Our code is an + * adaptation of the original code by the author: + * + *
+ * https://github.com/Cyan4973/xxHash
+ * 
+ * + * Copyright (C) 2012-2014, Yann Collet. \n + * The original code has been released under the BSD 2-Clause License: + * + *
+ * http://www.opensource.org/licenses/bsd-license.php
+ * 
+ * + * \ingroup hash_functions + */ +inline uint64 Hash64( const void* data, size_type size, uint64 seed = 0 ) noexcept +{ +#define PRIME64_1 11400714785074694791ULL +#define PRIME64_2 14029467366897019727ULL +#define PRIME64_3 1609587929392839161ULL +#define PRIME64_4 9650029242287828579ULL +#define PRIME64_5 2870177450012600261ULL + + const uint8* p = (const uint8*)data; + const uint8* end = p + size; + uint64 h64; + + if ( seed == 0 ) + seed = size; + + if ( size >= 32 ) + { + const uint8* limit = end - 32; + uint64 v1 = seed + PRIME64_1 + PRIME64_2; + uint64 v2 = seed + PRIME64_2; + uint64 v3 = seed + 0; + uint64 v4 = seed - PRIME64_1; + + do + { + v1 += *(uint64*)p * PRIME64_2; + p += 8; + v1 = RotL( v1, 31 ); + v1 *= PRIME64_1; + v2 += *(uint64*)p * PRIME64_2; + p += 8; + v2 = RotL( v2, 31 ); + v2 *= PRIME64_1; + v3 += *(uint64*)p * PRIME64_2; + p += 8; + v3 = RotL( v3, 31 ); + v3 *= PRIME64_1; + v4 += *(uint64*)p * PRIME64_2; + p += 8; + v4 = RotL( v4, 31 ); + v4 *= PRIME64_1; + } + while ( p <= limit ); + + h64 = RotL( v1, 1 ) + RotL( v2, 7 ) + RotL( v3, 12 ) + RotL( v4, 18 ); + + v1 *= PRIME64_2; + v1 = RotL( v1, 31 ); + v1 *= PRIME64_1; + h64 ^= v1; + h64 = h64 * PRIME64_1 + PRIME64_4; + + v2 *= PRIME64_2; + v2 = RotL( v2, 31 ); + v2 *= PRIME64_1; + h64 ^= v2; + h64 = h64 * PRIME64_1 + PRIME64_4; + + v3 *= PRIME64_2; + v3 = RotL( v3, 31 ); + v3 *= PRIME64_1; + h64 ^= v3; + h64 = h64 * PRIME64_1 + PRIME64_4; + + v4 *= PRIME64_2; + v4 = RotL( v4, 31 ); + v4 *= PRIME64_1; + h64 ^= v4; + h64 = h64 * PRIME64_1 + PRIME64_4; + } + else + { + h64 = seed + PRIME64_5; + } + + h64 += size; + + while ( p+8 <= end ) + { + uint64 k1 = *(uint64*)p; + k1 *= PRIME64_2; + k1 = RotL( k1, 31 ); + k1 *= PRIME64_1; + h64 ^= k1; + h64 = RotL( h64, 27 ) * PRIME64_1 + PRIME64_4; + p += 8; + } + + if ( p+4 <= end ) + { + h64 ^= (uint64)(*(uint32*)p) * PRIME64_1; + h64 = RotL( h64, 23 ) * PRIME64_2 + PRIME64_3; + p += 4; + } + + while ( p < end ) + { + h64 ^= *p * PRIME64_5; + h64 = RotL( h64, 11 ) * PRIME64_1; + ++p; + } + + h64 ^= h64 >> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; + +#undef PRIME64_1 +#undef PRIME64_2 +#undef PRIME64_3 +#undef PRIME64_4 +#undef PRIME64_5 +} + +/*! + * Computes a 32-bit non-cryptographic hash function. + * + * \param data Address of the first byte of the input data block. + * + * \param size Length in bytes of the input data block. + * + * \param seed Optional seed value for initialization of the hash function. + * If \a seed is zero or is not specified, the seed will be set + * equal to the length of the data block. + * + * Returns a 32-bit hash value computed from the input data block. + * + *
+ * Test vector: "The quick brown fox jumps over the lazy dog"\n
+ * Hash32 checksum = 752cd1b8
+ *
+ * Test vector: "" (empty string)\n
+ * Hash32 checksum = 2cc5d05
+ * 
+ * + * This function implements the xxHash algorithm by Yann Collet. Our code is an + * adaptation of the original code by the author: + * + *
+ * https://github.com/Cyan4973/xxHash
+ * 
+ * + * Copyright (C) 2012-2014, Yann Collet. \n + * The original code has been released under the BSD 2-Clause License: + * + *
+ * http://www.opensource.org/licenses/bsd-license.php
+ * 
+ * + * \ingroup hash_functions + */ +inline uint32 Hash32( const void* data, size_type size, uint32 seed = 0 ) noexcept +{ +#define PRIME32_1 2654435761U +#define PRIME32_2 2246822519U +#define PRIME32_3 3266489917U +#define PRIME32_4 668265263U +#define PRIME32_5 374761393U + + const uint8* p = (const uint8*)data; + const uint8* end = p + size; + uint32 h32; + + if ( seed == 0 ) + seed = uint32( size ); + + if ( size >= 16 ) + { + const uint8* limit = end - 16; + uint32 v1 = seed + PRIME32_1 + PRIME32_2; + uint32 v2 = seed + PRIME32_2; + uint32 v3 = seed + 0; + uint32 v4 = seed - PRIME32_1; + + do + { + v1 += *(uint32*)p * PRIME32_2; + v1 = RotL( v1, 13 ); + v1 *= PRIME32_1; + p += 4; + v2 += *(uint32*)p * PRIME32_2; + v2 = RotL( v2, 13 ); + v2 *= PRIME32_1; + p += 4; + v3 += *(uint32*)p * PRIME32_2; + v3 = RotL( v3, 13 ); + v3 *= PRIME32_1; + p += 4; + v4 += *(uint32*)p * PRIME32_2; + v4 = RotL( v4, 13 ); + v4 *= PRIME32_1; + p += 4; + } + while ( p <= limit ); + + h32 = RotL( v1, 1 ) + RotL( v2, 7 ) + RotL( v3, 12 ) + RotL( v4, 18 ); + } + else + { + h32 = seed + PRIME32_5; + } + + h32 += (uint32)size; + + while ( p+4 <= end ) + { + h32 += *(uint32*)p * PRIME32_3; + h32 = RotL( h32, 17 ) * PRIME32_4 ; + p+=4; + } + + while ( p < end ) + { + h32 += *p * PRIME32_5; + h32 = RotL( h32, 11 ) * PRIME32_1 ; + ++p; + } + + h32 ^= h32 >> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; + +#undef PRIME32_1 +#undef PRIME32_2 +#undef PRIME32_3 +#undef PRIME32_4 +#undef PRIME32_5 +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Math_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Math.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Matrix.h b/3rdparty/include/pcl/Matrix.h new file mode 100644 index 0000000..087bca9 --- /dev/null +++ b/3rdparty/include/pcl/Matrix.h @@ -0,0 +1,3749 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Matrix.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_Matrix_h +#define __PCL_Matrix_h + +/// \file pcl/Matrix.h + +#include +#include + +#include +#include +#include +#include +#include +#include // pcl::Reverse() +#include +#include + +#ifndef __PCL_NO_MATRIX_STATISTICS +# include +# include +#endif + +#if !defined( __PCL_NO_MATRIX_IMAGE_RENDERING ) && !defined( __PCL_NO_MATRIX_IMAGE_CONVERSION ) +# include +# include +#endif + +#if !defined( __PCL_NO_MATRIX_PHASE_MATRICES ) && !defined( __PCL_NO_VECTOR_INSTANTIATE ) +# include +#endif + +/* + * Valid filter kernel sizes are odd integers >= 3. This macro is used for the + * KernelFilter and SeparableFilter classes to ensure validity of filter + * matrices and vectors. + */ +#define PCL_VALID_KERNEL_SIZE( n ) (n ? Max( 3, n|1 ) : 0) + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericMatrix + * \brief Generic dynamic matrix of arbitrary dimensions. + * + * %GenericMatrix is a lightweight template class implementing a matrix of + * arbitrary size. This class provides the following main features: + * + * \li Implicit data sharing with reference counting and copy-on-write + * functionality. %GenericMatrix instances can safely be passed as function + * return values and by-value function arguments. + * + * \li Thread-safe. %GenericMatrix instances can safely be accessed from + * multiple threads. The reference counter implements atomic reference and + * dereference operations. + * + * \li Efficient matrix storage and access to matrix elements. %Matrix + * elements are dynamically allocated as a single, contiguous memory block. + * + * \li Support for a comprehensive set of matrix operations, including matrix + * inversion and transposition, scalar-to-matrix and matrix-to-matrix + * arithmetic operations, and image to/from matrix conversions. + * + * \li Calculation of a variety of descriptive statistics for matrix elements. + * + * \sa GenericVector, \ref matrix_operators, \ref matrix_types + */ +template +class PCL_CLASS GenericMatrix : public DirectContainer +{ +public: + + /*! + * Represents a matrix element. + */ + typedef T element; + + /*! + * Represents a vector of matrix elements. + */ + typedef GenericVector vector; + + /*! + * Represents a mutable matrix block iterator. In a matrix of n rows and m + * columns, a block iterator allows iteration on the entire set of matrix + * elements from {0,0} to {n-1,m-1} in row-column order. + */ + typedef element* block_iterator; + + /*! + * Represents an immutable matrix block iterator. In a matrix of n rows and + * m columns, a block iterator allows iteration on the entire set of matrix + * elements from {0,0} to {n-1,m-1} in row-column order. + */ + typedef const element* const_block_iterator; + + /*! + * Constructs an empty matrix. + * An empty matrix has no elements and zero dimensions. + */ + GenericMatrix() + { + m_data = new Data; + } + + /*! + * Constructs an uninitialized matrix. + * + * \param rows Number of matrix rows (≥ 0). + * \param cols Number of matrix columns (≥ 0). + * + * Matrix elements are not initialized by this constructor; the newly + * created matrix will contain unpredictable values. + */ + GenericMatrix( int rows, int cols ) + { + PCL_PRECONDITION( rows >= 0 && cols >= 0 ) + m_data = new Data( rows, cols ); + } + + /*! + * Constructs a matrix and fills it with a constant value. + * + * \param x Initial value for all matrix elements. + * \param rows Number of matrix rows (≥ 0). + * \param cols Number of matrix columns (≥ 0). + */ + GenericMatrix( const element& x, int rows, int cols ) + { + PCL_PRECONDITION( rows >= 0 && cols >= 0 ) + m_data = new Data( rows, cols ); + pcl::Fill( m_data->Begin(), m_data->End(), x ); + } + + /*! + * Constructs a matrix and initializes it with values from a static buffer. + * + * \param a Address of the first item of a static array for + * initialization of matrix elements. The array must provide + * at least \a rows x \a cols consecutive elements stored in + * row order (all elements of the first matrix row followed + * by all elements of the second row, and so on). + * + * \param rows Number of matrix rows (≥ 0). + * + * \param cols Number of matrix columns (≥ 0). + */ + template + GenericMatrix( const T1* a, int rows, int cols ) + { + PCL_PRECONDITION( rows >= 0 && cols >= 0 ) + m_data = new Data( rows, cols ); + if ( a != nullptr ) + { + block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + const T1* __restrict__ k = a; + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = element( *k ); + } + } + + /*! + * Constructs a 3x3 matrix initialized with the specified element values. + * + * The resulting square matrix will be initialized as follows: + * + *
+    * a00, a01, a02
+    * a10, a11, a12
+    * a20, a21, a22
+    * 
+ */ + template + GenericMatrix( const T1& a00, const T1& a01, const T1& a02, + const T1& a10, const T1& a11, const T1& a12, + const T1& a20, const T1& a21, const T1& a22 ) + { + m_data = new Data( 3, 3 ); + block_iterator __restrict__ v = m_data->Begin(); + v[0] = element( a00 ); v[1] = element( a01 ); v[2] = element( a02 ); + v[3] = element( a10 ); v[4] = element( a11 ); v[5] = element( a12 ); + v[6] = element( a20 ); v[7] = element( a21 ); v[8] = element( a22 ); + } + + /*! + * Copy constructor. This object will reference the same data that is being + * referenced by the specified matrix \a x. + */ + GenericMatrix( const GenericMatrix& x ) + : m_data( x.m_data ) + { + m_data->Attach(); + } + + /*! + * Move constructor. + */ + GenericMatrix( GenericMatrix&& x ) + : m_data( x.m_data ) + { + x.m_data = nullptr; + } + + /*! + * Constructs a matrix as a copy of a rectangular subset of another matrix. + * + * \param x Source matrix from which this object will acquire element + * values. + * + * \param i0 Starting row in \a x. Corresponds to the first (top) row + * of this matrix. + * + * \param j0 Starting column in \a x. Corresponds to the first + * (leftmost) column of this matrix. + * + * \param rows Number of matrix rows. + * + * \param cols Number of matrix columns. + * + * If the specified submatrix is invalid, i.e. if the specified row or + * column don't exist, or if the specified number of rows and columns exceed + * the dimensions of the source matrix \a x, this constructor constrains the + * submatrix coordinates and dimensions to the nearest valid values, + * possibly constructing an empty matrix. + */ + GenericMatrix( const GenericMatrix& x, int i0, int j0, int rows, int cols ) + { + i0 = Range( i0, 0, Max( 0, x.Rows()-1 ) ); + j0 = Range( j0, 0, Max( 0, x.Cols()-1 ) ); + rows = Range( rows, 0, Max( 0, x.Rows()-i0 ) ); + cols = Range( cols, 0, Max( 0, x.Cols()-j0 ) ); + m_data = new Data( rows, cols ); + for ( int i = 0; i < m_data->Rows(); ++i, ++i0 ) + for ( int j = 0; j < m_data->Cols(); ++j, ++j0 ) + m_data->v[i][j] = x.m_data->v[i0][j0]; + } + +#ifndef __PCL_NO_MATRIX_IMAGE_CONVERSION + + /*! + * Constructs a matrix from image pixel samples. + * + * This constructor converts pixel sample values to matrix elements for a + * rectangular region of a channel of the specified \a image. + * + * \param image %Image from which matrix elements will be generated. + * + * \param rect A rectangular region in image pixel coordinates, from + * which this matrix will be generated. If this parameter is + * not specified, or if an empty rectangle is specified, this + * function will perform the matrix conversion for the + * current rectangular selection in the image, that is, for + * image.SelectedRectangle(). + * + * \param channel Channel index. Must be the zero-based index of an existing + * channel in the image, or an integer < 0. If this parameter + * is not specified, or if a negative integer is specified, + * this function will perform the matrix conversion for the + * currently selected channel in the image, that is, for + * image.SelectedChannel(). + * + * The newly created matrix is a representation of the intersection of the + * specified (or implicitly selected) rectangular region with the image for + * the scalar data type T of this matrix instantiation. All predefined pixel + * sample types are supported, including integer, real and complex pixels. + * + * If there is no intersection between the rectangular region and the image, + * this constructor yields an empty matrix. + * + * Note that if the source image is of a floating point type (either real or + * complex) and the scalar type T of this matrix instantiation is of an + * integer type, out-of-range matrix elements will be truncated to either + * zero or to the maximum integer value, if the corresponding source pixel + * sample is outside the normalized [0,1] range. + */ + template + GenericMatrix( const GenericImage

& image, const Rect& rect = Rect( 0 ), int channel = -1 ) + { + GenericMatrix M = FromImage( image, rect, channel ); + pcl::Swap( m_data, M.m_data ); + } + + /*! + * Constructs a matrix from image pixel samples. + * + * This constructor converts pixel sample values to matrix elements for a + * rectangular region of a channel of the image transported by the specified + * %ImageVariant. + * + * If the specified %ImageVariant object does not transport an image, this + * constructor yields an empty matrix. + * + * Refer to the documentation for + * GenericMatrix::GenericMatrix( const GenericImage&, const Rect&, int ) for + * more information about the conversion performed by this constructor. + */ + GenericMatrix( const ImageVariant& image, const Rect& rect = Rect( 0 ), int channel = -1 ) + { + GenericMatrix M = FromImage( image, rect, channel ); + pcl::Swap( m_data, M.m_data ); + } + +#endif // !__PCL_NO_MATRIX_IMAGE_CONVERSION + + /*! + * Destroys a %GenericMatrix object. This destructor dereferences the matrix + * data. If the matrix data becomes unreferenced, it is destroyed and + * deallocated immediately. + */ + virtual ~GenericMatrix() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + /*! + * Deallocates matrix data, yielding an empty matrix. + */ + void Clear() + { + if ( !IsEmpty() ) + if ( m_data->IsUnique() ) + m_data->Deallocate(); + else + { + Data* newData = new Data( 0, 0 ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * If this instance and the specified source instance \a x reference + * different matrix data, the data previously referenced by this object is + * dereferenced. If the previous data becomes unreferenced, it is destroyed + * and deallocated. Then the data being referenced by \a x is also + * referenced by this object. + * + * If this instance and the specified source instance \a x already reference + * the same matrix data, then this function does nothing. + */ + GenericMatrix& operator =( const GenericMatrix& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns a matrix \a x to this object. + * + * If this instance and the specified source instance \a x reference + * different matrix data, the data previously referenced by this object is + * dereferenced. If the previous data becomes unreferenced, it is destroyed + * and deallocated. Then the data being referenced by \a x is also + * referenced by this object. + * + * If this instance and the specified source instance \a x already reference + * the same matrix data, then this function does nothing. + */ + void Assign( const GenericMatrix& x ) + { + x.m_data->Attach(); + DetachFromData(); + m_data = x.m_data; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GenericMatrix& operator =( GenericMatrix&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from another matrix \a x to this object. + * + * Decrements the reference counter of the current matrix data. If the data + * becomes unreferenced, it is destroyed and deallocated. The matrix data + * referenced by the source object \a x is then transferred to this object, + * and the source object \a x is left empty. + * + * \warning The source matrix \a x will be an invalid object after calling + * this function, and hence should be destroyed immediately. Any attempt to + * access an invalid object will most likely lead to a crash. + */ + void Transfer( GenericMatrix& x ) + { + DetachFromData(); + m_data = x.m_data; + x.m_data = nullptr; + } + + /*! + * Transfers data from another matrix \a x to this object. + * + * Decrements the reference counter of the current matrix data. If the data + * becomes unreferenced, it is destroyed and deallocated. The matrix data + * referenced by the source object \a x is then transferred to this object, + * and the source object \a x is left empty. + * + * \warning The source matrix \a x will be an invalid object after calling + * this function, and hence should be destroyed immediately. Any attempt to + * access an invalid object will most likely lead to a crash. + */ + void Transfer( GenericMatrix&& x ) + { + DetachFromData(); + m_data = x.m_data; + x.m_data = nullptr; + } + + /*! + * Exchanges two matrices \a x1 and \a x2. + * + * This function is efficient because it simply swaps the internal matrix + * data pointers owned by the objects. + */ + friend void Swap( GenericMatrix& x1, GenericMatrix& x2 ) noexcept + { + pcl::Swap( x1.m_data, x2.m_data ); + } + + /*! + * Assigns a constant scalar \a x to all elements of this matrix. Returns a + * reference to this object. + * + * Before assigning a constant value to all matrix elements, this function + * ensures that this instance uniquely references its matrix data, + * generating a new matrix data block if necessary. + */ + GenericMatrix& operator =( const element& x ) + { + if ( !IsUnique() ) + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + DetachFromData(); + m_data = newData; + } + pcl::Fill( m_data->Begin(), m_data->End(), x ); + return *this; + } + +#define IMPLEMENT_SCALAR_ASSIGN_OP( op ) \ + if ( IsUnique() ) \ + { \ + block_iterator __restrict__ i = m_data->Begin(); \ + const_block_iterator __restrict__ j = m_data->End(); \ + PCL_IVDEP \ + for ( ; i < j; ++i ) \ + *i op##= x; \ + } \ + else \ + { \ + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); \ + block_iterator __restrict__ i = newData->Begin(); \ + const_block_iterator __restrict__ j = newData->End(); \ + const_block_iterator __restrict__ k = m_data->Begin(); \ + PCL_IVDEP \ + for ( ; i < j; ++i, ++k ) \ + *i = *k op x; \ + DetachFromData(); \ + m_data = newData; \ + } \ + return *this; + + /*! + * Adds a constant scalar \a x to all elements of this matrix. Returns a + * reference to this object. + * + * Before adding a constant value to all matrix elements, this function + * ensures that this instance uniquely references its matrix data, + * generating a duplicate if necessary. + */ + GenericMatrix& operator +=( const element& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( + ) + } + + /*! + * Subtracts a constant scalar \a x from all elements of this matrix. + * Returns a reference to this object. + * + * Before subtracting a constant value from all matrix elements, this + * function ensures that this instance uniquely references its matrix data, + * generating a duplicate if necessary. + */ + GenericMatrix& operator -=( const element& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( - ) + } + + /*! + * Multiplies all elements of this matrix by a constant scalar \a x. Returns + * a reference to this object. + * + * Before multiplying all matrix elements by a constant value, this function + * ensures that this instance uniquely references its matrix data, + * generating a duplicate if necessary. + */ + GenericMatrix& operator *=( const element& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( * ) + } + + /*! + * Divides all elements of this matrix by a constant scalar \a x. Returns a + * reference to this object. + * + * Before dividing all matrix elements by a constant value, this function + * ensures that this instance uniquely references its matrix data, + * generating a duplicate if necessary. + */ + GenericMatrix& operator /=( const element& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( / ) + } + + /*! + * Raises all elements of this matrix to a constant scalar \a x. Returns a + * reference to this object. + * + * Before raising all matrix elements to a constant value, this function + * ensures that this instance uniquely references its matrix data, + * generating a duplicate if necessary. + */ + GenericMatrix& operator ^=( const element& x ) + { + if ( IsUnique() ) + { + block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = pcl::Pow( *i, x ); + } + else + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = newData->Begin(); + const_block_iterator __restrict__ j = newData->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Pow( *k, x ); + DetachFromData(); + m_data = newData; + } + return *this; + } + +#undef IMPLEMENT_SCALAR_ASSIGN_OP + +#ifndef __PCL_NO_MATRIX_ELEMENT_WISE_ARITHMETIC_OPERATIONS + +#define IMPLEMENT_ELEMENT_WISE_ASSIGN_OP( op ) \ + if ( IsUnique() ) \ + { \ + block_iterator __restrict__ i = m_data->Begin(); \ + const_block_iterator __restrict__ j = pcl::Min( m_data->End(), \ + m_data->Begin() + x.NumberOfElements() ); \ + const_block_iterator __restrict__ k = x.m_data->Begin(); \ + PCL_IVDEP \ + for ( ; i < j; ++i, ++k ) \ + *i op##= *k; \ + } \ + else \ + { \ + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); \ + block_iterator __restrict__ i = newData->Begin(); \ + const_block_iterator __restrict__ j = pcl::Min( newData->End(), \ + newData->Begin() + x.NumberOfElements() ); \ + const_block_iterator __restrict__ k = x.m_data->Begin(); \ + const_block_iterator __restrict__ t = m_data->Begin(); \ + PCL_IVDEP \ + for ( ; i < j; ++i, ++k, ++t ) \ + *i = *t op *k; \ + DetachFromData(); \ + m_data = newData; \ + } \ + return *this; + + /*! + * Performs the element-wise addition of a matrix \a x to this matrix. + * Returns a reference to this object. + * + * The specified operand matrix \a x should have at least the same number of + * elements as this matrix. Otherwise the operation will be aborted upon + * reaching the end of the operand matrix, but no exception will be thrown. + * + * This function ensures that this instance uniquely references its matrix + * data before the element-wise addition operation, generating a duplicate + * if necessary. + */ + GenericMatrix& operator +=( const GenericMatrix& x ) + { + IMPLEMENT_ELEMENT_WISE_ASSIGN_OP( + ) + } + + /*! + * Performs the element-wise subtraction of a matrix \a x to this matrix. + * Returns a reference to this object. + * + * The specified operand matrix \a x should have at least the same number of + * elements as this matrix. Otherwise the operation will be aborted upon + * reaching the end of the operand matrix, but no exception will be thrown. + * + * This function ensures that this instance uniquely references its matrix + * data before the element-wise subtraction operation, generating a + * duplicate if necessary. + */ + GenericMatrix& operator -=( const GenericMatrix& x ) + { + IMPLEMENT_ELEMENT_WISE_ASSIGN_OP( - ) + } + + /*! + * Performs the element-wise multiplication of a matrix \a x with this + * matrix. Returns a reference to this object. + * + * The specified operand matrix \a x should have at least the same number of + * elements as this matrix. Otherwise the operation will be aborted upon + * reaching the end of the operand matrix, but no exception will be thrown. + * + * This function ensures that this instance uniquely references its matrix + * data before the element-wise multiplication operation, generating a + * duplicate if necessary. + */ + GenericMatrix& operator *=( const GenericMatrix& x ) + { + IMPLEMENT_ELEMENT_WISE_ASSIGN_OP( * ) + } + + /*! + * Performs the element-wise division of this matrix by a matrix \a x. + * Returns a reference to this object. + * + * The specified operand matrix \a x should have at least the same number of + * elements as this matrix. Otherwise the operation will be aborted upon + * reaching the end of the operand matrix, but no exception will be thrown. + * + * This function ensures that this instance uniquely references its matrix + * data before the element-wise division operation, generating a duplicate + * if necessary. + */ + GenericMatrix& operator /=( const GenericMatrix& x ) + { + IMPLEMENT_ELEMENT_WISE_ASSIGN_OP( / ) + } + + /*! + * Performs the element-wise exponentiation of this matrix by a matrix \a x. + * Returns a reference to this object. + * + * The specified matrix \a x must have at least the same number of elements + * as this matrix. Otherwise an Error exception will be thrown. + * + * This function ensures that this instance uniquely references its matrix + * data before the element-wise raise operation, generating a duplicate if + * necessary. + */ + GenericMatrix& operator ^=( const GenericMatrix& x ) + { + if ( IsUnique() ) + { + block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = pcl::Min( m_data->End(), + m_data->Begin() + x.NumberOfElements() ); + const_block_iterator __restrict__ k = x.m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Pow( *i, *k ); + } + else + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = newData->Begin(); + const_block_iterator __restrict__ j = pcl::Min( newData->End(), + newData->Begin() + x.NumberOfElements() ); + const_block_iterator __restrict__ k = x.m_data->Begin(); + const_block_iterator __restrict__ t = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k, ++t ) + *i = pcl::Pow( *t, *k ); + DetachFromData(); + m_data = newData; + } + return *this; + } + +#undef IMPLEMENT_ELEMENT_WISE_ASSIGN_OP + +#endif // __PCL_NO_MATRIX_ELEMENT_WISE_ARITHMETIC_OPERATIONS + + /*! + * Returns the square of this matrix. The result is a new matrix of the same + * dimensions where each element is the square of its counterpart in this + * matrix. + */ + GenericMatrix Sqr() const + { + GenericMatrix R( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = R.m_data->Begin(); + const_block_iterator __restrict__ j = R.m_data->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = *k * *k; + return R; + } + + /*! + * Replaces all elements of this matrix with their squares. + * + * Before performing its task, this function ensures that this instance + * uniquely references its matrix data, generating a duplicate if necessary. + */ + void SetSqr() + { + if ( IsUnique() ) + { + block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i *= *i; + } + else + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = newData->Begin(); + const_block_iterator __restrict__ j = newData->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = *k * *k; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the square root of this matrix. The result is a new matrix of the + * same dimensions where each element is the square root of its counterpart + * in this matrix. + */ + GenericMatrix Sqrt() const + { + GenericMatrix R( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = R.m_data->Begin(); + const_block_iterator __restrict__ j = R.m_data->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Sqrt( *k ); + return R; + } + + /*! + * Replaces all elements of this matrix with their square roots. + * + * Before performing its task, this function ensures that this instance + * uniquely references its matrix data, generating a duplicate if necessary. + */ + void SetSqrt() + { + if ( IsUnique() ) + { + block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = pcl::Sqrt( *i ); + } + else + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = newData->Begin(); + const_block_iterator __restrict__ j = newData->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Sqrt( *k ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the absolute value of this matrix. The result is a new matrix of + * the same dimensions where each element is the absolute value of its + * counterpart in this matrix. + */ + GenericMatrix Abs() const + { + GenericMatrix R( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = R.m_data->Begin(); + const_block_iterator __restrict__ j = R.m_data->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Abs( *k ); + return R; + } + + /*! + * Replaces all elements of this matrix with their absolute values. + * + * Before performing its task, this function ensures that this instance + * uniquely references its matrix data, generating a duplicate if necessary. + */ + void SetAbs() + { + if ( IsUnique() ) + { + block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = pcl::Abs( *i ); + } + else + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + block_iterator __restrict__ i = newData->Begin(); + const_block_iterator __restrict__ j = newData->End(); + const_block_iterator __restrict__ k = m_data->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Abs( *k ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns true iff this instance uniquely references its matrix data. + */ + bool IsUnique() const noexcept + { + return m_data->IsUnique(); + } + + /*! + * Returns true iff this instance references (shares) the same matrix data as + * another instance \a x. + */ + bool IsAliasOf( const GenericMatrix& x ) const noexcept + { + return m_data == x.m_data; + } + + /*! + * Ensures that this instance uniquely references its matrix data. + * + * If necessary, this member function generates a duplicate of the matrix + * data, references it, and then decrements the reference counter of the + * original matrix data. + */ + void EnsureUnique() + { + if ( !IsUnique() ) + { + Data* newData = new Data( m_data->Rows(), m_data->Cols() ); + const_block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + block_iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = *i; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the number of rows in this matrix. If this object is an empty + * matrix, this member function returns zero. + */ + int Rows() const noexcept + { + return m_data->Rows(); + } + + /*! + * Returns the number of columns in this matrix. If this object is an empty + * matrix, this member function returns zero. + */ + int Cols() const noexcept + { + return m_data->Cols(); + } + + /*! + * Returns the number of columns in this matrix. If this object is an empty + * matrix, this member function returns zero. + * + * This function is a synonym for Cols(). + */ + int Columns() const noexcept + { + return Cols(); + } + + /*! + * Returns true only if this matrix is valid. A matrix is valid if it + * references an internal matrix structure, even if it is an empty matrix. + * + * In general, all %GenericMatrix objects are valid with only two + * exceptions: + * + * \li Objects that have been move-copied or move-assigned to other + * matrices. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid matrix object cannot be used and should be destroyed + * immediately. Invalid matrices are always destroyed automatically during + * move construction and move assignment operations. + */ + bool IsValid() const noexcept + { + return m_data != nullptr; + } + + /*! + * Returns true iff this is an empty matrix. An empty matrix has no elements, + * and hence its dimensions are zero. + */ + bool IsEmpty() const noexcept + { + return Rows() == 0 || Cols() == 0; + } + + /*! + * Returns true iff this matrix is not empty. This operator is equivalent to: + * + * \code !IsEmpty(); \endcode + */ + operator bool() const noexcept + { + return !IsEmpty(); + } + + /*! + * Returns the total number of matrix elements in this object, or + * Rows()*Cols(). + */ + size_type NumberOfElements() const noexcept + { + return m_data->NumberOfElements(); + } + + /*! + * Returns the total number of bytes required to store the data contained in + * this matrix. + */ + size_type Size() const noexcept + { + return m_data->Size(); + } + + /*! + * Equality operator. Returns true if this matrix is equal to another matrix + * \a x. + * + * %Matrix comparisons are performed element-wise. Two matrices are equal if + * both have the same dimensions and identical element values. + */ + bool operator ==( const GenericMatrix& x ) const noexcept + { + return IsAliasOf( x ) || SameDimensions( x ) && pcl::Equal( Begin(), x.Begin(), x.End() ); + } + + /*! + * Less than relational operator. Returns true if this matrix is less than + * another matrix \a x. + * + * In this operator, matrix comparisons are performed element-wise, + * irrespective of matrix dimensions, until either two matrix elements + * differ, or until the end of one of the matrices is reached. In the latter + * case the shortest matrix is the lesser one. + */ + bool operator <( const GenericMatrix& x ) const noexcept + { + return !IsAliasOf( x ) && pcl::Compare( Begin(), End(), x.Begin(), x.End() ) < 0; + } + + /*! + * Returns true iff this matrix has the same dimensions, i.e. the same number + * of rows and columns, as another matrix \a x. + */ + bool SameDimensions( const GenericMatrix& x ) const noexcept + { + return Rows() == x.Rows() && Cols() == x.Cols(); + } + + /*! + * Returns true iff this matrix has the same elements as another matrix \a x. + * + * In this member function, matrix comparisons are performed element-wise, + * irrespective of matrix dimensions. Note that two matrices can have + * exactly the same elements even if their dimensions, i.e. their number of + * rows and columns, are different. Only the number and order of elements + * are relevant for this comparison. + */ + bool SameElements( const GenericMatrix& x ) const noexcept + { + if ( unlikely( IsAliasOf( x ) ) ) + return true; + if ( unlikely( NumberOfElements() != x.NumberOfElements() ) ) + return false; + const_block_iterator __restrict__ i = Begin(); + const_block_iterator __restrict__ j = End(); + const_block_iterator __restrict__ k = x.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + if ( *i != *k ) + return false; + return true; + } + + /*! + * Returns a reference to the matrix element at row \a i and column \a j. + * + * Before returning, this function ensures that this instance uniquely + * references its matrix data. + */ + element& Element( int i, int j ) + { + EnsureUnique(); + return m_data->Element( i, j ); + } + + /*! + * Returns a reference to the immutable matrix element at row \a i and + * column \a j. + */ + const element& Element( int i, int j ) const noexcept + { + return m_data->Element( i, j ); + } + + /*! + * Returns a pointer to the first matrix element of row \a i. + * + * All elements in row \a i are guaranteed to be stored at consecutive + * locations addressable from the pointer returned by this function. + * + * Before returning, this function ensures that this instance uniquely + * references its matrix data. + */ + block_iterator operator []( int i ) + { + EnsureUnique(); + return m_data->v[i]; + } + + /*! + * Returns a pointer to the immutable first matrix element of row \a i. + * + * All elements in row \a i are guaranteed to be stored at consecutive + * locations addressable from the pointer returned by this function. + */ + const_block_iterator operator []( int i ) const noexcept + { + return m_data->v[i]; + } + + /*! + * Returns a pointer to the first matrix element, that is to the element at + * row 0 and column 0 of this matrix. + * + * All matrix elements are guaranteed to be stored at consecutive locations + * addressable from the pointer returned by this function. Matrix elements + * are stored in row order: all elements of row 0 followed by all elements + * of row 1, and so on. + * + * Before returning, this function ensures that this instance uniquely + * references its matrix data. + */ + block_iterator Begin() + { + EnsureUnique(); + return m_data->Begin(); + } + + /*! + * Returns a pointer to the immutable first matrix element, that is to the + * element at row 0 and column 0 of this matrix. + * + * All matrix elements are guaranteed to be stored at consecutive locations + * addressable from the pointer returned by this function. Matrix elements + * are stored in row order: all elements of row 0 followed by all elements + * of row 1, and so on. + */ + const_block_iterator Begin() const noexcept + { + return m_data->Begin(); + } + + /*! + * A synonym for Begin() const. + */ + const_block_iterator ConstBegin() const noexcept + { + return Begin(); + } + + /*! + * Returns a pointer to the first matrix element, that is to the element at + * row 0 and column 0 of this matrix. + * + * This member function is a convenience alias to Begin(). + */ + block_iterator operator *() + { + return Begin(); + } + + /*! + * Returns a pointer to the immutable first matrix element, that is to the + * element at row 0 and column 0 of this matrix. + * + * This member function is a convenience alias to Begin() const. + */ + const_block_iterator operator *() const noexcept + { + return Begin(); + } + + /*! + * Returns a pointer past the last matrix element, that is a pointer to an + * (nonexistent) element located at row=Rows()-1 and column=Cols(). + * + * All matrix elements are guaranteed to be stored in reverse order at + * consecutive locations addressable from the pointer returned by this + * function. Matrix elements are stored in row order (all elements of row n + * followed by all elements of row n-1, and so on). + * + * Before returning, this function ensures that this instance uniquely + * references its matrix data. + */ + block_iterator End() + { + EnsureUnique(); + return m_data->End(); + } + + /*! + * Returns a pointer past the last immutable matrix element, that is a + * pointer to an immutable (and nonexistent) element located at row=Rows()-1 + * and column=Cols(). + * + * All matrix elements are guaranteed to be stored in reverse order at + * consecutive locations addressable from the pointer returned by this + * function. Matrix elements are stored in row order (all elements of row n + * followed by all elements of row n-1, and so on). + */ + const_block_iterator End() const noexcept + { + return m_data->End(); + } + + /*! + * A synonym for End() const. + */ + const_block_iterator ConstEnd() const noexcept + { + return End(); + } + + /*! + * Returns a pointer to a pointer to the first element in this matrix. + * + * The returned pointer can be used as a common C array, where all matrix + * rows are guaranteed to be addressable through consecutive pointers + * starting from the pointer returned by this function. + * + * This member function does nothing to ensure that this instance uniquely + * references its matrix data. Consequently, the caller must take into + * account that all modifications made to matrix elements accessed through + * the value returned by this function will apply to all instances sharing + * the same matrix data. + * + * This function can be used to perform fast operations on matrix elements, + * avoiding the overhead caused by deep copies of matrix data, when such + * copies are not necessary. Typically this happens when two or more threads + * work simultaneously on non-overlapping regions of the same matrix. + */ + block_iterator* DataPtr() noexcept + { + return m_data->v; + } + + /*! + * Returns a pointer to the first matrix element of row \a i. + * + * All elements in row \a i are guaranteed to be stored at consecutive + * locations addressable from the pointer returned by this function. + * + * This member function does not ensure that the data referenced by this + * matrix is unique. See DataPtr() for more information on how to use this + * member function. + */ + block_iterator RowPtr( int i ) noexcept + { + return m_data->v[i]; + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + block_iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_block_iterator begin() const noexcept + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + block_iterator end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_block_iterator end() const noexcept + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Returns a vector with the matrix elements at the specified row \a i. + */ + vector RowVector( int i ) const + { + vector r( m_data->Cols() ); + for ( int j = 0; j < m_data->Cols(); ++j ) + r[j] = m_data->v[i][j]; + return r; + } + + /*! + * Returns a vector with the matrix elements at the specified column \a j. + */ + vector ColumnVector( int j ) const + { + vector c( m_data->Rows() ); + for ( int i = 0; i < m_data->Rows(); ++i ) + c[i] = m_data->v[i][j]; + return c; + } + + /*! + * Returns a vector with the matrix elements at the specified column \a j. + * + * This member function is an alias for ColumnVector(). + */ + vector ColVector( int j ) const + { + return ColumnVector( j ); + } + + /*! + * Assigns the components of a vector \a r to the corresponding elements of + * a matrix row \a i. + */ + template + void SetRow( int i, const V& r ) + { + EnsureUnique(); + for ( int j = 0; j < m_data->Cols() && j < r.Length(); ++j ) + m_data->v[i][j] = element( r[j] ); + } + + /*! + * Assigns the components of a vector \a c to the corresponding elements of + * a matrix column \a i. + */ + template + void SetColumn( int j, const V& c ) + { + EnsureUnique(); + for ( int i = 0; i < m_data->Rows() && i < c.Length(); ++i ) + m_data->v[i][j] = element( c[i] ); + } + + /*! + * Assigns the components of a vector \a c to the corresponding elements of + * a matrix column \a i. + * + * This member function is an alias for SetColumn(). + */ + template + void SetCol( int j, const V& c ) + { + SetColumn( j, c ); + } + + /*! + * Returns a matrix whose first row is a copy of the specified vector \a r. + * The rest of matrix elements are set to zero. The returned object is a + * square matrix whose dimensions are equal to the length of \a r. + */ + static GenericMatrix FromRowVector( const vector& r ) + { + GenericMatrix R( element( 0 ), r.Length(), r.Length() ); + for ( int j = 0; j < r.Length(); ++j ) + R.m_data->v[0][j] = r[j]; + return R; + } + + /*! + * Returns a matrix whose first column is a copy of the specified vector + * \a c. The rest of matrix elements are set to zero. The returned object is + * a square matrix whose dimensions are equal to the length of \a c. + */ + static GenericMatrix FromColumnVector( const vector& c ) + { + GenericMatrix C( element( 0 ), c.Length(), c.Length() ); + for ( int i = 0; i < c.Length(); ++i ) + C.m_data->v[i][0] = c[i]; + return C; + } + + /*! + * This member function is an alias for FromColumnVector(). + */ + static GenericMatrix FromColVector( const vector& c ) + { + return FromColumnVector( c ); + } + + /*! + * Returns a unit matrix of size \a n. + * + * A unit matrix is an n x n square matrix whose elements + * are ones on its main diagonal and zeros elsewhere. + */ + static GenericMatrix UnitMatrix( int n ) + { + GenericMatrix One( element( 0 ), n, n ); + for ( int i = 0; i < n; ++i ) + One[i][i] = element( 1 ); + return One; + } + + /*! + * Returns the transpose of this matrix. + * + * The transpose of a matrix A is another matrix AT whose rows + * are the columns of A (or, equivalently, whose columns are the rows of A). + */ + GenericMatrix Transpose() const + { + GenericMatrix Tr( m_data->Cols(), m_data->Rows() ); + for ( int i = 0; i < m_data->Rows(); ++i ) + for ( int j = 0; j < m_data->Cols(); ++j ) + Tr.m_data->v[j][i] = m_data->v[i][j]; + return Tr; + } + + /*! + * Returns the inverse of this matrix. + * + * When a square matrix is multiplied by its inverse, the result is the + * identity matrix. Non-square matrices do not have inverses. + * + * If this is an empty or non-square matrix, or if it is singular (i.e. if + * its determinant is zero or insignificant), then this function throws the + * appropriate Error exception. + */ + GenericMatrix Inverse() const; + + /*! + * Inverts this matrix. + * + * When a square matrix is multiplied by its inverse, the result is the + * identity matrix. Non-square matrices do not have inverses. + * + * If this is an empty or non-square matrix, or if it is singular (i.e. if + * its determinant is zero or insignificant), then this function throws the + * appropriate Error exception. + */ + void Invert(); + + /*! + * Flips this matrix. Flipping a matrix consists of rotating its elements by + * 180 degrees. + * + * This function ensures that this instance uniquely references its matrix + * data before performing matrix rotation. + */ + void Flip() + { + EnsureUnique(); + pcl::Reverse( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns a flipped copy of this matrix. Flipping a matrix consists of + * rotating its elements by 180 degrees. + */ + GenericMatrix Flipped() const + { + GenericMatrix Tf( m_data->Cols(), m_data->Rows() ); + pcl::CopyReversed( Tf.m_data->End(), m_data->Begin(), m_data->End() ); + return Tf; + } + + /*! + * Returns a 3x3 rotation matrix about the X axis. + * + * \param sphi Sine of the rotation angle. + * + * \param cphi Cosine of the rotation angle. + * + * Positive rotation angles apply anticlockwise rotations about the X axis, + * as seen looking towards the origin from positive x. + * + * The returned matrix is: + * + *

+    * 1     0       0
+    * 0   +cphi   +sphi
+    * 0   -sphi   +cphi
+    * 
+ * + * \sa RotationX( double ) + */ + static GenericMatrix RotationX( double sphi, double cphi ) + { + return GenericMatrix( element( 1 ), element( 0 ), element( 0 ), + element( 0 ), element( +cphi ), element( +sphi ), + element( 0 ), element( -sphi ), element( +cphi ) ); + } + + /*! + * Returns a 3x3 rotation matrix about the X axis by the specified angle + * \a phi in radians. + * + * Calling this function is equivalent to: + * + * \code RotationX( Sin( phi ), Cos( phi ) ) \endcode + */ + static GenericMatrix RotationX( double phi ) + { + double sphi, cphi; + SinCos( phi, sphi, cphi ); + return RotationX( sphi, cphi ); + } + + /*! + * Returns a 3x3 rotation matrix about the Y axis. + * + * \param sphi Sine of the rotation angle. + * + * \param cphi Cosine of the rotation angle. + * + * Positive rotation angles apply anticlockwise rotations about the Y axis, + * as seen looking towards the origin from positive y. + * + * The returned matrix is: + * + *
+    * +cphi  0  -sphi
+    *   0    1    0
+    * +sphi  0  +cphi
+    * 
+ * + * \sa RotationY( double ) + */ + static GenericMatrix RotationY( double sphi, double cphi ) + { + return GenericMatrix( element( +cphi ), element( 0 ), element( -sphi ), + element( 0 ), element( 1 ), element( 0 ), + element( +sphi ), element( 0 ), element( +cphi ) ); + } + + /*! + * Returns a 3x3 rotation matrix about the Y axis by the specified angle + * \a phi in radians. + * + * Calling this function is equivalent to: + * + * \code RotationY( Sin( phi ), Cos( phi ) ) \endcode + */ + static GenericMatrix RotationY( double phi ) + { + double sphi, cphi; + SinCos( phi, sphi, cphi ); + return RotationY( sphi, cphi ); + } + + /*! + * Returns a 3x3 rotation matrix about the Z axis. + * + * \param sphi Sine of the rotation angle. + * + * \param cphi Cosine of the rotation angle. + * + * Positive rotation angles apply anticlockwise rotations about the Z axis, + * as seen looking towards the origin from positive z. + * + * The returned matrix is: + * + *
+    * +cphi  +sphi  0
+    * -sphi  +cphi  0
+    *   0      0    1
+    * 
+ * + * \sa RotationZ( double ) + */ + static GenericMatrix RotationZ( double sphi, double cphi ) + { + return GenericMatrix( element( +cphi ), element( +sphi ), element( 0 ), + element( -sphi ), element( +cphi ), element( 0 ), + element( 0 ), element( 0 ), element( 1 ) ); + } + + /*! + * Returns a 3x3 rotation matrix about the Z axis by the specified angle + * \a phi in radians. + * + * Calling this function is equivalent to: + * + * \code RotationZ( Sin( phi ), Cos( phi ) ) \endcode + */ + static GenericMatrix RotationZ( double phi ) + { + double sphi, cphi; + SinCos( phi, sphi, cphi ); + return RotationZ( sphi, cphi ); + } + + /*! + * Rotates this 3x3 matrix about the X axis. + * + * \param sphi Sine of the rotation angle. + * + * \param cphi Cosine of the rotation angle. + * + * Positive rotation angles apply anticlockwise rotations about the X axis, + * as seen looking towards the origin from positive x. The applied + * transformation can be represented by the matrix: + * + *
+    * 1     0        0
+    * 0   +cphi   +sphi
+    * 0   -sphi   +cphi
+    * 
+ * + * If this matrix has dimensions different from 3 rows and 3 columns, this + * function invokes undefined behavior. For the sake of performance, this + * condition is not explicitly verified. + * + * \sa RotateX( double ), RotatedX() + */ + void RotateX( double sphi, double cphi ) + { + PCL_PRECONDITION( Rows() == 3 && Cols() == 3 ) + EnsureUnique(); + block_iterator __restrict__ A1 = m_data->v[1]; + block_iterator __restrict__ A2 = m_data->v[2]; + double a10 = cphi*A1[0] + sphi*A2[0]; + double a11 = cphi*A1[1] + sphi*A2[1]; + double a12 = cphi*A1[2] + sphi*A2[2]; + double a20 = -sphi*A1[0] + cphi*A2[0]; + double a21 = -sphi*A1[1] + cphi*A2[1]; + double a22 = -sphi*A1[2] + cphi*A2[2]; + A1[0] = element( a10 ); + A1[1] = element( a11 ); + A1[2] = element( a12 ); + A2[0] = element( a20 ); + A2[1] = element( a21 ); + A2[2] = element( a22 ); + } + + /*! + * Rotates this 3x3 matrix about the X axis by the specified angle \a phi in + * radians. + * + * Calling this function is equivalent to: + * + * \code RotateX( Sin( phi ), Cos( phi ) ) \endcode + */ + void RotateX( double phi ) + { + double sphi, cphi; + SinCos( phi, sphi, cphi ); + RotateX( sphi, cphi ); + } + + /*! + * Returns a rotated copy of this 3x3 matrix about the X axis by a rotation + * angle given by its sine \a sphi and cosine \a cphi. + * See RotateX( double, double ). + */ + GenericMatrix RotatedX( double sphi, double cphi ) const + { + GenericMatrix R( *this ); + R.RotateX( sphi, cphi ); + return R; + } + + /*! + * Returns a rotated copy of this 3x3 matrix about the X axis by the + * specified rotation angle \a phi in radians. See RotateX( double ). + */ + GenericMatrix RotatedX( double phi ) const + { + GenericMatrix R( *this ); + R.RotateX( phi ); + return R; + } + + /*! + * Rotates this 3x3 matrix about the Y axis. + * + * \param sphi Sine of the rotation angle. + * + * \param cphi Cosine of the rotation angle. + * + * Positive rotation angles apply anticlockwise rotations about the Y axis, + * as seen looking towards the origin from positive y. The applied + * transformation can be represented by the matrix: + * + *
+    * +cphi  0  -sphi
+    *   0    1    0
+    * +sphi  0  +cphi
+    * 
+ * + * If this matrix has dimensions different from 3 rows and 3 columns, this + * function invokes undefined behavior. For the sake of performance, this + * condition is not explicitly verified. + * + * \sa RotateY( double ), RotatedY() + */ + void RotateY( double sphi, double cphi ) + { + PCL_PRECONDITION( Rows() == 3 && Cols() == 3 ) + EnsureUnique(); + block_iterator __restrict__ A0 = m_data->v[0]; + block_iterator __restrict__ A2 = m_data->v[2]; + double a00 = cphi*A0[0] - sphi*A2[0]; + double a01 = cphi*A0[1] - sphi*A2[1]; + double a02 = cphi*A0[2] - sphi*A2[2]; + double a20 = sphi*A0[0] + cphi*A2[0]; + double a21 = sphi*A0[1] + cphi*A2[1]; + double a22 = sphi*A0[2] + cphi*A2[2]; + A0[0] = a00; + A0[1] = a01; + A0[2] = a02; + A2[0] = a20; + A2[1] = a21; + A2[2] = a22; + } + + /*! + * Rotates this 3x3 matrix about the Y axis by the specified angle \a phi in + * radians. + * + * Calling this function is equivalent to: + * + * \code RotateY( Sin( phi ), Cos( phi ) ) \endcode + */ + void RotateY( double phi ) + { + double sphi, cphi; + SinCos( phi, sphi, cphi ); + RotateY( sphi, cphi ); + } + + /*! + * Returns a rotated copy of this 3x3 matrix about the Y axis by a rotation + * angle given by its sine \a sphi and cosine \a cphi. + * See RotateY( double, double ). + */ + GenericMatrix RotatedY( double sphi, double cphi ) const + { + GenericMatrix R( *this ); + R.RotateY( sphi, cphi ); + return R; + } + + /*! + * Returns a rotated copy of this 3x3 matrix about the Y axis by the + * specified rotation angle \a phi in radians. See RotateY( double ). + */ + GenericMatrix RotatedY( double phi ) const + { + GenericMatrix R( *this ); + R.RotateY( phi ); + return R; + } + + /*! + * Rotates this 3x3 matrix about the Z axis. + * + * \param sphi Sine of the rotation angle. + * + * \param cphi Cosine of the rotation angle. + * + * Positive rotation angles apply anticlockwise rotations about the Z axis, + * as seen looking towards the origin from positive z. The applied + * transformation can be represented by the matrix: + * + *
+    * +cphi  +sphi  0
+    * -sphi  +cphi  0
+    *   0      0    1
+    * 
+ * + * If this matrix has dimensions different from 3 rows and 3 columns, this + * function invokes undefined behavior. For the sake of performance, this + * condition is not explicitly verified. + * + * \sa RotateZ( double ), RotatedZ() + */ + void RotateZ( double sphi, double cphi ) + { + PCL_PRECONDITION( Rows() == 3 && Cols() == 3 ) + EnsureUnique(); + block_iterator __restrict__ A0 = m_data->v[0]; + block_iterator __restrict__ A1 = m_data->v[1]; + double a00 = cphi*A0[0] + sphi*A1[0]; + double a01 = cphi*A0[1] + sphi*A1[1]; + double a02 = cphi*A0[2] + sphi*A1[2]; + double a10 = -sphi*A0[0] + cphi*A1[0]; + double a11 = -sphi*A0[1] + cphi*A1[1]; + double a12 = -sphi*A0[2] + cphi*A1[2]; + A0[0] = a00; + A0[1] = a01; + A0[2] = a02; + A1[0] = a10; + A1[1] = a11; + A1[2] = a12; + } + + /*! + * Rotates this 3x3 matrix about the Z axis by the specified angle \a phi in + * radians. + * + * Calling this function is equivalent to: + * + * \code RotateZ( Sin( phi ), Cos( phi ) ) \endcode + */ + void RotateZ( double phi ) + { + double sphi, cphi; + SinCos( phi, sphi, cphi ); + RotateZ( sphi, cphi ); + } + + /*! + * Returns a rotated copy of this 3x3 matrix about the Z axis by a rotation + * angle given by its sine \a sphi and cosine \a cphi. + * See RotateZ( double, double ). + */ + GenericMatrix RotatedZ( double sphi, double cphi ) const + { + GenericMatrix R( *this ); + R.RotateZ( sphi, cphi ); + return R; + } + + /*! + * Returns a rotated copy of this 3x3 matrix about the Z axis by the + * specified rotation angle \a phi in radians. See RotateZ( double ). + */ + GenericMatrix RotatedZ( double phi ) const + { + GenericMatrix R( *this ); + R.RotateZ( phi ); + return R; + } + + /*! + * Truncates all matrix elements to the specified range. + * + * \param f0 Lower bound of the truncation range. If not specified, the + * default value is zero. + * + * \param f1 Upper bound of the truncation range. If not specified, the + * default value is one. + * + * After calling this member function, all matrix elements will be within + * the [\a f0,\a f1] range. + */ + void Truncate( const element& f0 = element( 0 ), const element& f1 = element( 1 ) ) + { + EnsureUnique(); + block_iterator __restrict__ i = m_data->Begin(); + block_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + if ( *i < f0 ) + *i = f0; + else if ( *i > f1 ) + *i = f1; + } + + /*! + * Returns a truncated copy of this matrix. See Truncate(). + */ + GenericMatrix Truncated( const element& f0 = element( 0 ), const element& f1 = element( 1 ) ) const + { + GenericMatrix R( *this ); + R.Truncate( f0, f1 ); + return R; + } + + /*! + * Rescales all matrix elements to the specified range. + * + * \param f0 Lower bound of the rescaling range. If not specified, the + * default value is zero. + * + * \param f1 Upper bound of the rescaling range. If not specified, the + * default value is one. + * + * The rescaling operation is as follows. if \a m and \a M are the minimum + * and maximum element values in this matrix, respectively, then for each + * matrix element s, its rescaled value r is given by: + * + * \a r = \a f0 + (\a s - \a m)*(\a f1 - \a f0)/(\a M - \a m) + */ + void Rescale( const element& f0 = element( 0 ), const element& f1 = element( 1 ) ) + { + element v0 = MinElement(); + element v1 = MaxElement(); + if ( v0 != f0 || v1 != f1 ) + { + EnsureUnique(); + if ( v0 != v1 ) + { + if ( f0 != f1 ) + { + block_iterator __restrict__ i = m_data->Begin(); + block_iterator __restrict__ j = m_data->End(); + double d = (double( f1 ) - double( f0 ))/(double( v1 ) - double( v0 )); + if ( f0 == element( 0 ) ) + { + PCL_IVDEP + for ( ; i < j; ++i ) + *i = element( d*(*i - v0) ); + } + else + { + PCL_IVDEP + for ( ; i < j; ++i ) + *i = element( d*(*i - v0) + f0 ); + } + } + else + pcl::Fill( m_data->Begin(), m_data->End(), f0 ); + } + else + pcl::Fill( m_data->Begin(), m_data->End(), pcl::Range( v0, f0, f1 ) ); + } + } + + /*! + * Returns a rescaled copy of this matrix. See Rescale(). + */ + GenericMatrix Rescaled( const element& f0 = element( 0 ), const element& f1 = element( 1 ) ) const + { + GenericMatrix R( *this ); + R.Rescale( f0, f1 ); + return R; + } + + /*! + * Sorts the elements of this matrix in ascending order. + */ + void Sort() + { + EnsureUnique(); + pcl::Sort( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns a sorted copy of this matrix. + */ + GenericMatrix Sorted() const + { + GenericMatrix R( *this ); + R.Sort(); + return R; + } + + /*! + * Sorts the elements of this matrix in reverse (descending) order. + */ + void ReverseSort() + { + EnsureUnique(); + pcl::Sort( m_data->Begin(), m_data->End(), + []( const element& a, const element& b ){ return b < a; } ); + } + + /*! + * Returns a reverse sorted copy of this matrix. + */ + GenericMatrix ReverseSorted() const + { + GenericMatrix R( *this ); + R.ReverseSort(); + return R; + } + + /*! + * Sorts the elements of this matrix in ascending order. Ordering of matrix + * elements is defined such that for any pair a, b of matrix elements, the + * specified binary predicate p( a, b ) is true if a precedes b. + */ + template + void Sort( BP p ) + { + EnsureUnique(); + pcl::Sort( m_data->Begin(), m_data->End(), p ); + } + + /*! + * Returns a sorted copy of this matrix, where ordering of matrix elements + * is defined by the specified binary predicate \a p. See Sort( BP p ). + */ + template + GenericMatrix Sorted( BP p ) const + { + GenericMatrix R( *this ); + R.Sort( p ); + return R; + } + + /*! + * Returns a pointer to the first immutable matrix element with the + * specified value \a x, or nullptr if this matrix does not contain such + * value. + */ + const_block_iterator Find( const element& x ) const noexcept + { + const_block_iterator p = pcl::LinearSearch( m_data->Begin(), m_data->End(), x ); + return (p != m_data->End()) ? p : nullptr; + } + + /*! + * Returns a pointer to the first immutable matrix element with the + * specified value \a x, or nullptr if this matrix does not contain such + * value. This function is an alias to Find(). + */ + const_block_iterator FindFirst( const element& x ) const noexcept + { + return Find( x ); + } + + /*! + * Returns a pointer to the last immutable matrix element with the specified + * value \a x, or nullptr if this matrix does not contain such value. + */ + const_block_iterator FindLast( const element& x ) const noexcept + { + const_block_iterator p = pcl::LinearSearchLast( m_data->Begin(), m_data->End(), x ); + return (p != m_data->End()) ? p : nullptr; + } + + /*! + * Returns true iff this matrix contains the specified value \a x. + */ + bool Contains( const element& x ) const noexcept + { + return pcl::LinearSearch( m_data->Begin(), m_data->End(), x ) != m_data->End(); + } + +#ifndef __PCL_NO_MATRIX_STATISTICS + + /*! + * Returns the value of the minimum element in this matrix. + * For empty matrices, this function returns zero. + */ + element MinElement() const noexcept + { + if ( !IsEmpty() ) + return *MinItem( m_data->Begin(), m_data->End() ); + return element( 0 ); + } + + /*! + * Returns the value of the minimum element in this matrix and its + * coordinates in the specified point \a p. + * For empty matrices, this function returns zero and assigns zero to the + * point coordinates. + */ + element MinElement( Point& p ) const noexcept + { + if ( !IsEmpty() ) + { + const_block_iterator m = MinItem( m_data->Begin(), m_data->End() ); + distance_type d = m - m_data->Begin(); + p.y = int( d/m_data->Cols() ); + p.x = int( d%m_data->Cols() ); + return *m; + } + p = 0; + return element( 0 ); + } + + /*! + * Returns the value of the maximum element in this matrix. + * For empty matrices, this function returns zero. + */ + element MaxElement() const noexcept + { + if ( !IsEmpty() ) + return *MaxItem( m_data->Begin(), m_data->End() ); + return element( 0 ); + } + + /*! + * Returns the value of the maximum element in this matrix and its + * coordinates in the specified point \a p. + * For empty matrices, this function returns zero and assigns zero to the + * point coordinates. + */ + element MaxElement( Point& p ) const noexcept + { + if ( !IsEmpty() ) + { + const_block_iterator m = MaxItem( m_data->Begin(), m_data->End() ); + int d = m - m_data->Begin(); + p.y = d/m_data->Cols(); + p.x = d%m_data->Cols(); + return *m; + } + p = 0; + return element( 0 ); + } + + /*! + * Returns the sum of all matrix elements. + * + * For empty matrices, this function returns zero. + */ + double Sum() const noexcept + { + return pcl::Sum( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the sum of all matrix elements using a numerically stable + * summation algorithm to minimize roundoff error. + * + * For empty matrices, this function returns zero. + */ + double StableSum() const noexcept + { + return pcl::StableSum( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the sum of the absolute values of all matrix elements. + * + * For empty matrices, this function returns zero. + */ + double Modulus() const noexcept + { + return pcl::Modulus( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the sum of the absolute values of all matrix elements using a + * numerically stable summation algorithm to minimize roundoff error. + * + * For empty matrices, this function returns zero. + */ + double StableModulus() const noexcept + { + return pcl::StableModulus( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the sum of the squares of all matrix elements. + * + * For empty matrices, this function returns zero. + */ + double SumOfSquares() const noexcept + { + return pcl::SumOfSquares( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the sum of the squares of all matrix elements using a + * numerically stable summation algorithm to minimize roundoff error. + * + * For empty matrices, this function returns zero. + */ + double StableSumOfSquares() const noexcept + { + return pcl::StableSumOfSquares( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the mean of the element values in this matrix. + * + * For empty matrices, this function returns zero. + */ + double Mean() const noexcept + { + return pcl::Mean( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the mean of the element values in this matrix using a + * numerically stable summation algorithm to minimize roundoff error. + * + * For empty matrices, this function returns zero. + */ + double StableMean() const noexcept + { + return pcl::StableMean( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the two-sided, asymmetric trimmed mean of the values in this + * matrix. See pcl::TrimmedMean() for a complete description of the + * implemented algorithm with information on function parameters. + * + * For empty matrices, this function returns zero. + */ + double TrimmedMean( distance_type l = 1, distance_type h = 1 ) const noexcept + { + return pcl::TrimmedMean( m_data->Begin(), m_data->End(), l, h ); + } + + /*! + * Computes the two-sided, asymmetric trimmed mean of the squared values in + * this matrix. See pcl::TrimmedMeanOfSquares() for a complete description + * of the implemented algorithm with information on function parameters. + * + * For empty matrices, this function returns zero. + */ + double TrimmedMeanOfSquares( distance_type l = 1, distance_type h = 1 ) const noexcept + { + return pcl::TrimmedMeanOfSquares( m_data->Begin(), m_data->End(), l, h ); + } + + /*! + * Returns the variance from the mean for the values in this matrix. + * + * For matrices with less than two elements, this function returns zero. + */ + double Variance() const noexcept + { + return pcl::Variance( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the standard deviation from the mean for the values in this + * matrix. + * + * For matrices with less than two elements, this function returns zero. + */ + double StdDev() const noexcept + { + return pcl::StdDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the median of element values in this matrix. + * + * For matrices with less than two elements, this function returns zero. + */ + double Median() const + { + return pcl::Median( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the average absolute deviation with respect to the specified + * \a center value. + * + * When the median of the matrix elements is used as the center value, this + * function returns the average absolute deviation from the median, which is + * a well-known estimator of dispersion. + * + * For matrices with less than two elements, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double AvgDev( double center ) const noexcept + { + return pcl::AvgDev( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Computes the average absolute deviation with respect to the specified + * \a center value, using a numerically stable summation algorithm to + * minimize roundoff error. + * + * When the median of the matrix elements is used as the center value, this + * function returns the average absolute deviation from the median, which is + * a well-known estimator of dispersion. + * + * For matrices with less than two elements, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double StableAvgDev( double center ) const noexcept + { + return pcl::StableAvgDev( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the average absolute deviation from the median. + * + * The mean absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For matrices with less than two elements, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double AvgDev() const + { + return pcl::AvgDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the average absolute deviation from the median using a + * numerically stable summation algorithm to minimize roundoff error. + * + * The mean absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For matrices with less than two elements, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double StableAvgDev() const + { + return pcl::StableAvgDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the two-sided average absolute deviation with respect to the + * specified \a center value. + * + * See AvgDev( double ) for more information. + */ + TwoSidedEstimate TwoSidedAvgDev( double center ) const noexcept + { + return pcl::TwoSidedAvgDev( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the two-sided average absolute deviation from the median. + * + * See AvgDev() for more information. + */ + TwoSidedEstimate TwoSidedAvgDev() const + { + return pcl::TwoSidedAvgDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the median absolute deviation (MAD) with respect to the specified + * \a center value. + * + * The MAD is a well-known robust estimator of scale. + * + * For matrices with less than two elements, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, it must be multiplied by the constant 1.4826. + */ + double MAD( double center ) const + { + return pcl::MAD( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the median absolute deviation from the median (MAD). + * + * The MAD is a well-known robust estimator of scale. + * + * For matrices with less than two elements, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, it must be multiplied by the constant 1.4826. + */ + double MAD() const + { + return pcl::MAD( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the two-sided median absolute deviation (MAD) with respect to the + * specified \a center value. + * + * See MAD( double ) for more information. + */ + TwoSidedEstimate TwoSidedMAD( double center ) const + { + return pcl::TwoSidedMAD( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the two-sided median absolute deviation from the median (MAD). + * + * See MAD() for more information. + */ + TwoSidedEstimate TwoSidedMAD() const + { + return pcl::TwoSidedMAD( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the biweight midvariance (BWMV). + * + * \param center Reference center value. Normally, the median of the matrix + * elements should be used. + * + * \param sigma A reference estimate of dispersion. Normally, the median + * absolute deviation from the median (MAD) of the matrix + * elements should be used. + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param reducedLength If true, reduce the sample size to exclude + * rejected matrix elements. This tends to approximate the + * true dispersion of the data more accurately for relatively + * small samples, or samples with large amounts of outliers. + * Note that this departs from the standard definition of + * biweight midvariance, where the total number of data items + * is used to scale the variance estimate. If false, use the + * full number of matrix elements, including rejected + * elements, which gives a standard biweight midvariance + * estimate. + * + * The square root of the biweight midvariance is a robust estimator of + * scale. It is an efficient estimator with respect to many statistical + * distributions (about 87% Gaussian efficiency), and appears to have a + * breakdown point close to 0.5 (the same as MAD). + * + * For matrices with less than two elements, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.1. + */ + double BiweightMidvariance( double center, double sigma, int k = 9, bool reducedLength = false ) const noexcept + { + return pcl::BiweightMidvariance( m_data->Begin(), m_data->End(), center, sigma, k, reducedLength ); + } + + /*! + * Returns the biweight midvariance (BWMV) with respect to the median and + * the median absolute deviation from the median (MAD). + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param reducedLength If true, reduce the sample size to exclude + * rejected matrix elements. This tends to approximate the + * true dispersion of the data more accurately for relatively + * small samples, or samples with large amounts of outliers. + * Note that this departs from the standard definition of + * biweight midvariance, where the total number of data items + * is used to scale the variance estimate. If false, use the + * full number of matrix elements, including rejected + * elements, which gives a standard biweight midvariance + * estimate. + * + * The square root of the biweight midvariance is a robust estimator of + * scale. It is an efficient estimator with respect to many statistical + * distributions (about 87% Gaussian efficiency), and appears to have a + * breakdown point close to 0.5 (the same as MAD). + * + * For matrices with less than two elements, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.1. + */ + double BiweightMidvariance( int k = 9, bool reducedLength = false ) const + { + double center = Median(); + return BiweightMidvariance( center, MAD( center ), k, reducedLength ); + } + + /*! + * Returns the two-sided biweight midvariance (BWMV). + * + * \param center Reference center value. Normally, the median of the vector + * components should be used. + * + * \param sigma A two-sided reference estimate of dispersion. Normally, + * the two-sided median absolute deviation from the median + * (MAD) of the vector components should be used. See the + * TwoSidedMAD() member function. + * + * See BiweightMidvariance( double, double, int, bool ) for more information + * on the rest of parameters and references. + */ + TwoSidedEstimate TwoSidedBiweightMidvariance( double center, const TwoSidedEstimate& sigma, + int k = 9, bool reducedLength = false ) const noexcept + { + return pcl::TwoSidedBiweightMidvariance( m_data->Begin(), m_data->End(), center, sigma, k, reducedLength ); + } + + /*! + * Returns the two-sided biweight midvariance (BWMV) with respect to the + * median and the two-sided median absolute deviation from the median (MAD). + * + * See BiweightMidvariance( int, bool ) for more information and references. + */ + TwoSidedEstimate TwoSidedBiweightMidvariance( int k = 9, bool reducedLength = false ) const + { + double center = Median(); + return TwoSidedBiweightMidvariance( center, TwoSidedMAD( center ), k, reducedLength ); + } + + /*! + * Returns a percentage bend midvariance (PBMV). + * + * \param center Reference center value. Normally, the median of the matrix + * elements should be used. + * + * \param beta Rejection parameter in the [0,0.5] range. Higher values + * improve robustness to outliers (i.e., increase the + * breakdown point of the estimator) at the expense of lower + * efficiency. The default value is beta=0.2. + * + * The square root of the percentage bend midvariance is a robust estimator + * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With + * beta=0.1, its efficiency is 85% but its breakdown is only 0.1. + * + * For matrices with less than two elements, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.3. + */ + double BendMidvariance( double center, double beta = 0.2 ) const + { + return pcl::BendMidvariance( m_data->Begin(), m_data->End(), center, beta ); + } + + /*! + * Returns a percentage bend midvariance (PBMV) with respect to the median. + * + * \param beta Rejection parameter in the [0,0.5] range. Higher values + * improve robustness to outliers (i.e., increase the + * breakdown point of the estimator) at the expense of lower + * efficiency. The default value is beta=0.2. + * + * The square root of the percentage bend midvariance is a robust estimator + * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With + * beta=0.1, its efficiency is 85% but its breakdown is only 0.1. + * + * For matrices with less than two elements, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2012), Introduction to Robust Estimation and + * Hypothesis Testing, 3rd Edition, Elsevier Inc., Section 3.12.3. + */ + double BendMidvariance( double beta = 0.2 ) const + { + return pcl::BendMidvariance( m_data->Begin(), m_data->End(), Median(), beta ); + } + + /*! + * Returns the Sn scale estimator of Rousseeuw and Croux: + * + *
+    * Sn = c * low_median( high_median( |x_i - x_j| ) )
+    * 
+ * + * where low_median() is the order statistic of rank (n + 1)/2, and + * high_median() is the order statistic of rank n/2 + 1. + * + * For matrices with less than two elements, this function returns zero. + * + * The constant c = 1.1926 must be used to make the Sn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for + * consistency with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median + * Absolute Deviation, Journal of the American Statistical Association, + * Vol. 88, pp. 1273-1283. + */ + double Sn() const + { + GenericMatrix A( *this ); + return pcl::Sn( A.Begin(), A.End() ); + } + + /*! + * Returns the Qn scale estimator of Rousseeuw and Croux: + * + *
+    * Qn = c * first_quartile( |x_i - x_j| : i < j )
+    * 
+ * + * where first_quartile() is the order statistic of rank (n + 1)/4. + * + * For matrices with less than two elements, this function returns zero. + * + * The constant c = 2.2219 must be used to make the Qn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for + * consistency with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median Absolute + * Deviation, Journal of the American Statistical Association, Vol. 88, + * pp. 1273-1283. + */ + double Qn() const + { + GenericMatrix A( *this ); + return pcl::Qn( A.Begin(), A.End() ); + } + +#endif // !__PCL_NO_MATRIX_STATISTICS + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this matrix. + * + * This function calls pcl::Hash64() for the internal matrix data. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const noexcept + { + return pcl::Hash64( m_data->Begin(), m_data->Size(), seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this matrix. + * + * This function calls pcl::Hash32() for the internal matrix data. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const noexcept + { + return pcl::Hash32( m_data->Begin(), m_data->Size(), seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this matrix. This + * function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const noexcept + { + return Hash64( seed ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each matrix element, this function appends a string representation + * (known as a \e token) to the target string \a s. If the matrix contains + * more than one element, successive tokens are separated with the specified + * \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform a matrix element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + const_block_iterator i = m_data->Begin(), j = m_data->End(); + if ( i < j ) + { + s.Append( S( *i ) ); + if ( ++i < j ) + do + { + s.Append( separator ); + s.Append( S( *i ) ); + } + while ( ++i < j ); + } + return s; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each matrix element x, this function appends a string representation + * (known as a \e token) to the target string \a s by calling the \a append + * function: + * + *\code append( s, S( x ) ); \endcode + * + * If the matrix has more than one element, successive tokens are separated + * by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform a + * matrix element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably better to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + const_block_iterator i = m_data->Begin(), j = m_data->End(); + if ( i < j ) + { + append( s, S( *i ) ); + if ( ++i < j ) + { + S p( separator ); + do + { + append( s, p ); + append( s, S( *i ) ); + } + while ( ++i < j ); + } + } + return s; + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return ToSeparated( s, ',' ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return ToSeparated( s, ' ' ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return ToSeparated( s, '\t' ); + } + +#ifndef __PCL_NO_MATRIX_PHASE_MATRICES + + /*! + * Returns the phase correlation matrix for two matrices \a A and \a B. + * \ingroup phase_matrices + */ + static GenericMatrix PhaseCorrelationMatrix( const GenericMatrix& A, const GenericMatrix& B ) + { + if ( B.Rows() != A.Rows() || B.Cols() != A.Cols() ) + throw Error( "Invalid matrix dimensions in PhaseCorrelationMatrix()" ); + GenericMatrix R( A.Rows(), A.Cols() ); + PhaseCorrelationMatrix( R.Begin(), R.End(), A.Begin(), B.Begin() ); + return R; + } + + /*! + * Returns the cross power spectrum matrix for two matrices \a A and \a B. + * \ingroup phase_matrices + */ + static GenericMatrix CrossPowerSpectrumMatrix( const GenericMatrix& A, const GenericMatrix& B ) + { + if ( B.Rows() != A.Rows() || B.Cols() != A.Cols() ) + throw Error( "Invalid matrix dimensions in CrossPowerSpectrumMatrix()" ); + GenericMatrix R( A.Rows(), A.Cols() ); + CrossPowerSpectrumMatrix( R.Begin(), R.End(), A.Begin(), B.Begin() ); + return R; + } + +#endif // !__PCL_NO_MATRIX_PHASE_MATRICES + +#ifndef __PCL_NO_MATRIX_IMAGE_RENDERING + + /*! + * Renders this matrix as an image. + * + * The contents of the specified \a image will be replaced with a grayscale + * rendition of this matrix, where the value of each pixel sample will be + * proportional to its corresponding matrix component counterpart. + * + * Note that if this matrix has out-of-range values for the pixel sample + * type of the target image, pixel saturation will occur at either the white + * or black points, or both. This only happens when the target image is of + * an integer type and this matrix contains floating point values outside + * the normalized [0,1] range. + * + * If the target image is of a floating-point type (either real or complex) + * and this matrix also stores floating point values, the output image may + * require a rescaling or normalization operation to constrain all pixel + * values to the normalized [0,1] range after calling this member function. + */ + template + void ToImage( GenericImage

& image ) const + { + image.AllocateData( Cols(), Rows() ); + typename P::sample* __restrict__ v = *image; + const_block_iterator __restrict__ i = m_data->Begin(); + const_block_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i, ++v ) + *v = P::ToSample( *i ); + } + + /*! + * Renders this matrix as an image. + * + * The contents of the image transported by the specified %ImageVariant + * object will be replaced with a grayscale rendition of this matrix, where + * the value of each pixel sample will be proportional to its corresponding + * matrix component counterpart. + * + * If the specified %ImageVariant does not transport an image, a new one + * will be created in 32-bit floating point format. + * + * Also take into account the information given for + * ToImage( GenericImage& ), relative to out-of-range values, which is + * entirely applicable to this member function. + */ + void ToImage( ImageVariant& image ) const + { + if ( !image ) + image.CreateFloatImage(); + + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: ToImage( static_cast( *image ) ); break; + case 64: ToImage( static_cast( *image ) ); break; + } + else if ( image.IsComplexSample() ) + switch ( image.BitsPerSample() ) + { + case 32: ToImage( static_cast( *image ) ); break; + case 64: ToImage( static_cast( *image ) ); break; + } + else + switch ( image.BitsPerSample() ) + { + case 8: ToImage( static_cast( *image ) ); break; + case 16: ToImage( static_cast( *image ) ); break; + case 32: ToImage( static_cast( *image ) ); break; + } + } + +#endif // !__PCL_NO_MATRIX_IMAGE_RENDERING + +#ifndef __PCL_NO_MATRIX_IMAGE_CONVERSION + + /*! + * Creates a matrix from image pixel samples. + * + * This static member function converts pixel sample values to matrix + * elements for a rectangular region of a channel of the specified \a image. + * + * \param image Image from which matrix elements will be generated. + * + * \param rect A rectangular region in image pixel coordinates, from + * which the returned matrix will be generated. If this + * parameter is not specified, or if an empty rectangle is + * specified, this function will perform the matrix + * conversion for the current rectangular selection in the + * image, that is, for image.SelectedRectangle(). + * + * \param channel Channel index. Must be the zero-based index of an existing + * channel in the image, or an integer < 0. If this parameter + * is not specified, or if a negative integer is specified, + * this function will perform the matrix conversion for the + * currently selected channel in the image, that is, for + * image.SelectedChannel(). + * + * The returned matrix is a representation of the intersection of the + * specified (or implicitly selected) rectangular region with the image for + * the scalar data type T of this matrix instantiation. All predefined pixel + * sample types are supported, including integer, real and complex pixels. + * + * If there is no intersection between the rectangular region and the image, + * or if an invalid channel index is specified, this function returns an + * empty matrix. + * + * Note that if the source image is of a floating point type (either real or + * complex) and the scalar type T of this matrix instantiation is of an + * integer type, out-of-range matrix elements will be truncated to either + * zero or to the maximum integer value, if the corresponding source pixel + * sample is outside the normalized [0,1] range. + */ + template + static GenericMatrix FromImage( const GenericImage

& image, const Rect& rect = Rect( 0 ), int channel = -1 ) + { + Rect r = rect; + if ( !image.ParseSelection( r, channel ) ) + return GenericMatrix(); + + if ( r == image.Bounds() ) + { + GenericMatrix M( image.Height(), image.Width() ); + const typename P::sample* __restrict__ v = image[channel]; + block_iterator __restrict__ i = M.m_data->Begin(); + const_block_iterator __restrict__ j = M.m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i, ++v ) + P::FromSample( *i, *v ); + return M; + } + else + { + int w = r.Width(); + int h = r.Height(); + GenericMatrix M( h, w ); + block_iterator __restrict__ m = M.m_data->Begin(); + PCL_IVDEP + for ( int i = r.y0; i < r.y1; ++i ) + { + const typename P::sample* __restrict__ v = image.PixelAddress( r.x0, i, channel ); + PCL_IVDEP + for ( int j = 0; j < w; ++j ) + P::FromSample( *m++, *v++ ); + } + return M; + } + } + + /*! + * Creates a matrix from image pixel samples. + * + * This static member function converts pixel sample values to matrix + * elements for a rectangular region of a channel of the image transported + * by the specified %ImageVariant. + * + * If the specified %ImageVariant object does not transport an image, this + * member function returns an empty matrix. + * + * Refer to the documentation for + * FromImage( const GenericImage&, const Rect&, int ) for more information + * about the conversion performed by this member function. + */ + static GenericMatrix FromImage( const ImageVariant& image, const Rect& rect = Rect( 0 ), int channel = -1 ) + { + if ( image ) + if ( image.IsFloatSample() ) + switch ( image.BitsPerSample() ) + { + case 32: return FromImage( static_cast( *image ), rect, channel ); + case 64: return FromImage( static_cast( *image ), rect, channel ); + } + else if ( image.IsComplexSample() ) + switch ( image.BitsPerSample() ) + { + case 32: return FromImage( static_cast( *image ), rect, channel ); + case 64: return FromImage( static_cast( *image ), rect, channel ); + } + else + switch ( image.BitsPerSample() ) + { + case 8: return FromImage( static_cast( *image ), rect, channel ); + case 16: return FromImage( static_cast( *image ), rect, channel ); + case 32: return FromImage( static_cast( *image ), rect, channel ); + } + + return GenericMatrix(); + } + +#endif // !__PCL_NO_MATRIX_IMAGE_CONVERSION + +private: + + /*! + * \struct Data + * \internal + * Reference-counted matrix data structure. + */ + struct Data : public ReferenceCounter + { + int n = 0; //!< Number of matrix rows + int m = 0; //!< Number of matrix columns + block_iterator* v = nullptr; //!< Pointer to a pointer to a contiguous block of matrix elements + + Data() = default; + + Data( int rows, int cols ) + { + if ( rows > 0 && cols > 0 ) + Allocate( rows, cols ); + } + + ~Data() + { + Deallocate(); + } + + int Rows() const noexcept + { + return n; + } + + int Cols() const noexcept + { + return m; + } + + size_type NumberOfElements() const noexcept + { + return size_type( n )*size_type( m ); + } + + size_type Size() const noexcept + { + return NumberOfElements()*sizeof( element ); + } + + block_iterator Begin() const + { + block_iterator p = (v != nullptr) ? *v : nullptr; + if ( likely( std::is_scalar::value ) ) + return reinterpret_cast( PCL_ASSUME_ALIGNED_32( p ) ); + return p; + } + + block_iterator End() const noexcept + { + return (v != nullptr) ? *v + NumberOfElements() : nullptr; + } + + element& Element( int i, int j ) const noexcept + { + return v[i][j]; + } + + void Allocate( int rows, int cols ) + { + n = rows; + m = cols; + v = new block_iterator[ n ]; + if ( likely( std::is_scalar::value ) ) + { + *v = reinterpret_cast( PCL_ALIGNED_MALLOC( Size(), 32 ) ); + if ( unlikely( *v == nullptr ) ) + { + delete [] v; + v = nullptr; + n = m = 0; + throw std::bad_alloc(); + } + } + else + *v = new element[ NumberOfElements() ]; + for ( int i = 1; i < n; ++i ) + v[i] = v[i-1] + m; + } + + void Deallocate() + { + PCL_PRECONDITION( refCount == 0 ) + if ( v != nullptr ) + { + if ( likely( std::is_scalar::value ) ) + PCL_ALIGNED_FREE( *v ); + else + delete [] *v; + delete [] v; + v = nullptr; + n = m = 0; + } + } + }; + + /*! + * \internal + * The reference-counted matrix data. + */ + Data* m_data = nullptr; + + /*! + * \internal + * Dereferences matrix data and disposes it if it becomes garbage. + */ + void DetachFromData() + { + if ( !m_data->Detach() ) + delete m_data; + } + + /*! + * \internal + * Inverts a small matrix of dimension <= 3. + */ + static bool Invert( block_iterator* Ai, const_block_iterator const* A, int n ) noexcept + { + switch ( n ) + { + case 1: + if ( 1 + **A == 1 ) + return false; + **Ai = 1/(**A); + break; + case 2: + { + const_block_iterator __restrict__ A0 = A[0]; + const_block_iterator __restrict__ A1 = A[1]; + element d = A0[0]*A1[1] - A0[1]*A1[0]; + if ( 1 + d == 1 ) + return false; + Ai[0][0] = A1[1]/d; + Ai[0][1] = -A0[1]/d; + Ai[1][0] = -A1[0]/d; + Ai[1][1] = A0[0]/d; + } + break; + case 3: + { + const_block_iterator __restrict__ A0 = A[0]; + const_block_iterator __restrict__ A1 = A[1]; + const_block_iterator __restrict__ A2 = A[2]; + element d1 = A1[1]*A2[2] - A1[2]*A2[1]; + element d2 = A1[2]*A2[0] - A1[0]*A2[2]; + element d3 = A1[0]*A2[1] - A1[1]*A2[0]; + element d = A0[0]*d1 + A0[1]*d2 + A0[2]*d3; + if ( 1 + d == 1 ) + return false; + Ai[0][0] = d1/d; + Ai[0][1] = (A2[1]*A0[2] - A2[2]*A0[1])/d; + Ai[0][2] = (A0[1]*A1[2] - A0[2]*A1[1])/d; + Ai[1][0] = d2/d; + Ai[1][1] = (A2[2]*A0[0] - A2[0]*A0[2])/d; + Ai[1][2] = (A0[2]*A1[0] - A0[0]*A1[2])/d; + Ai[2][0] = d3/d; + Ai[2][1] = (A2[0]*A0[1] - A2[1]*A0[0])/d; + Ai[2][2] = (A0[0]*A1[1] - A0[1]*A1[0])/d; + } + break; + default: // ?! + return false; + } + return true; + } +}; + +// ### N.B.: Visual C++ is unable to compile the next two member functions if +// the following external function declarations are placed within the +// member function bodies. This forces us to implement them after the +// GenericMatrix<> class declaration. + +void PCL_FUNC InPlaceGaussJordan( GenericMatrix&, GenericMatrix& ); +void PCL_FUNC InPlaceGaussJordan( GenericMatrix&, GenericMatrix& ); + +template inline +GenericMatrix GenericMatrix::Inverse() const +{ + if ( Rows() != Cols() || Rows() == 0 ) + throw Error( "Invalid matrix inversion: Non-square or empty matrix." ); + + /* + * - Use direct formulae to invert 1x1, 2x2 and 3x3 matrices. + * - Use Gauss-Jordan elimination to invert 4x4 and larger matrices. + */ + if ( Rows() < 4 ) + { + GenericMatrix Ai( Rows(), Rows() ); + if ( !Invert( Ai.m_data->v, m_data->v, Rows() ) ) + throw Error( "Invalid matrix inversion: Singular matrix." ); + return Ai; + } + else + { + GenericMatrix Ai( *this ); + GenericMatrix B = UnitMatrix( Rows() ); + InPlaceGaussJordan( Ai, B ); + return Ai; + } +} + +template inline +void GenericMatrix::Invert() +{ + if ( Rows() <= 3 ) + Transfer( Inverse() ); + else + { + if ( Rows() != Cols() || Rows() == 0 ) + throw Error( "Invalid matrix inversion: Non-square or empty matrix." ); + EnsureUnique(); + GenericMatrix B = UnitMatrix( Rows() ); + InPlaceGaussJordan( *this, B ); + } +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup matrix_operators Matrix Operators + * + * This section includes scalar-to-matrix and matrix-to-matrix arithmetic + * operator functions that are not members of the GenericMatrix template class. + */ + +/*! + * Returns the sum of two matrices \a A and \a B. + * + * If the specified matrices are incompatible for matrix addition (because + * their dimensions are different), this function throws an Error exception. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator +( const GenericMatrix& A, const GenericMatrix& B ) +{ + if ( B.Rows() != A.Rows() || B.Cols() != A.Cols() ) + throw Error( "Invalid matrix addition." ); + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ t = B.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k, ++t ) + *i = *k + *t; + return R; +} + +/*! + * Returns the sum of a matrix \a A and a scalar \a x. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator +( const GenericMatrix& A, const T& x ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = *k + x; + return R; +} + +/*! + * Returns the sum of a scalar \a x and a matrix \a A. + * + * This function exists to implement the commutative property of + * scalar-to-matrix addition. It is equivalent to A + x. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator +( const T& x, const GenericMatrix& A ) +{ + return A + x; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the result of subtracting a matrix \a B from another matrix \a A. + * + * If the specified matrices are incompatible for matrix subtraction (because + * their dimensions are different), this function throws an Error exception. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator -( const GenericMatrix& A, const GenericMatrix& B ) +{ + if ( B.Rows() != A.Rows() || B.Cols() != A.Cols() ) + throw Error( "Invalid matrix subtraction." ); + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ t = B.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k, ++t ) + *i = *k - *t; + return R; +} + +/*! + * Returns the subtraction of a scalar \a x from a matrix \a A. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator -( const GenericMatrix& A, const T& x ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = *k - x; + return R; +} + +/*! + * Returns the subtraction of a matrix \a A from a scalar \a x. + * + * This function exists because scalar-to-matrix subtraction is not a + * commutative operation. A - x is not equal to x - A (the resulting matrix + * elements have the same magnitudes but opposite signs). + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator -( const T& x, const GenericMatrix& A ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = x - *k; + return R; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the product of two matrices \a A and \a B. + * + * If the specified matrices are incompatible for matrix multiplication + * (because the number of rows in \a B is not equal to the number of columns in + * \a A), this function throws an appropriate Error exception. + * + * Bear in mind that matrix multiplication has O(N^3) complexity. This is + * relevant to multiply large matrices. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator *( const GenericMatrix& A, const GenericMatrix& B ) +{ + int n = A.Rows(); + int m = B.Cols(); + int p = A.Cols(); + if ( B.Rows() != p ) + throw Error( "Invalid matrix multiplication." ); + GenericMatrix R( n, m ); + for ( int i = 0; i < n; ++i ) + for ( int j = 0; j < m; ++j ) + { + T rij = 0; + for ( int k = 0; k < p; ++k ) + rij += A[i][k] * B[k][j]; + R[i][j] = rij; + } + return R; +} + +/*! + * Returns the product of a matrix \a A by a vector \a x. + * + * If the specified objects are incompatible for multiplication (because the + * number of components in \a x is not equal to the number of columns in \a A), + * this function throws the appropriate Error exception. + * + * The result of the product of a matrix with \e m rows and \e n columns by a + * vector of \e n components is a vector of \e m components. + * + * \ingroup matrix_operators + */ +template inline +GenericVector operator *( const GenericMatrix& A, const GenericVector& x ) +{ + int n = A.Cols(); + int m = A.Rows(); + if ( x.Length() != n ) + throw Error( "Invalid matrix-vector multiplication." ); + GenericVector r( m ); + for ( int i = 0; i < m; ++i ) + { + T ri = 0; + for ( int j = 0; j < n; ++j ) + ri += A[i][j] * x[j]; + r[i] = ri; + } + return r; +} + +/*! + * Returns the product of a matrix \a A and a scalar \a x. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator *( const GenericMatrix& A, const T& x ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = *k * x; + return R; +} + +/*! + * Returns the product of a scalar \a x and a matrix \a A. + * + * This function exists to implement the commutative property of + * scalar-to-matrix multiplication. It is equivalent to A * x. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator *( const T& x, const GenericMatrix& A ) +{ + return A * x; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the result of dividing a matrix \a A by a scalar \a x. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator /( const GenericMatrix& A, const T& x ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = *k / x; + return R; +} + +/*! + * Returns the result of dividing a scalar \a x by a matrix \a A. + * + * This function exists because scalar-to-matrix division is not a + * commutative operation. A/x is not equal to x/A. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator /( const T& x, const GenericMatrix& A ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = x / *k; + return R; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the result of raising a matrix \a A to a scalar \a x. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator ^( const GenericMatrix& A, const T& x ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Pow( *k, x ); + return R; +} + +/*! + * Returns the result of raising a scalar \a x to a matrix \a A. + * + * This function exists because scalar-to-matrix exponentiation is not a + * commutative operation. A^x is not equal to x^A. + * + * \ingroup matrix_operators + */ +template inline +GenericMatrix operator ^( const T& x, const GenericMatrix& A ) +{ + GenericMatrix R( A.Rows(), A.Cols() ); + typename GenericMatrix::block_iterator __restrict__ i = R.Begin(); + typename GenericMatrix::const_block_iterator __restrict__ j = R.End(); + typename GenericMatrix::const_block_iterator __restrict__ k = A.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = pcl::Pow( x, *k ); + return R; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_MATRIX_INSTANTIATE + +/*! + * \defgroup matrix_types Matrix Types + */ + +/*! + * \class pcl::I8Matrix + * \ingroup matrix_types + * \brief 8-bit signed integer matrix. + * + * %I8Matrix is a template instantiation of GenericMatrix for \c int8. + */ +typedef GenericMatrix I8Matrix; + +/*! + * \class pcl::CharMatrix + * \ingroup matrix_types + * \brief 8-bit signed integer matrix. + * + * %CharMatrix is an alias for I8Matrix. It is a template instantiation of + * GenericMatrix for \c int8. + */ +typedef I8Matrix CharMatrix; + +/*! + * \class pcl::UI8Matrix + * \ingroup matrix_types + * \brief 8-bit unsigned integer matrix. + * + * %UI8Matrix is a template instantiation of GenericMatrix for \c uint8. + */ +typedef GenericMatrix UI8Matrix; + +/*! + * \class pcl::ByteMatrix + * \ingroup matrix_types + * \brief 8-bit unsigned integer matrix. + * + * %ByteMatrix is an alias for UI8Matrix. It is a template instantiation of + * GenericMatrix for \c uint8. + */ +typedef UI8Matrix ByteMatrix; + +/*! + * \class pcl::I16Matrix + * \ingroup matrix_types + * \brief 16-bit signed integer matrix. + * + * %I16Matrix is a template instantiation of GenericMatrix for \c int16. + */ +typedef GenericMatrix I16Matrix; + +/*! + * \class pcl::UI16Matrix + * \ingroup matrix_types + * \brief 16-bit unsigned integer matrix. + * + * %UI16Matrix is a template instantiation of GenericMatrix for \c uint16. + */ +typedef GenericMatrix UI16Matrix; + +/*! + * \class pcl::I32Matrix + * \ingroup matrix_types + * \brief 32-bit signed integer matrix. + * + * %I32Matrix is a template instantiation of GenericMatrix for \c int32. + */ +typedef GenericMatrix I32Matrix; + +/*! + * \class pcl::IMatrix + * \ingroup matrix_types + * \brief 32-bit signed integer matrix. + * + * %IMatrix is an alias for I32Matrix. It is a template instantiation of + * GenericMatrix for \c int32. + */ +typedef I32Matrix IMatrix; + +/*! + * \class pcl::UI32Matrix + * \ingroup matrix_types + * \brief 32-bit unsigned integer matrix. + * + * %UI32Matrix is a template instantiation of GenericMatrix for \c uint32. + */ +typedef GenericMatrix UI32Matrix; + +/*! + * \class pcl::UIMatrix + * \ingroup matrix_types + * \brief Unsigned integer matrix. + * + * %UIMatrix is an alias for UI32Matrix. It is a template instantiation of + * GenericMatrix for \c uint32. + */ +typedef UI32Matrix UIMatrix; + +/*! + * \class pcl::I64Matrix + * \ingroup matrix_types + * \brief 64-bit integer matrix. + * + * %I64Matrix is a template instantiation of GenericMatrix for \c int64. + */ +typedef GenericMatrix I64Matrix; + +/*! + * \class pcl::UI64Matrix + * \ingroup matrix_types + * \brief 64-bit unsigned integer matrix. + * + * %UI64Matrix is a template instantiation of GenericMatrix for \c uint64. + */ +typedef GenericMatrix UI64Matrix; + +/*! + * \class pcl::F32Matrix + * \ingroup matrix_types + * \brief 32-bit floating point real matrix. + * + * %F32Matrix is a template instantiation of GenericMatrix for \c float. + */ +typedef GenericMatrix F32Matrix; + +/*! + * \class pcl::FMatrix + * \ingroup matrix_types + * \brief 32-bit floating point real matrix. + * + * %FMatrix is an alias for F32Matrix. It is a template instantiation of + * GenericMatrix for \c float. + */ +typedef F32Matrix FMatrix; + +/*! + * \class pcl::F64Matrix + * \ingroup matrix_types + * \brief 64-bit floating point real matrix. + * + * %F64Matrix is a template instantiation of GenericMatrix for \c double. + */ +typedef GenericMatrix F64Matrix; + +/*! + * \class pcl::DMatrix + * \ingroup matrix_types + * \brief 64-bit floating point real matrix. + * + * %DMatrix is an alias for F64Matrix. It is a template instantiation of + * GenericMatrix for \c double. + */ +typedef F64Matrix DMatrix; + +/*! + * \class pcl::Matrix + * \ingroup matrix_types + * \brief 64-bit floating point real matrix. + * + * %Matrix is an alias for DMatrix. It is a template instantiation of + * GenericMatrix for the \c double type. + */ +typedef DMatrix Matrix; + +/*! + * \class pcl::C32Matrix + * \ingroup matrix_types + * \brief 32-bit floating point complex matrix. + * + * %C32Matrix is a template instantiation of GenericMatrix for \c Complex32. + */ +typedef GenericMatrix C32Matrix; + +/*! + * \class pcl::C64Matrix + * \ingroup matrix_types + * \brief 64-bit floating point complex matrix. + * + * %C64Matrix is a template instantiation of GenericMatrix for \c Complex64. + */ +typedef GenericMatrix C64Matrix; + +#ifndef _MSC_VER + +/*! + * \class pcl::F80Matrix + * \ingroup matrix_types + * \brief 80-bit extended precision floating point real matrix. + * + * %F80Matrix is a template instantiation of GenericMatrix for \c long + * \c double. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef GenericMatrix F80Matrix; + +/*! + * \class pcl::LDMatrix + * \ingroup matrix_types + * \brief 80-bit extended precision floating point real matrix. + * + * %LDMatrix is an alias for F80Matrix. It is a template instantiation of + * GenericMatrix for \c long \c double. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef F80Matrix LDMatrix; + +#endif // !_MSC_VER + +#endif // !__PCL_NO_MATRIX_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Matrix_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Matrix.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MeanFilter.h b/3rdparty/include/pcl/MeanFilter.h new file mode 100644 index 0000000..f7c87df --- /dev/null +++ b/3rdparty/include/pcl/MeanFilter.h @@ -0,0 +1,182 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MeanFilter.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_MeanFilter_h +#define __PCL_MeanFilter_h + +/// \file pcl/MeanFilter.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MeanFilter + * \brief Square block average kernel filter + * + * A %MeanFilter object is a specialized KernelFilter whose elements are + * identical and form a square symmetrically distributed around the origin: + * + * M(x,y) = 1/(s^2) + * + * where s is the filter size, which is the same on the horizontal and vertical + * axes. This filter is separable. + * + * %MeanFilter is a building block of some important algorithms on the + * PixInsight/PCL platform, such as the Multiscale Local Normalization, + * algorithm, which uses these kernels to compute local variances. + * + * \sa KernelFilter, VariableShapeFilter, MoffatFilter, LinearFilter, + * GaussianFilter + */ +class PCL_CLASS MeanFilter : public KernelFilter +{ +public: + + /*! + * Constructs an empty %MeanFilter object. + */ + MeanFilter() = default; + + /*! + * Constructs a %MeanFilter object given the odd kernel size \a n >= 3, or + * an empty kernel filter if \a n = 0. Assigns an optional \a name to the + * new filter object. + */ + MeanFilter( int n, const String& name = String() ) + { + Initialize( n ); + Rename( name ); + } + + /*! + * Copy constructor. + */ + MeanFilter( const MeanFilter& ) = default; + + /*! + * Move constructor. + */ + MeanFilter( MeanFilter&& ) = default; + + /*! + */ + KernelFilter* Clone() const override + { + return new MeanFilter( *this ); + } + + /*! + * Returns a separable filter equivalent to this Gaussian kernel filter. + * + * A block average filter is always separable, so this member function + * should always return a valid SeparableFilter object. + */ + SeparableFilter AsSeparableFilter( float tolerance = __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE ) const override + { + FVector v = coefficients.RowVector( Size()>>1 ); + return SeparableFilter( v, v ); + } + + /*! + * Returns true iff this filter is separable. + * + * A block average filter is separable. As reimplemented in %MeanFilter, + * this member function returns true. + */ + bool IsSeparable() const override + { + return true; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + MeanFilter& operator =( const MeanFilter& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + MeanFilter& operator =( MeanFilter&& ) = default; + + /*! + * Recalculates filter coefficients for the given odd kernel size \a n >= 3. + */ + void Resize( int n ) override + { + Initialize( n ); + } + +private: + + void Initialize( int n ) + { + PCL_PRECONDITION( n == 0 || n >= 3 && (n & 1) != 0 ) + KernelFilter::Resize( n ); + if ( !IsEmpty() ) + coefficients = 1.0/NumberOfCoefficients(); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MeanFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MeanFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Memory.h b/3rdparty/include/pcl/Memory.h new file mode 100644 index 0000000..35fc63e --- /dev/null +++ b/3rdparty/include/pcl/Memory.h @@ -0,0 +1,241 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Memory.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_Memory_h +#define __PCL_Memory_h + +#include + +// Template formal parameters: +// +// FI Forward iterator +// BI Bidirectional iterator +// RI Random access iterator +// UP Unary predicate +// BP Binary predicate +// T Item type +// F Function + +// ### TODO: Document this file + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +template inline +void Fill( FI i, FI j, const T& v ) +{ + for ( ; i != j; ++i ) + *i = v; +} + +// ---------------------------------------------------------------------------- + +template inline +void Fill( FI i, FI j, const T& v, F f ) +{ + for ( ; i != j; ++i ) + f( *i, v ); +} + +// ---------------------------------------------------------------------------- + +template inline +FI1 Copy( FI1 i1, FI2 i2, FI2 j2 ) +{ + for ( ; i2 != j2; ++i1, ++i2 ) + *i1 = *i2; + return i1; +} + +// ---------------------------------------------------------------------------- + +template inline +FI1 Copy( FI1 i1, FI2 i2, FI2 j2, F f ) +{ + for ( ; i2 != j2; ++i1, ++i2 ) + f( *i1, *i2 ); + return i1; +} + +// ---------------------------------------------------------------------------- + +template inline +BI1 CopyBackward( BI1 j1, BI2 i2, BI2 j2 ) +{ + while ( i2 != j2 ) + *--j1 = *--j2; + return j1; +} + +// ---------------------------------------------------------------------------- + +template inline +BI1 CopyBackward( BI1 j1, BI2 i2, BI2 j2, F f ) +{ + while ( i2 != j2 ) + f( *--j1, *--j2 ); + return j1; +} + +// ---------------------------------------------------------------------------- + +template inline +BI1 CopyReversed( BI1 j1, FI2 i2, FI2 j2 ) +{ + for ( ; i2 != j2; ++i2 ) + *--j1 = *i2; + return j1; +} + +// ---------------------------------------------------------------------------- + +template inline +BI1 CopyReversed( BI1 j1, FI2 i2, FI2 j2, F f ) +{ + for ( ; i2 != j2; ++i2 ) + f( *--j1, *i2 ); + return j1; +} + +// ---------------------------------------------------------------------------- + +template inline +RI1 Move( RI1 i1, RI2 i2, RI2 j2 ) +{ + RI1 j1; + if ( i1 < i2 ) + j1 = Copy( i1, i2, j2 ); + else + { + j1 = i1 + (j2-i2); + CopyBackward( j1, i2, j2 ); + } + return j1; +} + +// ---------------------------------------------------------------------------- + +template inline +RI1 Move( RI1 i1, RI2 i2, RI2 j2, F f ) +{ + RI1 j1; + if ( i1 < i2 ) + j1 = Copy( i1, i2, j2, f ); + else + { + j1 = i1 + (j2-i2); + CopyBackward( j1, i2, j2, f ); + } + return j1; +} + +// ---------------------------------------------------------------------------- + +template inline +RI1 MoveBackward( RI1 j1, RI2 i2, RI2 j2 ) +{ + RI1 i1; + if ( j2 < j1 ) + i1 = CopyBackward( j1, i2, j2 ); + else + { + i1 = j1 - (j2-i2); + Copy( i1, i2, j2 ); + } + return i1; +} + +// ---------------------------------------------------------------------------- + +template inline +RI1 MoveBackward( RI1 j1, RI2 i2, RI2 j2, F f ) +{ + RI1 i1; + if ( j2 < j1 ) + i1 = CopyBackward( j1, i2, j2, f ); + else + { + i1 = j1 - (j2-i2); + Copy( i1, i2, j2, f ); + } + return i1; +} + +// ---------------------------------------------------------------------------- + +template inline +void Replace( FI i, FI j, const T1& v1, const T2& v2 ) +{ + for ( ; i != j; ++i ) + if ( *i == v1 ) + *i = v2; +} + +// ---------------------------------------------------------------------------- + +template inline +void Replace( FI i, FI j, const T1& v1, const T2& v2, BP p ) +{ + for ( ; i != j; ++i ) + if ( p( *i, v1 ) ) + *i = v2; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Memory_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Memory.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MercatorProjection.h b/3rdparty/include/pcl/MercatorProjection.h new file mode 100644 index 0000000..fb14b02 --- /dev/null +++ b/3rdparty/include/pcl/MercatorProjection.h @@ -0,0 +1,134 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MercatorProjection.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_MercatorProjection_h +#define __PCL_MercatorProjection_h + +/// \file pcl/MercatorProjection.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MercatorProjection + * \brief Mercator projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS MercatorProjection : public ProjectionBase +{ +public: + + /*! + * Default constructor. + */ + MercatorProjection() = default; + + /*! + * Copy constructor. + */ + MercatorProjection( const MercatorProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new MercatorProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "MER"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Mercator"; + } + +protected: + + bool Project( DPoint& pW, const DPoint& pN ) const noexcept override; + + bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept override; + +private: + + double m_r0 = Const::deg(); + double m_x0 = 0; + double m_y0 = 0; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MercatorProjection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MercatorProjection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MessageBox.h b/3rdparty/include/pcl/MessageBox.h new file mode 100644 index 0000000..adb793e --- /dev/null +++ b/3rdparty/include/pcl/MessageBox.h @@ -0,0 +1,337 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MessageBox.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_MessageBox_h +#define __PCL_MessageBox_h + +/// \file pcl/MessageBox.h + +#include + +#include +#include + +#ifndef __PCL_MSGBOX_DONT_REMOVE_PREVIOUS_DECLARATION +/* + * Remove conflicting identifiers from Win32 SDK headers. + * + * Unfortunately, MessageBox is #defined as a macro in winuser.h, and this may + * cause problems with our code on Windows platforms. + * + * If for some eccentric reason you really want to use the Win32 API MessageBox + * function (why should you?), then call either MessageBoxA() or MessageBoxW(). + */ +# ifdef MessageBox +# undef MessageBox +# endif +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::StdIcon + * \brief Standard MessageBox icons. + * + * + * + * + * + * + * + *
StdIcon::NoIcon No icon will be shown on the %MessageBox
StdIcon::Question Standard question mark icon
StdIcon::Information Standard information icon
StdIcon::Warning Standard warning icon
StdIcon::Error Standard error icon
+ */ +namespace StdIcon +{ + enum value_type + { + NoIcon, + Question, + Information, + Warning, + Error, + + NumberOfStandardIcons + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::StdButton + * \brief Standard MessageBox buttons. + * + * + * + * + * + * + * + * + * + * + * + * + *
StdButton::NoButton No button
StdButton::Ok Ok button
StdButton::Cancel Cancel button
StdButton::Yes Yes button
StdButton::No No button
StdButton::Abort Abort button
StdButton::Retry Retry button
StdButton::Ignore Ignore button
StdButton::YesToAll Yes to All button
StdButton::NoToAll No to All button
+ */ +namespace StdButton +{ + enum value_type + { + NoButton, + Ok, + Cancel, + Yes, + No, + Abort, + Retry, + Ignore, + YesToAll, + NoToAll, + + NumberOfStandardButtons + }; +} + +// ---------------------------------------------------------------------------- + +class MessageBoxPrivate; + +/*! + * \class MessageBox + * \brief High-level interface to a PixInsight %MessageBox object. + * + * A %MessageBox object executes as a modal window relative to PixInsight's + * main window. Message boxes are useful to show brief messages, to notify + * errors, warnings and other special conditions, and to obtain simple answers + * (yes/no, ok/cancel, and so on) from the user. + * + * \sa Dialog + */ +class PCL_CLASS MessageBox +{ +public: + + /*! + * Represents a standard message box icon. + */ + typedef StdIcon::value_type std_icon; + + /*! + * Represents a standard message box button. + */ + typedef StdButton::value_type std_button; + + /*! + * Constructs a %MessageBox object. + * + * \param text The text that will be shown on the message box's client + * area. Can be either plain text or include basic html tags + * like \, \\, \\, \\, + * \\, etc. + * + * \param caption The caption of the message box window. If an empty string + * is specified, the platform will assign a default caption. + * + * \param icon The message box icon. By default, no icon appears on a + * message box. + * + * \param button0,button1,button2 Specify up to three buttons that will be + * included on the bottom row of this message box. By default a + * message box includes just an Ok standard button. + * + * \param defaultButtonIdx The button index (from 0 to 2) of the + * default button on this dialog box. The default + * button will be activated when the user presses the Return or + * Enter keys. + * + * \param escapeButtonIdx The button index (from 0 to 2) of the button + * that will be activated when the user presses the Escape key, + * or when (s)he closes the message box window explicitly. If a + * value < 0 is specified (the default value), pressing the Esc + * key simply cancels the dialog and forces a return value of + * StdButton::Cancel. + */ + MessageBox( const String& text = String(), + const String& caption = String(), // default caption + std_icon icon = StdIcon::NoIcon, + std_button button0 = StdButton::Ok, + std_button button1 = StdButton::NoButton, + std_button button2 = StdButton::NoButton, + int defaultButtonIdx = 0, + int escapeButtonIdx = -1 ); // escape cancels dialog + + /*! + * Destroys a %MessageBox object. + */ + virtual ~MessageBox(); + + /*! + * Executes this message box modally. Returns a StdButton identifier + * corresponding to the button that the user activated to close the message + * box. + * + * For example, when the user clicks on the Ok button (if that button has + * been included in this message box), this function returns StdButton::Ok. + */ + std_button Execute(); + + /*! + * Returns the last modal result, or StdButton::NoButton if this box has not + * been executed previously. + */ + std_button Result() const; + + /*! + * Returns the text that this message box shows on its client area. + */ + String Text() const; + + /*! + * Sets the \a text to be shown on the client area of this message box. + */ + void SetText( const String& text ); + + /*! + * Returns the caption text of this message box. + */ + String Caption() const; + + /*! + * Sets the caption \a text of this message box. + */ + void SetCaption( const String& text ); + + /*! + * Returns the icon that will be shown on this message box. + */ + std_icon Icon() const; + + /*! + * Sets the \a icon that will be shown on this message box. + */ + void SetIcon( std_icon icon ); + + /*! + * Returns the identifier of the first button on this message box. + */ + std_button FirstButton() const; + + /*! + * Sets the first button on this message box. + */ + void SetFirstButton( std_button button ); + + /*! + * Returns the identifier of the second button on this message box. + */ + std_button SecondButton() const; + + /*! + * Sets the second button on this message box. + */ + void SetSecondButton( std_button button ); + + /*! + * Returns the identifier of the third button on this message box. + */ + std_button ThirdButton() const; + + /*! + * Sets the third button on this message box. + */ + void SetThirdButton( std_button button ); + + /*! + * Returns the index, from 0 to 2, of the default button on this + * message box. + * + * The default button will be activated if the user presses the Return or + * Enter keys. + */ + int DefaultButtonIndex() const; + + /*! + * Sets the index, from 0 to 2, of the default button on this + * message box. + */ + void SetDefaultButtonIndex( int index ); + + /*! + * Returns the index, from 0 to 2, of the escape button on this + * message box. + * + * The escape button will be activated if the user presses the Escape key, + * or if (s)he closes the message box's window explicitly. + */ + int EscapeButtonIndex() const; + + /*! + * Sets the index, from 0 to 2, of the escape button on this + * message box. + */ + void SetEscapeButtonIndex( int index ); + +private: + + AutoPointer p; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MessageBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MessageBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MetaFileFormat.h b/3rdparty/include/pcl/MetaFileFormat.h new file mode 100644 index 0000000..427b0df --- /dev/null +++ b/3rdparty/include/pcl/MetaFileFormat.h @@ -0,0 +1,895 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MetaFileFormat.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_MetaFileFormat_h +#define __PCL_MetaFileFormat_h + +/// \file pcl/MetaFileFormat.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS FileFormatImplementation; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaFileFormat + * \brief A formal description of an image file format in PixInsight. + * + * %MetaFileFormat provides a formal description of the basic functionality and + * properties of an image file format in a PixInsight module. + * + * A module implements an \e installable file format as a derived class of + * %MetaFileFormat. Such subclass describes general properties of the file + * format, and also provides the basic mechanisms to instantiate a format and + * to generate duplicates of existing format instances. + * + * %MetaFileFormat and its subclasses don't implement any file handling + * capabilities. Actual file access work must be implemented through a + * format instance implementation class, which is always a subclass of + * the FileFormatImplementation class in the PixInsight/PCL framework. + * + * In PixInsight's terminology, a format instance can be thought of as + * an image stored as a disk file of the format in question, although the + * concept of format instances allows for more flexible, generalized + * interpretations. + * + * Note that the %MetaFileFormat and FileFormatImplementation classes are + * conceptually parallel to MetaProcess and ProcessImplementation, + * respectively. In the same way, a process is to a format like a process + * instance is to a format instance in PixInsight. This is just a reflection of + * the strong object orientation that characterizes the PixInsight platform. + * + * Each file format must have a unique name, or \e identifier. Identifiers are + * crucial for many key features of the PixInsight environment, as scripts, the + * command-line interface, image icons and image containers, etc. + * + * \sa MetaObject, FileFormatBase, FileFormat, FileFormatImplementation, + * FileFormatInstance + */ +class PCL_CLASS MetaFileFormat : public MetaObject, public FileFormatBase +{ +public: + + /*! + * Constructs a %MetaFileFormat object. + */ + MetaFileFormat(); + + /*! + * Destroys this %MetaFileFormat object. + */ + virtual ~MetaFileFormat() noexcept( false ) + { + } + + /*! + * Copy constructor. This constructor is disabled because %MetaFileFormat + * represents unique server-side objects. + */ + MetaFileFormat( const MetaFileFormat& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %MetaFileFormat + * represents unique server-side objects. + */ + MetaFileFormat& operator =( const MetaFileFormat& ) = delete; + + /*! + */ + virtual IsoString Name() const override = 0; + + /*! + */ + virtual StringList FileExtensions() const override = 0; + + /*! + * Returns a list of MIME types corresponding to the data supported by + * this file format. + * + * The returned list must be a sequence of "media_type/content_type" items + * approved by IANA (see http://www.iana.org/assignments/media-types/), for + * example: "image/fits", "application/fits". + * + * Providing a list of MIME types is not mandatory, but highly recommended + * for all format support modules implementing standard (i.e., recognized by + * IANA) image formats. + * + * \note The default implementation of this function returns an empty + * string list, so by default a format does not provide a set of supported + * MIME types. This is legal, but considered bad practice when the format + * implements a standard image format recognized by IANA. + */ + IsoStringList MimeTypes() const override + { + return IsoStringList(); + } + + /*! + */ + uint32 Version() const override; + + /*! + * Returns a brief description text for this file format. + * + * This function must provide a simple, typically single-line, description + * of this image file format for quick reference. Example: "Flexible Image + * Transport System". The Implementation() member function has been designed + * to provide a more complete description of a format's functionality and + * capabilities. + * + * \note The default implementation of this function returns an empty + * string, so by default a format does not provide a description. This is + * legal, but it is considered bad practice, so this function \e should be + * reimplemented. + */ + String Description() const override + { + return String(); + } + + /*! + * Returns a descriptive text about this implementation of a particular + * image file format. + * + * This function must provide a brief but sufficiently informative + * description of this file format implementation. The returned description + * will appear on the Format Explorer window, and should provide information + * about how this format has been implemented in a module. Avoid too + * exhaustive descriptions that are better reserved for a technical manual. + * Avoid also describing a file format itself; the information given should + * not intend to replace an official/formal definition of an image format. + * + * Descriptions of file format implementations are always written on + * PixInsight consoles. This means that the text output functionality of the + * Console class can be used to format the string returned by this function. + * Refer to that class and its documentation for further information. + * + * \note The default implementation of this function returns an empty + * string, so by default a format does not provide an implementation + * description. This is legal, but it is considered bad practice, so this + * function \e should be reimplemented. + */ + String Implementation() const override + { + return String(); + } + + /*! + * Returns a description of the current status of this file format + * implementation. + * + * This function should return an empty string for normal file format + * implementations. Exceptions to this rule are obsolete or deprecated file + * formats (see the IsDeprecated() member function), deficient + * implementations, or other special cases where the user should be aware of + * important potential problems or limitations. + * + * The output of this function should be essentially plain text with basic + * HTML tags. No console tags should be used. + * + * \note The default implementation of this function returns an empty + * string, so by default a format does not provide any status information. + */ + String Status() const override + { + return String(); + } + + /*! + * Returns the icon image of this file format as a document in SVG format. + * + * The specified image will be used to identify all instances of this file + * format in the core application's GUI. It will be used on the %Format + * Explorer window, on image icons of this format, and in general for every + * graphical item related to this format or to an instance of this format. + * + * The returned string must be the source code of a valid SVG document + * representing the icon image, encoded in UTF-8. + * + * Since core version 1.8.8-6, all process, interface and file format icons + * should be specified in SVG format. Raster formats, such as XPM and PNG, + * have been deprecated for this purpose. + * + * If both this function and IconImageSVGFile() return an empty string, or + * if the specified SVG document does not exist or is not valid, a default + * icon will be assigned to this format automatically by the PixInsight core + * application. + * + * \note The default implementation of this function returns an empty + * string. + * + * \sa IconImageSVGFile() + */ + virtual IsoString IconImageSVG() const + { + return IsoString(); + } + + /*! + * Returns the icon image of this file format as a document in SVG format, + * stored as an external file. + * + * The specified image will be used to identify all instances of this file + * format in the core application's GUI. It will be used on the %Format + * Explorer window, on image icons of this format, and in general for every + * graphical item related to this format or to an instance of this format. + * + * The returned string must be a path to an existing file in the local + * file system (remote resources are not supported in current PCL versions), + * which must store a valid SVG document representing the icon image. The + * SVG source code must be encoded in UTF-8. + * + * Since core version 1.8.8-6, all process, interface and file format icons + * should be specified in SVG format. Raster formats, such as XPM and PNG, + * have been deprecated for this purpose. + * + * If both this function and IconImageSVG() return an empty string, or if + * the specified SVG document does not exist or is not valid, a default icon + * will be assigned to this format automatically by the PixInsight core + * application. + * + * Automatic Resource Location + * + * Format icon image files can be loaded from arbitrary locations on the + * local file system. However, modules typically install their file format + * icons on the /rsc/icons/module directory under the local PixInsight + * installation. A module can specify the "@module_icons_dir/" prefix in + * icon file paths to let the PixInsight core application load the + * corresponding SVG documents from the appropriate standard distribution + * directory automatically. For example, suppose that a "Bar" file format, + * pertaining to a "Foo" module, reimplements this member function in its + * %MetaFileFormat derived class as follows: + * + * \code + * class Bar : public MetaFileFormat + * { + * public: + * ... + * + * String IconImageSVGFile() const override + * { + * return "@module_icons_dir/Bar.svg"; + * } + * + * ... + * }; + * \endcode + * + * Then the core application will attempt to load the following SVG file: + * + * <install-dir>/rsc/icons/module/Foo/Bar.svg + * + * where <install-dir> is the local directory where the running + * PixInsight core application is installed. + * + * \note The default implementation of this function returns an empty + * string. + * + * \sa IconImageSVG() + */ + virtual String IconImageSVGFile() const + { + return String(); + } + + /*! + * Returns a large icon for this format as an image in the + * standard XPM format. + * + * The specified image will be used to identify all instances of this file + * format in the core application's GUI. It will be used on the %Format + * Explorer window, on image icons of this format, and in general for every + * graphical item related to this format or to an instance of this format. + * + * 32-bit RGBA color images (including an alpha channel) are fully + * supported. + * + * If this function returns nullptr, a default icon will be assigned to this + * file format automatically. + * + * \note The default implementation of this function returns nullptr. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define file format icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa IconImageFile() + */ + virtual const char** IconImageXPM() const + { + return nullptr; + } + + /*! + * Returns a large icon for this format as a path specification to + * an existing image file. + * + * Supported image file formats include PNG, XPM, JPG and BMP. + * + * For details on format icon images, see the documentation for + * IconImageXPM(). + * + * \note The default implementation of this function returns an empty + * string. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define file format icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa IconImageXPM() + */ + virtual String IconImageFile() const + { + return String(); + } + + /*! + * Returns a small icon for this format as an image in the + * standard XPM format. + * + * For details on format icon images, see the documentation for + * IconImageXPM(). + * + * Small icons are used on interface elements where screen space must be + * preserved. Two good examples are the Format Explorer window and the + * ImageContainer interface. + * + * When this function is not reimplemented in a derived class, the core + * PixInsight application automatically generates a small icon by resampling + * down the large icon provided by IconImageXPM(). + * + * You normally should not need to reimplement this function; the core + * application does a fine work resampling large icons to obtain reduced + * versions. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define file format icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa SmallIconImageFile() + */ + virtual const char** SmallIconImageXPM() const + { + return 0; + } + + /*! + * Returns a small icon for this format as a path specification to + * an existing image file. + * + * Supported image file formats include PNG, XPM, JPG and BMP. + * + * For details on small format icon images, see the documentation for + * SmallIconImageXPM(). + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define file format icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa SmallIconImageXPM() + */ + virtual String SmallIconImageFile() const + { + return String(); + } + + /*! + */ + Bitmap Icon() const override; + + /*! + */ + Bitmap SmallIcon() const override; + + /*! + * Returns true only if this file format implementation can read an entire + * image in a single operation. + * + * The default implementation returns true. + */ + bool CanRead() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation can write an entire + * image in a single operation. + * + * The default implementation returns true. + */ + bool CanWrite() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation supports + * incremental read operations on image files. + * + * Incremental read operations allow the PixInsight core application and + * other modules to load images by successive row strips. + * + * The default implementation returns false. + */ + bool CanReadIncrementally() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation supports + * incremental write operations on image files. + * + * Incremental write operations allow the PixInsight core application and + * other modules to write images by successive row strips. + * + * The default implementation returns false. + */ + bool CanWriteIncrementally() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write 8-bit + * unsigned integer images + * + * The default implementation returns true. + */ + bool CanStore8Bit() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation can read/write + * 16-bit unsigned integer images + * + * The default implementation returns true. + */ + bool CanStore16Bit() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation can read/write + * 32-bit unsigned integer images + * + * The default implementation returns false. + */ + bool CanStore32Bit() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write + * 64-bit unsigned integer images + * + * The default implementation returns false. + */ + bool CanStore64Bit() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write + * 32-bit floating point real images (IEEE 754 32-bit single + * precision format for pixel sample values). + * + * The default implementation returns false. + */ + bool CanStoreFloat() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write + * 64-bit floating point real images (IEEE 754 64-bit double + * precision format for pixel sample values). + * + * The default implementation returns false. + */ + bool CanStoreDouble() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write + * 32-bit floating point complex images (IEEE 754 32-bit single + * precision format for components of complex pixel sample values). + * + * The default implementation returns false. + */ + bool CanStoreComplex() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write + * 64-bit floating point complex images (IEEE 754 64-bit double + * precision format for components of complex pixel sample values). + * + * The default implementation returns false. + */ + bool CanStoreDComplex() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can read/write + * grayscale pixel data. + * + * The default implementation returns true. + */ + bool CanStoreGrayscale() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation can read/write RGB + * color pixel data. + * + * The default implementation returns true. + */ + bool CanStoreRGBColor() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation supports alpha + * image channels. + * + * The default implementation returns true. + */ + bool CanStoreAlphaChannels() const override + { + return true; + } + + /*! + * Returns true only if this file format implementation can store/retrieve + * image resolution data. + * + * The default implementation returns false. + */ + bool CanStoreResolution() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can embed/extract + * FITS header keyword collections. + * + * The default implementation returns false. + */ + bool CanStoreKeywords() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can embed/extract + * ICC color profiles. + * + * The default implementation returns false. + */ + bool CanStoreICCProfiles() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can embed/extract + * thumbnail images. + * + * The default implementation returns false. + */ + bool CanStoreThumbnails() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can store/retrieve + * data properties associated with format instances or image files. + * + * \note Don't confuse this member function with CanStoreImageProperties(). + * This function returns true if the implementation can store properties + * associated with an entire file or format instance, while + * CanStoreImageProperties() returns true if the implementation can store + * properties associated with individual images. + * + * The default implementation returns false. + * + * \sa CanStoreImageProperties(), SupportsViewProperties() + */ + bool CanStoreProperties() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can store/retrieve + * properties associated with individual images. + * + * The default implementation returns false. + * + * \sa CanStoreProperties(), SupportsViewProperties() + */ + bool CanStoreImageProperties() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can store/retrieve + * RGB working space data. + * + * The default implementation returns false. + */ + bool CanStoreRGBWS() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can store/retrieve + * DisplayFunction objects. + * + * The default implementation returns false. + */ + bool CanStoreDisplayFunctions() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation can store/retrieve + * color filter array (CFA) descriptions. + * + * The default implementation returns false. + */ + bool CanStoreColorFilterArrays() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation supports compression + * of pixel data. + * + * This refers to compression of \e source pixels, not to native compression + * schemes used by some file formats. + * + * For examle, the compression schemes employed in the JPEG and JPEG2000 + * formats must \e not cause this member function to return true. The + * optional ZIP and LZW compressions used in TIFF are the exact kind of + * compressions that must cause this member function to return true. + * + * The default implementation returns false. + */ + bool SupportsCompression() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation supports multiple + * images stored in a single file. + * + * For example, multiple images (e.g., taken with different filters) can be + * stored in FITS files by means of FITS image extensions, forming a + * data cube of several images with the same dimensions, or even a + * collection of independent images. + * + * The default implementation returns false. + */ + bool SupportsMultipleImages() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation supports data + * properties of different data types such as Float64, UI32Vector, String, + * Complex32, etc. + * + * If this member function returns true, a reimplementation of + * CanStoreProperties() and/or CanStoreImageProperties() (depending on + * format capabilities) must also return true, and the format must implement + * all property data types supported by View objects. For information on + * supported view property types, see the VTYPE_XXX predefined constants in + * PCL API headers. + * + * This function should return false if this format only supports storage of + * BLOB properties, represented as ByteArray objects, or a limited subset of + * view property types. + * + * The default implementation returns false. + * + * \sa CanStoreProperties(), CanStoreImageProperties(), + * View::PropertyValue(), View::SetPropertyValue() + */ + bool SupportsViewProperties() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation allows the user to + * edit specific format preferences. + * + * If this function returns true, then the EditPreferences() procedure must + * be reimplemented in a derived class. + * + * The default implementation returns false. + */ + bool CanEditPreferences() const override + { + return false; + } + + /*! + * Returns true only if this file format implementation uses + * format-specific data. + * + * Format-specific data are preserved on a per-instance (say per-file) basis + * by the PixInsight application, who actually knows nothing about them. + * + * The default implementation returns false. + * + * \sa ValidateFormatSpecificData(), DisposeFormatSpecificData() + */ + bool UsesFormatSpecificData() const override + { + return false; + } + + /*! + * Returns true only if this file format has been deprecated or declared + * obsolete on the PixInsight platform. + * + * When this function returns true, the Status() member function should also + * return information about the current status of this file format, + * including an explanation of the reasons for deprecation. + * + * The default implementation returns false. + */ + bool IsDeprecated() const override + { + return false; + } + + /*! + */ + bool ValidateFormatSpecificData( const void* data ) const override; + + /*! + */ + void DisposeFormatSpecificData( void* data ) const override; + + /*! + * Handles a request to edit format preferences. Returns true iff the + * preferences were successfully edited. + * + * When implemented, this procedure should open a dialog box to let the + * user edit format-specific preferences and operating options. This + * function should only return true if the user accepts the new settings + * (e.g. by clicking the dialog's OK button). + * + * \note This member function will never be called if the + * CanEditPreferences() member function is not reimplemented to return true. + */ + bool EditPreferences() const override; + + /*! + * Creates a new instance of this file format. + * + * Typically, we have a %MetaFileFormat descendant class describing an image + * file format in generic terms, and a FileFormatImplementation descendant + * class implementing format instantiation (i.e. doing actual file reading, + * writing, embedding, etc.). + * + * \note This is a pure virtual function that must be reimplemented in all + * derived classes. + */ + virtual FileFormatImplementation* Create() const = 0; + +private: + + void PerformAPIDefinitions() const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_MetaFileFormat_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MetaFileFormat.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MetaModule.h b/3rdparty/include/pcl/MetaModule.h new file mode 100644 index 0000000..244a4c3 --- /dev/null +++ b/3rdparty/include/pcl/MetaModule.h @@ -0,0 +1,1037 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MetaModule.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_MetaModule_h +#define __PCL_MetaModule_h + +/// \file pcl/MetaModule.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaModule + * \brief A formal description of a PixInsight module. + * + * %MetaModule is the root element in the hierarchical structure of components + * that constitute every PixInsight module. This class provides a formal + * description of the basic functionality and properties of a module. + * + * Every PixInsight module must define a \e unique subclass of %MetaModule. + * That subclass, besides describing the module, will be the primary interface + * between all module components (processes, file formats and interfaces) and + * the PixInsight core application. + * + * In any PixInsight module, there exists a \e unique instance of a derived + * class of %MetaModule, accessible as a global pointer variable declared in + * the pcl namespace, namely: + * + * \code + * namespace pcl + * { + * extern MetaModule* Module; + * } // pcl + * \endcode + * + * The entire tree of existing module components can always be accessed by + * using the MetaObject::operator[]( size_type ) operator function recursively, + * starting from the \c Module global variable. + * + * \sa MetaObject, MetaProcess, MetaParameter, MetaFileFormat + */ +class MetaModule : public MetaObject +{ +public: + + /*! + * Constructs a %MetaModule object. + */ + MetaModule(); + + /*! + * Destroys a %MetaModule object and all of its child module components. + * + * This function effectively destroys \e all existing module components by + * indirect recursion of MetaObject::~MetaObject(). + */ + virtual ~MetaModule(); + + /*! + * Copy constructor. This constructor is disabled because %MetaModule + * represents unique server-side objects. + */ + MetaModule( const MetaModule& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %MetaModule represents + * unique server-side objects. + */ + MetaModule& operator =( const MetaModule& ) = delete; + + /*! + * \deprecated This member function has been deprecated. It is maintained for + * compatibility with existing code - do not use it in newly produced code. + */ + virtual const char* UniqueId() const; + + /*! + * Returns a version information string for this PixInsight module. + * + * This member function must be reimplemented to return the + * starting address of an invariant sequence of 8-bit characters. The + * returned character string shall have the following format: + * + * PIXINSIGHT_MODULE_VERSION_\\ + * + * where: + * + * * PIXINSIGHT_MODULE_VERSION_ is a mandatory prefix. It must be included + * literally at the beginning of the returned string. + * + * * \ is a mandatory version string composed by + * at least 17 characters. It must have the following format: + * + * MM.mm.rr.bbbb.LLL[.\] + * + * where MM is the major version number, mm is the minor + * version number, rr is the release version number, and bbbb + * is a build number. The three version numbers must be in the + * range from zero to 99. The build number must be in the range from 1 to + * 9999. The four numbers must be left padded with zeros in the returned + * string, if necessary, and their values are supposed to increase with each + * successive version of the module. + * + * LLL is a three-letter ISO 639.2 language code, which must correspond to + * the primary language of the module (generally, the language used to write + * visible messages and information of the user interface). + * + * \ is an optional version status word. If included, it can be one + * of the following: + * + * alpha Indicates an alpha version of the module (a version at the early + * development stages, where the final features and functionality + * of the module still have not been defined). + * + * beta Indicates a beta version of the module (a development version + * that still is not suitable for production release). + * + * rc\ A release candidate version (an almost finished version, still + * under development but very close to a final release). \ is + * an arbitrary release candidate number. + * + * release Indicates a release (final, production) version. + * + * exp An experimental version (a special development version, not + * intended for public release; usually a confidential version + * distributed among the members of a development team) + * + * If no status is specified in the version information string, a release + * version will be assumed. + * + * \note This is a pure virtual function that must be reimplemented by all + * derived classes. + * + * \sa GetVersion() + */ + virtual const char* Version() const = 0; + + /*! + * Provides the version numbers, language code and development status of + * this module. + * + * \param[out] major Main (major) version number. + * + * \param[out] minor Secondary (minor) version number. + * + * \param[out] release Release number. + * + * \param[out] build Build number. + * + * \param[out] language An ISO 639.2 language code (3-letter code) that + * identifies the primary language of this module. + * + * \param[out] status A string indicating the development status of + * this module (alpha, beta, release, etc.), or an empty string + * if no specific status has been specified. For possible + * values and their meanings, see the documentation for the + * Version() member function. + * + * This is a utility function, provided for convenience. It parses the + * version information string returned by the Version() member + * function, and stores the extracted values in the specified argument + * variables. + * + * \sa Version() + */ + void GetVersion( int& major, int& minor, int& release, int& build, + IsoString& language, IsoString& status ) const; + + /*! + * Returns a readable version string for this module of the form: + * + * <module-name> version M.m.r.b + * + * where <module-name> is the string returned by the (reimplemented) + * Name() virtual member function, and M.m.r.b are the major, minor, release + * and build numbers, as provided by GetVersion(). + * + * The string returned by this member function is suitable to be used for + * module identification purposes, including metadata such as FITS keywords. + */ + IsoString ReadableVersion() const; + + /*! + * Returns an identifier for this module. + * + * The returned string must be a valid C identifier. The identifier must be + * unique among the identifiers of all installed modules in the calling + * instance of the PixInsight core application. + * + * This function is not intended to provide a descriptive name, but just a + * reference identifier for this module. For example, some identifiers of + * standard PixInsight modules are: Geometry, Image, FITS. + * + * \note This is a pure virtual function that must be reimplemented by all + * derived classes. + */ + virtual IsoString Name() const = 0; + + /*! + * Provides a \e brief description of this module. + * + * This function is not intended to give a thorough description, but just a + * succint sentence to quickly identify this module and its contents. + * + * Example of good module description: + * "MyFancyCrop Process Module". + * + * Example of \e bad module description: + * "This module implements MyFancyCrop: A high-performance process to + * crop and rotate images arbitrarily.". + * + * \note Reimplementing this function in a derived class is optional. + * However, this function \e should be reimplemented by all modules, to + * provide meaningful information to the users during module installation + * procedures. + */ + virtual String Description() const + { + return String(); + } + + /*! + * Returns the name of the software company responsible for the development + * of this module. + * + * Please don't advertise your company here. A module returning something + * like "MySoftwareCompany - Advanced Imaging Solutions for the Serious + * Imager" wouldn't be certified. + * + * \note Reimplementing this function is optional, but advisable. + */ + virtual String Company() const + { + return String(); + } + + /*! + * Returns the name of the author or authors of this module. + * + * To specify multiple author names, separate them with commas. + * + * \note Reimplementing this function is optional, but advisable. + */ + virtual String Author() const + { + return String(); + } + + /*! + * Provides copyright information for this module. + * + * Example: "Copyright (c) 2007, MySoftwareCompany. All Rights + * Reserved". + * + * \note Reimplementing this function is optional, but advisable. + */ + virtual String Copyright() const + { + return String(); + } + + /*! + * Returns a string with a trade mark or a list of trade marks. + * + * To specify multiple trade marks, separate them with commas. + * + * \note Reimplementing this function is optional. + */ + virtual String TradeMarks() const + { + return String(); + } + + /*! + * Returns the original file name of this module. + * + * \note Reimplementing this function is optional. + */ + virtual String OriginalFileName() const + { + return String(); + } + + /*! + * Provides release date information for this module. + * + * \param[out] year The (full) year this module has been released. + * + * \param[out] month The month this module has been released, + * 1 <= month <= 12, 1=January. + * + * \param[out] day The day this module has been released, + * 1 <= day <= 31. + * + * The specified date must be correct; for example, something like + * 2007/02/30 will not be accepted (the module won't install). + * + * \note Reimplementing this function is optional. If it is not + * reimplemented by a derived class to return a valid date, the module will + * provide no specific release date. + */ + virtual void GetReleaseDate( int& year, int& month, int& day ) const + { + year = month = day = 0; // unspecified + } + + /*! + * Acquires current physical memory statistics. + * + * \param[out] totalBytes On output, an estimate of the total amount of + * existing physical memory in bytes. + * + * \param[out] availableBytes On output, an estimate of the amount of + * memory in bytes that can be allocated by the + * caller without pushing the system into swap, + * taking into account memory being used for file + * caches that can be reclaimed. + * + * The current platform-dependent implementation provides accurate values on + * supported versions of FreeBSD, Linux, macOS, and Windows. + * + * Returns true if the required system calls and external processes were + * executed correctly and provided valid values. Returns false in the event + * of error, in which case the passed variables could be modified, possibly + * with meaningless values. + * + * \sa AvailablePhysicalMemory(), PhysicalMemoryLoad() + */ + bool GetPhysicalMemoryStatus( size_type& totalBytes, size_type& availableBytes ) const; + + /*! + * Returns an estimate of how much free memory is currently available. + * + * This function returns the amount of memory in bytes that can be allocated + * by the caller without pushing the system into swap, taking into account + * memory being used for file caches that can be reclaimed. The current + * platform-dependent implementation returns accurate values on supported + * versions of FreeBSD, Linux, macOS, and Windows. + * + * The returned value is zero in the event of error. In theory this can only + * happen on Linux if /proc/meminfo cannot be accessed, which should never + * happen on a healthy system under normal working conditions. + */ + size_type AvailablePhysicalMemory() const + { + size_type dum, availableBytes; + if ( GetPhysicalMemoryStatus( dum, availableBytes ) ) + return availableBytes; + return 0; + } + + /*! + * Returns an estimate of the fraction of physical memory currently in use. + * + * This function acquires estimates of the total amount of existing physical + * memory and the amount of memory that can be currently allocated by the + * caller without causing the system to swap. See AvailablePhysicalMemory() + * for more information. + * + * The returned value is zero in the event of error, or in the range (0,1) + * if valid, representing the fraction of physical memory that is currently + * allocated, excluding memory used for reclaimable file caches. + */ + float PhysicalMemoryLoad() const + { + size_type totalBytes, availableBytes; + if ( GetPhysicalMemoryStatus( totalBytes, availableBytes ) ) + return float( 1 - double( availableBytes )/totalBytes ); + return 0; + } + + /*! + * Module allocation routine. Allocates a contiguous block of \a sz bytes, + * and returns its starting address. + * + * This routine is called by PCL internal code, and indirectly by the + * PixInsight core application. + * + * The default implementation simply calls ::operator new( sz ) to allocate + * a block of the specified size. + * + * You usually should not need to reimplement this function, unless you want + * to implement a special memory management strategy for your module. + * + * \sa Deallocate() + */ + virtual void* Allocate( size_type sz ) + { + PCL_PRECONDITION( sz != 0 ) + return reinterpret_cast( ::operator new( sz ) ); + } + + /*! + * Module deallocation routine. Deallocates a previously allocated + * contiguous block of memory starting at address \a p. + * + * This routine is called by PCL internal code, and indirectly by the + * PixInsight core application. + * + * The default implementation simply calls ::operator delete( p ) to free + * the specified block. + * + * You usually should not need to reimplement this function, unless you want + * to implement a special memory management strategy for your module. + * + * \sa Allocate() + */ + virtual void Deallocate( void* p ) + { + PCL_PRECONDITION( p != nullptr ) + ::operator delete( p ); + } + + /*! + * Routine invoked just after this module has been installed. + * + * This function can be reimplemented to perform module-specific + * initialization procedures. + * + * \sa OnUnload() + */ + virtual void OnLoad() + { + } + + /*! + * Routine invoked just before this module is unloaded in response to an + * uninstall request, or just before the PixInsight core application is + * about to terminate execution. + * + * This function can be reimplemented to perform module-specific + * finalization procedures. + * + * \sa OnLoad() + */ + virtual void OnUnload() + { + } + + /*! + * Returns true iff this module has been successfully installed. Only when + * the module has been installed, communication with the PixInsight core + * application is fully operative. + */ + bool IsInstalled() const; + + /*! + * Processes pending user interface and thread events. + * + * Call this function from the root thread (aka GUI thread) to let + * the PixInsight core application process pending interface events, which + * may accumulate while your code is running. + * + * Modules typically call this function during real-time preview generation + * procedures. Calling this function from the root thread ensures that the + * GUI remains responsive during long, calculation-intensive operations. + * + * If the \a excludeUserInputEvents parameter is set to true, no user input + * events will be processed by calling this function. This includes mainly + * mouse and keyboard events. Unprocessed input events will remain pending + * and will be processed as appropriate when execution returns to + * PixInsight's main event handling loop, or when this function is called + * with \a excludeUserInputEvents set to false. + * + * When this function is invoked from a running thread, a ProcessAborted + * exception will be thrown automatically if the Thread::Abort() member + * function has been previously called for the running thread. This allows + * stopping running processes in a thread-safe and controlled way. For more + * information, read the documentation for the Thread class. + * + * \note Do not call this function too frequently from the root thread, as + * doing so may degrade the performance of the whole PixInsight graphical + * interface. For example, calling this function at 250 ms intervals is + * reasonable and more than sufficient in most cases. Normally, you should + * only need to call this function during real-time image and graphics + * generation procedures, or from time-consuming processes, especially from + * multithreaded code. + * + * \sa Thread, Thread::Abort() + */ + void ProcessEvents( bool excludeUserInputEvents = false ); + + /*! + * Loads a bitmap resource file. + * + * \param filePath Path to a resource file in Qt's binary resource format + * (RCC format). This path must point to a location on the + * local file system (remote resources are not allowed in + * current PCL versions). + * + * \param rootPath Root path for all the loaded bitmap resources. This + * parameter is an empty string by default. + * + * If the specified resource file does not exist or is invalid, this + * function will throw an Error exception. + * + * Automatic Resource Location + * + * Resource files can be loaded from arbitrary locations. However, modules + * typically install their resources on the /rsc/rcc/module directory under + * the local PixInsight installation. A module can specify the + * "@module_rcc_dir/" prefix in resource file paths to let the + * PixInsight core application load the resources from the appropriate + * standard distribution directory automatically. For example, if a module + * whose name is "Foo" makes the following call: + * + * \code LoadResource( "@module_rcc_dir/MyResources.rcc" ); \endcode + * + * the core application will attempt to load the following resource file: + * + * <install-dir>/rsc/rcc/module/Foo/MyResources.rcc + * + * where <install-dir> is the local directory where the running + * PixInsight core application is installed. + * + * Resource Root Paths + * + * All the resources loaded by a call to this function will be rooted at the + * specified \a rootPath under a standard ":/module/<module-name>/" + * root path prefix set by the PixInsight core application automatically. + * For example, if the Foo module calls this function as follows: + * + * \code LoadResource( "@module_rcc_dir/MyResources.rcc" ); \endcode + * + * and the MyResources.rcc file contains a resource named "foo-icon.png", it + * will be available at the following resource path: + * + * :/module/Foo/foo-icon.png + * + * This system guarantees that a module will never invalidate or replace + * existing resources loaded by the core application or other modules. Note + * that a module still can cause problems by loading resources incorrectly, + * but these problems cannot propagate outside the failing module. + * + * To ease working with module-defined resources, the standard + * ":/@module_root/" prefix can be specified in resource file paths: + * + * \code Bitmap bmp( ":/@module_root/foo-icon.png" ); \endcode + * + * Continuing with the Foo module example, this call would load the bitmap + * at ":/module/Foo/foo-icon.png". + * + * \b References + * + * \li The Qt Resource System: http://doc.qt.io/qt-5/resources.html + * + * \sa UnloadResource() + */ + void LoadResource( const String& filePath, const String& rootPath = String() ); + + /*! + * Unloads a bitmap resource file. + * + * After calling this function, all the resources available from the + * specified resource file will be unavailable. The \a filePath and + * \a rootPath arguments must be identical to the ones used when the + * resource was loaded by a call to LoadResource(). + * + * If the specified resource has not been loaded, or if there are active + * references to the resource (for example, because one or more existing + * Bitmap objects depend on data stored in the resource), this function + * will throw an Error exception. + * + * \sa LoadResource() + */ + void UnloadResource( const String& filePath, const String& rootPath = String() ); + + /*! + * Executes a script in the platform's core scripting engine. + * + * \param sourceCode A string containing valid source code in the + * specified \a language. + * + * \param language The name of a supported scripting language. + * Currently only the JavaScript language is supported + * by this function. JavaScript is assumed if this + * string is either empty or equal to "JavaScript". + * + * Returns the result value of the executed script. The result value is the + * value of the last executed expression statement in the script that is not + * in a function definition. + * + * The script will be executed in the core JavaScript Runtime (PJSR). All + * PJSR resources are available. + * + * If the script cannot be evaluated, for example because it has syntax + * errors, or attempts to execute invalid code, or throws an exception, this + * member function throws an Error exception. + * + * \note This function can only be called from the root thread, since the + * core JavaScript engine in not reentrant in current versions of + * PixInsight. Calling this function from a running thread will throw an + * Error exception. + * + * \warning You should make sure that your code has been well tested before + * calling this function. PixInsight pursues efficiency and script execution + * is no exception. Nothing will protect or watch your code, or help you + * stop it at any point. If your code enters an infinite loop, it will crash + * the whole PixInsight platform without remedy. Also bear in mind that + * scripts are extremely powerful and potentially dangerous if you don't + * know well what you are doing. What happens during execution of your + * scripts is your entire responsibility. + */ + Variant EvaluateScript( const String& sourceCode, const IsoString& language = IsoString() ); + + /*! + * Returns true iff the module has the specified security \a entitlement. + * + * Entitlements are special permissions granted to installed modules by the + * PixInsight core application, as part of the implemented code security + * infrastructure. + * + * An entitlement may be necessary to perform certain operations considered + * potentially dangerous, either for the user or for the PixInsight + * platform. Entitlements can also be required by running process and format + * instances to perform specific actions. + * + * String representations of entitlements normally follow the inverse URL + * format. For example: "com.pixinsight.security.pcl.experimental-features". + */ + bool HasEntitlement( const IsoString& entitlement ); + +private: + + void PerformAPIDefinitions() const override; + + friend class APIInitializer; +}; + +// ---------------------------------------------------------------------------- + +extern MetaModule* Module; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::InstallMode + * \brief Module installation modes. + * + * This namespace enumerates module installation modes that the PixInsight core + * application passes to the module installation entry point (PMINS). See the + * \ref module_entry_points "Module Entry Points" section for detailed + * information. + * + * The current installation modes are:\n + * + * + * + * + * + *
InstallMode::FullInstall Normal, full installation
InstallMode::QueryModuleInfo Temporary load to gather module properties
InstallMode::VerifyModule Temporary load to verify module integrity
+ */ +namespace InstallMode +{ + enum value_type + { + FullInstall, // Normal, full installation + QueryModuleInfo, // Temporary load to gather module properties + VerifyModule // Temporary load to verify module integrity + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup metamodule_utility_macros MetaModule Utility Macros + */ + +/*! + * \def PCL_MODULE_UNIQUE_ID + * \deprecated This macro has been deprecated. It is kept as part of PCL for + * compatibility with existing modules. Do not use it in newly + * produced code. + * \ingroup metamodule_utility_macros + */ +#define PCL_MODULE_UNIQUE_ID( uid ) \ + ("PIXINSIGHT_MODULE_UNIQUE_ID_" PCL_STRINGIFY( uid )) + +/*! + * \def PCL_MODULE_VERSION + * \brief A utility macro to build a module version string. + * \ingroup metamodule_utility_macros + * + * \param MM The main (major) version number of the module. Must be an + * integer in the range from 0 to 99, and must be left-padded with + * a zero, when necessary. + * + * \param mm The second (minor) version number of the module. Must be an + * integer in the range from 0 to 99, and must be left-padded with + * a zero, when necessary. + * + * \param rr The revision version number of the module. Must be an integer in + * the range from 0 to 99, and must be left-padded with a zero, + * when necessary. + * + * \param bbbb The build version number of the module. Must be an integer in + * the range from 1 to 9999, and must be left-padded with a maximum + * of three zeros, as necessary. + * + * \param lan The primary language of the module. Must be a valid ISO 639.2 + * language code (a 3-letter code identifying a language). + * + * This macro generates a string literal with the mandatory + * "PIXINSIGHT_MODULE_VERSION_" prefix prepended to the actual module version + * string, which is composed by concatenation of the specified macro arguments. + * + * Example: + * + * \code + * #define MODULE_VERSION_MAJOR 01 + * #define MODULE_VERSION_MINOR 00 + * #define MODULE_VERSION_REVISION 02 + * #define MODULE_VERSION_BUILD 0045 + * #define MODULE_VERSION_LANGUAGE eng + * ... + * #include + * ... + * class MyModule : public pcl::MetaModule + * { + * // Define your module class here + * }; + * ... + * const char* MyModule::Version() const + * { + * return PCL_MODULE_VERSION( MODULE_VERSION_MAJOR, + * MODULE_VERSION_MINOR, + * MODULE_VERSION_REVISION, + * MODULE_VERSION_BUILD, + * MODULE_VERSION_LANGUAGE ); + * } + * \endcode + * + * In the example above, the Version() member of MyModule would return the + * following version string: + * + * "PIXINSIGHT_MODULE_VERSION_01.00.02.0045.eng" + * + * \sa PCL_MODULE_VERSION_S, PCL_MODULE_UNIQUE_ID + */ +#define PCL_MODULE_VERSION( MM, mm, rr, bbbb, lan ) \ + ("PIXINSIGHT_MODULE_VERSION_" \ + PCL_STRINGIFY( MM ) "." \ + PCL_STRINGIFY( mm ) "." \ + PCL_STRINGIFY( rr ) "." \ + PCL_STRINGIFY( bbbb ) "." \ + PCL_STRINGIFY( lan )) + +/*! + * \def PCL_MODULE_VERSION_S + * \brief A utility macro to build a module version string, including a + * development status specification. + * \ingroup metamodule_utility_macros + * + * This macro is an extension of the PCL_MODULE_VERSION macro. It generates a + * version string that also includes a development status, specified + * as the \a status macro argument. + * + * The \a status argument can have the following values: + * + * alpha For an alpha development status + * + * beta For a beta development status + * + * release For a release (final) version + * + * rc\ For a release candidate version, where \ is the release + * candidate number. + * + * exp For an experimental version (usually a development version not + * intended for public release). + * + * Other values are not recognized by the platform and cause rejection of a + * module for installation. + * + * This macro generates a string that is suitable to be returned by a + * reimplementation of MetaModule::Version(). An example follows: + * + * Example: + * + * \code + * #define MODULE_VERSION_MAJOR 01 + * #define MODULE_VERSION_MINOR 00 + * #define MODULE_VERSION_REVISION 02 + * #define MODULE_VERSION_BUILD 0045 + * #define MODULE_VERSION_LANGUAGE eng + * #define MODULE_VERSION_STATUS rc3 + * ... + * #include + * ... + * class MyModule : public pcl::MetaModule + * { + * // Define your module class here + * }; + * ... + * const char* MyModule::Version() const + * { + * return PCL_MODULE_VERSION_S( MODULE_VERSION_MAJOR, + * MODULE_VERSION_MINOR, + * MODULE_VERSION_REVISION, + * MODULE_VERSION_BUILD, + * MODULE_VERSION_LANGUAGE, + * MODULE_VERSION_STATUS ); + * } + * \endcode + * + * In the example above, the Version() member of MyModule would return the + * following version string: + * + * "PIXINSIGHT_MODULE_VERSION_01.00.02.0045.eng.rc3" + * + * \sa PCL_MODULE_VERSION, PCL_MODULE_UNIQUE_ID + */ +#define PCL_MODULE_VERSION_S( MM, mm, rr, bbbb, lan, status ) \ + ("PIXINSIGHT_MODULE_VERSION_" \ + PCL_STRINGIFY( MM ) "." \ + PCL_STRINGIFY( mm ) "." \ + PCL_STRINGIFY( rr ) "." \ + PCL_STRINGIFY( bbbb ) "." \ + PCL_STRINGIFY( lan ) "." \ + PCL_STRINGIFY( status )) + +// ---------------------------------------------------------------------------- + +} // pcl + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup module_entry_points Module Entry Point Functions + * + * Module entry points are special functions required for module installation + * and initialization. Entry points are called directly by the PixInsight core + * application and must be implemented following the standard 'C' naming and + * calling conventions as nonstatic, publicly visible global symbols. + * + * In current versions of the PixInsight platform, there are two mandatory + * module entry points, namely the identification and initialization entry + * points (known as PMIDN and PMINI, respectively), and an optional (although + * usually necessary) installation entry point (PMINS). We describe these + * special functions in detail in this section. + * + * \n + *

PixInsight Module Identification (PMIDN) entry point

+ * + * This function will be called by the PixInsight core application when it + * needs to retrieve identification and descriptive data from a module. This + * happens when a module is about to be installed, but also when a module is + * being inspected, either for security reasons or after a direct user request. + * + * A PMIDN must have the following declaration: + * + * \code + * PCL_MODULE_EXPORT uint32 IdentifyPixInsightModule( api_module_description** description, int32 phase ); + * \endcode + * + * \param description Pointer to a pointer to an API module description + * structure. See the declaration of api_module_description in + * API/APIDefs.h for details. This structure must be provided by the + * called module as POD, and its starting address must be written to + * the pointer pointed to by this argument in a call to this function + * with \a phase = 1 (see below). + * + * \param phase Module identification request:\n + * \li \a phase = 0x00 - Prepare for module identification.\n + * \li \a phase = 0x01 - Report module descriptive data in a structure + * of type 'api_module_description', whose address must be stored in + * the pointer pointed to by the \a description argument.\n + * \li \a phase = 0xff - Module identification process completed. The + * module description structure provided when \a phase = 1 can be + * deallocated and disposed as necessary. + * + * Other values of \a phase may be passed in additional calls to a PMIDN. Those + * values and calls are reserved for special modules pertaining to the core of + * the PixInsight platform, and hence not in the user land. In current versions + * of PixInsight, such special calls must be ignored by the invoked module. + * + * A PMIDN must return zero upon success. Any other return value will be + * interpreted as a module-specific error code. + * + * Module developers using the standard PixInsight Class Library (PCL) + * distribution don't have to care about PMIDN, since it is already implemented + * internally by PCL. + * + * \note A PMIDN is mandatory for all PixInsight modules, and must be + * implemented as a nonstatic, publicly visible global symbol following the + * standard 'C' naming and calling conventions. The PCL_MODULE_EXPORT macro + * guarantees these conditions on all supported C++ compilers. + * + * \n + *

PixInsight Module Initialization (PMINI) entry point

+ * + * This function will be called by the PixInsight core application when a + * module is being installed. It provides a module with the necessary elements + * to perform a bidirectional communication with the core application via the + * standard PCL API callback system. + * + * A PMINI must have the following declaration: + * + * \code + * PCL_MODULE_EXPORT uint32 InitializePixInsightModule( api_handle hModule, function_resolver R, uint32 apiVersion, void* reserved ); + * \endcode + * + * \param hModule Handle to the module being installed. This handle + * uniquely identifies the module, and must be used in all + * subsequent API calls requiring a module handle. + * + * \param R Pointer to an API function resolver callback. See the + * declaration of function_resolver in API/APIDefs.h and + * the automatically generated file pcl/APIInterface.cpp + * for details. + * + * \param apiVersion API version number. + * + * \param reserved Reserved for special invocations to core platform + * modules. Must not be used or altered in any way. + * + * A PMINI must return zero upon success. Any other return value will be + * interpreted as a module-specific error code. + * + * Module developers using the standard PixInsight Class Library (PCL) + * distribution don't have to care about PMINI, since it is already implemented + * internally by PCL. + * + * \note A PMINI is mandatory for all PixInsight modules, and must be + * implemented as a nonstatic, publicly visible global symbol following the + * standard 'C' naming and calling conventions. The PCL_MODULE_EXPORT macro + * guarantees these conditions on all supported C++ compilers. + * + * \n + *

PixInsight Module Installation (PMINS) entry point

+ * + * If this function is defined as a public symbol in a module, the PixInsight + * core application will call it just after loading and initializing the module + * shared object or dynamic-link library. This happens after calling the + * mandatory module entry points PMIDN and PMINI. + * + * A PMINS must have the following declaration: + * + * \code + * PCL_MODULE_EXPORT int32 InstallPixInsightModule( int32 mode ); + * \endcode + * + * \param mode Specifies the kind of installation being performed by + * the PixInsight core application. See the + * pcl::InstallMode namespace for more information. + * + * A PMINS must return zero upon successful installation. Any other return + * value will be interpreted as a module-specific error code. + * + * Although a PMINS is optional, it normally has to be defined by non-trivial + * modules in order to create and initialize the different objects and + * meta-objects required to implement their functionality, since most of these + * objects are dynamic in PCL. See the source code of the open-source standard + * modules for examples. Look for <module_name>Module.cpp files. + * + * \note If available, a PMINS must be implemented as a nonstatic, publicly + * visible global symbol following the standard 'C' naming and calling + * conventions. The PCL_MODULE_EXPORT macro guarantees these conditions on all + * supported C++ compilers. + */ + +// ---------------------------------------------------------------------------- + +// end global namespace + +#endif // __PCL_MetaModule_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MetaModule.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MetaObject.h b/3rdparty/include/pcl/MetaObject.h new file mode 100644 index 0000000..a0a9dcb --- /dev/null +++ b/3rdparty/include/pcl/MetaObject.h @@ -0,0 +1,192 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MetaObject.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_MetaObject_h +#define __PCL_MetaObject_h + +/// \file pcl/MetaObject.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaObject + * \brief Root base class for all PixInsight module components. + * + * In PCL, a \e metaobject is a special class describing in formal terms the + * functionality and properties of a \e component in a PixInsight module. + * + * The %MetaObject class provides basic functionality to implement the existing + * hierarchical relationships between a module and all of its components. A + * %MetaObject contains a list of %MetaObject instances, which generates a tree + * structure based on parent-children container relations. This structural + * layout has been used in PCL to automatize communication between the core + * PixInsight application, modules, and all module components. + * + * \sa MetaModule, MetaProcess, MetaParameter, MetaFileFormat + */ +class PCL_CLASS MetaObject +{ +public: + + /*! + * A container used to implement the list of children module components in + * %MetaObject. + */ + typedef IndirectArray children_list; + + /*! + * Constructs a %MetaObject as a child of the specified \a parent object. + */ + MetaObject( MetaObject* parent ) + : m_parent( parent ) + { + if ( m_parent != nullptr ) + m_parent->m_children.Add( this ); + } + + /*! + * Destroys this %MetaObject and all of its children module components. + */ + virtual ~MetaObject() noexcept( false ) + { + m_children.Destroy(); + } + + /*! + * Copy constructor. Copy semantics are disabled for %MetaObject because + * this class represents unique server-side objects. + */ + MetaObject( const MetaObject& ) = delete; + + /*! + * Copy assignment. Copy semantics are disabled for %MetaObject because + * this class represents unique server-side objects. + */ + MetaObject& operator =( const MetaObject& ) = delete; + + /*! + * Move constructor. Move semantics are disabled for %MetaObject because + * because of parent-child server-side object relations. + */ + MetaObject( MetaObject&& x ) = delete; + + /*! + * Move assignment. Move semantics are disabled for %MetaObject because + * because of parent-child server-side object relations. + */ + MetaObject& operator =( MetaObject&& x ) = delete; + + /*! + * Returns the number of module components that depend on this %MetaObject. + */ + size_type Length() const + { + return m_children.Length(); + } + + /*! + * Returns a pointer to the unmodifiable parent %MetaObject. + */ + const MetaObject* Parent() const + { + return m_parent; + } + + /*! + * Returns a pointer to the parent %MetaObject. + */ + MetaObject* Parent() + { + return m_parent; + } + + /*! + * Returns a pointer to a %MetaObject children module component, selected by + * its array index \a i. + */ + const MetaObject* operator[]( size_type i ) const + { + return m_children[i]; + } + +protected: + + MetaObject* m_parent = nullptr; + children_list m_children; + + /*! + * \internal + */ + virtual void PerformAPIDefinitions() const = 0; + + friend class MetaModule; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_MetaObject_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MetaObject.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MetaParameter.h b/3rdparty/include/pcl/MetaParameter.h new file mode 100644 index 0000000..624c62a --- /dev/null +++ b/3rdparty/include/pcl/MetaParameter.h @@ -0,0 +1,1999 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MetaParameter.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_MetaParameter_h +#define __PCL_MetaParameter_h + +/// \file pcl/MetaParameter.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +#include // DBL_MAX + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS MetaProcess; +class PCL_CLASS MetaTable; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaParameter + * \brief Root base class for PCL classes providing formal descriptions of + * process parameters. + * + * %MetaParameter represents a process parameter. This is an abstract + * base class providing fundamental functionality common to all process + * parameters available in PCL. Derived classes implement and extended that + * functionality to represent a wide variety of process parameter types. + * + * %Process parameters can be numerical values (MetaInteger and MetaReal, and + * their derived classes with different ranges), Boolean values (MetaBoolean), + * enumerated types (MetaEnumeration), and dynamic strings (MetaString). + * + * In addition, a set of arbitrary process parameters can be organized to + * define the columns of a table parameter (MetaTable). A table + * parameter can have an unlimited, variable number of rows. + * + * Finally, block parameters (MetaBlock) can also be defined to store + * arbitrary data as memory blocks of variable size. + * + * \sa MetaProcess, ProcessImplementation + */ +class PCL_CLASS MetaParameter : public MetaObject +{ +public: + + /*! + * Constructs a metaparameter representing a parameter of the specified + * process class \a *P. + */ + MetaParameter( MetaProcess* P ); + + /*! + * Constructs a metaparameter representing a column of a table process + * parameter represented by the metatable \a *T. The new metaparameter is + * appended to the list of existing columns in the metatable \a *T. + */ + MetaParameter( MetaTable* T ); + + /*! + * Destroys a %MetaParameter object. + */ + virtual ~MetaParameter() noexcept( false ) + { + } + + /*! + * Returns the identifier of the process parameter that this metaparameter + * represents. + * + * Each process parameter must have a valid, unique (within its parent + * process) C identifier. + * + * \sa Aliases() + */ + virtual IsoString Id() const = 0; + + /*! + * Returns a list of alias identifiers for this process parameter. + * + * A process parameter can have one or more alias identifiers. + * Aliased parameters are useful to maintain compatibility with previous + * versions of a process. + * + * When the PixInsight core application imports a process instance (e.g. + * from a process icon) it automatically replaces alias parameter + * identifiers with actual (current) identifiers. This allows a developer to + * change the identifiers of some process parameters without breaking + * compatibility with process instances in existing icon collections or + * projects. + * + * The returned string is a comma-separated list of identifiers that will be + * treated as synonyms to the actual identifier of this parameter, which is + * returned by the Id() member function. Two parameters of a process can't + * have the same alias, so each identifier included in the list must be + * unique within its parent process. + * + * \note The default implementation of this member function returns an empty + * string (no aliases). + * + * \sa Id() + */ + virtual IsoString Aliases() const + { + return IsoString(); + } + + /*! + * Returns true iff actual process parameters represented by this + * metaparameter require explicit unlock calls. + * + * An explicit unlock is a call to ProcessImplementation::UnlockParameter(), + * which always happens after an initial call to + * ProcessImplementation::LockParameter(). + * + * \note The default implementation of this function returns false, so a + * process parameter is not explicitly unlocked by default. + */ + virtual bool NeedsUnlocking() const + { + return false; + } + + /*! + * Returns true iff actual process parameters represented by this + * metaparameter require explicit validation. + * + * An explicit validation occurs when the PixInsight core application + * performs a call to ProcessImplementation::ValidateParameter(), either as + * part of a process instance execution, or indirectly because a module has + * requested it by calling ProcessInstance::Validate(). + * + * For example, suppose that you define an integer parameter for a process. + * The MetaInteger class is a descendant of MetaNumeric, which allows you to + * define a valid range of values. This is sufficient to automatically + * reject any actual parameter value outside the declared range. But suppose + * that only \e odd integer values (1, 3, 5, 7 ...) are valid values for the + * parameter in question. The only way to impose such restriction is + * reimplementing this function to return true, and the corresponding + * ProcessImplementation::ValidateParameter() function to reject any even + * integer value. + * + * \note The default implementation of this function returns false, so a + * process parameter is never validated by default, unless a module + * explicitly requests validation of a process instance. + */ + virtual bool NeedsValidation() const + { + return false; + } + + // ### Undocumented + virtual uint32 FirstProcessVersion() const + { + return 0; + } + + // ### Undocumented + virtual uint32 LastProcessVersion() const + { + return 0; + } + + /*! + * Returns true iff the process parameter represented by this metaparameter + * is required to build new process instances. Returns false if a default + * value can be valid for the process parameter when an actual value is not + * available. + * + * When a new instance is being constructed and the represented process + * parameter is not present, this function is called to decide whether a + * default, automatically generated value may be acceptable, or if the + * explicit presence of an actual value for the represented parameter is + * imprescindible. + * + * For example, if you implement a new version of an existing process, + * perhaps you will define new parameters as well. The new parameters will + * not be available in existing stored instances (e.g., in PSM files, or + * scripts) of previous versions. In this case, if you can provide plausible + * default values for the new parameters, and you don't reimplement this + * function for them, then the old process instances will still be reusable. + * + * \note The default implementation of this function returns false, so + * actual parameter values are not strictly required by default. + */ + virtual bool IsRequired() const + { + return false; + } + + /*! + * Returns true if this metaparameter represents a read-only process + * parameter. Otherwise full read/write access to this parameter is granted + * for external processes. + * + * Read-only parameters or \e properties cannot be changed by external + * processes. For example, a script running on the core application can + * retrieve a read-only property from a process instance, but it cannot + * change its value. + * + * Read-only properties are often used to provide resulting values or + * process status information after instance execution. For example, the + * standard ImageIntegration process includes several read-only properties + * that can be accessed from a script to know the identifiers of the views + * generated to store the integrated image and the rejection map images. + * This improves versatility and usability of processes from scripts, and + * provides more accurate and extensive information to the users. + * + * \note The default implementation of this function returns false, so + * process parameters allow normal read/write access by default. + */ + virtual bool IsReadOnly() const + { + return false; + } + + /*! + * Returns a brief description of the process parameter represented by this + * metaparameter. + * + * The returned string will be used on the %Process Explorer window, which + * gives a summary of the parameters of each installed process. The + * information will be written to a console, so you can use the whole + * functionality of Console to format the text given here. + * + * Try to write succint but meaningful parameter descriptions. + */ + virtual String Description() const + { + return String(); + } + + /*! + * Returns a script comment for the process parameter represented by this + * metaparameter. + * + * For the sake of compatibility, the returned string should contain only + * valid ISO-8859-1 characters (represented as UTF-16 since the return value + * is a String object). No special characters, control tags or character + * entities are supported. This string will be used as a source code comment + * to document process parameters in automatically generated scripts. + * + * If this member function is not reimplemented for a table parameter (see + * MetaTable), PCL automatically generates a script comment including the + * identifiers of all table column parameters. + */ + virtual String Comment() const + { + return String(); + } + + /*! + * Returns true iff this metaparameter represents a numeric process + * parameter. Numeric process parameters are represented as subclasses of + * MetaNumeric. + */ + virtual bool IsNumeric() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents a Boolean process + * parameter. Boolean process parameters are represented as subclasses of + * MetaBoolean. + */ + virtual bool IsBoolean() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents an enumerated process + * parameter. Enumerated process parameters are represented as subclasses of + * MetaEnumeration. + */ + virtual bool IsEnumeration() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents a variable-length process + * parameter. Variable-length process parameters are represented as + * subclasses of MetaVariableLengthParameter. + */ + virtual bool IsVariableLength() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents a string process parameter. + * %String process parameters are represented as subclasses of MetaString. + */ + virtual bool IsString() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents a table process parameter. + * Table process parameters are represented as subclasses of MetaTable. + */ + virtual bool IsTable() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents a block process parameter. + * Block process parameters are represented as subclasses of MetaBlock. + */ + virtual bool IsBlock() const + { + return false; + } + +protected: + + void PerformAPIDefinitions() const override; + + virtual void PerformTypeAPIDefinitions() const + { + } + + virtual uint32 APIParType() const = 0; + + static bool inTableDefinition; + + friend class MetaTable; + friend class MetaProcess; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaNumeric + * \brief A formal description of a numeric process parameter. + * + * Numeric process parameters can be integers (MetaInteger) and floating-point + * reals (MetaReal). + * + * Integer process parameters can be signed (MetaSignedInteger) and unsigned + * (MetaUnsignedInteger) 8, 16, 32 and 64-bit integers. Real process parameters + * can be 32 and 64-bit IEEE 754 floating point values. This leads to the + * following numeric metaparameter classes: + * + * \li Unsigned integer process parameters: MetaUInt8, MetaUInt16, MetaUInt32, + * and MetaUInt64. + * + * \li Signed integer process parameters: MetaInt8, MetaInt16, MetaInt32, and + * MetaInt64. + * + * \li Real process parameters: MetaFloat and MetaDouble. + */ +class PCL_CLASS MetaNumeric : public MetaParameter +{ +public: + + /*! + * Constructs a metaparameter representing a numeric parameter of the + * specified process class \a *P. + */ + MetaNumeric( MetaProcess* P ) + : MetaParameter( P ) + { + } + + /*! + * Constructs a metaparameter representing a numeric value in a column of a + * table process parameter represented by the metatable \a *T. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaNumeric( MetaTable* T ) + : MetaParameter( T ) + { + } + + /*! + * Destroys a %MetaNumeric object. + */ + virtual ~MetaNumeric() noexcept( false ) + { + } + + /*! + */ + bool IsNumeric() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns true iff this metaparameter represents a real (floating-point) + * process parameter. Real process parameters are represented as subclasses + * of MetaReal. + */ + virtual bool IsReal() const + { + return false; + } + + /*! + * Returns true iff this metaparameter represents an integer process + * parameter. Integer process parameters are represented as subclasses of + * MetaReal. + */ + virtual bool IsInteger() const + { + return false; + } + + /*! + * Returns the default value of the numeric process parameter represented by + * this metaparameter. + * + * \note The default implementation of this function returns zero. + */ + virtual double DefaultValue() const + { + return 0; + } + + /*! + * Returns the minimum valid value for the numeric process parameter + * represented by this metaparameter. + * + * \note The default implementation of this function returns -DBL_MAX, + * which is the minimum possible value of a \c double number. + */ + virtual double MinimumValue() const + { + return -DBL_MAX; + } + + /*! + * Returns the maximum valid value for the numeric process parameter + * represented by this metaparameter. + * + * \note The default implementation of this function returns DBL_MAX, + * which is the maximum possible value of a \c double number. + */ + virtual double MaximumValue() const + { + return +DBL_MAX; + } + +protected: + + void PerformTypeAPIDefinitions() const override; + virtual uint32 APIParType() const override = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaInteger + * \brief A formal description of an integer process parameter. + * + * Integer process parameters can be signed (MetaSignedInteger) and unsigned + * (MetaUnsignedInteger) 8, 16, 32 and 64-bit integers. This leads to the + * following integer process parameter classes: + * + * \li Unsigned integer process parameters: MetaUInt8, MetaUInt16, MetaUInt32, + * and MetaUInt64. + * + * \li Signed integer process parameters: MetaInt8, MetaInt16, MetaInt32, and + * MetaInt64. + */ +class PCL_CLASS MetaInteger : public MetaNumeric +{ +public: + + /*! + * Constructs a metaparameter representing an integer parameter of the + * specified process class \a *P. + */ + MetaInteger( MetaProcess* P ) + : MetaNumeric( P ) + { + } + + /*! + * Constructs a metaparameter representing an integer value in a column of a + * table process parameter represented by the metatable \a *T. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaInteger( MetaTable* T ) + : MetaNumeric( T ) + { + } + + /*! + * Destroys a %MetaInteger object. + */ + virtual ~MetaInteger() noexcept( false ) + { + } + + /*! + */ + bool IsInteger() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns true if this metaparameter represents a signed integer process + * parameter; false if it represents an unsigned integer process parameter. + */ + virtual bool IsSigned() const = 0; + +private: + + virtual uint32 APIParType() const override = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaUnsignedInteger + * \brief A formal description of an unsigned integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit unsigned integer process parameters. This + * leads to the following unsigned process parameter classes: MetaUInt8, + * MetaUInt16, MetaUInt32, and MetaUInt64. + */ +class PCL_CLASS MetaUnsignedInteger : public MetaInteger +{ +public: + + /*! + * Constructs a metaparameter representing an unsigned integer parameter of + * the specified process class \a *P. + */ + MetaUnsignedInteger( MetaProcess* P ) + : MetaInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing an unsigned integer value in a + * column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaUnsignedInteger( MetaTable* T ) + : MetaInteger( T ) + { + } + + /*! + * Destroys a %MetaUnsignedInteger object. + */ + virtual ~MetaUnsignedInteger() noexcept( false ) + { + } + + /*! + */ + bool IsSigned() const override + { + return false; + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + virtual uint32 APIParType() const override = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaSignedInteger + * \brief A formal description of a signed integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit signed integer process parameters. This + * leads to the following signed process parameter classes: MetaInt8, + * MetaInt16, MetaInt32, and MetaInt64. + */ +class PCL_CLASS MetaSignedInteger : public MetaInteger +{ +public: + + /*! + * Constructs a metaparameter representing a signed integer parameter of + * the specified process class \a *P. + */ + MetaSignedInteger( MetaProcess* P ) + : MetaInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing a signed integer value in a + * column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaSignedInteger( MetaTable* T ) + : MetaInteger( T ) + { + } + + /*! + * Destroys a %MetaSignedInteger object. + */ + virtual ~MetaSignedInteger() noexcept( false ) + { + } + + /*! + */ + bool IsSigned() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + virtual uint32 APIParType() const override = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaUInt8 + * \brief A formal description of an 8-bit unsigned integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit unsigned integer process parameters. This + * leads to the following unsigned process parameter classes: MetaUInt8, + * MetaUInt16, MetaUInt32, and MetaUInt64. + */ +class PCL_CLASS MetaUInt8 : public MetaUnsignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing an 8-bit unsigned integer + * parameter of the specified process class \a *P. + */ + MetaUInt8( MetaProcess* P ) + : MetaUnsignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing an 8-bit unsigned integer value + * in a column of a table process parameter represented by the metatable + * \a *T. The new metaparameter is appended to the list of existing columns + * in the metatable \a *T. + */ + MetaUInt8( MetaTable* T ) + : MetaUnsignedInteger( T ) + { + } + + /*! + * Destroys a %MetaUInt8 object. + */ + virtual ~MetaUInt8() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaUInt16 + * \brief A formal description of a 16-bit unsigned integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit unsigned integer process parameters. This + * leads to the following unsigned process parameter classes: MetaUInt8, + * MetaUInt16, MetaUInt32, and MetaUInt64. + */ +class PCL_CLASS MetaUInt16 : public MetaUnsignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing a 16-bit unsigned integer + * parameter of the specified process class \a *P. + */ + MetaUInt16( MetaProcess* P ) + : MetaUnsignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing a 16-bit unsigned integer value + * in a column of a table process parameter represented by the metatable + * \a *T. The new metaparameter is appended to the list of existing columns + * in the metatable \a *T. + */ + MetaUInt16( MetaTable* T ) + : MetaUnsignedInteger( T ) + { + } + + /*! + * Destroys a %MetaUInt16 object. + */ + virtual ~MetaUInt16() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaUInt32 + * \brief A formal description of a 32-bit unsigned integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit unsigned integer process parameters. This + * leads to the following unsigned process parameter classes: MetaUInt8, + * MetaUInt16, MetaUInt32, and MetaUInt64. + */ +class PCL_CLASS MetaUInt32 : public MetaUnsignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing a 32-bit unsigned integer + * parameter of the specified process class \a *P. + */ + MetaUInt32( MetaProcess* P ) + : MetaUnsignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing a 32-bit unsigned integer value + * in a column of a table process parameter represented by the metatable + * \a *T. The new metaparameter is appended to the list of existing columns + * in the metatable \a *T. + */ + MetaUInt32( MetaTable* T ) + : MetaUnsignedInteger( T ) + { + } + + /*! + * Destroys a %MetaUInt32 object. + */ + virtual ~MetaUInt32() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaUInt64 + * \brief A formal description of a 64-bit unsigned integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit unsigned integer process parameters. This + * leads to the following unsigned process parameter classes: MetaUInt8, + * MetaUInt16, MetaUInt32, and MetaUInt64. + */ +class PCL_CLASS MetaUInt64 : public MetaUnsignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing a 64-bit unsigned integer + * parameter of the specified process class \a *P. + */ + MetaUInt64( MetaProcess* P ) + : MetaUnsignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing a 64-bit unsigned integer value + * in a column of a table process parameter represented by the metatable + * \a *T. The new metaparameter is appended to the list of existing columns + * in the metatable \a *T. + */ + MetaUInt64( MetaTable* T ) + : MetaUnsignedInteger( T ) + { + } + + /*! + * Destroys a %MetaUInt64 object. + */ + virtual ~MetaUInt64() noexcept( false ) + { + } + + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaInt8 + * \brief A formal description of an 8-bit signed integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit signed integer process parameters. This + * leads to the following signed process parameter classes: MetaInt8, + * MetaInt16, MetaInt32, and MetaInt64. + */ +class PCL_CLASS MetaInt8 : public MetaSignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing an 8-bit signed integer parameter + * of the specified process class \a *P. + */ + MetaInt8( MetaProcess* P ) + : MetaSignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing an 8-bit signed integer value in + * a column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaInt8( MetaTable* T ) + : MetaSignedInteger( T ) + { + } + + /*! + * Destroys a %MetaInt8 object. + */ + virtual ~MetaInt8() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaInt16 + * \brief A formal description of a 16-bit signed integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit signed integer process parameters. This + * leads to the following signed process parameter classes: MetaInt8, + * MetaInt16, MetaInt32, and MetaInt64. + */ +class MetaInt16 : public MetaSignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing a 16-bit signed integer parameter + * of the specified process class \a *P. + */ + MetaInt16( MetaProcess* P ) + : MetaSignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing a 16-bit signed integer value in + * a column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaInt16( MetaTable* T ) + : MetaSignedInteger( T ) + { + } + + /*! + * Destroys a %MetaInt16 object. + */ + virtual ~MetaInt16() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaInt32 + * \brief A formal description of a 32-bit signed integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit signed integer process parameters. This + * leads to the following signed process parameter classes: MetaInt8, + * MetaInt16, MetaInt32, and MetaInt64. + */ +class PCL_CLASS MetaInt32 : public MetaSignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing a 32-bit signed integer parameter + * of the specified process class \a *P. + */ + MetaInt32( MetaProcess* P ) + : MetaSignedInteger( P ) + { + } + + /*! + * Constructs a metaparameter representing a 32-bit signed integer value in + * a column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaInt32( MetaTable* T ) + : MetaSignedInteger( T ) + { + } + + /*! + * Destroys a %MetaInt32 object. + */ + virtual ~MetaInt32() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaInt64 + * \brief A formal description of a 64-bit signed integer process parameter. + * + * PCL supports 8, 16, 32 and 64-bit signed integer process parameters. This + * leads to the following signed process parameter classes: MetaInt8, + * MetaInt16, MetaInt32, and MetaInt64. + */ +class PCL_CLASS MetaInt64 : public MetaSignedInteger +{ +public: + + /*! + * Constructs a metaparameter representing a 64-bit signed integer parameter + * of the specified process class \a *P. + */ + MetaInt64( MetaProcess* p ) + : MetaSignedInteger( p ) + { + } + + /*! + * Constructs a metaparameter representing a 64-bit signed integer value in + * a column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaInt64( MetaTable* t ) + : MetaSignedInteger( t ) + { + } + + /*! + * Destroys a %MetaInt64 object. + */ + virtual ~MetaInt64() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaReal + * \brief A formal description of a real process parameter. + * + * Real process parameters can be 32 and 64-bit IEEE 754 floating point + * values. This leads to the MetaFloat and MetaDouble real process parameter + * classes, respectively. + */ +class PCL_CLASS MetaReal : public MetaNumeric +{ +public: + + /*! + * Constructs a metaparameter representing a real parameter of the + * specified process class \a *P. + */ + MetaReal( MetaProcess* P ) + : MetaNumeric( P ) + { + } + + /*! + * Constructs a metaparameter representing a real value in a column of a + * table process parameter represented by the metatable \a *T. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaReal( MetaTable* T ) + : MetaNumeric( T ) + { + } + + /*! + * Destroys a %MetaReal object. + */ + virtual ~MetaReal() noexcept( false ) + { + } + + /*! + */ + bool IsReal() const override + { + return true; + } + + /*! + * Returns the number of decimal digits that should be used to represent + * actual values of the real process parameter represented by this + * metaparameter. + * + * The returned number of decimal digits will be used for literal + * representations of the represented parameter, especially in generated + * scripts. Good examples are automatically generated scripts on the + * Processing History and ProcessContainer windows in the PixInsight core + * application. + * + * The returned value should be in the range from -1 to 16. A maximum of 7 + * decimal digits will be used for 32-bit real process parameters, and a + * maximum of 16 decimal digits for 64-bit real process parameters, even + * if this function returns a larger value. + * + * If a value ≥ 0 is returned, real literal representations are always + * rounded to the nearest value with the specified amount of decimal digits. + * If this function returns zero, output values corresponding to this + * parameter will always be rounded to the nearest integer. + * + * If this function returns a negative integer, literal representations will + * use the standard printf's \e g-format. In this format, numerical values + * are represented in a compact fashion, with automatic selection of + * exponential or fixed representations, depending on the value's magnitude + * and fractional accuracy. + * + * \note The default implementation of this function returns -1. This + * means that printf's \e g-format is used by default. + */ + virtual int Precision() const + { + return -1; // printf's g format + } + + /*! + * Returns true iff actual values of this real process parameter must be + * represented using scientific notation (printf's \e e-format). + * + * If this function returns false, actual parameter values of this parameter + * will be represented using ordinary decimal notation (printf's + * \e f-format), unless the Precision() member function returns -1, in which + * case the automatic \e g-format will always be used. + * + * \note The default implementation of this function returns false. This + * means that the ordinary decimal notation (printf's \e f-format) is used + * to represent real parameters by default. + */ + virtual bool ScientificNotation() const + { + return false; + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + void PerformTypeAPIDefinitions() const override; + virtual uint32 APIParType() const override = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaFloat + * \brief A formal description of a 32-bit IEEE 754 floating point process + * parameter. + * + * Real process parameters can be 32 and 64-bit IEEE 754 floating point values. + * This leads to the %MetaFloat and MetaDouble real process parameter classes, + * respectively. + */ +class PCL_CLASS MetaFloat : public MetaReal +{ +public: + + /*! + * Constructs a metaparameter representing a 32-bit floating point parameter + * of the specified process class \a *P. + */ + MetaFloat( MetaProcess* P ) + : MetaReal( P ) + { + } + + /*! + * Constructs a metaparameter representing a 32-bit floating point value in + * a column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaFloat( MetaTable* T ) + : MetaReal( T ) + { + } + + /*! + * Destroys a %MetaFloat object. + */ + virtual ~MetaFloat() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaDouble + * \brief A formal description of a 64-bit IEEE 754 floating point process + * parameter. + * + * Real process parameters can be 32 and 64-bit IEEE 754 floating point values. + * This leads to the MetaFloat and %MetaDouble real process parameter classes, + * respectively. + */ +class PCL_CLASS MetaDouble : public MetaReal +{ +public: + + /*! + * Constructs a metaparameter representing a 64-bit floating point parameter + * of the specified process class \a *P. + */ + MetaDouble( MetaProcess* P ) + : MetaReal( P ) + { + } + + /*! + * Constructs a metaparameter representing a 64-bit floating point value in + * a column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaDouble( MetaTable* T ) + : MetaReal( T ) + { + } + + /*! + * Destroys a %MetaDouble object. + */ + virtual ~MetaDouble() noexcept( false ) + { + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaBoolean + * \brief A formal description of a Boolean process parameter. + * + * %MetaBoolean represents a Boolean process parameter. A Boolean process + * parameter can only have one of the two logical values \c true and \c false. + * + * \note \b Important - Boolean process parameters must be implemented as + * 32-bit signed integers (int32). When the PixInsight core application reads + * or writes a Boolean process parameter, what it reads or writes is actually a + * 32-bit integer that will represent the Boolean \c true value as a nonzero + * integer value, and \c false as a zero integer value. The best way to + * implement Boolean process parameters is by using the pcl_bool class. + * + * \sa pcl_bool + */ +class PCL_CLASS MetaBoolean : public MetaParameter +{ +public: + + /*! + * Constructs a metaparameter representing a Boolean parameter of the + * specified process class \a *P. + */ + MetaBoolean( MetaProcess* P ) + : MetaParameter( P ) + { + } + + /*! + * Constructs a metaparameter representing a Boolean value in a column of a + * table process parameter represented by the metatable \a *T. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaBoolean( MetaTable* T ) + : MetaParameter( T ) + { + } + + /*! + * Destroys a %MetaBoolean object. + */ + virtual ~MetaBoolean() noexcept( false ) + { + } + + /*! + */ + bool IsBoolean() const override + { + return true; + } + + /*! + * Returns the default value for actual Boolean parameters represented by + * this metaparameter. + * + * \note The default implementation of this function returns \c false. + */ + virtual bool DefaultValue() const + { + return false; + } + + /*! + */ + virtual IsoString Id() const override = 0; + +private: + + void PerformTypeAPIDefinitions() const override; + uint32 APIParType() const override; +}; + +/*! + * \defgroup safe_parameter_types Safe Process Parameter Types + */ + +/*! + * \class pcl_bool + * \brief A first-class data type that can be safely used to implement Boolean + * process parameters on all supported platforms. + * + * %pcl_bool is the \e only recommended way to implement process parameters + * that are formally described by the MetaBoolean class. %Process parameters + * declared as %pcl_bool instances will have the correct size and numerical + * type to be accessed and interpreted as valid Boolean parameters by the + * PixInsight core application on all supported platforms and C++ compilers. + * + * \ingroup safe_parameter_types + * \sa MetaBoolean + */ +class PCL_CLASS pcl_bool +{ +public: + + /*! + * Default constructor. Constructs a %pcl_bool instance with the logical + * false value. + */ + pcl_bool() = default; + + /*! + * Copy constructor. Constructs a %pcl_bool instance whose logical state is + * true if and only if the specified \a value is nonzero. + * The T template argument type must have integer equality comparison + * semantics. + */ + template pcl_bool( const T& value ) + : m_value( value ? 1 : 0 ) + { + } + + /*! + * Assignment operator. Sets the logical state of this %pcl_bool instance to + * true if and only if the specified \a value is nonzero. + * The T template argument type must have integer equality comparison + * semantics. + */ + template pcl_bool& operator =( const T& value ) + { + m_value = value ? 1 : 0; + return *this; + } + + /*! + * bool type conversion operator. Returns the current logical state of this + * %pcl_bool instance as a bool object. + */ + constexpr operator bool() const + { + return m_value != 0; + } + +#ifndef _MSC_VER + + /*! + * int type conversion operator. Returns zero if the current logical state + * of this %pcl_bool object is false; one if it is true. + */ + constexpr operator int() const + { + return int( m_value ); + } + +#endif // !_MSC_VER + + constexpr bool operator ==( const pcl_bool& b ) const + { + return m_value == b.m_value; + } + + constexpr bool operator <( const pcl_bool& b ) const + { + return m_value < b.m_value; + } + +private: + + int32 m_value = 0; // MetaBoolean equivalent type +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaEnumeration + * \brief A formal description of an enumerated process parameter. + * + * %MetaEnumeration represents an enumerated process parameter. An enumerated + * process parameter defines a finite set of unique-identifier/value + * associations. + * + * \note \b Important - Enumerated parameters must be implemented as 32-bit + * signed integers (int32). When the PixInsight core application reads or + * writes an enumerated parameter value, what it actually reads or writes is an + * enumeration \e value as a 32-bit signed integer, \e not the index of an + * enumeration element (which should be an unsigned integer). The best way to + * implement enumerated process parameters is by using the pcl_enum type. + * + * \sa pcl_enum + */ +class PCL_CLASS MetaEnumeration : public MetaParameter +{ +public: + + /*! + * Constructs a metaparameter representing an enumerated parameter of the + * specified process class \a *P. + */ + MetaEnumeration( MetaProcess* P ) + : MetaParameter( P ) + { + } + + /*! + * Constructs a metaparameter representing an enumerated value in a column + * of a table process parameter represented by the metatable \a *T. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaEnumeration( MetaTable* T ) + : MetaParameter( T ) + { + } + + /*! + * Destroys a %MetaEnumeration object. + */ + virtual ~MetaEnumeration() noexcept( false ) + { + } + + /*! + */ + bool IsEnumeration() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns the number of enumeration elements defined in the enumerated + * process parameter represented by this metaparameter. + * + * Each enumeration element is a unique-identifier/value association. + * + * The returned value must be > 0. + */ + virtual size_type NumberOfElements() const = 0; + + /*! + * Returns the unique enumeration identifier corresponding to the specified + * enumeration index \a idx, in the enumerated process parameter represented + * by this metaparameter. + * + * Enumeration identifiers must be valid C identifiers, unique within the + * set of enumeration elements defined in the enumerated process parameter. + * + * \note \b Important - An enumeration index should not be confused with an + * enumeration \e value. Enumeration indices range from 0 to \a n-1, where + * \a n is the number of enumeration elements defined in the enumerated + * process parameter. + */ + virtual IsoString ElementId( size_type idx ) const = 0; + + /*! + * Returns the enumeration value corresponding to the specified enumeration + * index \a idx, in the enumerated process parameter represented by this + * metaparameter. + * + * \note \b Important - An enumeration index should not be confused with an + * enumeration \e value. Enumeration indices range from 0 to \a n-1, where + * \a n is the number of enumeration elements defined in the enumerated + * process parameter. + */ + virtual int ElementValue( size_type idx ) const = 0; + + /*! + * Returns the enumeration index corresponding to the default value for the + * enumerated process parameter that this metaparameter represents. + * + * The returned value must be in the range 0 to \a n-1, where \a n is the + * number of enumeration elements defined in the enumerated process + * parameter. + * + * \note The default implementation of this function returns zero. + */ + virtual size_type DefaultValueIndex() const + { + return 0; + } + + /*! + * Returns a list of alias identifiers for this enumerated parameter. + * + * An enumerated process parameter can define one or more aliased + * elements. Aliased enumeration elements are useful to maintain + * compatibility with previous versions of a process. + * + * The returned string is a comma-separated list of "alias_id=element_id" + * items. Formally: + * + *
+    * aliased-elements-list:
+    *    alias-specification[, aliased-elements-list]
+    * alias-specification:
+    *    alias-element-id = element-id
+    * 
+ * + * When the PixInsight core application imports a process instance (e.g., + * from a process icon) it automatically replaces alias enumeration + * identifiers with actual (current) identifiers. This allows a developer to + * change the enumeration identifiers of a process parameters without + * breaking compatibility with existing process instances. + * + * \note The default implementation of this member function returns an empty + * string (no aliases). + */ + virtual IsoString ElementAliases() const + { + return IsoString(); + } + +private: + + void PerformTypeAPIDefinitions() const override; + uint32 APIParType() const override; +}; + +/*! + * \brief An integer type that can be safely used to implement enumerated + * process parameters on all supported platforms. + * + * %pcl_enum is the \e only recommended way to implement process parameters + * that are formally described by the MetaEnumeration class. %Process + * parameters declared as %pcl_enum instances will have the correct size and + * numerical type to be accessed and interpreted as valid enumeration values by + * the PixInsight core application on all supported platforms. + * + * \ingroup safe_parameter_types + * \sa MetaEnumeration + */ +typedef int32 pcl_enum; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaVariableLengthParameter + * \brief A formal description of a variable length process parameter. + * + * Variable length process parameters can be strings (MetaString), tables + * (MetaTable) or blocks (MetaBlock). + */ +class PCL_CLASS MetaVariableLengthParameter : public MetaParameter +{ +public: + + /*! + * Constructs a metaparameter representing a variable length parameter of + * the specified process class \a *P. + */ + MetaVariableLengthParameter( MetaProcess* P ) + : MetaParameter( P ) + { + } + + /*! + * Constructs a metaparameter representing a variable-length data item in a + * column of a table process parameter represented by the metatable \a *T. + * The new metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaVariableLengthParameter( MetaTable* T ) + : MetaParameter( T ) + { + } + + /*! + * Destroys a %MetaVariableLengthParameter object. + */ + virtual ~MetaVariableLengthParameter() noexcept( false ) + { + } + + /*! + */ + bool IsVariableLength() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns the minimum valid length for the variable length process + * parameter represented by this metaparameter. + * + * \note The default implementation of this function returns zero, so + * variable length process parameters can be empty by default. + */ + virtual size_type MinLength() const + { + return 0; // can be empty + } + + /*! + * Returns the maximum valid length for the variable length process + * parameter represented by this metaparameter. + * + * If the returned value is zero, then the represented variable length + * process parameter can have unlimited length. + * + * \note The default implementation of this function returns zero, so + * variable length process parameters have unlimited length by default. + */ + virtual size_type MaxLength() const + { + return 0; // unlimited length + } + +private: + + virtual void PerformTypeAPIDefinitions() const override = 0; + virtual uint32 APIParType() const override = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaString + * \brief A formal description of a string process parameter. + * + * %String process parameters are sequences of zero-terminated 16-bit Unicode + * characters (UTF-16). + */ +class PCL_CLASS MetaString : public MetaVariableLengthParameter +{ +public: + + /*! + * Constructs a metaparameter representing a string parameter of the + * specified process class \a *P. + */ + MetaString( MetaProcess* P ) + : MetaVariableLengthParameter( P ) + { + } + + /*! + * Constructs a metaparameter representing a string in a column of a table + * process parameter represented by the metatable \a *T. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *T. + */ + MetaString( MetaTable* T ) + : MetaVariableLengthParameter( T ) + { + } + + /*! + * Destroys a %MetaString object. + */ + virtual ~MetaString() noexcept( false ) + { + } + + /*! + */ + bool IsString() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns the default value of the string process parameter represented by + * this metaparameter. + * + * If this function returns zero, the default value for the string process + * parameter will be an empty string. + * + * \note The default implementation of this function returns zero, so + * string process parameters have empty string default values. + */ + virtual String DefaultValue() const + { + return String(); + } + + /*! + * Returns a string with the set of valid characters for the string process + * parameter represented by this metaparameter. + * + * If this function returns zero, any character is valid for the represented + * string process parameter. + * + * \note The default implementation of this function returns zero, so + * string process parameters can contain any character by default. + */ + virtual String AllowedCharacters() const + { + return String(); // any character is valid + } + +private: + + void PerformTypeAPIDefinitions() const override; + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaTable + * \brief A formal description of a table process parameter. + * + * A table process parameter is a container that groups a set of process + * parameters defining the columns of a two-dimensional matrix of parameter + * values. + * + * \note Important: Table process parameters cannot be nested, that is, a table + * process parameter cannot be specified as a column of an existing table + * process parameter. + */ +class PCL_CLASS MetaTable : public MetaVariableLengthParameter +{ +public: + + /*! + * Constructs a metaparameter representing a table parameter of the + * specified process class \a *P. + */ + MetaTable( MetaProcess* P ) + : MetaVariableLengthParameter( P ) + { + } + + /*! + * Destroys a %MetaTable object. + */ + virtual ~MetaTable() noexcept( false ) + { + } + + /*! + */ + bool IsTable() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns the address of a metaparameter representing the process + * parameter at column index \a i. + * + * You should not need to call this function directly under normal + * conditions. + */ + const MetaParameter* operator[]( size_type i ) const; + +private: + + // Nested tables are not allowed. + MetaTable( MetaTable* ); + + void PerformTypeAPIDefinitions() const override; + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MetaBlock + * \brief A formal description of a block process parameter. + * + * A block process parameter is a container that stores arbitrary data as a + * sequence of bytes. + * + * Block parameters should only be used for parameters that definitely cannot + * be represented as any of the supported numerical, Boolean, enumerated, + * or string parameter types. This is because block parameters lead to + * poorly readable transcriptions in scripts and other visual representations. + */ +class PCL_CLASS MetaBlock : public MetaVariableLengthParameter +{ +public: + + /*! + * Constructs a metaparameter representing a block parameter of the + * specified process class \a *p. + */ + MetaBlock( MetaProcess* p ) + : MetaVariableLengthParameter( p ) + { + } + + /*! + * Constructs a metaparameter representing a data block in a column of a + * table process parameter represented by the metatable \a *t. The new + * metaparameter is appended to the list of existing columns in the + * metatable \a *t. + */ + MetaBlock( MetaTable* t ) + : MetaVariableLengthParameter( t ) + { + } + + /*! + * Destroys a %MetaBlock object. + */ + virtual ~MetaBlock() noexcept( false ) + { + } + + /*! + */ + bool IsBlock() const override + { + return true; + } + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * %MetaBlock data interpretation modes used for automatic script + * generation. + * + * Supported data interpretation modes: + * + * + * + * + * + * + * + * + * + * + * + * + *
MetaBlock::DataAsUInt8 Block data are interpreted as a sequence of 8-bit unsigned integers
MetaBlock::DataAsInt8 Block data are interpreted as a sequence of 8-bit signed integers
MetaBlock::DataAsUInt16 Block data are interpreted as a sequence of 16-bit unsigned integers
MetaBlock::DataAsInt16 Block data are interpreted as a sequence of 16-bit signed integers
MetaBlock::DataAsUInt32 Block data are interpreted as a sequence of 32-bit unsigned integers
MetaBlock::DataAsInt32 Block data are interpreted as a sequence of 32-bit signed integers
MetaBlock::DataAsUInt64 Block data are interpreted as a sequence of 64-bit unsigned integers
MetaBlock::DataAsInt64 Block data are interpreted as a sequence of 64-bit signed integers
MetaBlock::DataAsFloat Block data are interpreted as a sequence of float (32-bit IEEE 754 floating point)
MetaBlock::DataAsDouble Block data are interpreted as a sequence of double (64-bit IEEE 754 floating point)
+ * + * The PixInsight core application takes into account these modes to + * generate readable and meaningful scripts for %MetaBlock parameters. + */ + enum data_interpretation + { + DataAsUInt8, // 8-bit unsigned integers + DataAsInt8, // 8-bit signed integers + DataAsUInt16, // 16-bit unsigned integers + DataAsInt16, // 16-bit signed integers + DataAsUInt32, // 32-bit unsigned integers + DataAsInt32, // 32-bit signed integers + DataAsUInt64, // 64-bit unsigned integers + DataAsInt64, // 64-bit signed integers + DataAsFloat, // float (32-bit IEEE 754 floating point) + DataAsDouble // double (64-bit IEEE 754 floating point) + }; + + /*! + * Defines how the data provided by this block parameter will be interpreted + * by the core application for automatic script generation. + * + * The default mode is MetaBlock::DataAsUInt8, which means that the data are + * interpreted as a sequence of plain bytes by default. + * + * This function must be reimplemented to indicate the correct data type for + * each particular MetaBlock parameter. This is essential to ensure + * generation of meaningful and readable scripts. + * + * \sa MetaBlock::data_interpretation + */ + virtual data_interpretation DataInterpretation() const + { + return DataAsUInt8; + } + +private: + + void PerformTypeAPIDefinitions() const override; + uint32 APIParType() const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_MetaParameter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MetaParameter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MetaProcess.h b/3rdparty/include/pcl/MetaProcess.h new file mode 100644 index 0000000..1a42f80 --- /dev/null +++ b/3rdparty/include/pcl/MetaProcess.h @@ -0,0 +1,1030 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MetaProcess.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_MetaProcess_h +#define __PCL_MetaProcess_h + +/// \file pcl/MetaProcess.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class View; +class ImageWindow; +class ProcessImplementation; +class ProcessInterface; +class MetaParameter; + +/*! + * \class MetaProcess + * \brief A formal description of a PixInsight process. + * + * %MetaProcess provides a formal description of the basic functionality and + * properties of a process in a PixInsight module. + * + * In a PixInsight module, every process must be implemented as a derived class + * of %MetaProcess. Such subclass will describe general properties of the + * process, and will provide the basic mechanisms to instantiate a process and + * generate duplicates of existing process instances. + * + * %MetaProcess and its subclasses don't implement any processing capabilities. + * The actual processing work must be implemented through a process + * instance implementation class, which is always a descendant of the + * ProcessImplementation class in the PixInsight/PCL framework. + * + * Each process must have a unique identifier. %Process identifiers are crucial + * for many key features of the PixInsight environment, like process + * scripting, command-line interfaces, process icons and containers, etc. + * + * Processes are organized by process categories in PixInsight. A + * process category groups similar or related processes together. The whole set + * of process categories forms a categorized tree of processes that + * can be accessed, for example, from the %Process Explorer window in the core + * PixInsight GUI. + * + * \sa MetaModule, MetaParameter, ProcessImplementation + */ +class PCL_CLASS MetaProcess : public MetaObject, public ProcessBase +{ +public: + + /*! + * Constructs a %MetaProcess object. + */ + MetaProcess(); + + /*! + * Destroys this %MetaProcess object. Also destroys all MetaParameter + * children of this %MetaProcess. + */ + virtual ~MetaProcess() noexcept( false ) + { + } + + /*! + * Copy constructor. Copy semantics are disabled for %MetaProcess because + * this class represents unique server-side objects. + */ + MetaProcess( const MetaProcess& ) = delete; + + /*! + * Copy assignment. Copy semantics are disabled for %MetaProcess because + * this class represents unique server-side objects. + */ + MetaProcess& operator =( const MetaProcess& ) = delete; + + /*! + * Move constructor. Move semantics are disabled for %MetaProcess because + * because of parent-child server-side object relations. + */ + MetaProcess( MetaProcess&& x ) = delete; + + /*! + * Move assignment. Move semantics are disabled for %MetaProcess because + * because of parent-child server-side object relations. + */ + MetaProcess& operator =( MetaProcess&& x ) = delete; + + /*! + */ + virtual IsoString Id() const override = 0; + + /*! + * Returns a list of alias identifiers for this process. + * + * A process can have one or more alias identifiers. Aliases are + * useful to maintain compatibility with previous versions of a process. + * + * When the PixInsight core application imports a process instance (e.g., + * from a process icon) it automatically replaces alias process identifiers + * with actual (current) identifiers. This allows a developer to change the + * identifier of a process without breaking compatibility with process + * instances in existing icon collections or projects. + * + * The returned string is a comma-separated list of distinct identifiers + * that will be treated as synonyms to the actual identifier of this + * process, which is returned by the Id() member function. Two installed + * processes can't have the same alias, so each identifier included in the + * returned list must be unique among all installed processes on the entire + * PixInsight platform. + * + * \note The default implementation of this member function returns an empty + * string (no aliases). + * + * \sa Id() + */ + virtual IsoString Aliases() const + { + return IsoString(); + } + + /*! + * Returns the identifiers of one or more categories to which this process + * belongs. + * + * Processes are organized hierarchically by categories in PixInsight. All + * installed processes appear classified by their categories on the %Process + * Explorer window, and also under the %Process main menu item. + * + * This member function can return a comma-separated list of category + * names, or a single category name. Each category name must be a valid C + * identifier. If one or more of the specified names are nonempty strings + * that don't correspond to already existing process categories, new + * categories will be created and this process will be added to them. If a + * category already exists with the specified identifier, then this process + * will be added to the existing category. + * + * If this function returns an empty string, then this process will not be + * associated to any particular category. It will then appear under a + * special, fallback pseudo-category identified as <Etc> on both the + * %Process Explorer window and the %Process main menu item. + * + * \note The default implementation of this function returns an empty + * string, so a process is not associated to any specific category unless a + * derived class reimplements this function. + */ + virtual IsoString Categories() const + { + return IsoString(); // General category + } + + /*! + * A synonym for Categories(), provided for compatibility with previous PCL + * versions. + * + * \deprecated This member function has been deprecated. Use Categories() in newly + * produced code. + */ + virtual IsoString Category() const // ### PCL 2.x: Remove + { + return Categories(); + } + + /*! + * Returns a version number for this process, encoded as a hexadecimal + * number. + * + * For example, version 1.0.5 should be returned as 0x105, and version + * 3.11.5 as 0x3B5. The default return value is 0x100, corresponding to + * version 1.0.0. + */ + uint32 Version() const override + { + return 0x100; + } + + /*! + * Returns a descriptive text for this process. + * + * This function must provide a brief but sufficiently informative + * description of this process. The returned description will appear on the + * %Process Explorer window, and should provide information about what this + * process does and how it can be used, avoiding too exhaustive descriptions + * that are better reserved for a technical manual. + * + * %Process descriptions are always printed on PixInsight consoles. This + * means that the text output functionality of the Console class can be used + * to format the string returned by this function. Refer to that class and + * its documentation for further information. + * + * \note The default implementation of this function returns an empty + * string, so by default a process does not provide a description. This is + * legal, but it is considered bad practice, so this function \e should be + * reimplemented. + */ + String Description() const override + { + return String(); + } + + /*! + * Returns a brief description for generated scripts. + * + * The returned text is intended to provide a brief comment to describe this + * process and its parameters, for quick reference on generated scripts. + * When writing these comments, think as you do when you're commenting your + * own source code. + * + * \note The default implementation of this function returns an empty + * string, so by default processes provide no script comments. + */ + String ScriptComment() const override + { + return String(); + } + + /*! + * Returns the icon image of this process as a document in SVG format. + * + * The specified image will be used to identify all instances of this + * process in the core application's GUI. It will be used on the %Process + * Explorer window, on process icons of this class, and in general for every + * graphical item related to this process or to an instance of this process. + * + * The returned string must be the source code of a valid SVG document + * representing the icon image, encoded in UTF-8. + * + * Since core version 1.8.8-6, all process, interface and file format icons + * should be specified in SVG format. Raster formats, such as XPM and PNG, + * have been deprecated for this purpose. + * + * If both this function and IconImageSVGFile() return an empty string, or + * if the specified SVG document does not exist or is not valid, a default + * icon will be assigned to this process automatically by the PixInsight + * core application. + * + * \note The default implementation of this function returns an empty + * string. + * + * \sa IconImageSVGFile() + */ + virtual IsoString IconImageSVG() const + { + return IsoString(); + } + + /*! + * Returns the icon image of this process as a document in SVG format, + * stored as an external file. + * + * The specified image will be used to identify all instances of this + * process in the core application's GUI. It will be used on the %Process + * Explorer window, on process icons of this class, and in general for every + * graphical item related to this process or to an instance of this process. + * + * The returned string must be a path to an existing file in the local + * file system (remote resources are not supported in current PCL versions), + * which must store a valid SVG document representing the icon image. The + * SVG source code must be encoded in UTF-8. + * + * Since core version 1.8.8-6, all process, interface and file format icons + * should be specified in SVG format. Raster formats, such as XPM and PNG, + * have been deprecated for this purpose. + * + * If both this function and IconImageSVG() return an empty string, or if + * the specified SVG document does not exist or is not valid, a default icon + * will be assigned to this process automatically by the PixInsight core + * application. + * + * Automatic Resource Location + * + * Process icon image files can be loaded from arbitrary locations on the + * local file system. However, modules typically install their process and + * interface icons on the /rsc/icons/module directory under the local + * PixInsight installation. A module can specify the "@module_icons_dir/" + * prefix in icon file paths to let the PixInsight core application load the + * corresponding SVG documents from the appropriate standard distribution + * directory automatically. For example, suppose that a "Bar" process, + * pertaining to a "Foo" module, reimplements this member function in its + * %MetaProcess derived class as follows: + * + * \code + * class Bar : public MetaProcess + * { + * public: + * ... + * + * String IconImageSVGFile() const override + * { + * return "@module_icons_dir/Bar.svg"; + * } + * + * ... + * }; + * \endcode + * + * Then the core application will attempt to load the following SVG file: + * + * <install-dir>/rsc/icons/module/Foo/Bar.svg + * + * where <install-dir> is the local directory where the running + * PixInsight core application is installed. + * + * \note The default implementation of this function returns an empty + * string. + * + * \sa IconImageSVG() + */ + virtual String IconImageSVGFile() const + { + return String(); + } + + /*! + * Returns a large icon for this process as an image in the + * standard XPM format. + * + * The specified image will be used to identify all instances of this + * process in the core application's GUI. It will be used on the %Process + * Explorer window, on process icons of this class, and in general for every + * graphical item related to this process or to an instance of this process. + * + * 32-bit RGBA color images (including an alpha channel) are fully + * supported. + * + * If this function returns nullptr, a default icon will be assigned to this + * process automatically. + * + * \note The default implementation of this function returns nullptr. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa IconImageFile() + */ + virtual const char** IconImageXPM() const + { + return nullptr; + } + + /*! + * Returns a large icon for this process as a path specification to + * an existing image file. + * + * Supported image file formats include PNG, XPM, JPG and BMP. + * + * For details on process icon images, see the documentation for + * IconImageXPM(). + * + * \note The default implementation of this function returns an empty + * string. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa IconImageXPM() + */ + virtual String IconImageFile() const + { + return String(); + } + + /*! + * Returns a small icon for this process as an image in the + * standard XPM format. + * + * For details on process icon images, see the documentation for + * IconImageXPM(). + * + * Small icons are used on interface elements where screen space must be + * preserved. Two good examples are the History Explorer window and the + * ProcessContainer interface. + * + * When this function is not reimplemented in a derived class, the core + * PixInsight application automatically generates a small icon by resampling + * down the large icon provided by IconImageXPM(). + * + * You normally should not need to reimplement this function; the core + * application usually does a fine work resampling large icons to obtain + * reduced versions. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa SmallIconImageFile() + */ + virtual const char** SmallIconImageXPM() const + { + return nullptr; + } + + /*! + * Returns a small icon for this process as a path specification to + * an existing image file. + * + * Supported image file formats include PNG, XPM, JPG and BMP. + * + * For details on small process icon images, see the documentation for + * SmallIconImageXPM(). + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process icons in SVG format. Existing modules should also be + * refactored in the same way to support scalable icons. + * + * \sa SmallIconImageXPM() + */ + virtual String SmallIconImageFile() const + { + return String(); + } + + /*! + */ + Bitmap Icon() const override; + + /*! + */ + Bitmap SmallIcon() const override; + + /*! + * %Process class initialization routine. + * + * This member function is called just after the module where this process + * lives has been completely installed. When this function is called, + * communication with the PixInsight core application is fully operative. + * + * This function is seldom reimplemented by derived classes. Reimplement + * it if your process requires some initialization that cannot be + * accomplished in the class constructor. This includes calling PCL + * functions that require active communication with the PixInsight core + * application, as retrieving global settings for example (see the + * pcl/GlobalSettings.h header). + * + * \note The default implementation of this function does nothing. + * + * \sa MetaProcess() + */ + virtual void InitializeClass() + { + } + + /*! + * Provides a default interface for this process. + * + * The interface addressed by this function will be activated in situations + * where this process is activated without a specific \e instance. In + * such situations, the core application will try to find a suitable + * default interface by calling this function, and if the address + * of a valid object is returned, the indicated interface will be launched. + * + * An example of process activation without an instance is when the user + * double-clicks an item on the %Process Explorer window. + * + * When an instance is available, the core application invokes + * ProcessImplementation::SelectInterface() instead of this member function. + * An example of process activation with an instance is when the user + * double-clicks a process icon on the core application's workspace. + * + * If this function returns nullptr, no interface will be launched when this + * process is activated without an instance. + * + * \note The default implementation of this function returns nullptr, so a + * process has no associated interface by default. + * + * \sa ProcessImplementation::SelectInterface() + */ + virtual ProcessInterface* DefaultInterface() const + { + return nullptr; // by default, processes have no associated interfaces. + } + + /*! + * Returns true iff this process class is able to process views. + * + * View execution of a process, also known as view context, is + * mainly implemented by the following member functions: + * + * bool ProcessImplementation::CanExecuteOn( const View&, String& ) + * bool ProcessImplementation::ExecuteOn( View& ) + * + * which must be reimplemented by any instance class corresponding to a + * process with view execution capabilities. + * + * \note The default implementation of this function returns true, so by + * default a process is supposed to be executable on views. This is indeed + * the case for the vast majority of processes. + */ + bool CanProcessViews() const override + { + return true; + } + + /*! + * Returns true iff this process class can be executed globally. + * + * Global execution of a process, also known as global context, is + * mainly implemented by the following member functions: + * + * bool ProcessImplementation::CanExecuteGlobal( String& ) + * bool ProcessImplementation::ExecuteGlobal() + * + * which must be reimplemented by any instance class corresponding to a + * process with global execution capabilities. + * + * \note For compatibility with previous PCL versions, the default + * implementation of this function returns true, so by default a process is + * supposed to be executable globally. There are not many global processes, + * and only a few processes can be executed in both the global and view + * contexts, so this default behavior is clearly suboptimal. However, as + * noted above it is necessary to maintain compatibility with 1.x PCL + * versions. This may change in a future version 2.x of PCL. + */ + bool CanProcessGlobal() const override + { + return true; + } + + /*! + * Returns true iff this process class is able to process standalone images. + * + * This refers to the ability of process instances to be executed on images + * passed to a reimplementation of the following member function: + * + * bool ProcessImplementation::ExecuteOn( ImageVariant&, const IsoString& ) + * + * Note that this is completely different from processing views with a + * reimplementation of: + * + * bool ProcessImplementation::ExecuteOn( View& ) + * + * Although both functions usually share the majority of their working code + * for most processes, they are unrelated from the point of view of the + * PixInsight core application, and they also play very different roles for + * the integration of a process with the platform. + * + * If a derived class reimplements this function to return true, the + * corresponding process instance implementation class should also + * reimplement the following ones: + * + * bool ProcessImplementation::CanExecuteOn( const ImageVariant&, String& ) const + * bool ProcessImplementation::ExecuteOn( ImageVariant& ) + * + * \note The default implementation of this function returns false, so by + * default a process has no standalone image processing capabilities. + */ + bool CanProcessImages() const override + { + return false; + } + + /*! + * Returns true iff this process class is able to process specific + * command-line invocations. + * + * If a derived class reimplements this function to return true, it should + * also reimplement the ProcessCommandLine() member function to perform + * actual command line processing, or a runtime exception will be thrown. + * + * \note The default implementation of this function returns false, so by + * default processes can't process command-line arguments. + * + * \sa ProcessCommandLine() + */ + bool CanProcessCommandLines() const override + { + return false; + } + + /*! + * Returns true iff this process is able to edit specific preferences. + * + * If a derived class reimplements this function to return true, it should + * also reimplement the EditPreferences() member function to perform the + * actual preferences edit work, or a runtime exception will be thrown. + * + * \note The default implementation of this function returns false, so by + * default processes can't edit specific preferences. + * + * \sa EditPreferences() + */ + bool CanEditPreferences() const override + { + return false; + } + + /*! + * Returns true iff this process is able to open a documentation browser with + * specific documentation contents. + * + * Starting from version 1.7, the PixInsight core application implements an + * integrated documentation system. The core application provides automatic + * documentation browsing and searching functionality. For this reason, the + * default implementation of this member function returns true. + * + * Unless a process has specific documentation requirements beyond the + * integrated documentation system --which is strongly discouraged--, the + * BrowseDocumentation() member function of %MetaProcess should not be + * reimplemented in derived classes. The default implementation drives the + * integrated documentation system automatically in a standardized way. + * + * \note The default implementation of this function returns true, for the + * same reasons explained above. + * + * \sa BrowseDocumentation() + */ + bool CanBrowseDocumentation() const override + { + return true; + } + + /*! + * Creates a new instance of this process. Returns a pointer to the newly + * created process instance. + * + * A process instance is implemented as an instance of a subclass of the + * ProcessImplementation class. + * + * \note This is a pure virtual member function that has to be implemented + * in a derived class. Every process in PixInsight must be able to generate + * new process instances. + * + * \sa Clone() + */ + virtual ProcessImplementation* Create() const = 0; + + /*! + * Creates a new instance of this process as a duplicate of an existing + * process instance. Returns a pointer to the newly created process + * instance. + * + * \note This is a pure virtual member function that has to be implemented + * in a derived class. Every process in PixInsight must be able to generate + * clones of existing process instances. + * + * \sa Create(), TestClone() + */ + virtual ProcessImplementation* Clone( const ProcessImplementation& ) const = 0; + + /*! + * Creates a new instance of this process as a duplicate of an existing + * process instance, for strict testing purposes. Returns a pointer to the + * newly created process instance. + * + * In certain situations, the core application needs a temporary process + * instance exclusively for testing purposes. This happens, for example, to + * verify if a given instance can be executed on a given view, or in the + * global context, during complex GUI operations. The core application tries + * to optimize GUI performance by calling this function when possible. + * + * If your process can provide a substantially simplified version of an + * existing instance, and such a simplified version still is able to know if + * it can be executed globally or on a given view, then reimplement this + * function. + * + * For example, if your process requires (or may require) some megabytes of + * data to work, but these data are not needed for testing purposes, then it + * is a pretty good candidate to reimplement this function. In practice, + * however, requiring a reimplementation of this function is infrequent. + * + * \note The default implementation of this function returns Clone( p ). + * + * \sa Clone() + */ + virtual ProcessImplementation* TestClone( const ProcessImplementation& p ) const + { + return Clone( p ); + } + + /*! + * Returns true iff the instances of this process are \e assignable. + * + * Assignable processes allow copying one instance to another. + * + * If you have a good reason to avoid instance assignment for your process, + * then reimplement this function to return false. A good reason could be + * that your process has no parameters, hence no data could be assigned. + * + * \note The default implementation of this function returns true, so + * processes are assignable by default. + */ + bool IsAssignable() const override + { + return true; // by default, processes are considered assignable. + } + + /*! + * Returns true iff the instances of this process require special + * initialization. + * + * Special initialization takes place just after instance creation. + * Sometimes, there are actions that cannot be implemented in the + * constructor of a process instance class. For example, this often happens + * when an instance must be initialized by calling reimplemented virtual + * functions from a base class constructor. Reimplemented virtual functions + * cannot be resolved from a base class constructor in C++. + * + * If your process instance class requires some initialization that cannot + * be implemented in a regular constructor function, then reimplement this + * function to return true. In this case, you must also reimplement + * ProcessImplementation::Initialize() for your instance implementation + * class to implement the special initialization work, or a runtime + * exception will be thrown. + * + * \note The default implementation of this function returns false, so by + * default processes don't require special instance initialization. + * + * \note Don't confuse the instance initialization that this function refers + * to with the InitializeClass() member function of %MetaProcess. + * + * \sa ProcessImplementation::Initialize() + */ + bool NeedsInitialization() const override + { + return false; // by default, process instances are not initialized. + } + + /*! + * Returns true iff the instances of this process require special + * validation. + * + * Some processes may require validation of their instances just before they + * are executed. This is known as special validation. The core + * application will never execute an instance of a process if its validation + * function fails. To implement your special validation, reimplement this + * function to return true, as well as ProcessImplementation::Validate() for + * your instance implementation subclass, or a runtime exception will be + * thrown. + * + * \note The default implementation of this function returns false, so by + * default processes don't require special instance validation. + * + * \sa ProcessImplementation::Validate() + */ + bool NeedsValidation() const override + { + return false; // by default, process instances are not validated. + } + + /*! + * Returns true iff the instances of this process prefer execution in the + * global context, instead of being executed on views. + * + * Note that the option indicated by this function is just a \e hint to the + * PixInsight core application, not necessarily observed, depending on the + * context. + * + * To prevent (or select) execution on a particular context, your process + * instance class must reimplement ProcessImplementation::CanExecuteOn() + * and/or ProcessImplementation::CanExecuteGlobal(), as appropriate. + * + * \note The default implementation of this function returns false, so by + * default processes prefer execution on views, instead of execution in the + * global context. + */ + bool PrefersGlobalExecution() const override + { + return false; // by default, processes prefer execution on views. + } + + /*! + * Handles a command line invocation. Returns a conventional exit code + * (customarily, zero signals a "normal" or successful execution). + * + * \param argv The list of command-line arguments. + * + * \note This function will never be called unless the + * CanProcessCommandLines() member function is reimplemented to return true. + * + * \sa CanProcessCommandLines() + */ + virtual int ProcessCommandLine( const StringList& argv ) const; + + /*! + * Handles a request to edit process preferences. Returns true if the + * preferences were successfully edited. + * + * Reimplement this function to allow the user to edit a set of preferences + * specific to this process. This task is usually implemented on a modal + * dialog box. In such case, if the user closes the dialog box without + * accepting the new preferences settings (e.g. by clicking the dialog's + * Cancel button) this member function should return false. This function + * should only return true if the user has edited and accepted a new set of + * preferences for this process. + * + * \note This function will never be called unless the CanEditPreferences() + * member function is reimplemented to return true. + * + * \sa CanEditPreferences(), ProcessInterface::EditPreferences() + */ + bool EditPreferences() const override; + + /*! + * Handles a request to browse documentation specific for this process. + * Returns true iff the documentation was loaded successfully. + * + * Reimplementing this function is strongly discouraged, unless some + * nonstandard behavior is absolutely necessary for a particular process. + * Since version 1.7 of the PixInsight core application, the integrated + * documentation system works in a completely automatic and standardized way + * to provide documentation browsing and searching functionality. + * + * The default implementation of this member function automatically launches + * and loads the integrated documentation browser with the documentation for + * this process, if it exists and has been installed. For more information, + * please read the documentation for the CanBrowseDocumentation() function. + * + * \note This function will never be called unless the + * CanBrowseDocumentation() member function is reimplemented to return true. + * + * \sa CanBrowseDocumentation() + */ + bool BrowseDocumentation() const override; + + /*! + * Provides access to the list of parameters defined for this process. + * + * This member is intended for internal use of API module initialization + * routines. You should not need to call this function directly under + * normal conditions. + */ + const MetaParameter* operator[]( size_type i ) const; + + /*! + * Returns true iff this process can handle inter-process communication + * (IPC) messages send among running instances of the PixInsight core + * application. + * + * The following IPC process messages are implemented in current versions of + * the PixInsight platform: + * + * \li Start Process. Handled by a reimplementation of the + * IPCStart() member function in a derived class. + * + * \li Stop Process. Handled by a reimplementation of the + * IPCStop() member function in a derived class. + * + * \li Set Process Parameters. Handled by a reimplementation of the + * IPCSetParameters() member function in a derived class. + * + * \li Get Process Status. Handled by a reimplementation of the + * IPCStatus() member function in a derived class. + * + * Process execution controlled by IPC messages is primarily intended for + * automation of non-interactive or unattended tasks. A good example is the + * NetworkService process, which can be controlled with IPC messages to + * implement generic, asynchronous online services without user interaction. + * + * The default implementation of this member function returns false. This + * means that IPC messages are not supported by default. To support them, + * this member function must be reimplemented in a derived class to return + * true, along with IPCStart(), IPCStop(), IPCSetParameters() and + * IPCStatus(). + */ + virtual bool CanProcessIPCMessages() const + { + return false; + } + + /*! + * Handles a start process IPC message. + * + * \param instance The instance number of the running PixInsight core + * application. This is an integer > 0, which can be used + * for task logging purposes. + * + * \param messageUID Unique identifier of the IPC message that originated + * this call. This parameter can be used for task logging + * purposes. + * + * \param parameters A string in UTF-16 format with process-specific + * parameters. Can be an empty string if no parameters + * were specified by the IPC message that originated this + * function call. + * + * \note This function will never be called unless the + * CanProcessIPCMessages() member function is reimplemented to return true. + */ + virtual void IPCStart( int instance, const IsoString& messageUID, const String& parameters ) const; + + /*! + * Handles a stop process IPC message. + * + * \param instance The instance number of the running PixInsight core + * application. This is an integer > 0, which can be used + * for task logging purposes. + * + * \param messageUID Unique identifier of the IPC message that originated + * this call. This parameter can be used for task logging + * purposes. + * + * \note This function will never be called unless the + * CanProcessIPCMessages() member function is reimplemented to return true. + */ + virtual void IPCStop( int instance, const IsoString& messageUID ) const; + + /*! + * Handles a set process parameters IPC message. + * + * \param instance The instance number of the running PixInsight core + * application. This is an integer > 0, which can be used + * for task logging purposes. + * + * \param messageUID Unique identifier of the IPC message that originated + * this call. This parameter can be used for task logging + * purposes. + * + * \param parameters A string in UTF-16 format with process-specific + * parameters. Can be an empty string if no parameters + * were specified by the IPC message that originated this + * function call. + * + * \note This function will never be called unless the + * CanProcessIPCMessages() member function is reimplemented to return true. + */ + virtual void IPCSetParameters( int instance, const IsoString& messageUID, const String& parameters ) const; + + /*! + * Handles a get process status IPC message. + * + * \param instance The instance number of the running PixInsight core + * application. This is an integer > 0, which can be used + * for task logging purposes. + * + * \param messageUID Unique identifier of the IPC message that originated + * this call. This parameter can be used for task logging + * purposes. + * + * The returned value is expected to be: + * + * = 0 If the process is not currently in execution. + * + * > 0 (process-specific positive nonzero integer codes) If the process is + * now running. + * + * < 0 (process-specific negative integer codes) If the process is not + * running because of an error condition. + * + * \note This function will never be called unless the + * CanProcessIPCMessages() member function is reimplemented to return true. + */ + virtual int IPCStatus( int instance, const IsoString& messageUID ) const; + +private: + + void PerformAPIDefinitions() const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_MetaProcess_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MetaProcess.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MoffatFilter.h b/3rdparty/include/pcl/MoffatFilter.h new file mode 100644 index 0000000..3c4c4d8 --- /dev/null +++ b/3rdparty/include/pcl/MoffatFilter.h @@ -0,0 +1,504 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MoffatFilter.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_MoffatFilter_h +#define __PCL_MoffatFilter_h + +/// \file pcl/MoffatFilter.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MoffatFilter + * \brief A kernel filter implementing a discrete Moffat distribution in two dimensions. + * + * A %MoffatFilter object is a specialized KernelFilter whose elements are + * calculated as a discrete representation of an elliptical Moffat[1] function + * centered at the origin: + * + * M(x,y) = 1/(1 + x^2/sx^2 + y^2/sy^2)^beta + * + * where sx and sy are the standard deviations of the distribution on the + * horizontal and vertical axes, respectively, and the beta exponent controls + * the shape of the function's profile. The lower the beta, the more peaked the + * overall shape of the function. For beta=1, the equation above corresponds to + * a Lorentzian function. + * + * %MoffatFilter also supports arbitrary rotation around the origin. When the + * filter is rotated, the coordinates x, y in the equation above are replaced + * by their rotated counterparts. + * + * A %MoffatFilter instance is formally defined by the following parameters: + * + * + * + * + * + * + * + *
\e sigma Standard deviation of the filter distribution on the X axis (sigma > 0).
\e rho The ratio sy/sx (see equation above) of the generated filter distribution (0 <= rho <= 1).
\e theta Rotation angle of the horizontal axis in radians (0 <= theta < PI). This parameter only makes sense when rho < 1.
\e beta Exponent controlling the overall shape of the function (beta > 0).
\e epsilon Maximum truncation error of the computed filter coefficients (eps > 0).
+ * + * References + * + * \li [1] Moffat, A. F. J., A Theoretical Investigation of Focal Stellar + * Images in the Photographic Emulsion and Application to Photographic + * Photometry, Astronomy and Astrophysics, Vol. 3, p. 455 (1969) + * + * \sa KernelFilter, GaussianFilter, VariableShapeFilter, LinearFilter + */ +class PCL_CLASS MoffatFilter : public KernelFilter +{ +public: + + /*! + * Constructs an empty %MoffatFilter object with default functional + * parameters: sigma=2, beta=4, epsilon=0.01, rho=1, theta=0. + */ + MoffatFilter() = default; + + /*! + * Constructs a %MoffatFilter object given the standard deviation + * \a sigma > 0, \a beta exponent > 0 and truncation error \a epsilon > 0. + * Assigns an optional \a name to the new filter object. + */ + MoffatFilter( float sigma, float beta = 4, float epsilon = 0.01, const String& name = String() ) + { + Initialize( sigma, beta, epsilon, 1, 0 ); + Rename( name ); + } + + /*! + * Constructs a %MoffatFilter object given the standard deviation + * \a sigma > 0, \a beta exponent > 0, truncation error \a epsilon > 0, + * aspect ratio 0 <= \a rho <= 1, and rotation angle 0 <= \a theta <= PI in + * radians. Assigns an optional \a name to the new filter object. + */ + MoffatFilter( float sigma, float beta, float epsilon, float rho, float theta = 0, const String& name = String() ) + { + Initialize( sigma, beta, epsilon, rho, theta ); + Rename( name ); + } + + /*! + * Constructs a %MoffatFilter object given the odd kernel size \a n >= 3, + * \a beta exponent > 0 and truncation error \a epsilon > 0. Assigns an + * optional \a name to the new filter object. + */ + MoffatFilter( int n, float beta = 4, float epsilon = 0.01, const String& name = String() ) + { + Initialize( n, beta, epsilon, 1, 0 ); + Rename( name ); + } + + /*! + * Constructs a %MoffatFilter object given the odd kernel size \a n >= 3, + * \a beta exponent > 0, truncation error \a epsilon > 0, aspect ratio + * 0 <= \a rho <= 1, and rotation angle 0 <= \a theta <= PI in radians. + * Assigns an optional \a name to the new filter object. + */ + MoffatFilter( int n, float beta, float epsilon, float rho, float theta = 0, const String& name = String() ) + { + Initialize( n, beta, epsilon, rho, theta ); + Rename( name ); + } + + /*! + * Copy constructor. + */ + MoffatFilter( const MoffatFilter& ) = default; + + /*! + * Move constructor. + */ + MoffatFilter( MoffatFilter&& ) = default; + + /*! + */ + KernelFilter* Clone() const override + { + return new MoffatFilter( *this ); + } + + /*! + * Returns a separable filter equivalent to this kernel filter. + * + * %MoffatFilter's reimplementation of this virtual member function returns + * an empty SeparableFilter object, as a Moffat filter is not separable. + */ + SeparableFilter AsSeparableFilter( float tolerance = __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE ) const override + { + return SeparableFilter(); + } + + /*! + * Returns true iff this filter is separable. + * + * %MoffatFilter's reimplementation of this virtual member function returns + * false, as a Moffat filter is not separable. + */ + bool IsSeparable() const override + { + return false; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + MoffatFilter& operator =( const MoffatFilter& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + MoffatFilter& operator =( MoffatFilter&& ) = default; + + /*! + * Returns the standard deviation of the filter distribution on the X + * (horizontal) axis. + */ + float SigmaX() const + { + return m_sigma; + } + + /*! + * Returns the standard deviation of the filter distribution on the Y + * (vertical) axis. + */ + float SigmaY() const + { + return m_rho*m_sigma; + } + + /*! + * Returns the standard deviation of the filter distribution on the X + * (horizontal) axis. + * + * This function is an alias to SigmaX(). + */ + float Sigma() const + { + return SigmaX(); + } + + /*! + * Returns the beta exponent of the Moffat filter function. The beta + * exponent controls the overall shape of the filter profile. + */ + float Beta() const + { + return m_beta; + } + + /*! + * Returns the maximum truncation error of the filter coefficients. + */ + float Truncation() const + { + return m_epsilon; + } + + /*! + * Returns the aspect ratio of the filter distribution. This is the ratio + * vertical:horizontal between filter axes in the range [0,1]. + */ + float AspectRatio() const + { + return m_rho; + } + + /*! + * Returns the rotation angle of the filter distribution. This is the + * rotation angle in radians with respect to the central pixel, in the + * range [0,+PI]. + */ + float RotationAngle() const + { + return m_theta; + } + + /*! + * Returns the full width at half maximum (FWHM), in sigma units, for the + * horizontal axis of the elliptical Moffat filter distribution. + */ + double FWHMx() const + { + return 2 * Sqrt( Pow2( 1/m_beta ) - 1 ) * m_sigma; + + } + + /*! + * Returns the full width at half maximum (FWHM), in sigma units, for the + * vertical axis of the elliptical Moffat filter distribution. + */ + double FWHMy() const + { + return m_rho * FWHMx(); + + } + + /*! + * Returns the full width at half maximum, in sigma units, for the + * horizontal axis of the elliptical Moffat filter distribution. + * + * This function is an alias to FWHMx(). + */ + double FWHM() const + { + return FWHMx(); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0, + * \a beta exponent, truncation error \a epsilon > 0, aspect ratio + * 0 <= \a rho <= 1 and rotation angle 0 <= \a theta <= PI in radians. + */ + void Set( float sigma, float beta, float epsilon, float rho, float theta ) + { + Initialize( sigma, beta, epsilon, rho, theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0, + * \a beta exponent, truncation error \a epsilon > 0 and aspect ratio + * 0 <= \a rho <= 1. Does not change the current rotation angle. + */ + void Set( float sigma, float beta, float epsilon, float rho ) + { + Initialize( sigma, beta, epsilon, rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0, + * \a beta exponent and truncation error \a epsilon > 0. Does not change the + * current aspect ratio and rotation angle. + */ + void Set( float sigma, float beta, float epsilon ) + { + Initialize( sigma, beta, epsilon, m_rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0 and + * \a beta exponent. The current coefficient truncation error, aspect ratio + * and rotation angle are not changed. + */ + void Set( float sigma, float beta ) + { + Initialize( sigma, beta, m_epsilon, m_rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified sigma \a sigma > 0. + * The current beta exponent, coefficient truncation error, aspect ratio and + * rotation angle are not changed. + */ + void Set( float sigma ) + { + Initialize( sigma, m_beta, m_epsilon, m_rho, m_theta ); + } + + /*! + * This is a convenience member function, equivalent to Set( sigma ). + */ + void SetSigma( float sigma ) + { + Set( sigma ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), beta ). + */ + void SetBeta( float beta ) + { + Set( m_sigma, beta ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Beta(), epsilon ). + */ + void SetTruncation( float epsilon ) + { + Set( m_sigma, m_beta, epsilon ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Beta(), Truncation(), rho ). + */ + void SetAspectRatio( float rho ) + { + Set( m_sigma, m_beta, m_epsilon, rho ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Beta(), Truncation(), AspectRatio(), a ). + */ + void SetRotationAngle( float theta ) + { + Set( m_sigma, m_beta, m_epsilon, m_rho, theta ); + } + + /*! + * Recalculates filter coefficients for the given odd kernel size \a n >= 3. + * This routine computes the required standard deviation to sample the + * Moffat function on a matrix of the specified size, preserving the + * current beta exponent, coefficient truncation error, aspect ratio and + * rotation angle. + */ + void Resize( int n ) override + { + Initialize( n, m_beta, m_epsilon, m_rho, m_theta ); + } + +private: + + float m_sigma = 2.0F; // standard deviation, horizontal axis + float m_beta = 4.0F; // beta exponent + float m_rho = 1.0F; // vertical:horizontal axis ratio + float m_theta = 0.0F; // rotation angle in radians, [0,+pi] + float m_epsilon = 0.01F; // maximum truncation error in sigma units + + void Initialize( float s, float b, float e, float r, float a ) + { + PCL_PRECONDITION( s > 0 ) + PCL_PRECONDITION( b > 0 ) + PCL_PRECONDITION( e > 0 ) + PCL_PRECONDITION( r >= 0 && r <= 1 ) + PCL_PRECONDITION( a >= 0 && a <= Const::pi() ) + m_sigma = Abs( s ); + m_beta = Abs( b ); + m_epsilon = Abs( e ); + m_rho = Range( r, 0.0F, 1.0F ); + m_theta = Range( a, 0.0F, Const::pi() ); + KernelFilter::Resize( 1 + (Max( 1, RoundInt( m_sigma*Sqrt( Pow( m_epsilon, -1/m_beta ) - 1 ) ) ) << 1) ); + Rebuild(); + } + + void Initialize( int n, float b, float e, float r, float a ) + { + PCL_PRECONDITION( n == 0 || n >= 3 && (n & 1) != 0 ) + PCL_PRECONDITION( b > 0 ) + PCL_PRECONDITION( e > 0 ) + PCL_PRECONDITION( r >= 0 && r <= 1 ) + PCL_PRECONDITION( a >= 0 && a <= Const::pi() ) + KernelFilter::Resize( n ); + m_beta = Abs( b ); + m_epsilon = Abs( e ); + m_sigma = (Size() >> 1)/Sqrt( Pow( m_epsilon, -1/m_beta ) - 1 ); + m_rho = Range( r, 0.0F, 1.0F ); + m_theta = Range( a, 0.0F, Const::pi() ); + Rebuild(); + } + + void Rebuild() + { + int size = Size(); + if ( size == 0 ) + return; + + float* h = *coefficients; + double sx = m_sigma; + double sy = m_rho * sx; + double mb = -m_beta; + + if ( m_theta == 0 || m_rho == 1 ) + { + double sx2 = sx*sx; + double sy2 = sy*sy; + for ( int n2 = size >> 1, dy = -n2; dy <= n2; ++dy ) + if ( dy > 0 ) + for ( int dx = 0; dx < size; ++dx, ++h ) + *h = *(h - ((dy+dy)*size)); + else + for ( int dx = -n2; dx <= n2; ++dx, ++h ) + *h = (dx > 0) ? *(h - (dx+dx)) : float( Pow( 1 + dx*dx/sx2 + dy*dy/sy2, mb ) ); + } + else + { + double st, ct; SinCos( double( m_theta ), st, ct ); + double sct = st*ct; + double st2 = st*st; + double ct2 = ct*ct; + double sx2 = sx*sx; + double sy2 = sy*sy; + double p1 = ct2/sx2 + st2/sy2; + double p2 = sct/sy2 - sct/sx2; + double p3 = st2/sx2 + ct2/sy2; + for ( int n2 = size >> 1, dy = -n2; dy <= n2; ++dy ) + { + double twop2dy = 2*p2*dy; + double p3dy2 = p3*dy*dy; + for ( int dx = -n2; dx <= n2; ++dx, ++h ) + *h = float( Pow( 1 + p1*dx*dx + twop2dy*dx + p3dy2, mb ) ); + } + } + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MoffatFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MoffatFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MorphologicalOperator.h b/3rdparty/include/pcl/MorphologicalOperator.h new file mode 100644 index 0000000..76c8c14 --- /dev/null +++ b/3rdparty/include/pcl/MorphologicalOperator.h @@ -0,0 +1,1237 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MorphologicalOperator.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_MorphologicalOperator_h +#define __PCL_MorphologicalOperator_h + +/// \file pcl/MorphologicalOperator.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MorphologicalOperator + * \brief Abstract base class of all PCL morphological operators. + * + * \sa ErosionFilter, DilationFilter, MedianFilter, SelectionFilter, + * MidpointFilter, AlphaTrimmedMeanFilter + */ +class PCL_CLASS MorphologicalOperator +{ +public: + + /*! + * Constructs a %MorphologicalOperator object. + */ + MorphologicalOperator() = default; + + /*! + * Copy constructor. + */ + MorphologicalOperator( const MorphologicalOperator& ) = default; + + /*! + * Destroys a %MorphologicalOperator object. + */ + virtual ~MorphologicalOperator() + { + } + + /*! + * Returns a pointer to a dynamically allocated duplicate of this + * morphological operator. + */ + virtual MorphologicalOperator* Clone() const = 0; + + /*! + * Returns a human-readable description of this morphological operator. + */ + virtual String Description() const + { + return String(); + } + + /*! + * \internal + * Returns true iff this object performs a dilation morphological operation. + * This member function is used internally to decide whether to reflect the + * structuring element during morphological transformations. + */ + virtual bool IsDilation() const + { + return false; + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + virtual FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 32-bit floating-point images" ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + virtual DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 64-bit floating-point images" ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point complex pixel samples. + */ + virtual ComplexPixelTraits::sample operator ()( ComplexPixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 32-bit complex images" ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point complex pixel samples. + */ + virtual DComplexPixelTraits::sample operator ()( DComplexPixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 64-bit complex images" ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + virtual UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 8-bit integer images" ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + virtual UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 16-bit integer images" ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + virtual UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const + { + throw NotImplemented( *this, "Apply to 32-bit integer images" ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ErosionFilter + * \brief Erosion morphological operator. + * + * The \e erosion morphological operator computes the minimum value in a pixel + * neighborhood. + */ +class PCL_CLASS ErosionFilter : public MorphologicalOperator +{ +public: + + /*! + */ + MorphologicalOperator* Clone() const override + { + return new ErosionFilter( *this ); + } + + /*! + */ + String Description() const override + { + return "Erosion"; + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + +private: + + template + static T Operate( T* __restrict__ f, size_type n ) + { + T x = *f++; + for ( ; --n > 0; ++f ) + if ( *f < x ) + x = *f; + return x; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class DilationFilter + * \brief Dilation morphological operator. + * + * The \e dilation morphological operator computes the maximum value in a pixel + * neighborhood. + */ +class PCL_CLASS DilationFilter : public MorphologicalOperator +{ +public: + + /*! + */ + MorphologicalOperator* Clone() const override + { + return new DilationFilter( *this ); + } + + /*! + */ + String Description() const override + { + return "Dilation"; + } + + /*! + */ + bool IsDilation() const override + { + return true; + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + +private: + + template + static T Operate( T* __restrict__ f, size_type n ) + { + T x = *f++; + for ( ; --n > 0; ++f ) + if ( x < *f ) + x = *f; + return x; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MedianFilter + * \brief Morphological median operator. + * + * The \e median morphological operator (or median order-statistic filter) + * computes the median of the values in a pixel neighborhood. + */ +class PCL_CLASS MedianFilter : public MorphologicalOperator +{ +public: + + /*! + */ + MorphologicalOperator* Clone() const override + { + return new MedianFilter( *this ); + } + + /*! + */ + String Description() const override + { + return "Median"; + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (FloatPixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (DoublePixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt8PixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt16PixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt32PixelTraits*)0 ); + } + +private: + +#define CMPXCHG( a, b ) \ + if ( f[b] < f[a] ) pcl::Swap( f[a], f[b] ) + +#define MEAN( a, b ) \ + P::FloatToSample( (double( a ) + double( b ))/2 ) + + template + static T Operate( T* __restrict__ f, size_type n, P* ) + { + /* + * Use fast, hard-coded selection networks for n <= 24: + * + * Knuth, D. E., The Art of Computer Programming, volume 3: Sorting and + * Searching, Addison Wesley, 1973. + * + * Hillis, W. D., Co-evolving parasites improve simulated evolution as an + * optimization procedure. Langton, C. et al. (Eds.), Artificial + * Life II. Addison Wesley, 1992. + * + * Hugues Juille, Evolution of Non-Deterministic Incremental Algorithms + * as a New Approach for Search in State Spaces, 1995. + * + * Use a quick selection algorithm for n > 24: + * + * William H. Press et al., Numerical Recipes 3rd Edition: The Art of + * Scientific Computing, Cambridge University Press, 2007, Section 8.5. + * + * Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, Addison-Wesley + * Professional, 2011, pp 345-347. + */ + switch ( n ) + { + case 0: // ?! + return 0; + case 1: // !? + return f[0]; + case 2: + return MEAN( f[0], f[1] ); + case 3: + CMPXCHG( 0, 1 ); CMPXCHG( 1, 2 ); + return pcl::Max( f[0], f[1] ); + case 4: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); + return MEAN( f[1], f[2] ); + case 5: + CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 0, 3 ); + CMPXCHG( 1, 4 ); CMPXCHG( 1, 2 ); CMPXCHG( 2, 3 ); + return pcl::Max( f[1], f[2] ); + case 6: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 1, 4 ); + CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 3, 4 ); + return MEAN( f[2], f[3] ); + case 7: + CMPXCHG( 0, 5 ); CMPXCHG( 0, 3 ); CMPXCHG( 1, 6 ); + CMPXCHG( 2, 4 ); CMPXCHG( 0, 1 ); CMPXCHG( 3, 5 ); + CMPXCHG( 2, 6 ); CMPXCHG( 2, 3 ); CMPXCHG( 3, 6 ); + CMPXCHG( 4, 5 ); CMPXCHG( 1, 4 ); CMPXCHG( 1, 3 ); + return pcl::Min( f[3], f[4] ); + case 8: + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); + CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); + CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 1, 4 ); + CMPXCHG( 3, 6 ); + return MEAN( f[3], f[4] ); + case 9: + CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 ); + CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 6, 7 ); + CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 ); + CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 ); CMPXCHG( 4, 7 ); + CMPXCHG( 3, 6 ); CMPXCHG( 1, 4 ); CMPXCHG( 2, 5 ); + CMPXCHG( 4, 7 ); CMPXCHG( 4, 2 ); CMPXCHG( 6, 4 ); + return pcl::Min( f[2], f[4] ); + case 10: + CMPXCHG( 4, 9 ); CMPXCHG( 3, 8 ); CMPXCHG( 2, 7 ); + CMPXCHG( 1, 6 ); CMPXCHG( 0, 5 ); CMPXCHG( 1, 4 ); + CMPXCHG( 6, 9 ); CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 ); + CMPXCHG( 0, 2 ); CMPXCHG( 3, 6 ); CMPXCHG( 7, 9 ); + CMPXCHG( 0, 1 ); CMPXCHG( 2, 4 ); CMPXCHG( 5, 7 ); + CMPXCHG( 8, 9 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 6 ); + CMPXCHG( 7, 8 ); CMPXCHG( 3, 5 ); CMPXCHG( 2, 5 ); + CMPXCHG( 6, 8 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 7 ); + CMPXCHG( 2, 3 ); CMPXCHG( 6, 7 ); CMPXCHG( 3, 4 ); + CMPXCHG( 5, 6 ); + return MEAN( f[4], f[5] ); + case 11: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 1, 3 ); + CMPXCHG( 5, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 ); + CMPXCHG( 8, 10 ); CMPXCHG( 1, 2 ); CMPXCHG( 5, 6 ); + CMPXCHG( 9, 10 ); CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 ); + CMPXCHG( 5, 9 ); CMPXCHG( 2, 6 ); CMPXCHG( 1, 5 ); + CMPXCHG( 6, 10 ); CMPXCHG( 0, 4 ); CMPXCHG( 3, 7 ); + CMPXCHG( 4, 8 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 4 ); + CMPXCHG( 7, 10 ); CMPXCHG( 3, 8 ); CMPXCHG( 2, 3 ); + CMPXCHG( 8, 9 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); + return pcl::Min( f[5], f[6] ); + case 12: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 ); + CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 ); CMPXCHG( 8, 10 ); + CMPXCHG( 1, 2 ); CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 ); + CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 ); CMPXCHG( 5, 9 ); + CMPXCHG( 2, 6 ); CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 ); + CMPXCHG( 0, 4 ); CMPXCHG( 7, 11 ); CMPXCHG( 3, 7 ); + CMPXCHG( 4, 8 ); CMPXCHG( 0, 4 ); CMPXCHG( 7, 11 ); + CMPXCHG( 1, 4 ); CMPXCHG( 7, 10 ); CMPXCHG( 3, 8 ); + CMPXCHG( 2, 3 ); CMPXCHG( 8, 9 ); CMPXCHG( 3, 5 ); + CMPXCHG( 6, 8 ); + return MEAN( f[5], f[6] ); + case 13: + CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); + CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 0, 4 ); + CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); + CMPXCHG( 8, 12 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); + CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); CMPXCHG( 2, 8 ); + CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); + CMPXCHG( 10, 12 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); + CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); + CMPXCHG( 10, 11 ); CMPXCHG( 1, 8 ); CMPXCHG( 3, 10 ); + CMPXCHG( 5, 12 ); CMPXCHG( 3, 6 ); CMPXCHG( 5, 8 ); + return pcl::Max( f[5], f[6] ); + case 14: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 12, 13 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 ); + CMPXCHG( 8, 10 ); CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); + CMPXCHG( 9, 11 ); CMPXCHG( 0, 4 ); CMPXCHG( 8, 12 ); + CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); + CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); + CMPXCHG( 5, 13 ); CMPXCHG( 5, 10 ); CMPXCHG( 6, 9 ); + CMPXCHG( 3, 12 ); CMPXCHG( 7, 11 ); CMPXCHG( 1, 2 ); + CMPXCHG( 4, 8 ); CMPXCHG( 7, 13 ); CMPXCHG( 2, 8 ); + CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 ); CMPXCHG( 3, 8 ); + CMPXCHG( 7, 12 ); CMPXCHG( 6, 8 ); CMPXCHG( 3, 5 ); + CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); CMPXCHG( 7, 8 ); + return MEAN( f[6], f[7] ); + case 15: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 12, 13 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 ); + CMPXCHG( 8, 10 ); CMPXCHG( 12, 14 ); CMPXCHG( 1, 3 ); + CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 ); CMPXCHG( 0, 4 ); + CMPXCHG( 8, 12 ); CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); + CMPXCHG( 2, 6 ); CMPXCHG( 10, 14 ); CMPXCHG( 3, 7 ); + CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); + CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); + CMPXCHG( 6, 14 ); CMPXCHG( 5, 10 ); CMPXCHG( 6, 9 ); + CMPXCHG( 3, 12 ); CMPXCHG( 13, 14 ); CMPXCHG( 7, 11 ); + CMPXCHG( 1, 2 ); CMPXCHG( 4, 8 ); CMPXCHG( 7, 13 ); + CMPXCHG( 2, 8 ); CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 ); + CMPXCHG( 3, 8 ); CMPXCHG( 7, 12 ); CMPXCHG( 6, 8 ); + CMPXCHG( 3, 5 ); CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); + CMPXCHG( 7, 8 ); + return pcl::Max( f[6], f[7] ); + case 16: + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 0, 2 ); + CMPXCHG( 4, 6 ); CMPXCHG( 8, 10 ); CMPXCHG( 12, 14 ); + CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 ); + CMPXCHG( 13, 15 ); CMPXCHG( 0, 4 ); CMPXCHG( 8, 12 ); + CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); CMPXCHG( 2, 6 ); + CMPXCHG( 10, 14 ); CMPXCHG( 3, 7 ); CMPXCHG( 11, 15 ); + CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); + CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); + CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 5, 10 ); + CMPXCHG( 6, 9 ); CMPXCHG( 3, 12 ); CMPXCHG( 13, 14 ); + CMPXCHG( 7, 11 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 8 ); + CMPXCHG( 7, 13 ); CMPXCHG( 2, 8 ); CMPXCHG( 5, 6 ); + CMPXCHG( 9, 10 ); CMPXCHG( 3, 8 ); CMPXCHG( 7, 12 ); + CMPXCHG( 6, 8 ); CMPXCHG( 10, 12 ); CMPXCHG( 3, 5 ); + CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); CMPXCHG( 7, 8 ); + CMPXCHG( 9, 10 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); + return MEAN( f[7], f[8] ); + case 17: + CMPXCHG( 0, 16 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); + CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); + CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); + CMPXCHG( 8, 16 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); + CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); + CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); + CMPXCHG( 4, 16 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); + CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); + CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 2, 16 ); + CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); + CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); + CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 1, 16 ); + CMPXCHG( 1, 8 ); CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); + CMPXCHG( 7, 14 ); CMPXCHG( 5, 8 ); CMPXCHG( 7, 10 ); + return pcl::Max( f[7], f[8] ); + case 18: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 0, 8 ); + CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); + CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); + CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); + CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 4, 16 ); + CMPXCHG( 5, 17 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); + CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); + CMPXCHG( 9, 11 ); CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); + CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); CMPXCHG( 2, 8 ); + CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); + CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); + CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); + CMPXCHG( 15, 17 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); + CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); + CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); + CMPXCHG( 16, 17 ); CMPXCHG( 1, 16 ); CMPXCHG( 1, 8 ); + CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); + CMPXCHG( 9, 16 ); CMPXCHG( 5, 8 ); CMPXCHG( 7, 10 ); + CMPXCHG( 9, 12 ); CMPXCHG( 7, 8 ); CMPXCHG( 9, 10 ); + return MEAN( f[8], f[9] ); + case 19: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 ); + CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); + CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); + CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); + CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); CMPXCHG( 0, 4 ); + CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); + CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); + CMPXCHG( 11, 15 ); CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); + CMPXCHG( 6, 18 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 0, 2 ); + CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); + CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); CMPXCHG( 12, 14 ); + CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); CMPXCHG( 2, 16 ); + CMPXCHG( 3, 17 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); + CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); + CMPXCHG( 11, 17 ); CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); + CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); + CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); + CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 3, 10 ); + CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); + CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 ); + return pcl::Min( f[9], f[10] ); + case 20: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 ); + CMPXCHG( 3, 19 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); + CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); + CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); + CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); + CMPXCHG( 11, 19 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); + CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); + CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); + CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 ); + CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 ); + CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); + CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); + CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); + CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); + CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); + CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); + CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); + CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); + CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); CMPXCHG( 0, 1 ); + CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); + CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); + CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 ); + CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 3, 10 ); + CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); + CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 ); + return MEAN( f[9], f[10] ); + case 21: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 ); + CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 0, 8 ); + CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); + CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); + CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); + CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 ); + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); + CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 ); + CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 ); + CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 ); + CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); + CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); + CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); + CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); + CMPXCHG( 6, 20 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); + CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); + CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); + CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); + CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); CMPXCHG( 0, 1 ); + CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); + CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); + CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 ); + CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 5, 20 ); + CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); + CMPXCHG( 9, 16 ); CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 ); + return pcl::Max( f[9], f[10] ); + case 22: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 ); + CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 ); + CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); + CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); + CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); + CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); + CMPXCHG( 12, 20 ); CMPXCHG( 13, 21 ); CMPXCHG( 0, 4 ); + CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); + CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); + CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 ); CMPXCHG( 17, 21 ); + CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 ); + CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 ); + CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); + CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); + CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); + CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); + CMPXCHG( 6, 20 ); CMPXCHG( 7, 21 ); CMPXCHG( 2, 8 ); + CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); + CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); + CMPXCHG( 15, 21 ); CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); + CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); + CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); + CMPXCHG( 18, 20 ); CMPXCHG( 19, 21 ); CMPXCHG( 0, 1 ); + CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); + CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); + CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 ); + CMPXCHG( 20, 21 ); CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); + CMPXCHG( 5, 20 ); CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); + CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); CMPXCHG( 11, 18 ); + CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 ); + CMPXCHG( 9, 10 ); CMPXCHG( 11, 12 ); + return MEAN( f[10], f[11] ); + case 23: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 ); + CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 ); + CMPXCHG( 6, 22 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); + CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); + CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); + CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); + CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 ); CMPXCHG( 13, 21 ); + CMPXCHG( 14, 22 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); + CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); + CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); + CMPXCHG( 16, 20 ); CMPXCHG( 17, 21 ); CMPXCHG( 18, 22 ); + CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 ); + CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 ); + CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); + CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); + CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); + CMPXCHG( 17, 19 ); CMPXCHG( 20, 22 ); CMPXCHG( 2, 16 ); + CMPXCHG( 3, 17 ); CMPXCHG( 6, 20 ); CMPXCHG( 7, 21 ); + CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); + CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); + CMPXCHG( 14, 20 ); CMPXCHG( 15, 21 ); CMPXCHG( 2, 4 ); + CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); + CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); + CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); CMPXCHG( 19, 21 ); + CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); + CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); + CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); + CMPXCHG( 18, 19 ); CMPXCHG( 20, 21 ); CMPXCHG( 1, 16 ); + CMPXCHG( 3, 18 ); CMPXCHG( 5, 20 ); CMPXCHG( 7, 22 ); + CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); + CMPXCHG( 11, 18 ); CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 ); + return pcl::Min( f[11], f[12] ); + case 24: + CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 ); + CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 ); + CMPXCHG( 6, 22 ); CMPXCHG( 7, 23 ); CMPXCHG( 0, 8 ); + CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); + CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); + CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); + CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 ); + CMPXCHG( 13, 21 ); CMPXCHG( 14, 22 ); CMPXCHG( 15, 23 ); + CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); + CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); + CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 ); + CMPXCHG( 17, 21 ); CMPXCHG( 18, 22 ); CMPXCHG( 19, 23 ); + CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 ); + CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 ); + CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 ); + CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 ); + CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); + CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); + CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); + CMPXCHG( 17, 19 ); CMPXCHG( 20, 22 ); CMPXCHG( 21, 23 ); + CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); CMPXCHG( 6, 20 ); + CMPXCHG( 7, 21 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); + CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); + CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); CMPXCHG( 15, 21 ); + CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); + CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); + CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); + CMPXCHG( 19, 21 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); + CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); + CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); + CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 ); CMPXCHG( 20, 21 ); + CMPXCHG( 22, 23 ); CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); + CMPXCHG( 5, 20 ); CMPXCHG( 7, 22 ); CMPXCHG( 5, 12 ); + CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); CMPXCHG( 11, 18 ); + CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 ); + return MEAN( f[11], f[12] ); + default: + { + distance_type n2 = distance_type( n >> 1 ); + if ( n & 1 ) + return *pcl::Select( f, f+n, n2 ); + return P::FloatToSample( (double( *pcl::Select( f, f+n, n2 ) ) + + double( *pcl::Select( f, f+n, n2-1 ) ))/2 ); + } + } + } + +#undef CMPXCHG +#undef MEAN +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SelectionFilter + * \brief Morphological selection operator. + * + * The \e selection morphological operator (or selection order-statistic + * filter) computes the value corresponding to a prescribed percentile in the + * ranked set of values from a pixel neighborhood. + * + * The selection point \a k of the selection operator defines the + * working percentile: for k=0, we have an erosion (or minimum) operator; for + * k=1 we have a dilation (or maximum) operator; k=0.5 defines the median + * operator. Other values work as a balance between erosion and dilation. + */ +class PCL_CLASS SelectionFilter : public MorphologicalOperator +{ +public: + + /*! + * Default constructor. The default selection point is 0.5, equivalent to a + * median operator. + */ + SelectionFilter() = default; + + /*! + * Constructs a %SelectionFilter with selection point \a p. + */ + SelectionFilter( float p ) + : k( pcl::Range( p, float( 0 ), float( 1 ) ) ) + { + PCL_PRECONDITION( 0 <= p && p <= 1 ) + PCL_CHECK( 0 <= k && k <= 1 ) + } + + /*! + * Copy constructor. + */ + SelectionFilter( const SelectionFilter& ) = default; + + /*! + */ + MorphologicalOperator* Clone() const override + { + return new SelectionFilter( *this ); + } + + /*! + * Returns the selection point of this morphological selection operator. + */ + float SelectionPoint() const + { + return k; + } + + /*! + * Sets the selection point of this morphological selection operator. + */ + void SetSelectionPoint( float _k ) + { + PCL_PRECONDITION( 0 <= _k && _k <= 1 ) + k = pcl::Range( _k, float( 0 ), float( 1 ) ); + } + + /*! + */ + String Description() const override + { + return String().Format( "Selection, k=%.5f", k ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n ); + } + +private: + + float k = 0.5F; + + template + T Operate( T* f, size_type n ) const + { + return *pcl::Select( f, f+n, distance_type( pcl::RoundInt( k*(n-1) ) ) ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class MidpointFilter + * \brief Midpoint operator. + * + * The \e midpoint operator computes the midpoint value in a pixel + * neighborhood, namely: (minimum + maximum)/2. + */ +class PCL_CLASS MidpointFilter : public MorphologicalOperator +{ +public: + + /*! + */ + MorphologicalOperator* Clone() const override + { + return new MidpointFilter( *this ); + } + + /*! + */ + String Description() const override + { + return "Midpoint"; + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (FloatPixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (DoublePixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt8PixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt16PixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt32PixelTraits*)0 ); + } + +private: + + template + static T Operate( T* f, size_type n, P* ) + { + T* min, * max; + pcl::FindExtremeItems( min, max, f, f+n ); + return P::FloatToSample( (double( *min ) + double( *max ))/2 ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class AlphaTrimmedMeanFilter + * \brief Alpha-trimmed mean operator + * + * The alpha-trimmed mean operator computes the mean of the remaining + * values in a pixel neighborhood, after suppressing the d/2 lowest and the d/2 + * highest values. The point \a d defines the trimming factor of the + * operator. When d=0, we have an arithmetic mean filter. If d=1, the filter is + * the median operator. + * + * The alpha-trimmed operator is not a morphological operator in the strict + * sense, although it allows for the implementation of robust filters that + * share some important properties with morphological filters in practical + * applications. + */ +class PCL_CLASS AlphaTrimmedMeanFilter : public MorphologicalOperator +{ +public: + + /*! + * Default constructor. The default trimming factor is 0.2, which leads to + * the suppression of a 10% of the lowest and highest neighbor pixels. The + * resulting object is a robust mean filter resilient to outliers in most + * practical cases. + */ + AlphaTrimmedMeanFilter() = default; + + /*! + * Constructs a %AlphaTrimmedMeanFilter object with the specified trimming + * factor \a t in the [0,1] range. + */ + AlphaTrimmedMeanFilter( float t ) + : d( pcl::Range( t, float( 0 ), float( 1 ) ) ) + { + PCL_PRECONDITION( 0 <= t && t <= 1 ) + PCL_CHECK( 0 <= d && d <= 1 ) + } + + /*! + * Copy constructor. + */ + AlphaTrimmedMeanFilter( const AlphaTrimmedMeanFilter& ) = default; + + /*! + */ + MorphologicalOperator* Clone() const override + { + return new AlphaTrimmedMeanFilter( *this ); + } + + /*! + * Returns the trimming factor of this alpha-trimmed mean operator. + */ + float TrimmingFactor() const + { + return d; + } + + /*! + * Sets the trimming factor \a t of this alpha-trimmed mean operator. + */ + void SetTrimmingFactor( float t ) + { + PCL_PRECONDITION( 0 <= t && t <= 1 ) + d = pcl::Range( t, float( 0 ), float( 1 ) ); + } + + /*! + */ + String Description() const override + { + return String().Format( "Alpha-trimmed mean, d=%.5f", d ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * floating point pixel samples. + */ + FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (FloatPixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 64-bit + * floating point pixel samples. + */ + DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (DoublePixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 8-bit + * unsigned integer pixel samples. + */ + UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt8PixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 16-bit + * unsigned integer pixel samples. + */ + UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt16PixelTraits*)0 ); + } + + /*! + * Applies this morphological operator to a vector \a f of \a n 32-bit + * unsigned integer pixel samples. + */ + UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override + { + return Operate( f, n, (UInt32PixelTraits*)0 ); + } + +private: + + float d = 0.2F; + + template + T Operate( T* f, size_type n, P* ) const + { + pcl::Sort( f, f+n ); + double s = 0; + size_type i1 = RoundInt( d*((n - 1) >> 1) ); + size_type i2 = n-i1; + for ( size_type i = i1; i < i2; ++i ) + s += f[i]; + return P::FloatToSample( s/(i2 - i1) ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MorphologicalOperator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MorphologicalOperator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MorphologicalTransformation.h b/3rdparty/include/pcl/MorphologicalTransformation.h new file mode 100644 index 0000000..9770222 --- /dev/null +++ b/3rdparty/include/pcl/MorphologicalTransformation.h @@ -0,0 +1,246 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MorphologicalTransformation.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_MorphologicalTransformation_h +#define __PCL_MorphologicalTransformation_h + +/// \file pcl/MorphologicalTransformation.h + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MorphologicalTransformation + * \brief Generic n-way morphological transformation. + * + * ### TODO: Write a detailed description for %MorphologicalTransformation. + * + * \sa MorphologicalOperator, StructuringElement + */ +class PCL_CLASS MorphologicalTransformation : public InterlacedTransformation, + public ThresholdedTransformation, + public ParallelProcess +{ // N.B. ImageTransformation is a virtual base class +public: + + /*! + * Constructs a default %MorphologicalTransformation object. + * + * \note This constructor creates an uninitialized instance. In order to use + * this object, it must be associated with a particular operator and + * structuring element by calling the SetOperator() and SetStructure() + * member functions, respectively, with the appropriate instances of + * MorphologicalOperator and StructuringElement. + */ + MorphologicalTransformation() = default; + + /*! + * Constructs a %MorphologicalTransformation object with the specified + * operator and structuring element. + * + * The specified objects don't have to remain valid while this + * %MorphologicalTransformation instance is actively used, since it will + * own private copies of the specified filter operator and structure. + */ + MorphologicalTransformation( const MorphologicalOperator& op, const StructuringElement& structure ) + { + m_operator = op.Clone(); + m_structure = structure.Clone(); + m_structure->Initialize(); + } + + /*! + * Copy constructor. + */ + MorphologicalTransformation( const MorphologicalTransformation& x ) + : InterlacedTransformation( x ) + , ThresholdedTransformation( x ) + , ParallelProcess( x ) + { + if ( !x.m_operator.IsNull() ) + if ( !x.m_structure.IsNull() ) + { + m_operator = x.m_operator->Clone(); + m_structure = x.m_structure->Clone(); + } + } + + /*! + * Move constructor. + */ + MorphologicalTransformation( MorphologicalTransformation&& x ) = default; + + /*! + * Destroys a %MorphologicalTransformation object. + */ + virtual ~MorphologicalTransformation() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + MorphologicalTransformation& operator =( const MorphologicalTransformation& x ) + { + if ( &x != this ) + { + (void)InterlacedTransformation::operator =( x ); + (void)ThresholdedTransformation::operator =( x ); + (void)ParallelProcess::operator =( x ); + if ( !x.m_operator.IsNull() && !x.m_structure.IsNull() ) + { + m_operator = x.m_operator->Clone(); + m_structure = x.m_structure->Clone(); + } + else + { + m_operator.Destroy(); + m_structure.Destroy(); + } + } + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + MorphologicalTransformation& operator =( MorphologicalTransformation&& ) = default; + + /*! + * Returns a reference to the morphological operator associated with this + * transformation. + */ + const MorphologicalOperator& Operator() const + { + PCL_PRECONDITION( !m_operator.IsNull() ) + return *m_operator; + } + + /*! + * Causes this transformation to use a duplicate of the specified + * morphological operator. + */ + void SetOperator( const MorphologicalOperator& op ) + { + m_operator = op.Clone(); + } + + /*! + * Returns a reference to the structuring element associated with this + * transformation. + */ + const StructuringElement& Structure() const + { + PCL_PRECONDITION( !m_structure.IsNull() ) + return *m_structure; + } + + /*! + * Causes this transformation to use a duplicate of the specified + * structuring element. + */ + void SetStructure( const StructuringElement& structure ) + { + m_structure = structure.Clone(); + m_structure->Initialize(); + } + + /*! + * Returns the size in pixels of the overlapping regions between adjacent + * areas processed by parallel execution threads. The overlapping distance + * is a function of the size of the associated structuring element and the + * current interlacing distance. + */ + int OverlappingDistance() const + { + PCL_PRECONDITION( !m_structure.IsNull() ) + return m_structure->Size() + (m_structure->Size() - 1)*(InterlacingDistance() - 1); + } + +protected: + + AutoPointer m_operator; // morphological operator + AutoPointer m_structure; // n-way structuring element + + /* + * In-Place 2-D Morphological Transformation Algorithm. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; + +private: + + void Validate() const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MorphologicalTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MorphologicalTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MultiVector.h b/3rdparty/include/pcl/MultiVector.h new file mode 100644 index 0000000..6ad8247 --- /dev/null +++ b/3rdparty/include/pcl/MultiVector.h @@ -0,0 +1,432 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MultiVector.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_MultiVector_h +#define __PCL_MultiVector_h + +/// \file pcl/MultiVector.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericMultiVector + * \brief Generic array of vectors. + * + * A multivector is a dynamic array of vectors. It can also be seen as a vector + * of vectors, or a vector whose components are also vectors. + * %GenericMultiVector implements a homogeneous multivector based on the Array + * and GenericVector template classes. Besides all the member functions + * inherited from its base class, it also provides some useful constructors and + * assignment operators, including arithmetic scalar-to-vector operators that + * work on all the contained vectors as a whole. + * + * Some typical applications of multivectors include: + * + * \li Implementation of more sophisticated mathematical objects and + * structures, such as tensors. + * + * \li Matrices where rows (or equivalently, columns) have to be manipulated + * as independent structures. For example, to swap two rows of a GenericMatrix + * you have to swap each pair of row elements successively, which is an O(N) + * operation. Swapping two component vectors of a multivector is an O(1) + * operation thanks to the implicit data sharing feature of %GenericVector, and + * hence does not require copying or duplicating data. + * + * \li Arrays and matrices where each component is a vector of variable length. + * + * As most PCL containers, %GenericMultiVector is a reference-counted class + * with implicit data sharing (or \e copy-on-write) functionality. + * + * \sa Array, GenericVector, GenericMatrix + */ +template +class PCL_CLASS GenericMultiVector : public Array > +{ +public: + + /*! + * The structure implementing this multivector class. + */ + typedef Array > multivector_implementation; + + /*! + * Represents a vector. + */ + typedef GenericVector vector; + + /*! + * Represents a scalar. + */ + typedef typename vector::scalar scalar; + + /*! + * Represents a vector component. + */ + typedef typename vector::component component; + + /*! + * Represents a mutable multivector iterator. + */ + typedef typename multivector_implementation::iterator + iterator; + + /*! + * Represents an immutable multivector iterator. + */ + typedef typename multivector_implementation::const_iterator + const_iterator; + + /*! + * Represents a mutable vector iterator. + */ + typedef typename vector::iterator vector_iterator; + + /*! + * Represents an immutable vector iterator. + */ + typedef typename vector::const_iterator const_vector_iterator; + + /*! + * Constructs an empty multivector. An empty multivector has no component + * vectors and zero length. + */ + GenericMultiVector() = default; + + /*! + * Constructs an uninitialized multivector of the specified \a length. + * + * This constructor does not initialize component vectors. The newly created + * multivector will contain \a length empty vectors. + */ + GenericMultiVector( size_type length ) + : multivector_implementation( length ) + { + } + + /*! + * Constructs a multivector with uninitialized component vectors. + * + * \param length Number of multivector components. + * + * \param vectorLength Number of vector components (>= 0). + * + * This constructor does not initialize vector components. The newly created + * vectors will contain unpredictable values. + */ + GenericMultiVector( size_type length, int vectorLength ) + : multivector_implementation( length ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i = vector( vectorLength ); + } + + /*! + * Constructs a multivector and fills it with a constant scalar. + * + * \param value Initial value for all vector components. + * + * \param length Number of multivector components. + * + * \param vectorLength Number of vector components (>= 0). + */ + GenericMultiVector( const scalar& value, size_type length, int vectorLength ) + : multivector_implementation( length ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i = vector( value, vectorLength ); + } + + /*! + * Constructs a multivector of two components initialized with copies of the + * specified vectors \a v0 and \a v1, respectively for the first and second + * component vectors. + */ + GenericMultiVector( const vector& v0, const vector& v1 ) + : GenericMultiVector( size_type( 2 ) ) + { + iterator i = this->Begin(); + *i = v0; *++i = v1; + } + + /*! + * Constructs a multivector of three components initialized with copies of + * the specified vectors \a v0, \a v1 and \a v2, respectively for the first, + * second and third component vectors. + */ + GenericMultiVector( const vector& v0, const vector& v1, const vector& v2 ) + : GenericMultiVector( size_type( 3 ) ) + { + iterator i = this->Begin(); + *i = v0; *++i = v1; *++i = v2; + } + + /*! + * Constructs a multivector of four components initialized with copies of + * the specified vectors \a v0, \a v1, \a v2 and \a v3, respectively for the + * first, second, third and fourth component vectors. + */ + GenericMultiVector( const vector& v0, const vector& v1, const vector& v2, const vector& v3 ) + : GenericMultiVector( size_type( 4 ) ) + { + iterator i = this->Begin(); + *i = v0; *++i = v1; *++i = v2; *++i = v3; + } + + /*! + * Copy constructor. + */ + GenericMultiVector( const GenericMultiVector& ) = default; + + /*! + * Move constructor. + */ + GenericMultiVector( GenericMultiVector&& ) = default; + + /*! + * Destroys a %GenericMultiVector object. + */ + ~GenericMultiVector() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + GenericMultiVector& operator =( const GenericMultiVector& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + GenericMultiVector& operator =( GenericMultiVector&& ) = default; + + /*! + * Assigns a constant scalar \a x to all vector components in this + * multivector. Returns a reference to this object. + */ + GenericMultiVector& operator =( const scalar& x ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i = x; + return *this; + } + + /*! + * Adds a constant scalar \a x to all vector components in this multivector. + * Returns a reference to this object. + */ + GenericMultiVector& operator +=( const scalar& x ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i += x; + return *this; + } + + /*! + * Subtracts a constant scalar \a x from all vector components of this + * multivector. Returns a reference to this object. + */ + GenericMultiVector& operator -=( const scalar& x ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i -= x; + return *this; + } + + /*! + * Multiplies all vector components in this multivector by a constant scalar + * \a x. Returns a reference to this object. + */ + GenericMultiVector& operator *=( const scalar& x ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i *= x; + return *this; + } + + /*! + * Divides all vector components in this multivector by a constant scalar + * \a x. Returns a reference to this object. + */ + GenericMultiVector& operator /=( const scalar& x ) + { + for ( iterator i = this->Begin(), j = this->End(); i < j; ++i ) + *i /= x; + return *this; + } + + /*! + * Returns the sum of all vector components. + */ + double Sum() const + { + double s = 0; + for ( const_iterator i = this->Begin(), j = this->End(); i < j; ++i ) + s += i->Sum(); + return s; + } + + /*! + * Computes the sum of vector components using a numerically stable + * summation algorithm to minimize roundoff error. + */ + double StableSum() const + { + DVector s( this->Length() ); + size_type n = 0; + for ( const_iterator i = this->Begin(), j = this->End(); i < j; ++i ) + s[n++] = i->StableSum(); + return s.StableSum(); + } + +#ifndef __PCL_NO_VECTOR_STATISTICS + + /*! + * Returns the value of the smallest vector component. For empty + * multivectors, this function returns zero. + */ + component MinComponent() const + { + if ( !this->IsEmpty() ) + { + component min = this->Begin()->MinComponent(); + for ( const_iterator i = this->Begin(), j = this->End(); ++i < j; ) + min = pcl::Min( min, i->MinComponent() ); + return min; + } + return component( 0 ); + } + + /*! + * Returns the value of the largest vector component. For empty + * multivectors, this function returns zero. + */ + component MaxComponent() const + { + if ( !this->IsEmpty() ) + { + component max = this->Begin()->MaxComponent(); + for ( const_iterator i = this->Begin(), j = this->End(); ++i < j; ) + max = pcl::Max( max, i->MaxComponent() ); + return max; + } + return component( 0 ); + } + +#endif // !__PCL_NO_VECTOR_STATISTICS +}; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_MULTIVECTOR_INSTANTIATE + +/*! + * \defgroup multivector_types Multivector Types + */ + +/*! + * \class pcl::DMultiVector + * \ingroup multivector_types + * \brief 64-bit floating point real multivector. + * + * %DMultiVector is a template instantiation of GenericMultiVector for the + * \c double data type. + */ +typedef GenericMultiVector DMultiVector; + +/*! + * \class pcl::FMultiVector + * \ingroup multivector_types + * \brief 32-bit floating point real multivector. + * + * %FMultiVector is a template instantiation of GenericMultiVector for the + * \c float data type. + */ +typedef GenericMultiVector FMultiVector; + +/*! + * \class pcl::IMultiVector + * \ingroup multivector_types + * \brief Integer multivector. + * + * %IMultiVector is a template instantiation of GenericMultiVector for the + * \c int data type. + */ +typedef GenericMultiVector IMultiVector; + +/*! + * \class pcl::MultiVector + * \ingroup multivector_types + * \brief 64-bit floating point real multivector. + * + * %MultiVector is an alias for DMultiVector. It is a template instantiation of + * GenericMultiVector for the \c double data type. + */ +typedef DMultiVector MultiVector; + +#endif // !__PCL_NO_MULTIVECTOR_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MultiVector_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MultiVector.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MultiViewSelectionDialog.h b/3rdparty/include/pcl/MultiViewSelectionDialog.h new file mode 100644 index 0000000..2642a3c --- /dev/null +++ b/3rdparty/include/pcl/MultiViewSelectionDialog.h @@ -0,0 +1,146 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MultiViewSelectionDialog.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_MultiViewSelectionDialog_h +#define __PCL_MultiViewSelectionDialog_h + +/// \file pcl/MultiViewSelectionDialog.h + +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MultiViewSelectionDialog + * \brief A simple dialog box to select a set of existing views. + * + * %MultiViewSelectionDialog consists of a TreeBox control, populated with all + * existing views, plus standard OK and Cancel push buttons. This class is a + * useful helper whenever a process needs access to several user-selected views + * in a single operation. + * + * \sa ViewSelectionDialog, PreviewSelectionDialog, Dialog + */ +class MultiViewSelectionDialog : public Dialog +{ +public: + + /*! + * Constructs a %MultiViewSelectionDialog object. + * + * \param allowPreviews Whether to allow selection of previews, along + * with main views. The default value is true. + */ + MultiViewSelectionDialog( bool allowPreviews = true ); + + /*! + * Destroys a %MultiViewSelectionDialog object. + */ + virtual ~MultiViewSelectionDialog() + { + } + + /*! + * Returns the set of selected views. + */ + const Array& Views() const + { + return m_selectedViews; + } + + /*! + * Returns true if this dialog allows selection of previews along with main + * views; false if it can only select main views. This option can be + * controlled with a constructor parameter. + */ + bool PreviewsAllowed() const + { + return m_allowPreviews; + } + +private: + + Array m_selectedViews; + bool m_allowPreviews = true; + + void Regenerate(); + + VerticalSizer Global_Sizer; + TreeBox Views_TreeBox; + HorizontalSizer Row2_Sizer; + PushButton SelectAll_PushButton; + PushButton UnselectAll_PushButton; + CheckBox IncludeMainViews_CheckBox; + CheckBox IncludePreviews_CheckBox; + HorizontalSizer Buttons_Sizer; + PushButton OK_PushButton; + PushButton Cancel_PushButton; + + void OptionClick( Button& sender, bool checked ); + void ButtonClick( Button& sender, bool checked ); + void ControlShow( Control& sender ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MultiViewSelectionDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MultiViewSelectionDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MultiscaleLinearTransform.h b/3rdparty/include/pcl/MultiscaleLinearTransform.h new file mode 100644 index 0000000..b888233 --- /dev/null +++ b/3rdparty/include/pcl/MultiscaleLinearTransform.h @@ -0,0 +1,228 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MultiscaleLinearTransform.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_MultiscaleLinearTransform_h +#define __PCL_MultiscaleLinearTransform_h + +/// \file pcl/MultiscaleLinearTransform.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MultiscaleLinearTransform + * \brief A redundant multiscale transform using separable convolutions. + * + * The multiscale linear transform algorithm produces a set {w1,w2,...,wN,cN}, + * where each wj is a set of coefficients at scale j, which we call detail + * layer, and cN is a large-scale smoothed residual, which we call + * residual layer. Each layer has the same dimensions as the input + * image, hence the generated multiscale transform is redundant. + * + * The algorithm applies successive convolutions with separable filter kernels + * of increasing size 2*s + 1, where s grows following a monotonically + * increasing sequence (the dyadic sequence 1, 2, 4, ... is used by default). + * Multiscale coefficients are the differences between each pair of successive + * convolved images. By default Gaussian filters are used, but block average + * filters can also be used (see the class constructor) for special + * applications. + * + * The reconstruction algorithm consists of the sum of all wj multiscale layers + * for 1 <= j <= N, plus the residual layer cN. + * + * In our implementation, each layer in a multiscale linear transform is a + * floating-point image with the same dimensions as the transformed image. + * Layers are indexed from 0 to N. Layers at indexes from 0 to N-1 are detail + * layers, whose elements are actually convolved difference coefficients. + * Pixels in a detail layer can be negative, zero or positive real values. + * + * The last layer, at index N, is the large-scale residual layer. + * Pixels in the residual layer image can only be positive or zero real values. + * + * \ingroup multiscale_transforms + */ +class PCL_CLASS MultiscaleLinearTransform : public RedundantMultiscaleTransform +{ +public: + + /*! + * Represents a multiscale transform layer. + */ + typedef RedundantMultiscaleTransform::layer layer; + + /*! + * Represents a set of multiscale transform layers, or multiscale transform. + */ + typedef RedundantMultiscaleTransform::transform transform; + + /*! + * Represents a set of layer enabled/disabled states. + */ + typedef RedundantMultiscaleTransform::layer_state_set layer_state_set; + + /*! + * Constructs a %MultiscaleLinearTransform instance. + * + * \param n Number of detail layers. The transform will consist of \a n + * detail layers plus a residual layer, that is n+1 total + * layers. The default value is 4. + * + * \param d Scaling sequence. If \a d <= 0, the transform will use the + * dyadic sequence: 1, 2, 4, ... 2^i. If \a d > 0, its value is + * the distance in pixels between two successive scales. + * + * \param useMeanFilters If true, the transformation will use block + * average filters (mean) instead of Gaussian filters. Mean + * filters have important special applications, such as + * computation of multiscale local variances. Gaussian filters + * are always used by default. + * + * The default values for \a n and \a d are 4 and 0, respectively (four + * layers and the dyadic scaling sequence). + * + * Successive layers are computed by applying separable convolutions with + * kernel filters of size 2*s + 1. The scaling sequence parameter \a d + * is interpreted as follows: + * + * - If the specified sequence parameter \a d is zero 0, then the transform + * uses the dyadic sequence: s = 1, 2, 4, ..., 2^j for 0 <= j < n. + * + * - If \a d > 0, then \a d is the constant increment in pixels between two + * successive scales (linear scaling sequence): s = d*j for 1 <= j < n. + */ + MultiscaleLinearTransform( int n = 4, int d = 0, bool useMeanFilters = false ) + : RedundantMultiscaleTransform( n, d ) + , m_useMeanFilters( useMeanFilters ) + { + } + + /*! + * Copy constructor. + */ + MultiscaleLinearTransform( const MultiscaleLinearTransform& ) = default; + + /*! + * Move constructor. + */ + MultiscaleLinearTransform( MultiscaleLinearTransform&& ) = default; + + /*! + * Destroys this %MultiscaleLinearTransform object. All existing transform + * layers are destroyed and deallocated. + */ + virtual ~MultiscaleLinearTransform() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + MultiscaleLinearTransform& operator =( const MultiscaleLinearTransform& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + MultiscaleLinearTransform& operator =( MultiscaleLinearTransform&& ) = default; + + /*! + * Returns true iff this transform applies block average filters instead of + * Gaussian filters. See the class constructor for more information. + */ + bool UsesMeanFilters() const + { + return m_useMeanFilters; + } + + /*! + * Returns true iff this transform applies Gaussian filters instead of block + * average filters. See the class constructor for more information. + */ + bool UsesGaussianFilters() const + { + return !m_useMeanFilters; + } + +protected: + + /* + * Whether we should use mean (block average) or Gaussian separable filters. + */ + bool m_useMeanFilters = false; + + /* + * Transform (decomposition) + */ + void Transform( const pcl::Image& ) override; + void Transform( const pcl::DImage& ) override; + void Transform( const pcl::ComplexImage& ) override; + void Transform( const pcl::DComplexImage& ) override; + void Transform( const pcl::UInt8Image& ) override; + void Transform( const pcl::UInt16Image& ) override; + void Transform( const pcl::UInt32Image& ) override; + + friend class MLTDecomposition; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MultiscaleLinearTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MultiscaleLinearTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MultiscaleMedianTransform.h b/3rdparty/include/pcl/MultiscaleMedianTransform.h new file mode 100644 index 0000000..ac938ea --- /dev/null +++ b/3rdparty/include/pcl/MultiscaleMedianTransform.h @@ -0,0 +1,344 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MultiscaleMedianTransform.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_MultiscaleMedianTransform_h +#define __PCL_MultiscaleMedianTransform_h + +/// \file pcl/MultiscaleMedianTransform.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MultiscaleMedianTransform + * \brief Multiscale median transform / hybrid median-wavelet transform. + * + * The multiscale median transform algorithm produces a set {w1,w2,...,wN,cN}, + * where each wj is a set of coefficients at scale j, which we call detail + * layer, and cN is a large-scale smoothed residual, which we call + * residual layer. Each layer has the same dimensions as the input + * image, hence the generated multiscale transform is redundant. + * + * The algorithm applies successive median filters with a structuring element + * of increasing size 2*s + 1, where s grows following a monotonically + * increasing sequence (the dyadic sequence 1, 2, 4, ... is used by default). + * Multiscale coefficients are the differences between each pair of successive + * median filtered images. + * + * The hybrid median-wavelet transform merges the multiscale median and wavelet + * transforms in a single high-level operation. Wavelets are used to represent + * nonsignificant structures, such as noise and smooth regions, while median + * filtering is used to represent strong significant structures. This hybrid + * transform provides an optimal representation of the image by combining the + * strongest points of both techniques: wavelets are good to support smooth + * structures with weak variations, while the median transform is better at + * isolating significant, high-contrast structures. + * + * The reconstruction algorithm consists of the sum of all wj multiscale layers + * for 1 <= j <= N, plus the residual layer cN. + * + * References + * + * \li Starck, J.-L., Murtagh, F. and J. Fadili, A. (2010), Sparse %Image + * and Signal Processing: Wavelets, Curvelets, Morphological Diversity, + * Cambridge University Press. + * + * \li Barth, Timothy J., Chan, Tony, Haimes, Robert (Eds.) (2002), + * Multiscale and Multiresolution Methods: Theory and Applications, + * Springer. invited paper: Jean-Luc Starck, Nonlinear Multiscale + * Transforms, pp. 239-279. + * + * In our implementation, each layer in a multiscale median transform is a + * floating-point image with the same dimensions as the transformed image. + * Layers are indexed from 0 to N. Layers at indexes from 0 to N-1 are detail + * layers, whose elements are actually median difference coefficients. Pixels + * in a multiscale layer can be negative, zero or positive real values. + * + * The last layer, at index N, is the large-scale residual layer. Pixels in the + * residual layer image can only be positive or zero real values. + * + * The original algorithm uses square structuring elements. Square structures + * lead to relatively simple and efficient implementations, but unfortunately + * they tend to generate objectionable artifacts around round shapes. In our + * implementation we use special multiway structures to minimize these + * artifacts and to improve the behavior of the algorithm to isolate isotropic + * image structures. + * + * \ingroup multiscale_transforms + */ +class PCL_CLASS MultiscaleMedianTransform : public RedundantMultiscaleTransform +{ +public: + + /*! + * Represents a multiscale transform layer. + */ + typedef RedundantMultiscaleTransform::layer layer; + + /*! + * Represents a set of multiscale transform layers, or multiscale transform. + */ + typedef RedundantMultiscaleTransform::transform transform; + + /*! + * Represents a set of layer enabled/disabled states. + */ + typedef RedundantMultiscaleTransform::layer_state_set layer_state_set; + + /*! + * Constructs a %MultiscaleMedianTransform instance. + * + * \param n Number of detail layers. The transform will consist of \a n + * detail layers plus a residual layer, that is n+1 total + * layers. The default value is 4. + * + * \param d Scaling sequence. If \a d <= 0, the transform will use the + * dyadic sequence: 1, 2, 4, ... 2^i. If \a d > 0, its value is + * the distance in pixels between two successive scales. + * + * The default values for \a n and \a d are 4 and 0, respectively (four + * layers and the dyadic scaling sequence). + * + * Successive layers are computed by applying median filters with + * structuring elements of size 2*s + 1. The scaling sequence parameter \a d + * is interpreted as follows: + * + * - If the specified sequence parameter \a d is zero 0, then the transform + * uses the dyadic sequence: s = 1, 2, 4, ..., 2^j for 0 <= j < n. + * + * - If \a d > 0, then \a d is the constant increment in pixels between two + * successive scales (linear scaling sequence): s = d*j for 1 <= j < n. + */ + MultiscaleMedianTransform( int n = 4, int d = 0 ) + : RedundantMultiscaleTransform( n, d ) + { + } + + /*! + * Copy constructor. + */ + MultiscaleMedianTransform( const MultiscaleMedianTransform& ) = default; + + /*! + * Move constructor. + */ + MultiscaleMedianTransform( MultiscaleMedianTransform&& ) = default; + + /*! + * Destroys this %MultiscaleMedianTransform object. All existing transform + * layers are destroyed and deallocated. + */ + virtual ~MultiscaleMedianTransform() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + MultiscaleMedianTransform& operator =( const MultiscaleMedianTransform& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + MultiscaleMedianTransform& operator =( MultiscaleMedianTransform&& ) = default; + + /*! + * Returns true if this transform applies special multiway structuring + * elements for improved isotropic behavior. Returns false if simple + * structures are used instead for improved execution speed, at the cost of + * some performance degradation in the isotropic behavior of the transform. + */ + bool UsingMultiwayStructures() const + { + return m_multiwayStructures; + } + + /*! + * Enables the use of multiway structuring elements. See + * UsingMultiwayStructures() for more information. + * + * \note Calling this member function implicitly deletes all existing + * transform layers. + */ + void EnableMultiwayStructures( bool enable = true ) + { + DestroyLayers(); + m_multiwayStructures = enable; + } + + /*! + * Disables the use of multiway structuring elements. See + * UsingMultiwayStructures() for more information. + * + * \note Calling this member function implicitly deletes all existing + * transform layers. + */ + void DisableMultiwayStructures( bool disable = true ) + { + EnableMultiwayStructures( !disable ); + } + + /*! + * Returns true iff this object performs a hybrid median-wavelet transform. + * Returns false if this is a pure multiscale median transform. + */ + bool IsMedianWaveletTransform() const + { + return m_medianWaveletTransform; + } + + /*! + * Causes this object to perform a hybrid wavelet-median transform. + * + * \param threshold Threshold in sigma units for per-layer suppression of + * significant median transform coefficients. Image + * structures represented by median coefficients with + * absolute values smaller than this threshold will be + * supported by wavelet transform coefficients. The + * default value is 5 sigma. + * + * \note Calling this member function implicitly deletes all existing + * transform layers. + */ + void SetMedianWaveletTransform( float threshold = 5 ) + { + DestroyLayers(); + m_medianWaveletTransform = true; + m_medianWaveletThreshold = Max( 0.F, threshold ); + } + + /*! + * Sets a threshold in sigma units for per-layer suppression of significant + * median transform coefficients. Image structures represented by median + * coefficients with absolute values smaller than this threshold will be + * supported by wavelet transform coefficients. The larger this value, the + * more image structures will be supported by wavelet coefficients. + * + * By default the median-wavelet threshold is 5 sigma. This is normally + * large enough to prevent inclusion of the noise in median transform + * coefficients. + * + * \note Calling this member function implicitly deletes all existing + * transform layers. + */ + void SetMedianWaveletThreshold( float threshold ) + { + DestroyLayers(); + m_medianWaveletThreshold = Max( 0.F, threshold ); + } + + /*! + * Returns the current median-wavelet threshold in sigma units. See the + * documentation for SetMedianWaveletThreshold() for more information. + */ + float MedianWaveletThreshold() const + { + return m_medianWaveletThreshold; + } + + /*! + * Causes this object to perform a pure multiscale median transform. + * + * \note Calling this member function implicitly deletes all existing + * transform layers. + */ + void SetMultiscaleMedianTransform() + { + DestroyLayers(); + m_medianWaveletTransform = false; + } + +private: + + /* + * Use multiway structural elements for improved isotropy. + */ + bool m_multiwayStructures = true; + + /* + * Compute a wavelet-median transform. + */ + bool m_medianWaveletTransform = false; + + /* + * Median-wavelet threshold in sigma units. + */ + float m_medianWaveletThreshold = 5.0F; + + /* + * Transform (decomposition) + */ + void Transform( const pcl::Image& ) override; + void Transform( const pcl::DImage& ) override; + void Transform( const pcl::ComplexImage& ) override; + void Transform( const pcl::DComplexImage& ) override; + void Transform( const pcl::UInt8Image& ) override; + void Transform( const pcl::UInt16Image& ) override; + void Transform( const pcl::UInt32Image& ) override; + + friend class MMTDecomposition; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_MultiscaleMedianTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MultiscaleMedianTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/MuteStatus.h b/3rdparty/include/pcl/MuteStatus.h new file mode 100644 index 0000000..d264f09 --- /dev/null +++ b/3rdparty/include/pcl/MuteStatus.h @@ -0,0 +1,189 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/MuteStatus.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_MuteStatus_h +#define __PCL_MuteStatus_h + +/// \file pcl/MuteStatus.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class MuteStatus + * \brief A status monitoring callback that does not provide any progress + * information. + * + * %MuteStatus does not provide any information on the ongoing monitored + * process. However, it does check if either the current thread has been + * aborted (when the status monitoring process has been initiated from a + * running Thread object), or if the user has requested to cancel the current + * process (when the process has been initiated from the main thread). In both + * cases %MuteStatus attempts to terminate the process being monitored. + * + * %MuteStatus is useful as a specialized monitoring callback for processes + * running in threads, or for fast processes that don't require providing + * detailed progress information to the user. Compared to other callback + * objects such as StandardStatus and SpinStatus, %MuteStatus saves the tasks + * of generating textual information and writing it to GUI controls. These + * auxiliary tasks can be expensive for fast processes, and in some cases they + * may require even more computing time than the processes themselves. + * + * \sa StatusCallback, StatusMonitor, StandardStatus, SpinStatus, + * ProgressBarStatus, RealTimeProgressStatus, Console + */ +class PCL_CLASS MuteStatus : public StatusCallback +{ +public: + + /*! + * Constructs a default %MuteStatus object. + */ + MuteStatus() = default; + + /*! + * Copy constructor. + */ + MuteStatus( const MuteStatus& x ) + : StatusCallback( x ) + { + } + + /*! + * Move constructor. + */ + MuteStatus( MuteStatus&& x ) + : StatusCallback( std::move( x ) ) + , m_console( std::move( x.m_console ) ) + , m_thread( x.m_thread ) + { + x.m_thread = nullptr; + } + + /*! + * Destroys a %MuteStatus instance. + */ + virtual ~MuteStatus() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + MuteStatus& operator =( const MuteStatus& x ) + { + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + MuteStatus& operator =( MuteStatus&& x ) + { + if ( this != &x ) + { + (void)StatusCallback::operator =( std::move( x ) ); + m_console = std::move( x.m_console ); + m_thread = x.m_thread; + x.m_thread = nullptr; + } + return *this; + } + + /*! + * This function is called by a status \a monitor object when a new + * monitored process is about to start. + */ + int Initialized( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object to signal an update of the + * progress count for the current process. + */ + int Updated( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object to signal that the current + * process has finished. + */ + int Completed( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object when the progress + * information for the current process has been changed. + */ + void InfoUpdated( const StatusMonitor& monitor ) const override; + +private: + + mutable pcl::Console m_console; + mutable void* m_thread = nullptr; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_MuteStatus_h + +// ---------------------------------------------------------------------------- +// EOF pcl/MuteStatus.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Mutex.h b/3rdparty/include/pcl/Mutex.h new file mode 100644 index 0000000..c70fe00 --- /dev/null +++ b/3rdparty/include/pcl/Mutex.h @@ -0,0 +1,436 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Mutex.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_Mutex_h +#define __PCL_Mutex_h + +/// \file pcl/Mutex.h + +#include +#include + +#include + +#ifdef __PCL_UNIX +# include +# include +# include +#endif + +#ifdef __PCL_WINDOWS +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Mutex + * \brief Adaptive mutual exclusion lock variable + * + * The word \e mutex is an abbreviation for mutual exclusion. A mutex + * object provides access synchronization for threads. A mutex protects one or + * more objects or a code section, so that only one thread can access them at a + * given time. + * + * To understand how mutual thread exclusion works and why is it needed, + * consider the following example code: + * + * \code + * int data; + * + * void functionOne() + * { + * data += 2; + * data *= 2; + * } + * + * void functionTwo() + * { + * data -= 3; + * data *= 3; + * } + * \endcode + * + * If functionOne() and functionTwo() are called in sequence, this happens: + * + * \code + * data = 3; + * functionOne(); // data is now = 10 + * functionTwo(); // data is now = 21 + * \endcode + * + * Now suppose that we define two threads that call the above functions: + * + * \code + * class ThreadOne : public Thread + * { + * //... + * void Run() override + * { + * functionOne(); + * } + * }; + * + * class ThreadTwo : public Thread + * { + * //... + * void Run() override + * { + * functionTwo(); + * } + * }; + * \endcode + * + * If we start both threads in sequence: + * + * \code + * data = 3; + * ThreadOne one; + * ThreadTwo two; + * one.Start(); + * two.Start(); + * \endcode + * + * then the following might happen: + * + * \code + * // ThreadOne calls functionOne: + * data += 2; // data is now = 5 + * + * // ThreadTwo calls functionTwo. This causes ThreadOne to enter a wait state + * // until ThreadTwo terminates: + * data -= 3; // data is now = 2 + * data *= 3; // data is now = 6 + * + * // ThreadOne resumes execution: + * data *= 2; // data is now = 12 + * \endcode + * + * Because both threads can access data in any order, and there is no + * guarantee as to when a given thread starts execution, the result may not be + * what we expect (we get 12 instead of 21). Adding synchronization with a + * %Mutex object in functionOne() and functionTwo() solves the problem: + * + * \code + * int data; + * Mutex mutex; + * + * void functionOne() + * { + * mutex.Lock(); + * data += 2; + * data *= 2; + * mutex.Unlock(); + * } + * + * void functionTwo() + * { + * mutex.Lock(); + * data -= 3; + * data *= 3; + * mutex.Unlock(); + * } + * \endcode + * + * A mutex can only be locked by a single thread at a time. After Lock() has + * been called from a thread T, other threads that call Lock() on the same + * mutex object block their execution until the thread T calls Unlock(). + * + * To attempt locking a mutex without blocking execution, the Mutex::TryLock() + * member function can be used. This can provide much higher performance than + * Mutex::Lock() when the calling threads don't depend on gaining exclusive + * access to the shared data being protected by the mutex object. + * + * %Mutex implements spinning locking, a technique that can also + * improve performance by avoiding expensive semaphore wait operations under + * high levels of contention. See the documentation for Mutex::Mutex( int ) and + * Mutex::Lock() for more information. + * + * %Mutex has been implemented as a low-level PCL class that does not depend on + * the PixInsight core application. On Windows platforms, %Mutex has been + * implemented as a wrapper to a critical section. On UNIX/Linux + * platforms, %Mutex uses atomic integer operations implemented as inline + * assembly code and direct calls to the pthreads library. + * + * \sa AutoLock, ReadWriteMutex + */ +class PCL_CLASS Mutex +{ +public: + + /*! + * Constructs a %Mutex object. + * + * \param spin Maximum number of spinning loops to do before + * performing a semaphore wait operation when a thread attempts + * to lock this mutex and it has already been locked by another + * thread. If this mutex becomes unlocked during the spinning + * loops, the expensive wait operation can be avoided. The spin + * count must be >= 0. The default value is 512. + */ + Mutex( int spin = 512 ) + : m_spinCount( Max( 0, spin ) ) + { +#ifdef __PCL_WINDOWS + (void)InitializeCriticalSectionAndSpinCount( &criticalSection, DWORD( m_spinCount ) ); +#else + (void)PThreadInitMutex(); +#endif + } + + /*! + * Destroys a %Mutex object. + * + * \warning Destroying a locked %Mutex object may result in undefined + * (mostly catastrophic) behavior. Always make sure that a mutex has been + * unlocked before destroying it. + */ + virtual ~Mutex() + { +#ifdef __PCL_WINDOWS + DeleteCriticalSection( &criticalSection ); +#else + (void)PThreadDestroyMutex(); +#endif + } + + /*! + * Copy constructor. This constructor is disabled because mutexes are unique + * objects. + */ + Mutex( const Mutex& ) = delete; + + /*! + * Copy assignment. This operator is disabled because mutexes are unique + * objects. + */ + Mutex& operator =( const Mutex& ) = delete; + + /*! + * Locks this %Mutex object. + * + * When a mutex has been locked in a thread T, other threads cannot lock it + * until the thread T unlocks it. When a thread attempts to lock a %Mutex + * object that has been previously locked, it blocks its execution until the + * %Mutex object is unlocked. + * + * If the mutex has already been locked by another thread, this routine + * performs a number of spin loops before doing an (expensive) wait + * operation on a semaphore associated with this mutex object. If this + * mutex becomes unlocked during the spinning loops, the wait operation can + * be avoided to lock the mutex in the calling thread. This can greatly + * improve efficiency of multithreaded code under high levels of contention + * (e.g. several running threads that depend on frequent concurrent accesses + * to shared data). For fine control and performance tuning, the maximum + * number of spinning loops performed can be specified as a parameter to the + * Mutex::Mutex( int ) constructor. + */ + void Lock() + { +#ifdef __PCL_WINDOWS + EnterCriticalSection( &criticalSection ); +#else + for ( int spin = m_spinCount; ; ) + { + // Is the mutex free? If so, get it now and don't look back! + if ( m_lockState.TestAndSet( 0, 1 ) ) + { + (void)PThreadLockMutex(); + break; + } + + if ( --spin < 0 ) + { + // Either no spinning, or spinned to no avail... + // Block thread until we can get this mutex. This is expensive. + (void)PThreadLockMutex(); + m_lockState.Store( 1 ); + break; + } + } +#endif + } + + /*! + * Unlocks this %Mutex object. + * + * See the Lock() documentation for more information. + */ + void Unlock() + { +#ifdef __PCL_WINDOWS + LeaveCriticalSection( &criticalSection ); +#else + m_lockState.Store( 0 ); + (void)PThreadUnlockMutex(); +#endif + } + + /*! + * Function call operator. This is a convenience operator that performs the + * lock and unlock operations in an alternative, perhaps more elegant way. + * + * \param lock Whether the mutex should be locked (when true) or unlocked + * (when \a lock is false). + * + * For example, the following code snippet: + * + * \code + * Mutex mutex; + * //... + * mutex( true ); + * // some code to be protected + * mutex( false ); + * \endcode + * + * is equivalent to: + * + * \code + * Mutex mutex; + * //... + * mutex.Lock(); + * // some code to be protected + * mutex.Unlock(); + * \endcode + */ + void operator ()( bool lock = true ) + { + if ( lock ) + Lock(); + else + Unlock(); + } + + /*! + * Attempts locking this %Mutex object. Returns true iff this mutex has been + * successfully locked. + * + * Unlike Lock(), this function does not block execution of the calling + * thread if this mutex cannot be locked. + */ + bool TryLock() + { +#ifdef __PCL_WINDOWS + return TryEnterCriticalSection( &criticalSection ) != FALSE; +#else + // ### N.B.: This code is performance and stability critical. DO NOT + // modify it unless you are absolutely sure of what you are doing. + return m_lockState == 0 && m_lockState.TestAndSet( 0, 1 ) && PThreadLockMutex(); +#endif + } + + /*! + * Returns the spin count of this %Mutex object. + * + * The spin count is a read-only property that can only be set upon object + * construction. For information on mutex spin counts, refer to %Mutex's + * constructor: Mutex::Mutex( int ). + */ + int SpinCount() const + { + return m_spinCount; + } + +private: + +#ifdef __PCL_WINDOWS + + CRITICAL_SECTION criticalSection; + +#else // Linux/UNIX + + AtomicInt m_lockState; // 0=unlocked, 1=acquired + pthread_mutex_t m_mutex; + + bool PThreadInitMutex() + { + return PThreadCheckError( pthread_mutex_init( &m_mutex, 0 ), "pthread_mutex_init" ); + } + + bool PThreadDestroyMutex() + { + return PThreadCheckError( pthread_mutex_destroy( &m_mutex ), "pthread_mutex_destroy" ); + } + + bool PThreadLockMutex() + { + return PThreadCheckError( pthread_mutex_lock( &m_mutex ), "pthread_mutex_lock" ); + } + + bool PThreadUnlockMutex() + { + return PThreadCheckError( pthread_mutex_unlock( &m_mutex ), "pthread_mutex_unlock" ); + } + + static bool PThreadCheckError( int errorCode, const char* funcName ) + { + if ( errorCode == 0 ) + return true; + fprintf( stderr, "%s() failed. Error code: %d\n", funcName, errorCode ); + return false; + } + +#endif // __PCL_WINDOWS + + int m_spinCount = 512; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Mutex_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Mutex.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/NearestNeighborInterpolation.h b/3rdparty/include/pcl/NearestNeighborInterpolation.h new file mode 100644 index 0000000..48cad0d --- /dev/null +++ b/3rdparty/include/pcl/NearestNeighborInterpolation.h @@ -0,0 +1,129 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/NearestNeighborInterpolation.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_NearestNeighborInterpolation_h +#define __PCL_NearestNeighborInterpolation_h + +/// \file pcl/NearestNeighborInterpolation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define m_width this->m_width +#define m_height this->m_height +#define m_data this->m_data + +// ---------------------------------------------------------------------------- + +/*! + * \class NearestNeighborInterpolation + * \brief Two-dimensional nearest neighbor interpolation algorithm + * + * Nearest neighbor interpolation selects the value of the nearest data point + * from the source 2-D matrix. This interpolation always returns existing data + * values in the source matrix, since it doesn't consider the values of other + * neighboring points. + * + * \sa BidimensionalInterpolation, BilinearInterpolation, + * BicubicSplineInterpolation, BicubicBSplineInterpolation, + * BicubicFilterInterpolation, + */ +template +class PCL_CLASS NearestNeighborInterpolation : public BidimensionalInterpolation +{ +public: + + /*! + * Constructs a %NearestNeighborInterpolation instance. + */ + NearestNeighborInterpolation() = default; + + /*! + * Copy constructor. + */ + NearestNeighborInterpolation( const NearestNeighborInterpolation& ) = default; + + /*! + * Returns an interpolated value at {\a x,\a y} location. + * + * \param x,y Coordinates of the interpolation point (horizontal,vertical). + */ + double operator()( double x, double y ) const override + { + PCL_PRECONDITION( m_data != nullptr ) + PCL_PRECONDITION( m_width > 0 && m_height > 0 ) + return double( *(m_data + (Range( RoundIntArithmetic( y ), 0, m_height-1 )*int64( m_width ) + + Range( RoundIntArithmetic( x ), 0, m_width-1 ))) ); + } +}; + +// ---------------------------------------------------------------------------- + +#undef m_width +#undef m_height +#undef m_data + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_NearestNeighborInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/NearestNeighborInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/NetworkTransfer.h b/3rdparty/include/pcl/NetworkTransfer.h new file mode 100644 index 0000000..506b171 --- /dev/null +++ b/3rdparty/include/pcl/NetworkTransfer.h @@ -0,0 +1,621 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/NetworkTransfer.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_NetworkTransfer_h +#define __PCL_NetworkTransfer_h + +/// \file pcl/NetworkTransfer.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class NetworkTransfer + * \brief Synchronous network transfers. + * + * %NetworkTransfer is a simple network utility class with the following + * capabilities: + * + * \li Synchronous download and upload network data transfers. + * + * \li HTTP, FTP, SMTP, HTTPS, FTPS and SMTPS protocols supported. + * + * \li Supports user authentication. + * + * \li Event-driven operation with separate download, upload and progress event + * handlers. + * + * \li Transparent reusable connections for maximum performance. + * + * \li Thread-safe class. + */ +class PCL_CLASS NetworkTransfer : public UIObject +{ +public: + + /*! + * Constructs a default %NetworkTransfer object. + */ + NetworkTransfer(); + + /*! + * Destroys this client-side instance and dereferences the server-side + * object. If the server-side object becomes unreferenced, it will be + * garbage-collected and eventually destroyed by the core application. + * + * When the server-side object is destroyed, all active network connections + * are also closed automatically. See the CloseConnection() member function + * form more information. + */ + virtual ~NetworkTransfer() + { + } + + /*! + * Copy constructor. This constructor is disabled because %NetworkTransfer + * represents unique server-side objects. + */ + NetworkTransfer( const NetworkTransfer& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %NetworkTransfer + * represents unique server-side objects. + */ + NetworkTransfer& operator =( const NetworkTransfer& ) = delete; + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since network transfers are unique objects by definition, calling this + * member function has no effect. + */ + void EnsureUnique() override + { + // Unique by definition + } + + /*! + * Returns a reference to a null %NetworkTransfer instance. A null + * %NetworkTransfer does not correspond to an existing network transfer in + * the PixInsight core application. + */ + static NetworkTransfer& Null(); + + /*! + * Sets the URL of this %NetworkTransfer object. + * + * \param url A valid URL identifying the network resource of this + * network transfer operation. + * + * \param userName The user name for authentication. The default value + * is an empty string. + * + * \param userPassword The user password for authentication. The default + * value is an empty string. + * + * URLs must be valid and conform to the URI specification from RFC 3986 + * (Uniform Resource Identifier: Generic Syntax). The HTTP, FTP, HTTPS, + * FTPS, SSH and SMTP protocols are supported. + * + * The \a url may include user authentication data in the 'user:password@' + * format. It may also include a port specification. For example: + * + * ftp://somebody:secretpwd@ftp.somewhere.com/mydir/myfile.txt:21 + * + * However, if explicit user name and password are specified, they will + * override any user authentication data included in the URL. In all cases, + * user authentication data will never be shown on the console. + * + * If the specified URL is not syntactically valid, this function throws an + * Error exception. Existence or responsiveness of the server are not + * verified. + */ + void SetURL( const String& url, const String& userName = String(), const String& userPassword = String() ); + + /*! + * Sets the proxy URL of this %NetworkTransfer object. + * + * \param url A valid URL identifying the proxy server used by + * this network transfer operation. + * + * \param userName The user name for proxy authentication. The default + * value is an empty string. + * + * \param userPassword The user password for proxy authentication. The + * default value is an empty string. + * + * The parameters used by this member function are identical to those of the + * SetURL() function. + * + * If the specified URL is not syntactically valid, this function throws an + * Error exception. Existence or responsiveness of the proxy server are not + * verified. + */ + void SetProxyURL( const String& url, const String& userName = String(), const String& userPassword = String() ); + + /*! + * Set SSL/TLS options. + * + * \param useSSL Enable SSL/TLS for the FTP, SMTP, POP3 and IMAP + * protocols. These are protocols that start plain text by + * default but can be restarted automatically using secure + * connections. The default value is true. + * + * \param forceSSL If true, SSL will be required for communication during + * the whole transfer operation; in this case, if SSL is + * not available the connection will fail. If this + * parameter is false, SSL/TLS will be used if available, + * but the operation will continue (insecurely) otherwise. + * The default value is false. + * + * \param verifyPeer Verify the authenticity of the peer's certificate, and + * fail if it is not authentic. The peer's certificate is + * checked through a chain of certification authority (CA) + * cerfificates supplied by the calling machine. If this + * parameter is false, the connection won't fail if the + * authenticity of the server's certificate cannot be + * verified. This parameter works for all TLS based + * protocols: HTTPS, FTPS, SMTPS, etc. The default value + * is true. + * + * \param verifyHost Verify the identity of the host. The connection will + * fail if the Common Name or Subject Alternate Name + * fields of the server's certificate don't match the host + * name in the URL set via the SetURL() member function. + * If this parameter is false, the connection won't fail + * if the identity of the server cannot be verified. This + * parameter works for all TLS based protocols: HTTPS, + * FTPS, SMTPS, etc. If the \a verifyPeer parameter is + * false, this parameter is ignored. The default value is + * true. + * + * By default, all %NetworkTransfer objects are initialized to use SSL/TLS + * if possible for plain text protocols. Authenticity of peer and host + * certificates are always verified by default. In other words, the default + * parameter values of this member function reflect the default state of the + * object upon construction. + * + * If the specified SSL settings are not valid for some reason, or if an + * internal error occurs, this function throws an Error exception. + */ + void SetSSL( bool useSSL = true, bool forceSSL = false, bool verifyPeer = true, bool verifyHost = true ); + + /*! + * Define a set of custom HTTP headers. + * + * \param nlsHeaders A newline-separated list of custom HTTP headers. To + * remove all custom headers and return to the default set + * of HTTP headers, specify an empty string. + * + * The specified list of custom headers will replace any previously defined + * list, if one was set by calling this function. + * + * To disable an HTTP header, specify an empty header value (no characters + * after the ':'). For example: + * + * "User-Agent:" + * + * To define a custom header without a value, include no ':' separator and + * end the header with a semicolon: + * + * "CustomHeader;" + * + * Example: + * + * \code + * NetworkTransfer N; + * N.SetURL( "http://foo-bar.com/" ); + * N.SetCustomHTTPHeaders( "Content-Type: text/plain\nMyCustomHeader: 1" ); + * N.OnUploadDataRequested( MyUploadDataFunc, receiver ); + * N.Upload(); + * \endcode + */ + void SetCustomHTTPHeaders( const String& nlsHeaders ); + + /*! + * Sets the connection timeout for this %NetworkTransfer object. + * + * \param seconds Connection timeout in seconds. Can legally be zero to + * reset the connection timeout to its default value of 30 + * seconds. + * + * If the specified timeout is not valid for some reason, or if an internal + * error occurs, this function throws an Error exception. + */ + void SetConnectionTimeout( int seconds ); + + /*! + * Performs a data download operation. + * + * Returns true upon successful completion of the download operation. + * Returns false in the event of error, or if the operation was aborted. + * + * \note Before invoking this function, a download event handler must be set + * by calling OnDownloadDataAvailable(). + */ + bool Download(); + + /*! + * Performs a data upload operation. + * + * \param uploadSize The total size in bytes of the data that will be + * transferred. For example, if you are going to upload a + * disk file, you should specify the file size here. If + * the size cannot be known in advance, this argument can + * legally be zero. However, specifying the total upload + * size can improve uploading performance significantly. + * The default value is zero. + * + * Returns true upon successful completion of the upload operation. Returns + * false in the event of error, or if the operation was aborted. + * + * \note Before invoking this function, an upload event handler must be set + * by calling OnUploadDataRequested(). + */ + bool Upload( fsize_type uploadSize = 0 ); + + /*! + * Performs an HTTP POST operation. + * + * Example: + * + * \code + * NetworkTransfer transfer; + * transfer.SetURL( "http://example-cars-info-site.com/" ); + * transfer.OnDownloadDataAvailable( GetCarInfo, receiver ); + * if ( !transfer.POST( "brand=Toyota&model=RAV4" ) ) + * throw Error( "POST operation failed: " + transfer.ErrorInformation() ); + * \endcode + * + * Returns true upon successful completion of the POST operation. Returns + * false in the event of error, or if the operation has been aborted. + * + * This member function performs a download operation. The downloaded data + * will be the server response to the POSTed \a fields. + * + * \note Before invoking this function, a download event handler must be set + * by calling OnDownloadDataAvailable(). + */ + bool POST( const String& fields ); + + /*! + * Performs an SMTP operation. + * + * \param mailFrom The 'return-to' email address. + * + * \param mailRecipients The list of recipients for this SMTP operation, + * usually a list of email addresses that will receive the + * transferred data as an email message. + * + * Returns true upon successful completion of the SMTP operation. Returns + * false in the event of error, or if the operation has been aborted. + * + * This member function performs an upload operation. The uploaded data will + * be the header and body of an email message. See RFC 5322 for detailed + * information on the data format applicable. + * + * \note Before invoking this function, an upload event handler must be set + * by calling OnUploadDataRequested(). + */ + bool SMTP( const String& mailFrom, const StringList& mailRecipients ); + + /*! + * Closes the internal network connection associated with this object. + * + * Normally, when you call one of the Download(), Upload(), POST() or SMTP() + * member functions for the first time with a %NetworkTransfer object, the + * PixInsight core application does not close the network connection + * automatically after completing the operation. The connection remains + * active for some time, ready to be reused if the same %NetworkTransfer + * object is used again to perform additional (and compatible) data + * transfers. This greatly improves performance of network transactions. + * + * By calling this function you can force immediate close of the active + * connection. If there is no active connection associated with this object, + * this function is simply ignored. Note that the destructor of + * %NetworkTransfer also closes any active connection automatically. + */ + void CloseConnection(); + + /*! + * Returns the URL of the last network transfer operation performed with + * this object, or an empty string if no transfer operation has been done. + * + * \note User authentication data (user name and password) will never be + * included in the URL returned by this function. + */ + String URL() const; + + /*! + * Returns the newline-separated list of custom HTTP headers defined for + * this object, or an empty string if no custom headers have been defined. + * Custom HTTP headers are defined by calling SetCustomHTTPHeaders(). + */ + String CustomHTTPHeaders() const; + + /*! + * Returns the URL of the proxy server used in the last network transfer + * operation performed with this object, or an empty string if no proxy + * server has been specified. + * + * \note Proxy user authentication data (user name and password) will never + * be included in the URL returned by this function. + */ + String ProxyURL() const; + + /*! + * Returns true if the last network transfer operation was successful; false + * in the event of error, if no transfer operation has been performed with + * this object, or if the last operation was aborted. + */ + bool PerformedOK() const; + + /*! + * A synonym for PerformedOK() + */ + operator bool() const + { + return PerformedOK(); + } + + /*! + * Returns true iff the last network transfer operation was aborted by an + * event handler. Returns false if the operation was not aborted (whether + * successful or not), or if no transfer operation has been performed with + * this object. + */ + bool WasAborted() const; + + /*! + * Returns the server response code after the last call to Perform(). + * Returns zero if the response code could not be retrieved, or if no + * transfer operation has been done. + */ + int ResponseCode() const; + + /*! + * The content type (or MIME type) reported by the remote server after a + * successful download operation, or an empty string if no valid content + * type could be retrieved, if the last operation was an upload, or if no + * transfer operation has been performed with this object. + */ + String ContentType() const; + + /*! + * Returns the total number of bytes transferred in the last network + * operation performed with this object (whether successful or not). + */ + fsize_type BytesTransferred() const; + + /*! + * Returns the transfer speed in KiB per second, measured for the last + * network transfer operation performed with this object. + */ + double TotalSpeed() const; + + /*! + * Returns the total elapsed time in seconds, measured for the last + * network transfer operation performed with this object. + */ + double TotalTime() const; + + /*! + * Returns the error information generated in the last network transfer + * operation. Returns an empty string if no error occurred, or if no + * transfer operation has been performed with this object. + * + * Note that this function may return some useful diagnostics information, + * even if the last operation was successful. + */ + String ErrorInformation() const; + + /*! + * \defgroup network_transfer_event_handlers NetworkTransfer Event Handlers + */ + + /*! + * Defines the prototype of a download event handler. + * + * A download event is generated when a %NetworkTransfer instance receives + * data from a remote location, which is ready to be processed by the + * calling process. + * + * \param sender The object that sends a download event. + * + * \param buffer The starting address of a contiguous block of data that + * has been downloaded. The handler function must not modify + * these data in any way. + * + * \param size The length in bytes of the \a buffer data block. + * + * The handler returns true to continue the download operation. If it + * returns false, the operation will be aborted. + * + * \ingroup network_transfer_event_handlers + */ + typedef bool (Control::*download_event_handler)( NetworkTransfer& sender, const void* buffer, fsize_type size ); + + /*! + * Defines the prototype of an upload event handler. + * + * An upload event is generated when a %NetworkTransfer instance is ready to + * send new data to a remote location, which must be provided by the calling + * process. + * + * \param sender The object that sends an upload event. + * + * \param buffer The starting address of a contiguous memory block where + * the data to be uploaded must be copied by the handler + * function. + * + * \param maxSize The maximum length in bytes of the \a buffer data block. + * The handler function must \e not store more bytes than the + * value passed in this argument. + * + * The handler returns an integer value, which will be interpreted as + * follows: + * + * \li An integer greater than zero is the actual size in bytes of the + * contiguous block that has been copied back to the passed \a buffer. In + * this case the returned value must be less than or equal to \a maxSize. + * + * \li Zero to finalize the upload operation. + * + * \li A negative integer to abort the upload operation. + * + * \ingroup network_transfer_event_handlers + */ + typedef fsize_type (Control::*upload_event_handler)( NetworkTransfer& sender, void* buffer, fsize_type maxSize ); + + /*! + * Defines the prototype of a progress event handler. + * + * A %NetworkTransfer instance generates progress events at regular + * intervals during an active data transfer operation. Handling these events + * can be useful to provide feedback to the user during long download or + * upload procedures. + * + * \param sender The object that sends a progress event. + * + * \param downloadTotal Total download size in bytes. + * + * \param downloadCurrent Size of currently downloaded data in bytes. + * + * \param uploadTotal Total upload size in bytes. + * + * \param uploadCurrent Size of currently uploaded data in bytes. + * + * The handler returns true to continue the ongoing operation. If it returns + * false, the operation will be aborted. + * + * \ingroup network_transfer_event_handlers + */ + typedef bool (Control::*progress_event_handler)( NetworkTransfer& sender, + fsize_type downloadTotal, fsize_type downloadCurrent, + fsize_type uploadTotal, fsize_type uploadCurrent ); + + /*! + * Sets the handler for download data available events generated by + * this %NetworkTransfer object. These events are generated when the object + * receives data from a remote location, which is ready to be processed. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive events from this object. + * + * \ingroup network_transfer_event_handlers + */ + void OnDownloadDataAvailable( download_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for upload data requested events generated by + * this %NetworkTransfer object. These events are generated when the object + * is ready to send new data to a remote location. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive events from this object. + * + * \ingroup network_transfer_event_handlers + */ + void OnUploadDataRequested( upload_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for transfer progress events generated by this + * %NetworkTransfer object. These events are generated at regular intervals + * during an active data transfer operation. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive events from this object. + * + * \ingroup network_transfer_event_handlers + */ + void OnTransferProgress( progress_event_handler handler, Control& receiver ); + +private: + + download_event_handler onDownloadDataAvailable = nullptr; + upload_event_handler onUploadDataRequested = nullptr; + progress_event_handler onTransferProgress = nullptr; + + NetworkTransfer( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class NetworkTransferEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_NetworkTransfer_h + +// ---------------------------------------------------------------------------- +// EOF pcl/NetworkTransfer.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/NumericControl.h b/3rdparty/include/pcl/NumericControl.h new file mode 100644 index 0000000..b6e2116 --- /dev/null +++ b/3rdparty/include/pcl/NumericControl.h @@ -0,0 +1,468 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/NumericControl.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_NumericControl_h +#define __PCL_NumericControl_h + +/// \file pcl/NumericControl.h + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class NumericEdit + * \brief A label/edit compound control to edit numeric parameters. + * + * ### TODO: Write a detailed description for %NumericEdit. + */ +class PCL_CLASS NumericEdit : public Control +{ +public: + + HorizontalSizer sizer; //!< The Sizer object of this %NumericEdit control + Label label; //!< The Label part of this %NumericEdit control + Edit edit; //!< The Edit part of this %NumericEdit control + + /*! + * Constructs a %NumericEdit object as a child control of \a parent. + */ + NumericEdit( Control& parent = Null() ); + + /*! + * Destroys a %NumericEdit object. + */ + virtual ~NumericEdit() + { + } + + /*! + * Returns the current value of this %NumericEdit object. + */ + double Value() const + { + return m_value; + } + + /*! + * Sets the current value of this %NumericEdit object. + */ + void SetValue( double ); + + /*! # + */ + String ValueAsString( double ) const; + + /*! # + */ + String ValueAsString() const + { + return ValueAsString( m_value ); + } + + /*! # + */ + int MinEditWidth() const; + + /*! # + */ + void AdjustEditWidth(); + + /*! # + */ + bool IsReal() const + { + return m_real; + } + + /*! # + */ + void SetReal( bool real = true ); + + /*! # + */ + void SetInteger( bool integer = true ) + { + SetReal( !integer ); + } + + /*! # + */ + double LowerBound() const + { + return m_lowerBound; + } + + /*! # + */ + double UpperBound() const + { + return m_upperBound; + } + + /*! + * Sets the range of allowed control values. + * + * \param lower Minimum allowed control value, or lower bound. + * + * \param upper Maximum allowed control value, or upper bound. + * + * If the specified lower and upper bounds are not sorted in ascending + * order, this member function will swap them automatically. + */ + virtual void SetRange( double lower, double upper ); + + /*! # + */ + int Precision() const + { + return m_precision; + } + + /*! # + */ + void SetPrecision( int n ); + + /*! + * Returns true if the precision property is being applied literally as a + * fixed number of digits after the decimal separator. Returns false if + * precision refers to the number of represented significant digits. + * + * For example, if the current value is 123.45678 and precision is 4, the + * represented value would be: + * + * With fixed precision enabled: 123.4568 \n + * With fixed precision disabled: 123.5 + * + * By default, the precision property of a %NumericEdit control refers to + * the number of represented significant digits, so fixed precision is + * disabled by default. + * + * \sa EnableFixedPrecision(), Precision() + */ + bool IsFixedPrecision() const + { + return m_fixed; + } + + /*! + * Enables the fixed precision property of this %NumericEdit object. See + * IsFixedPrecision() for detailed information. + */ + void EnableFixedPrecision( bool enable = true ); + + /*! + * Disables the fixed precision property of this %NumericEdit object. See + * IsFixedPrecision() for detailed information. + */ + void DisableFixedPrecision( bool disable = true ) + { + EnableFixedPrecision( !disable ); + } + + /*! # + */ + bool IsScientificNotation() const + { + return m_scientific; + } + + /*! # + */ + void EnableScientificNotation( bool enable = true ); + + /*! # + */ + void DisableScientificNotation( bool disable = true ) + { + EnableScientificNotation( !disable ); + } + + /*! # + */ + int ScientificNotationTriggerExponent() const + { + return m_sciTriggerExp; + } + + /*! # + */ + void SetScientificNotationTriggerExponent( int exp10 ); + + /*! # + */ + bool IsFixedSign() const + { + return m_sign; + } + + /*! # + */ + void EnableFixedSign( bool enable = true ); + + /*! # + */ + void DisableFixedSign( bool disable = true ) + { + EnableFixedSign( !disable ); + } + + /*! # + */ + bool IsAutoAdjustEditWidth() const + { + return m_autoEditWidth; + } + + /*! # + */ + void EnableAutoAdjustEditWidth( bool enable = true ) + { + if ( (m_autoEditWidth = enable) != false ) + AdjustEditWidth(); + } + + /*! # + */ + void DisableAutoAdjustEditWidth( bool disable = true ) + { + EnableAutoAdjustEditWidth( !disable ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnValueUpdated( NumericControl& sender, double value ); + + /*! # + */ + typedef void (Control::*value_event_handler)( NumericEdit& sender, double value ); + + /*! # + */ + void OnValueUpdated( value_event_handler, Control& ); + +protected: + + struct EventHandlers + { + value_event_handler onValueUpdated = nullptr; + Control* onValueUpdatedReceiver = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + double m_value = 0; // current value + double m_lowerBound = 0; // acceptable range, lower bound + double m_upperBound = 1; // acceptable range, upper bound + int m_precision = 6; // number of decimal digits in non-sci mode, [0,16] + bool m_real = true; // whether this is a real or integer parameter + bool m_fixed = false; // precision is literal instead of significant digits? + bool m_scientific = false; // scientific notation enabled? + bool m_sign = false; // always show a sign character + bool m_autoEditWidth = true; // set width of edit control automatically + int m_sciTriggerExp = -1; // exponent (of ten) to trigger sci notation + + PCL_MEMBER_REENTRANCY_GUARD( EditCompleted ) + + virtual void UpdateControls(); + + virtual void EditCompleted( Edit& ); + virtual void KeyPressed( Control&, int, unsigned, bool& ); + virtual void ReturnPressed( Edit& ); + virtual void GetFocus( Control& ); + virtual void LoseFocus( Control& ); + virtual void MousePress( Control&, const pcl::Point&, int, unsigned, unsigned ); + + int PrecisionForValue( double ) const; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class NumericControl + * \brief A label/edit/slider compound control to edit numeric parameters + * + * ### TODO: Write a detailed description for %NumericControl. + */ +class PCL_CLASS NumericControl : public NumericEdit +{ +public: + + HorizontalSlider slider; //!< The Slider part of this %NumericEdit control + + /*! + * Constructs a %NumericControl object as a child control of \a parent. + */ + NumericControl( Control& parent = Null() ); + + /*! + * Destroys a %NumericControl object. + */ + virtual ~NumericControl() + { + } + + /*! + * Sets the range of allowed control values. + * + * \param lower Minimum allowed control value, or lower bound. + * + * \param upper Maximum allowed control value, or upper bound. + * + * If the specified lower and upper bounds are not sorted in ascending + * order, this member function will swap them automatically. + * + * If the resulting lower bound is negative, the exponential slider response + * feature will be implicitly disabled. + */ + void SetRange( double lower, double upper ) override; + + /*! + * Returns true if the slider component of this %NumericControl has + * exponential response. Returns false if the slider has the default linear + * response. + * + * When exponential response is enabled, the slider defines control values + * following an exponential growth function of the form: + * + * y = (1 + y0)*Exp( k*x ) - 1 + * + * where y is the current control value, y0 is the minimum allowed control + * value (as returned by LowerBound()), x is the current slider position + * normalized to the [0,1] range, and k is an automatically calculated + * exponential growth factor given by: + * + * k = Ln( (1 + y1)/(1 + y0) ) + * + * where y1 is the maximum allowed control value, as returned by + * UpperBound(). + * + * Exponential slider response is useful for %NumericControl objects used to + * define parameters with very large numeric ranges, such as [0,500] or + * [0,1000] for example. For such large ranges, one normally wants to + * provide finer control for low parameter values, which is impossible with + * a linear slider response. The exponential slider response feature is + * disabled by default, that is, sliders have linear response by default. + * + * The exponential slider response feature is only available for controls + * where the minimum allowed value (given by LowerBound()) is greater than + * or equal to zero. + * + * \sa EnableExponentialResponse(), DisableExponentialResponse() + */ + bool IsExponentialResponse() const + { + return m_exponential; + } + + /*! + * Enables the exponential slider response feature. See + * IsExponentialResponse() for detailed information. + * + * If the minimum allowed control value is negative, this member function + * throws an Error exception: The exponential slider response feature can + * only be enabled when LowerBound() ≥ 0. + * + * \sa IsExponentialResponse(), DisableExponentialResponse() + */ + void EnableExponentialResponse( bool enable = true ); + + /*! + * Disables the exponential slider response feature. See + * IsExponentialResponse() for detailed information. + * + * \sa IsExponentialResponse(), EnableExponentialResponse() + */ + void DisableExponentialResponse( bool disable = true ) + { + EnableExponentialResponse( !disable ); + } + +protected: + + void UpdateControls() override; + + virtual void ValueUpdated( Slider&, int ); + void KeyPressed( Control&, int, unsigned, bool& ) override; + void GetFocus( Control& ) override; + +private: + + bool m_exponential = false; + + double SliderValueToControl( int ) const; + int ControlValueToSlider( double ) const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_NumericControl_h + +// ---------------------------------------------------------------------------- +// EOF pcl/NumericControl.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/OnlineObjectSearchDialog.h b/3rdparty/include/pcl/OnlineObjectSearchDialog.h new file mode 100644 index 0000000..0ada84a --- /dev/null +++ b/3rdparty/include/pcl/OnlineObjectSearchDialog.h @@ -0,0 +1,300 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/OnlineObjectSearchDialog.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_OnlineObjectSearchDialog_h +#define __PCL_OnlineObjectSearchDialog_h + +/// \file pcl/OnlineObjectSearchDialog.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS NetworkTransfer; + +// ---------------------------------------------------------------------------- + +/*! + * \class OnlineObjectSearchDialog + * \brief A dialog box to search for object data on online astronomical + * database services. + * + * %OnlineObjectSearchDialog allows the user to enter the name or identifier of + * an object to search for, such as 'M31', 'Pleiades', 'NGC 253', + * 'Orion Nebula', 'Antares', or 'alpha Lyr'. The dialog sends an ADQL query to + * a public SIMBAD database service to retrieve several object properties, + * including ICRS equatorial coordinates, proper motions and visual magnitude, + * among others. + * + * This class is a useful component for processes requiring a flexible and fast + * way to retrieve data for user-selected objects. Currently two public SIMBAD + * database services can be used: the master SIMBAD service in France (Centre + * de Données Astronomiques de Strasbourg) and its mirror site in the + * USA (Harvard-Smithsonian Center for Astrophysics). + * + * \b References + * + * SIMBAD Astronomical Database - CDS Strasbourg:\n + * http://simbad.u-strasbg.fr/simbad/ + * + * SIMBAD mirror site in the USA - CFA Harvard:\n + * http://simbad.cfa.harvard.edu/ + * + * SIMBAD TAP Service:\n + * http://simbad.u-strasbg.fr/simbad/sim-tap + * + * ADQL Cheat sheet:\n + * http://simbad.u-strasbg.fr/simbad/tap/help/adqlHelp.html + */ +class PCL_CLASS OnlineObjectSearchDialog : public Dialog +{ +public: + + /*! + * Default constructor. + */ + OnlineObjectSearchDialog(); + + /*! + * Returns the name of the object that has been found, or an empty string if + * no object has been found or searched for. + */ + const String& ObjectName() const + { + return m_objectName; + } + + /*! + * Returns a code representing the type of the object, or an empty string if + * no object has been found or searched for. + * + * Object type codes are abbreviations standardized on the SIMBAD database, + * such as 'GlC' (globular cluster), 'G' (galaxy), or '*' (star). + */ + const String& ObjectType() const + { + return m_objectType; + } + + /*! + * Returns a string representing the spectral type, or an empty string if no + * object has been found or searched for, or if the spectral type is not + * available for the specified object. + */ + const String& SpectralType() const + { + return m_spectralType; + } + + /*! + * Returns the V (visual) magnitude of the object, or zero if no object has + * been found or searched for, or if the V magnitude is not available for + * the specified object. + */ + double VMagnitude() const + { + return m_vmag; + } + + /*! + * Returns the ICRS right ascension coordinate in degrees, or zero if no + * object has been found or searched for. + */ + double RA() const + { + return m_RA; + } + + /*! + * Returns the ICRS declination coordinate in degrees, or zero if no object + * has been found or searched for. + */ + double Dec() const + { + return m_Dec; + } + + /*! + * Returns the proper motion in right ascension in mas/year, or zero if no + * object has been found or searched for, or if proper motions are not + * available for the specified object. + */ + double MuRA() const + { + return m_muRA; + } + + /*! + * Returns the proper motion in declination in mas/year, or zero if no + * object has been found or searched for, or if proper motions are not + * available for the specified object. + */ + double MuDec() const + { + return m_muDec; + } + + /*! + * Returns the parallax in mas, or zero if no object has been found or + * searched for, or if the parallax is not available for the specified + * object. + */ + double Parallax() const + { + return m_parallax; + } + + /*! + * Returns the radial velocity in km/s, or zero if no object has been found + * or searched for, or if the radial velocity is not available for the + * specified object. + */ + double RadialVelocity() const + { + return m_radVel; + } + + /*! + * Returns true iff an object has been specified and valid data have been + * found. In such case valid right ascension and declination coordinates are + * always available. Other data items (proper motions, etc) are optional, + * depending on the type of the object that has been searched for. + */ + bool IsValid() const + { + return m_valid; + } + + /*! + * Returns the user-defined text that has been searched for during the + * latest dialog execution. Typically this is either an empty string or the + * name or identifier of an astronomical object, such as 'M31', 'Pleiades', + * 'NGC 253', 'Orion Nebula', 'Antares', or 'alpha Lyr'. + */ + String SearchText() const + { + return ObjectName_Edit.Text(); + } + + /*! + * Returns the URL of the online database service provider that is currently + * selected on this dialog. + * + * The database server URL selected by the user on these dialogs is a global + * item stored in core application settings. It is restored by each instance + * of this class upon creation. + */ + String ServerURL() const; + +protected: + + VerticalSizer Global_Sizer; + HorizontalSizer Search_Sizer; + Label ObjectName_Label; + Edit ObjectName_Edit; + PushButton Search_Button; + HorizontalSizer Server_Sizer; + Label Server_Label; + ComboBox Server_ComboBox; + TextBox SearchInfo_TextBox; + HorizontalSizer Buttons_Sizer; + PushButton Get_Button; + PushButton Cancel_Button; + + String m_objectName; + String m_objectType; + String m_spectralType; + double m_vmag = 0; // V magnitude + double m_RA = 0; // degrees + double m_Dec = 0; // degrees + double m_muRA = 0; // mas/year + double m_muDec = 0; // mas/year + double m_parallax = 0; // mas + double m_radVel = 0; // km/s + bool m_valid = false; + bool m_downloading = false; + bool m_abort = false; + IsoString m_downloadData; + + void e_Show( Control& sender ); + void e_GetFocus( Control& sender ); + void e_LoseFocus( Control& sender ); + bool e_Download( NetworkTransfer& sender, const void* buffer, fsize_type size ); + bool e_Progress( NetworkTransfer& sender, + fsize_type downloadTotal, fsize_type downloadCurrent, + fsize_type uploadTotal, fsize_type uploadCurrent ); + void e_Click( Button& sender, bool checked ); + void e_ItemSelected( ComboBox& sender, int itemIndex ); + + void LoadSettings(); + void SaveSettings() const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_OnlineObjectSearchDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/OnlineObjectSearchDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Optional.h b/3rdparty/include/pcl/Optional.h new file mode 100644 index 0000000..0877267 --- /dev/null +++ b/3rdparty/include/pcl/Optional.h @@ -0,0 +1,283 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Optional.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_Optional_h +#define __PCL_Optional_h + +/// \file pcl/Optional.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Optional + * \brief An object that can be in a defined or undefined state + * + * %Optional stores an instance of the template argument T along with a + * defined state Boolean flag. %Optional objects update their defined + * state automatically as they are created, copied and assigned. + * + * This class is useful to deal with objects that can be defined optionally, + * when it is inconvenient to manage the object's value and its defined state + * as two separate items. %Optional offers the power of encapsulation in + * object-oriented languages to solve these problems efficiently. + */ +template +class PCL_CLASS Optional +{ +public: + + /*! + * Constructs an undefined %Optional object. + * + * The value instance will be default-constructed implicitly, which means + * that the type T must provide valid default construction semantics. + */ + Optional() + : m_value() // N.B: this initialization prevents warnings such as + { // 'Optional<>::m_value may be used uninitialized...' + } + + /*! + * Copy constructor. + * + * The value instance will be copy-constructed implicitly, which means that + * the type T must provide valid copy construction semantics if this + * constructor is invoked. + */ + Optional( const Optional& ) = default; + + /* + * Move constructor. + */ + Optional( Optional&& ) = default; + + /*! + * Constructs a defined %Optional object with the specified \a value. + */ + Optional( const T& value ) + : m_value( value ) + , m_defined( true ) + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Optional& operator =( const Optional& x ) + { + if ( bool( m_defined = x.m_defined ) ) + m_value = x.m_value; + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Optional& operator =( Optional&& x ) + { + if ( bool( m_defined = x.m_defined ) ) + m_value = std::move( x.m_value ); + return *this; + } + + /*! + * Assigns the specified \a value to this object. Returns a reference to + * this object. After assigning a value, an %Optional object will be in + * defined state. + */ + Optional& operator =( const T& value ) + { + m_value = value; + m_defined = true; + return *this; + } + + /*! + * Type conversion operator. Returns a reference to the value stored in this + * %Optional object. + * + * If this object is undefined, the returned value may be unpredictable, + * depending on construction semantics for the type T. + */ + operator const T&() const + { + return m_value; + } + + /*! + * Returns a reference to the value stored in this %Optional object. + * + * If this object is undefined, the returned value may be unpredictable, + * depending on construction semantics for the type T. + * + * This function performs the same role as operator const T&(). It is + * required for cases where an automatic type conversion is not applicable. + */ + const T& operator ()() const + { + return m_value; + } + + /*! + * Returns true if this %Optional object has been defined. + */ + bool IsDefined() const + { + return m_defined; + } + + /*! + * Undefines this %Optional object. Assigns a default-constructed object of + * type T to the value of this object, and sets the internal defined flag to + * false. + */ + void Undefine() + { + m_value = T(); + m_defined = false; + } + + /*! + * Returns the value stored in this object if it has been defined. Otherwise + * returns the specified \a value. + */ + const T& OrElse( const T& value ) const + { + return m_defined ? m_value : value; + } + + /*! + * Returns the value stored in this object if it has been defined. Otherwise + * throws the specified \a exception. + */ + template + const T& OrElseThrow( const Exception& exception ) const + { + if ( m_defined ) + return m_value; + throw exception; + } + + /*! + * Returns the value stored in this object if it has been defined. Otherwise + * throws an Error exception with the specified \a message. + */ + const T& OrElseThrow( const String& message ) const + { + if ( m_defined ) + return m_value; + throw Error( message ); + } + + /*! + * Equality operator. Returns true iff one of the following condition holds: + * + * \li This object has been defined, \a x has been defined, and the value in + * this object equals the value in \a x. + * + * \li Neither this object nor \a x have been defined. + */ + bool operator ==( const Optional& x ) const + { + return m_defined ? (x.m_defined ? m_value == x.m_value : false) : !x.m_defined; + } + + /*! + * Value equality operator. Returns true iff this object has been defined + * and its value equals the specified \a value. + */ + bool operator ==( const T& value ) const + { + return m_defined && m_value == value; + } + + /*! + * Less than relational operator. Returns true iff this object has been + * defined and either \a x has not been defined (defined objects always + * precede undefined ones), or the value in this object precedes the value + * in \a x. + */ + bool operator <( const Optional& x ) const + { + return m_defined && (!x.m_defined || m_value < x.m_value); + } + + /*! + * Less-than-value relational operator. Returns true iff this object has + * been defined and its value precedes the specified \a value. + */ + bool operator <( const T& value ) const + { + return m_defined && m_value < value; + } + +private: + + T m_value; + bool m_defined = false; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Optional_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Optional.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/OrthographicProjection.h b/3rdparty/include/pcl/OrthographicProjection.h new file mode 100644 index 0000000..6623f0f --- /dev/null +++ b/3rdparty/include/pcl/OrthographicProjection.h @@ -0,0 +1,144 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/OrthographicProjection.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_OrthographicProjection_h +#define __PCL_OrthographicProjection_h + +/// \file pcl/OrthographicProjection.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class OrthographicProjection + * \brief Orthographic projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS OrthographicProjection : public ProjectionBase +{ +public: + + /*! + * Default constructor. + */ + OrthographicProjection() + { + m_theta0 = 90; + } + + /*! + * Copy constructor. + */ + OrthographicProjection( const OrthographicProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new OrthographicProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "SIN"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Orthographic"; + } + + /*! + * + */ + bool CheckBrokenLine( const DPoint& cp1, const DPoint& cp2 ) const noexcept override + { + return DistanceFast( m_sph.CelestialToNative( cp1 ), m_sph.CelestialToNative( cp2 ) ) < 150; + } + +protected: + + bool Project( DPoint& pW, const DPoint& pN ) const noexcept override; + bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept override; + +private: + + double m_r0 = Const::deg(); + double m_x0 = 0; + double m_y0 = 0; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_OrthographicProjection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/OrthographicProjection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PSFEstimator.h b/3rdparty/include/pcl/PSFEstimator.h new file mode 100644 index 0000000..a97865d --- /dev/null +++ b/3rdparty/include/pcl/PSFEstimator.h @@ -0,0 +1,392 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PSFEstimator.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_PSFEstimator_h +#define __PCL_PSFEstimator_h + +/// \file pcl/PSFEstimator.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PSFEstimator + * \brief Base class of estimators based on PSF photometry + * \sa PSFSignalEstimator, PSFScaleEstimator, StarDetector, PSFFit + */ +class PCL_CLASS PSFEstimator : public ParallelProcess +{ +public: + + /*! + * Represents a point spread function type. + */ + typedef StarDetector::psf_function psf_function; + + /*! + * Default constructor. + */ + PSFEstimator() = default; + + /*! + * Copy constructor. + */ + PSFEstimator( const PSFEstimator& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~PSFEstimator() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PSFEstimator& operator =( const PSFEstimator& ) = default; + + /*! + * Returns a reference to the (immutable) internal star detector used by + * this PSF estimator. + * + * PSF fitting will always be performed as a separate step after star + * detection, so the PSF fitting parameters of the returned object are + * meaningless for the estimation tasks implemented by derived classes. + */ + const StarDetector& Detector() const + { + return const_cast( m_starDetector ); + } + + /*! + * Returns a reference to the (mutable) internal star detector used by this + * PSF estimator. + * + * PSF fitting will always be performed as a separate step after star + * detection, so changing the PSF fitting parameters of the returned object + * will have no effect on the estimation tasks implemented by derived + * classes. + */ + StarDetector& Detector() + { + return m_starDetector; + } + + /*! + * Returns the type of point spread function (PSF) used by this estimator. + * Elliptical PSFs are always used for PSF-based evaluation. + * + * This implementation supports the special PSFunction::Auto PSF type. When + * this type is selected, a series of different PSFs will be fitted for each + * source, and the fit that leads to the least absolute difference among + * function values and sampled pixel values will be used for estimation. + * Currently the following functions are tested in this special mode: + * Gaussian, Lorentzian, and Moffat functions with beta shape parameters of + * 1.5, 4 and 10. + * + * The default PSF type is PSFunction::Moffat4. + */ + psf_function PSFType() const + { + return m_psfType; + } + + /*! + * Sets the type of point spread function used by this estimator. See + * PSFType() for more information. + */ + void SetPSFType( psf_function type ) + { + m_psfType = type; + } + + /*! + * Returns the centroid tolerance in pixels. + * + * The centroid tolerance is the maximum allowed distance in pixels between + * a detected star position (or \e barycenter) and the centroid position of + * the corresponding fitted PSF. Stars where that distance is greater than + * the value returned by this function will be rejected and excluded for + * estimation. This allows preventing PSF fits departing too much from + * detected star coordinates, which enforces robustness and stability of the + * PSF fitting process. + * + * The default centroid tolerance is 1.5 pixels. + */ + float PSFCentroidTolerance() const + { + return m_psfCentroidTolerance; + } + + /*! + * Sets the centroid tolerance in pixels. See PSFCentroidTolerance() for a + * description of this parameter. + */ + void SetPSFCentroidTolerance( float t ) + { + PCL_PRECONDITION( t >= 0 ) + m_psfCentroidTolerance = Max( 0.0F, t ); + } + + /*! + * Returns the saturation threshold for PSF flux measurements. + * + * Detected stars with one or more pixels with values above this threshold + * will be excluded to perform the PSF estimation task. + * + * The returned value is expressed in the [0,1] range. It can applied either + * as an absolute pixel sample value in the normalized [0,1] range, or as a + * value relative to the maximum pixel sample value of the measured image. + * See IsRelativeSaturationEnabled() for more information. + * + * The default saturation threshold is 0.75. + */ + float SaturationThreshold() const + { + return m_saturationThreshold; + } + + /*! + * Sets the saturation threshold in the [0,1] range. The minimum acceptable + * value \a t is 0.1. See SaturationThreshold() for a description of this + * parameter. + */ + void SetSaturationThreshold( float t ) + { + PCL_PRECONDITION( t >= 0.1 && t <= 1.0 ) + m_saturationThreshold = Range( t, 0.1F, 1.0F ); + } + + /*! + * The saturation threshold parameter can be applied either as an absolute + * pixel sample value in the normalized [0,1] range, or as a value relative + * to the maximum pixel sample value of the measured image. + * + * The relative saturation threshold option is enabled by default. + */ + bool IsRelativeSaturationEnabled() const + { + return m_saturationRelative; + } + + /*! + * Enables the relative saturation threshold option. See + * SaturationThreshold() and IsRelativeSaturationEnabled() for complete + * information on these parameters. + */ + void EnableRelativeSaturation( bool enable = true ) + { + m_saturationRelative = enable; + } + + /*! + * Disables the relative saturation threshold option. See + * SaturationThreshold() and IsRelativeSaturationEnabled() for complete + * information on these parameters. + */ + void DisableRelativeSaturation( bool disable = true ) + { + EnableRelativeSaturation( !disable ); + } + + /*! + * Returns the rejection limit parameter of this estimator. + * + * The rejection limit parameter defines an order statistic, in the [0.5,1] + * range, used to exclude a fraction of the brightest PSF signal samples + * during the estimation process. + * + * The brightest signal samples usually tend to be unreliable because of + * relative saturation and nonlinearity. However, reliability of PSF flux + * measurements is normally ensured by robust star detection, where the + * source detection algorithm excludes too dim stars, and the saturation + * threshold parameter should impose a reliable upper limit in most + * practical cases. So this parameter should not be necessary under normal + * working conditions. + * + * The default value of this parameter is 1.0, meaning that the sample of + * PSF flux measurements is not clipped by default. + */ + float RejectionLimit() const + { + return m_rejectionLimit; + } + + /*! + * Sets a new value of the rejection limit parameter in the [0.5,1] range. + * See RejectionLimit() for a complete description of this parameter. + */ + void SetRejectionLimit( float r ) + { + PCL_PRECONDITION( r >= 0.5 && r <= 1 ) + m_rejectionLimit = Range( r, 0.5F, 1.0F ); + } + + /*! + * Returns the growing factor for expansion/contraction of the PSF flux + * measurement region, in units of the Full Width at Tenth Maximum (FWTM), + * assuming a normalized PSF of unit height. + * + * The default value of this parameter is 1.0, meaning that flux is measured + * exclusively for pixels within the elliptical region defined at one tenth + * of the fitted PSF maximum. + */ + float GrowthFactorForFluxMeasurement() const + { + return m_growthForFlux; + } + + /*! + * Sets a new value of the growing factor for the PSF flux measurement + * region. See GrowthFactorForFluxMeasurement() for a description of this + * parameter. The valid range for the specified factor \a k is [0.5,2.0]. + */ + void SetGrowthFactorForFluxMeasurement( float k ) + { + PCL_PRECONDITION( k >= 0.5 && k <= 2.0 ) + m_growthForFlux = Range( k, 0.5F, 2.0F ); + } + + /*! + * Returns the maximum number of stars that will be measured. Returns zero + * if no limit has been set on the maximum number of PSF measurements. + * + * When a limit \a n greater than zero is specified, PSF-based estimation + * will be performed for no more than the \a n brightest stars detected in + * the target image. + * + * The default value is zero, meaning that no specific limit is set. + */ + int MaxStars() const + { + return m_maxStars; + } + + /*! + * Sets the maximum number of stars that will be measured. See MaxStars() + * for more information on this parameter. + * + * When a limit \a n greater than zero is specified, PSF-based estimation + * will be performed for no more than the \a n brightest stars detected in + * the target image. When a value ≤ 0 is specified, no specific limit + * will be set on the number of measured stars. + */ + void SetMaxStars( int n ) + { + PCL_PRECONDITION( n >= 0 ) + m_maxStars = Max( 0, n ); + } + + /*! + * Returns true iff PSF weighting is enabled. When PSF weighting is enabled, + * each photometric PSF sample is multiplied by the inverse of the mean + * absolute deviation of the fitted PSF measured with respect to sampled + * image data. + * + * PSF weighting is disabled by default. + */ + bool IsPSFWeightingEnabled() const + { + return m_weighted; + } + + /*! + * Enables PSF weighting for this signal estimator. See + * IsPSFWeightingEnabled() for more information. + */ + void EnablePSFWeighting( bool enable = true ) + { + m_weighted = enable; + } + + /*! + * Disables PSF weighting for this signal estimator. See + * IsPSFWeightingEnabled() for more information. + */ + void DisablePSFWeighting( bool disable = true ) + { + EnablePSFWeighting( !disable ); + } + +protected: + + mutable pcl::StarDetector m_starDetector; + psf_function m_psfType = PSFunction::Moffat4; + float m_psfCentroidTolerance = 1.5F; + float m_saturationThreshold = 0.75F; + bool m_saturationRelative = true; + float m_rejectionLimit = 1.0F; + float m_growthForFlux = 1.0F; + int m_maxStars = 0; + bool m_weighted = false; + + /*! + * \internal + * Thread-safe PSF fitting routine. + */ + Array FitStars( const ImageVariant& ) const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PSFEstimator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PSFEstimator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PSFFit.h b/3rdparty/include/pcl/PSFFit.h new file mode 100644 index 0000000..08daca2 --- /dev/null +++ b/3rdparty/include/pcl/PSFFit.h @@ -0,0 +1,611 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PSFFit.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_PSFFit_h +#define __PCL_PSFFit_h + +/// \file pcl/PSFFit.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::PSFunction + * \brief Point spread function types. + * + * + * + * + * + * + * + * + * + * + * + * + * + *
PSFunction::Invalid Represents an invalid or unsupported PSF type.
PSFunction::Gaussian Gaussian PSF.
PSFunction::Moffat Moffat PSF with a fitted beta parameter.
PSFunction::MoffatA Moffat PSF with fixed beta=10 parameter.
PSFunction::Moffat8 Moffat PSF with fixed beta=8 parameter.
PSFunction::Moffat6 Moffat PSF with fixed beta=6 parameter.
PSFunction::Moffat4 Moffat PSF with fixed beta=4 parameter.
PSFunction::Moffat25 Moffat PSF with fixed beta=2.5 parameter.
PSFunction::Moffat15 Moffat PSF with fixed beta=1.5 parameter.
PSFunction::Lorentzian Lorentzian PSF, equivalent to a Moffat PSF with fixed beta=1 parameter.
PSFunction::VariableShape Variable shape PSF
+ */ +namespace PSFunction +{ + enum value_type + { + Invalid = -1, // Represents an invalid or unsupported PSF type + Gaussian = 0, // Gaussian PSF + Moffat, // Moffat PSF with a fitted beta parameter + MoffatA, // Moffat PSF with fixed beta=10 + Moffat8, // Moffat PSF with fixed beta=8 + Moffat6, // Moffat PSF with fixed beta=6 + Moffat4, // Moffat PSF with fixed beta=4 + Moffat25, // Moffat PSF with fixed beta=2.5 + Moffat15, // Moffat PSF with fixed beta=1.5 + Lorentzian, // Lorentzian PSF, equivalent to a Moffat PSF with fixed beta=1 + VariableShape, // Variable shape PSF + NumberOfFunctions, + Auto = 999, // Automatic selection for optimization, process-dependent. + Default = Gaussian + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::PSFFitStatus + * \brief PSF fit process results. + * + * + * + * + * + * + * + * + * + * + *
PSFFitStatus::Invalid Represents an invalid or unsupported PSF fit status
PSFFitStatus::NotFitted The PSF has not been fitted because the process has not been executed.
PSFFitStatus::FittedOk PSF fitted correctly. The relative error of the solution is at most equal to the specified tolerance.
PSFFitStatus::BadParameters The PSF fitting process failed because of improper input parameters.
PSFFitStatus::NoSolution There is no solution with the specified parameters and source data.
PSFFitStatus::NoConvergence The Levenberg-Marquardt algorithm did not find a valid solution after a prescribed maximum number of iterations.
PSFFitStatus::InaccurateSolution A PSF has been fitted, but the Levenberg-Marquardt algorithm couldn't find a valid solution to the specified tolerance.
PSFFitStatus::UnknownError The PSF fitting process failed for an unspecified reason.
+ */ +namespace PSFFitStatus +{ + enum value_type + { + Invalid = -1, + NotFitted = 0, + FittedOk, + BadParameters, + NoSolution, + NoConvergence, + InaccurateSolution, + UnknownError + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class PSFData + * \brief PSF fit parameters. + */ +struct PSFData +{ + /*! + * Represents a point spread function type. + */ + typedef PSFunction::value_type psf_function; + + /*! + * Represents a PSF fitting process status. + */ + typedef PSFFitStatus::value_type psf_fit_status; + + /*! + * Represents a component of a centroid position vector (required for + * QuadTree compatibility). + */ + typedef DPoint::component component; + + psf_function function = PSFunction::Invalid; //!< Point spread function type (PSFunction namespace). + bool circular = false; //!< Circular or elliptical PSF. + psf_fit_status status = PSFFitStatus::NotFitted; //!< Status code (PSFFitStatus namespace). + bool celestial = false; //!< True iff equatorial coordinates are available. + double B = 0; //!< Local background estimate in pixel value units. + double A = 0; //!< Function amplitude (or estimated maximum) in pixel value units. + DPoint b0 = 0.0; //!< Barycenter position (initial star detection position) in image coordinates. + DPoint c0 = 0.0; //!< Fitted centroid position in image coordinates. + DPoint q0 = 0.0; //!< Centroid equatorial coordinates, when celestial=true. + double sx = 0; //!< Function width in pixels on the X axis, sx >= sy. + double sy = 0; //!< Function width in pixels on the Y axis, sx >= sy. + double theta = 0; //!< Rotation angle of the sx axis in degrees, in the [0,180) range. + double beta = 0; //!< Moffat beta or shape parameter (dimensionless). + double flux = 0; //!< Total flux above the local background, measured over the rectangular fitting region. + double signal = 0; //!< Total flux above the local background, measured over the elliptical PSF region. + unsigned signalCount = 0; //!< Number of pixels used for signal evaluation. + double mad = 0; /*!< Goodness of fit estimate. A robust, mean absolute difference between the + fitted PSF and the sample of source image pixels over the fitting region, scaled + by the total signal estimate. */ + /*! + * Default constructor. + */ + PSFData() = default; + + /*! + * Copy constructor. + */ + PSFData( const PSFData& ) = default; + + /*! + * Move constructor. + */ + PSFData( PSFData&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PSFData& operator =( const PSFData& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PSFData& operator =( PSFData&& ) = default; + + /*! + * Returns true iff this object contained valid PSF fitting parameters. This + * happens (or \e should happen, under normal conditions) when the status + * data member is equal to PSFFitStatus::FittedOk. + */ + operator bool() const + { + return status == PSFFitStatus::FittedOk; + } + + /*! + * Conversion to double operator. Returns the PSF signal estimate if + * nonzero, or the total flux otherwise. Useful for sorting and statistics + * calculations. + */ + operator double() const + { + return (signal != 0) ? signal : flux; + } + + /*! + * Returns a centroid coordinate. Returns the X centroid coordinate if the + * specified index \a i is zero, or the Y coordinate otherwise. + * + * \note This operator provides compatibility with the QuadTree class. + */ + double operator []( int i ) const noexcept + { + return (i == 0) ? c0.x : c0.y; + } + + /*! + * Returns the name of the fitted PSF function. See the PSFunction namespace + * for supported functions. + */ + String FunctionName() const; + + /*! + * Returns a string with a brief description of the current fitting status. + */ + String StatusText() const; + + /*! + * Returns the full width at half maximum (FWHM) on the X axis in pixels. + * + * For an elliptic PSF, the X axis corresponds to the orientation of the + * major function axis as projected on the image. + * + * For a circular PSF, FWHMx() and FWHMy() are equivalent. + */ + double FWHMx() const + { + return FWHM( function, sx, beta ); + } + + /*! + * Returns the full width at half maximum (FWHM) on the Y axis in pixels. + * + * For an elliptic PSF, the Y axis corresponds to the orientation of the + * minor function axis as projected on the image. + * + * For a circular PSF, FWHMx() and FWHMy() are equivalent. + */ + double FWHMy() const + { + return FWHM( function, sy, beta ); + } + + /*! + * Returns the full width at tenth maximum (FWTM) on the X axis in pixels. + * + * For an elliptic PSF, the X axis corresponds to the orientation of the + * major function axis as projected on the image. + * + * For a circular PSF, FWTMx() and FWTMy() are equivalent. + */ + double FWTMx() const + { + return FWTM( function, sx, beta ); + } + + /*! + * Returns the full width at tenth maximum (FWTM) on the Y axis in pixels. + * + * For an elliptic PSF, the Y axis corresponds to the orientation of the + * minor function axis as projected on the image. + * + * For a circular PSF, FWTMx() and FWTMy() are equivalent. + */ + double FWTMy() const + { + return FWTM( function, sy, beta ); + } + + /*! + * Returns the double integral of the PSF, or the estimated volume over the + * XY plane for z > B. + */ + double Volume() const + { + return A*Volume( function, sx, sy, beta ); + } + + /*! + * Returns the PSF bounding rectangle. The coordinates of the bounding + * rectangle \a r are calculated as follows: + * + * r.x0 = c0.x - d \n + * r.y0 = c0.y - d \n + * r.x1 = c0.x + d \n + * r.y1 = c0.y + d \n + * + * where d is equal to: + * + * FWHMx()/2 for a circular PSF, \n + * Max( FWHMx(), FWHMy() )/2 for an elliptic PSF. + */ + DRect Bounds() const + { + double d = (circular ? FWHMx() : Max( FWHMx(), FWHMy() ))/2; + return DRect( c0.x-d, c0.y-d, c0.x+d, c0.y+d ); + } + + /*! + * Returns true iff this object contains valid equatorial coordinates + * computed by an astrometric solution of the image for the centroid + * coordinates. + */ + bool HasCelestialCoordinates() const + { + return celestial; + } + + /*! + * Returns an image representation (in 32-bit floating point format) of the + * fitted point spread function. + */ + void ToImage( Image& ) const; + + /*! + * Returns the full width at half maximum (FWHM) corresponding to a + * supported function with the specified parameters. + * + * \param function The type of point spread function. See the PSFunction + * namespace for supported functions. + * + * \param sigma Estimated function width. + * + * \param beta Moffat beta or VariableShape shape parameter. + * Must be > 0. + * + * The returned value is the FWHM in sigma units, or zero if an invalid or + * unsupported function type has been specified. + */ + static double FWHM( psf_function function, double sigma, double beta = 2 ) + { + PCL_PRECONDITION( beta > 0 ) + switch ( function ) + { + case PSFunction::Gaussian: return 2.3548200450309493 * sigma; + case PSFunction::Moffat: return 2 * sigma * Sqrt( Pow2( 1/beta ) - 1 ); + case PSFunction::MoffatA: return 0.5358113941912513 * sigma; + case PSFunction::Moffat8: return 0.6016900619596693 * sigma; + case PSFunction::Moffat6: return 0.6998915581984769 * sigma; + case PSFunction::Moffat4: return 0.8699588840921645 * sigma; + case PSFunction::Moffat25: return 1.1305006161394060 * sigma; + case PSFunction::Moffat15: return 1.5328418730817597 * sigma; + case PSFunction::Lorentzian: return 2 * sigma; + case PSFunction::VariableShape: return 2 * sigma * Pow( beta*0.6931471805599453, 1/beta ); + default: return 0; // ?! + } + } + + /*! + * Returns the full width at tenth maximum (FWTM) corresponding to a + * supported function with the specified parameters. + * + * \param function The type of point spread function. See the PSFunction + * namespace for supported functions. + * + * \param sigma Estimated function width. + * + * \param beta Moffat beta or VariableShape shape parameter. + * Must be > 0. + * + * The returned value is the FWTM in sigma units, or zero if an invalid or + * unsupported function type has been specified. + */ + static double FWTM( psf_function function, double sigma, double beta = 2 ) + { + PCL_PRECONDITION( beta > 0 ) + switch ( function ) + { + case PSFunction::Gaussian: return 4.291932052578694 * sigma; + case PSFunction::Moffat: return 2 * sigma * Sqrt( Pow( 10.0, 1/beta ) - 1 ); + case PSFunction::MoffatA: return 1.017694279819175 * sigma; + case PSFunction::Moffat8: return 1.155026289161115 * sigma; + case PSFunction::Moffat6: return 1.367917055412454 * sigma; + case PSFunction::Moffat4: return 1.764402913213331 * sigma; + case PSFunction::Moffat25: return 2.459175822514185 * sigma; + case PSFunction::Moffat15: return 3.816589489904712 * sigma; + case PSFunction::Lorentzian: return 6 * sigma; + case PSFunction::VariableShape: return 2 * sigma * Pow( beta*2.302585092994045, 1/beta ); + default: return 0; // ?! + } + } + + /*! + * Returns the double integral of a supported elliptical function with the + * specified parameters. + * + * \param function The type of point spread function. See the PSFunction + * namespace for supported functions. + * + * \param sigma_x Estimated function width on the X axis. + * + * \param sigma_y Estimated function width on the Y axis. + * + * \param beta Moffat beta or VariableShape shape parameter. + * Must be > 0. Must be > 1 for Moffat and Lorentzian + * functions. + * + * The returned value is the volume of the PSF over the XY plane, or zero if + * an invalid or unsupported function type has been specified, or if the + * \a beta parameter is invalid for the type of PSF specified. + */ + static double Volume( psf_function function, double sigma_x, double sigma_y, double beta = 2 ) + { + PCL_PRECONDITION( beta > 0 ) + PCL_PRECONDITION( function != PSFunction::Lorentzian && (function != PSFunction::Moffat || beta > 1) ) + switch ( function ) + { + case PSFunction::Gaussian: return 6.2831853071795862 * sigma_x*sigma_y; + case PSFunction::Moffat: return 3.1415926535897931 * sigma_x*sigma_y/(beta - 1); + case PSFunction::MoffatA: return 0.3490658503988659 * sigma_x*sigma_y; + case PSFunction::Moffat8: return 0.4487989505128276 * sigma_x*sigma_y; + case PSFunction::Moffat6: return 0.6283185307179586 * sigma_x*sigma_y; + case PSFunction::Moffat4: return 1.0471975511965976 * sigma_x*sigma_y; + case PSFunction::Moffat25: return 2.0943951023931953 * sigma_x*sigma_y; + case PSFunction::Moffat15: return 6.2831853071795862 * sigma_x*sigma_y; + default: return 0; // ?! + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PSFFit + * \brief Numerical Point Spread Function (PSF) fit to a source in an image. + * \sa StarDetector, PSFSignalEstimator, PSFScaleEstimator + */ +class PSFFit +{ +public: + + /*! + * Represents a point spread function type. + */ + typedef PSFData::psf_function psf_function; + + /*! + * Represents a PSF fitting process status. + */ + typedef PSFData::psf_fit_status psf_fit_status; + + /*! + * Fitted PSF parameters. + */ + PSFData psf; + + /*! + * Fits a point spread function to a source in the specified \a image. + * + * \param image The source image. + * + * \param center The intial search point in image coordinates. For + * consistent results, these coordinates must be the + * result of a robust object detection process. + * + * \param rect The PSF sampling region in image coordinates. + * This is the rectangular region of the image where + * the function fitting process will take place. PSF + * parameters will be evaluated from source pixel + * values acquired exclusively from this region. + * + * \param function The point spread function type to be fitted. A + * Gaussian PSF is fitted by default. + * + * \param circular Whether to fit a circular or an elliptical PSF. + * Elliptical functions are fitted by default. + * + * \param betaMin,betaMax The range of shape parameter values when + * \a function is PSFunction::VariableShape; ignored + * for other point spread functions. When the values of these + * parameters are such that \a betaMin < \a betaMax, an optimal + * value of the beta (shape) PSF parameter will be searched for + * iteratively within the specified range. The shape parameter will be + * optimized for minimization of the absolute difference between the + * estimated PSF and the sample of source image pixels. When + * \a betaMin ≥ \a betaMax, the shape parameter will stay constant + * and equal to the specified \a betaMin value during the entire PSF + * fitting process, and the rest of PSF parameters will be estimated + * accordingly. The valid range of beta parameter values is [1.0,6.0]. + * Values outside this range may lead to numerically unstable PSF + * fitting processes. + * + * \param tolerance Tolerance of the Levenberg-Marquardt algorithm. + * The default value is 1.0e-08. The valid range is + * from 1.0e-12 to 0.001. + * + * \param bkgMaxVar Maximum relative difference allowed between the + * fitted local background (\e B PSF parameter) and + * the initial local background estimated as the median pixel sample + * value of the sampling region. The default value is 0.1, meaning + * that a maximum relative difference of a 10% will be allowed. This + * parameter is useful to enforce stability of the PSF fitting + * process: assuming that the median pixel sample value is a robust + * estimate of the local background, by constraining the range of + * variation of the \e B parameter the PSF fitting process can be more + * accurate and robust. + * + * \param growthForFlux Growing factor in units of the Full Width at + * Tenth Maximum (FWTM) for extension/contraction of + * the PSF flux measurement region. The default + * value is 1.0. + * + * The implementation of the Levenberg-Marquardt algorithm used internally + * by this function is extremely sensitive to the specified \a center and + * \a rect parameters. These starting parameters should always be + * calculated using robust procedures to achieve consistent results. + * + * In the most frequent use case, where a star detection procedure is + * typically used to obtain these starting parameters, robustness to poorly + * sampled data and resilience to outlier pixels and noise are particularly + * important to this task. + */ + PSFFit( const ImageVariant& image, + const DPoint& center, const DRect& rect, + psf_function function = PSFunction::Gaussian, bool circular = false, + float betaMin = 1.0F, float betaMax = 4.0F, + double tolerance = 1.0e-08, float bkgMaxVar = 0.1F, float growthForFlux = 1.0F ); + + /*! + * Copy constructor. + */ + PSFFit( const PSFFit& ) = default; + + /*! + * Move constructor. + */ + PSFFit( PSFFit&& ) = default; + + /*! + * Copy assignment opèrator. Returns a reference to this object. + */ + PSFFit& operator =( const PSFFit& x ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PSFFit& operator =( PSFFit&& x ) = default; + + /*! + * Returns true iff this object contains a valid PSF fit, i.e. valid PSF + * fitted parameters. + */ + operator bool() const + { + return psf; + } + +private: + + Matrix S; // matrix of sampled pixel data + Vector P; // vector of function parameters + + // The initial local background measured on the sampling region and the + // maximum allowed relative difference, for stabilization of local + // background PSF parameters. + double m_bkg; + float m_bkgMaxVar; + + // Growing factor in units of the Full Width at Tenth Maximum (FWTM) for + // extension/contraction of the PSF flux measurement region. + float m_growthForFlux = 1.0F; + + // Keep track of successive beta values in L-M iterations for stabilization + // of shape parameters. This guarantees convergence for Moffat functions. + mutable float m_beta; + + Vector GoodnessOfFit( psf_function, bool circular, bool test = false ) const; + + friend class PSFFitEngine; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PSFFit_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PSFFit.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PSFScaleEstimator.h b/3rdparty/include/pcl/PSFScaleEstimator.h new file mode 100644 index 0000000..f1edcc7 --- /dev/null +++ b/3rdparty/include/pcl/PSFScaleEstimator.h @@ -0,0 +1,276 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PSFScaleEstimator.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_PSFScaleEstimator_h +#define __PCL_PSFScaleEstimator_h + +/// \file pcl/PSFScaleEstimator.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PSFScaleEstimator + * \brief Estimation of relative image scale based on PSF photometry + * \sa PSFEstimator, PSFSignalEstimator, StarDetector, PSFFit + */ +class PCL_CLASS PSFScaleEstimator : public PSFEstimator +{ +public: + + /*! + * Represents a point spread function type. + */ + typedef PSFEstimator::psf_function psf_function; + + typedef SurfaceSpline local_model; + + /*! + * \struct pcl::PSFScaleEstimator::Estimates + * \brief Structure to hold a PSF relative scale estimate. + */ + struct Estimates + { + double scale = 1; //!< Estimate of the mean relative scale with respect to the reference image. + double sigma = 0; //!< Standard deviation of the sample of scale measurements used for evaluation. + int total = 0; //!< Number of valid PSF fits. + int count = 0; //!< Number of valid PSF flux measurements used for scale evaluation. + local_model local; //!< 2-D model of local scale variations. + + /*! + * Conversion to double operator. + */ + operator double() const + { + return scale; + } + + /*! + * Returns true iff this is a valid scale estimate. + */ + bool IsValid() const + { + return count > 0 && 1 + scale != 1; + } + }; + + /*! + * Default constructor. + */ + PSFScaleEstimator() = default; + + /*! + * Copy constructor. + */ + PSFScaleEstimator( const PSFScaleEstimator& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~PSFScaleEstimator() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PSFScaleEstimator& operator =( const PSFScaleEstimator& ) = default; + + /*! + * Returns the search tolerance in pixels. + * + * For evaluation of relative scale finding a set of matched pairs of PSF + * measurements, i.e. matched stars, is necessary to ensure robustness of + * the computed scale estimate. The search tolerance is the half side in + * pixels of a square region around each fitted PSF used to find matched + * pairs of stars by proximity search. + * + * In theory a very small search tolerance (about 0.01 - 0.05 pixels, + * depending on the scale of the image) should be applicable, since the + * reference and target images are assumed to be registered and our standard + * image registration processes, such as StarAlignment for example, sport + * centipixel accuracy. However, in practice we may have to deal with larger + * registration errors, especially for wide field images if the user has not + * defined the necessary parameters to apply distortion corrections. + * + * The default search tolerance is 4 pixels. + */ + float PSFSearchTolerance() const + { + return m_psfSearchTolerance; + } + + /*! + * Sets the search tolerance in pixels. See PSFSearchTolerance() for a + * description of this parameter. + */ + void SetPSFSearchTolerance( float t ) + { + PCL_PRECONDITION( t >= 0 ) + m_psfSearchTolerance = Max( 0.0F, t ); + } + + /*! + * Sets a new reference image for relative scale estimation. + * + * This function performs the star detection and PSF fitting tasks for the + * specified image. The resulting set of PSF signal measurements will be + * stored in this object for relative scale evaluation by subsequent calls + * to EstimateScale(). + * + * Returns the number of valid PSF signal measurements gathered for the + * specified reference \a image. + */ + int SetReference( const ImageVariant& image ); + + /*! + * Returns true iff generation of models of local relative scale variations + * is enabled for this object. + * + * When this option is enabled, local scale variations are modeled with an + * approximating thin plate spline during relative scale estimation. This + * feature is disabled by default. + */ + bool IsLocalModelEnabled() const + { + return m_enableLocalModel; + } + + /*! + * Enables generation of local scale variation models. + */ + void EnableLocalModel( bool enable = true ) + { + m_enableLocalModel = enable; + } + + /*! + * Disables generation of local scale variation models. + */ + void DisableLocalModel( bool disable = true ) + { + EnableLocalModel( !disable ); + } + + /*! + * Evaluates the mean relative scaling factor of the currently selected + * reference image with respect to the specified target \a image. + * + * A successful call to SetReference() is required to select a reference + * image \e before calling this function; otherwise an Error exception will + * be thrown. The specified target \a image must be accurately registered + * with respect to the reference image. + * + * The returned object contains the estimated mean ratio of the reference + * signal to the target signal, as well as the number of PSF measurements + * used for scale evaluation. All PSF signal measurements exclude local + * background estimates. + * + * \note This function is thread-safe. + */ + Estimates EstimateScale( const ImageVariant& image ) const; + + /*! + * Evaluates the mean relative scaling factor of the currently selected + * reference image with respect to the specified target \a image. + * + * This operator is equivalent to the + * EstimateScale( const ImageVariant& ) const member function. + * + * \note This function is thread-safe. + */ + Estimates operator()( const ImageVariant& image ) const + { + return EstimateScale( image ); + } + +private: + + Array m_psfReference; + float m_psfSearchTolerance = 4.0F; // px + bool m_enableLocalModel = false; + + /* + * Auxiliary structure for generation of first-order local scale models. + */ + struct Sample + { + double x, y, z; + + operator double() const + { + return z; + } + + bool operator <( const Sample& s ) const + { + return z < s.z; + } + }; + + typedef GenericVector sample_vector; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PSFScaleEstimator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PSFScaleEstimator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PSFSignalEstimator.h b/3rdparty/include/pcl/PSFSignalEstimator.h new file mode 100644 index 0000000..8662772 --- /dev/null +++ b/3rdparty/include/pcl/PSFSignalEstimator.h @@ -0,0 +1,280 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PSFSignalEstimator.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_PSFSignalEstimator_h +#define __PCL_PSFSignalEstimator_h + +/// \file pcl/PSFSignalEstimator.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PSFSignalEstimator + * \brief Signal estimation based on PSF photometry + * \sa PSFEstimator, PSFScaleEstimator, StarDetector, PSFFit + */ +class PCL_CLASS PSFSignalEstimator : public PSFEstimator +{ +public: + + /*! + * Represents a point spread function type. + */ + typedef PSFEstimator::psf_function psf_function; + + /*! + * \struct pcl::PSFSignalEstimator::Estimates + * \brief Structure to hold PSF flux and robust mean background estimates. + */ + struct Estimates + { + double totalFlux = 0; //!< The sum of PSF flux estimates. + double totalPowerFlux = 0; //!< The sum of squared PSF flux estimates. + double totalMeanFlux = 0; //!< The sum of mean PSF flux estimates. + double totalMeanPowerFlux = 0; //!< The sum of mean squared PSF flux estimates. + double MStar = 0; //!< The M* robust mean background estimate. + double NStar = 0; /*!< The N* robust estimate of the standard deviation of the noise. + As generated by the EstimateSignal() member function, this + estimate is already multiplied by the normalization constant + 2.05435, which makes it consistent with the standard deviation + of a normal distribution. */ + int count = 0; //!< Number of valid PSF flux estimates. + + /*! + * Conversion to double operator. + */ + operator double() const + { + return totalFlux; + } + + /*! + * Returns true iff this object contains valid PSF flux estimates. + */ + bool IsValid() const + { + return count > 0 && 1 + totalFlux != 1 && 1 + MStar != 1; + } + }; + + /*! + * Default constructor. + */ + PSFSignalEstimator() + { + // Override default PSF estimator parameters with appropriate values for + // signal evaluation. + m_saturationThreshold = 1.0F; + m_saturationRelative = false; + } + + /*! + * Copy constructor. + */ + PSFSignalEstimator( const PSFSignalEstimator& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~PSFSignalEstimator() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PSFSignalEstimator& operator =( const PSFSignalEstimator& ) = default; + + /*! + * Returns the scale for local background model generation in pixels. + * + * The implemented algorithm uses nonlinear multiscale transforms to + * generate a model of the large-scale background component of the image. + * This is necessary to calculate robust estimates of the mean background + * level and the standard deviation of the noise, M* and N* respectively. + * + * This parameter defines the dimensional scale in pixels for isolation of + * large-scale image structures. The current implementation supports the + * following scale parameter values in pixels: 1024, 768, 512, 384, 256, + * 192, 128, 64 and 32. The default scale is 256 pixels. + */ + int BackgroundModelScale() const + { + return m_scale; + } + + /*! + * Sets the scale for local background model generation in pixels. + * + * See the BackgroundModelScale() member function for a description of this + * parameter. + */ + void SetBackgroundModelScale( int scale ) + { + PCL_PRECONDITION( scale >= 32 && scale <= 1024 ) + m_scale = Range( scale, 32, 1024 ); + } + + /*! + * Evaluates the total and mean PSF flux and square flux, along with the M* + * and N* estimates of mean background level and noise standard deviation, + * for the selected channel of the specified \a image. Returns the estimates + * as a new PSFSignalEstimator::Estimates object. + * + * \note This function is thread-safe. + */ + Estimates EstimateSignal( const ImageVariant& image ) const; + + /*! + * Evaluates the total and mean PSF flux and square flux, along with the M* + * and N* estimates of mean background level and noise standard deviation, + * for the selected channel of the specified \a image. Returns the estimates + * as a new PSFSignalEstimator::Estimates object. + * + * This operator is equivalent to the EstimateSignal( const ImageVariant& ) + * member function. + * + * \note This function is thread-safe. + */ + Estimates operator()( const ImageVariant& image ) const + { + return EstimateSignal( image ); + } + + /*! + * Extracts the set of residual pixels from a large-scale local background + * model. + * + * \param image The target image, from which the set of residual pixels + * will be evaluated and extracted. The task will work + * exclusively on the selected channel of the image, ignoring + * region selections. + * + * \param scale The dimensional \a scale in pixels. This is the scale of + * the generated local background model used for detection of + * non-significant and residual pixels. The current + * implementation supports the following scales for + * large-scale local background modeling: 512, 384, 256, 192, + * 128, 64 and 32 pixels. The default scale is 256 pixels. + * + * \param maxThreads If specified, the task will use at most this number + * of parallel execution threads. Otherwise, or if a value + * ≤ 0 is specified, the number of threads will be set + * according to current platform settings. + * + * The mean (or median) and standard deviation of the returned residual are + * the M* and N* robust estimators, respectively. M* estimates the mean + * background level, and N* the standard deviation of the noise. + */ + static Array LocalBackgroundResidual( const ImageVariant& image, int scale = 256, int maxThreads = 0 ); + + /*! + * The PSF Signal Weight (PSFSW) image quality estimator. + * + * \param E PSF flux and robust mean background and noise estimates. + * The estimates held by this object should be the result of + * a previous call to the EstimateSignal() member function, + * or be assigned with values retrieved from the appropriate + * image metadata items. + * + * \param sigmaN Estimate of the standard deviation of the noise. If no + * value is specified for this parameter, or if a value + * ≤ 0 is specified, the N* robust noise estimate held by + * the specified \a E structure will be used. + */ + static double PSFSignalWeight( const Estimates& E, double sigmaN = 0 ) + { + if ( sigmaN <= 0 ) + sigmaN = E.NStar; + return (3.18e-6 * E.totalFlux * E.totalMeanFlux) / (9.00e+6 * sigmaN * E.MStar); + } + + /*! + * The PSF Signal to Noise Ratio (PSFSNR) estimator. + * + * \param E PSF flux and robust mean background and noise estimates. + * The estimates held by this object should be the result of + * a previous call to the EstimateSignal() member function, + * or be assigned with values retrieved from the appropriate + * image metadata items. + * + * \param sigmaN Estimate of the standard deviation of the noise. If no + * value is specified for this parameter, or if a value + * ≤ 0 is specified, the N* robust noise estimate held by + * the specified \a E structure will be used. + */ + static double PSFSNR( const Estimates& E, double sigmaN = 0 ) + { + if ( sigmaN <= 0 ) + sigmaN = E.NStar; + return (1.350e-7 * E.totalFlux * E.totalFlux) / (4.987e+6 * sigmaN * sigmaN); + } + +private: + + int m_scale = 256; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PSFSignalEstimator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PSFSignalEstimator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ParallelProcess.h b/3rdparty/include/pcl/ParallelProcess.h new file mode 100644 index 0000000..ea39d86 --- /dev/null +++ b/3rdparty/include/pcl/ParallelProcess.h @@ -0,0 +1,187 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ParallelProcess.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_ParallelProcess_h +#define __PCL_ParallelProcess_h + +/// \file pcl/ParallelProcess.h + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ParallelProcess + * \brief A process using multiple concurrent execution threads. + * + * %ParallelProcess is a base class for classes implementing multithreaded + * processes in PCL. + */ +class PCL_CLASS ParallelProcess +{ +public: + + /*! + * Default constructor. + * + * By default, parallel processing is always enabled, and any process can + * use the maximum possible number of parallel execution threads. + */ + ParallelProcess() = default; + + /*! + * Copy constructor. + */ + ParallelProcess( const ParallelProcess& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ParallelProcess& operator =( const ParallelProcess& ) = default; + + /*! + * Returns true iff this process is allowed to use multiple parallel + * execution threads, when multiple threads are permitted and available. + */ + bool IsParallelProcessingEnabled() const noexcept + { + return m_parallel; + } + + /*! + * Enables parallel processing for this process. + * + * \param enable Whether to enable or disable parallel processing. True by + * default. + * + * \param maxProcessors The maximum number of processors allowed for this + * instance. If \a enable is false this parameter is ignored. + * A value ≤ 0 is ignored. The default value is zero. + */ + void EnableParallelProcessing( bool enable = true, int maxProcessors = 0 ) noexcept + { + m_parallel = enable; + if ( m_parallel ) + if ( maxProcessors > 0 ) + SetMaxProcessors( maxProcessors ); + } + + /*! + * Disables parallel processing for this process. + * + * This is a convenience function, equivalent to: + * + * \code EnableParallelProcessing( !disable ) \endcode + */ + void DisableParallelProcessing( bool disable = true ) noexcept + { + EnableParallelProcessing( !disable ); + } + + /*! + * Returns the maximum number of processors allowed for this process. + * + * Irrespective of the value returned by this function, a module should not + * use more processors than the maximum number of parallel threads allowed + * for external modules on the PixInsight platform. This number is given by + * the "Process/MaxProcessors" global variable. Refer to the GlobalSettings + * class for information on global variables. + */ + int MaxProcessors() const noexcept + { + return m_maxProcessors; + } + + /*! + * Sets the maximum number of processors allowed for this process. + * + * In the current version of PCL, a module can use a maximum of 1023 + * processors. The term \e processor actually refers to the number of + * threads a module can execute concurrently. + * + * Irrespective of the value specified by this function, a module should not + * use more processors than the maximum number of parallel threads allowed + * for external modules on the PixInsight platform. This number is given by + * the "Process/MaxProcessors" global variable. Refer to the GlobalSettings + * class for information on global variables. + */ + void SetMaxProcessors( int maxProcessors ) noexcept + { + m_maxProcessors = Range( maxProcessors, 1, PCL_MAX_PROCESSORS ); + } + + /*! + * Exchanges two %ParallelProcess instances. + */ + void Swap( ParallelProcess& process ) noexcept + { + pcl::Swap( m_maxProcessors, process.m_maxProcessors ); + pcl::Swap( m_parallel, process.m_parallel ); + } + +protected: + + int m_maxProcessors = PCL_MAX_PROCESSORS; // maximum number of processors allowed + bool m_parallel = true; // use multiple threads? +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ParallelProcess_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ParallelProcess.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Pen.h b/3rdparty/include/pcl/Pen.h new file mode 100644 index 0000000..177cb89 --- /dev/null +++ b/3rdparty/include/pcl/Pen.h @@ -0,0 +1,371 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Pen.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_Pen_h +#define __PCL_Pen_h + +/// \file pcl/Pen.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::PenStyle + * \brief Pen drawing styles + * + * + * + * + * + * + * + * + *
PenStyle::Empty Nothing is drawn
PenStyle::Solid _____________
PenStyle::Dash _ _ _ _ _ _ _
PenStyle::Dot .............
PenStyle::DashDot _._._._._._._
PenStyle::DashDotDot _.._.._.._.._
+ */ +namespace PenStyle +{ + enum value_type + { + Empty, // Nothing drawn + Solid, // _____________ + Dash, // _ _ _ _ _ _ _ + Dot, // ............. + DashDot, // _._._._._._._ + DashDotDot, // _.._.._.._.._ + + NumberOfPenStyles + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::PenCap + * \brief Pen cap styles + * + * + * + * + * + *
PenCap::Flat Square caps not reaching the end points of lines
PenCap::Square Square caps extending beyond end points by half the line width
PenCap::Round Round caps centered at the line end points
+ */ +namespace PenCap +{ + enum value_type + { + Flat, // Square caps not reaching the end points of lines + Square, // Square caps extending beyond end points by half the line width + Round, // Round caps centered at the line end points + + NumberOfPenCaps + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::PenJoin + * \brief Pen join styles + * + * + * + * + * + *
PenJoin::Miter Lines are joined by sharp corners
PenJoin::Bevel Lines are joined by flat corners
PenJoin::Round Circular arcs are drawn between lines
+ */ +namespace PenJoin +{ + enum value_type + { + Miter, // Lines are joined by sharp corners + Bevel, // Lines are joined by flat corners + Round, // Circular arcs are drawn between lines + + NumberOfPenJoins + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class PCL_CLASS Brush; + +// ---------------------------------------------------------------------------- + +/*! + * \class Pen + * \brief Client-side interface to a PixInsight %Pen object + * + * ### TODO: Write a detailed description for %Pen. + */ +class PCL_CLASS Pen : public UIObject +{ +public: + + /*! + * Represents a pen drawing style. + */ + typedef PenStyle::value_type style; + + /*! + * Represents a pen cap style. + */ + typedef PenCap::value_type cap; + + /*! + * Represents a pen join style. + */ + typedef PenJoin::value_type join; + + /*! + * Constructs a %Pen object with the specified \a color, \a width in pixels, + * and drawing, cap and join styles. + */ + Pen( RGBA color = 0xff000000, float width = 0, style s = PenStyle::Solid, + cap c = PenCap::Square, join j = PenJoin::Miter ); + + /*! + * Copy constructor. This object will reference the same server-side pen + * as the specified instance \a p. + */ + Pen( const Pen& p ) : UIObject( p ) + { + } + + /*! + * Destroys a %Pen object. If this object references an existing pen in the + * PixInsight core application, its reference count is decremented. If it + * becomes unreferenced, it will be garbage-collected. + */ + virtual ~Pen() + { + } + + /*! + * Assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side pen as the specified + * instance \a p. If the previous pen becomes unreferenced, it will be + * garbage-collected by the PixInsight core application. + */ + Pen& operator =( const Pen& p ) + { + SetHandle( p.handle ); + return *this; + } + + /*! + * Returns a reference to a null pen. A null %Pen object does not + * correspond to an existing pen object in the PixInsight core application. + */ + static Pen& Null(); + + /*! + * Returns the pen width in pixels. + * + * A zero width means that this is a cosmetic pen. Cosmetic pens + * always draw one-pixel strokes, regardless of the transformation applied + * to the graphics context where they are applied. + * + * \sa SetWidth() + */ + float Width() const; + + /*! + * Sets the pen width in pixels. + * + * A zero width means that this is a cosmetic pen. Cosmetic pens + * always draw one-pixel strokes, regardless of the transformation applied + * to the graphics context where they are applied. + * + * \sa Width() + */ + void SetWidth( float w ); + + /*! + * Returns the pen color as a 32-bit AARRGGBB pixel color value. + * + * \sa SetColor() + */ + RGBA Color() const; + + /*! + * Sets the pen \a color as a 32-bit AARRGGBB pixel color value. + * + * \sa Color() + */ + void SetColor( RGBA color ); + + /*! + * Returns the current pen drawing style. + * + * \sa SetStyle(), IsSolid(), IsEmpty() + */ + style Style() const; + + /*! + * Returns true iff this pen draws solid strokes, i.e. if the current pen + * drawing style is PenStyle::Solid. + * + * \sa IsEmpty(), Style() + */ + bool IsSolid() const + { + return Style() == PenStyle::Solid; + } + + /*! + * Returns true iff this pen draws no strokes, i.e. if the current pen + * drawing style is PenStyle::Empty. + * + * \sa IsSolid(), Style() + */ + bool IsEmpty() const + { + return Style() == PenStyle::Empty; + } + + /*! + * Sets the pen drawing style. + * + * \sa Style(), IsSolid(), IsEmpty() + */ + void SetStyle( style ); + + /*! + * Returns the current pen cap style. + * + * \sa SetCap() + */ + cap Cap() const; + + /*! + * Sets the current pen cap style. + * + * \sa Cap() + */ + void SetCap( cap c ); + + /*! + * Returns the current pen join style. + * + * \sa SetJoin() + */ + join Join() const; + + /*! + * Sets the current pen join style. + * + * \sa Join() + */ + void SetJoin( join j ); + + /*! + * Returns the current pen brush. + * + * \sa SetBrush() + */ + pcl::Brush Brush() const; + + /*! + * Returns the current pen brush. + * + * \deprecated Use Pen::Brush() in newly produced code. + * \sa SetBrush() + */ + pcl::Brush GetBrush() const + { + return this->Brush(); + } + + /*! + * Sets the current pen brush + * + * \sa Brush() + */ + void SetBrush( const pcl::Brush& brush ); + +private: + + Pen( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class GraphicsContextBase; + friend class Graphics; + friend class VectorGraphics; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Pen_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Pen.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PhaseMatrices.h b/3rdparty/include/pcl/PhaseMatrices.h new file mode 100644 index 0000000..e7f4e89 --- /dev/null +++ b/3rdparty/include/pcl/PhaseMatrices.h @@ -0,0 +1,168 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PhaseMatrices.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_PhaseMatrices_h +#define __PCL_PhaseMatrices_h + +/// \file pcl/PhaseMatrices.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * Calculation of the phase correlation matrix (PCM). + * + * \param[out] R The resulting PCM as a single-channel complex image with the + * same dimensions of the source images \a A and \a B. + * + * \param A A single-channel complex image with the discrete Fourier + * transform of the reference image. + * + * \param B A single-channel complex image with the discrete Fourier + * transform of the working image. + * + * Both source images \a A and \a B must be nonempty and have the same + * dimensions. If the result image \a R does not have the same geometry as the + * source images, it is reallocated as necessary. + * + * \note Increments the status monitoring object of the result image \a R by + * its area in square pixels. + * + * \ingroup phase_matrices + */ +template inline +void PCL_FUNC PhaseCorrelationMatrix( GenericImage& R, const GenericImage& A, const GenericImage& B ) +{ + const typename GenericImage::sample::component tiny( 1.0e-20 ); + + size_type N = A.NumberOfPixels(); + + if ( A.IsEmpty() || B.NumberOfPixels() != N ) + throw Error( "Invalid image geometry in PhaseCorrelationMatrix()" ); + + if ( R.NumberOfPixels() != N ) + R.AllocateData( A.Width(), B.Width() ); + + if ( R.Status().IsInitializationEnabled() ) + R.Status().Initialize( "Phase correlation matrix", N ); + + const typename GenericImage::sample* a = *A; + const typename GenericImage::sample* b = *B; + typename GenericImage::sample* r = *R; + typename GenericImage::sample* rN = r + N; + + for ( ; r < rN; ++r, ++a, ++b, ++R.Status() ) + { + typename GenericImage::sample num = *a * ~*b; + *r = P1::ToSample( num/Max( tiny, Abs( num ) ) ); + } +} + +/*! + * Calculation of the cross power spectrum matrix (CPSM). + * + * \param[out] R The resulting CPSM as a single-channel complex image with the + * same dimensions of the source images \a A and \a B. + * + * \param A A single-channel complex image with the discrete Fourier + * transform of the reference image. + * + * \param B A single-channel complex image with the discrete Fourier + * transform of the working image. + * + * Both source images \a A and \a B must be nonempty and have the same + * dimensions. If the result image \a R does not have the same geometry as the + * source images, it is reallocated as necessary. + * + * \note Increments the status monitoring object of the result image \a R by + * its area in square pixels. + * + * \ingroup phase_matrices + */ +template inline +void PCL_FUNC CrossPowerSpectrumMatrix( GenericImage& R, const GenericImage& A, const GenericImage& B ) +{ + const typename GenericImage::sample::component tiny( 1.0e-20 ); + + size_type N = A.NumberOfPixels(); + + if ( A.IsEmpty() || B.NumberOfPixels() != N ) + throw Error( "Invalid image geometry in CrossPowerSpectrumMatrix()" ); + + if ( R.NumberOfPixels() != N ) + R.AllocateData( A.Width(), B.Width() ); + + if ( R.Status().IsInitializationEnabled() ) + R.Status().Initialize( "Cross power spectrum matrix", N ); + + const typename GenericImage::sample* a = *A; + const typename GenericImage::sample* b = *B; + typename GenericImage::sample* r = *R; + typename GenericImage::sample* rN = r + N; + + for ( ; r < rN; ++r, ++a, ++b, ++R.Status() ) + *r = P1::ToSample( (*b * ~*a)/Max( tiny, Abs( *a ) * Abs( *b ) ) ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PhaseMatrices_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PhaseMatrices.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PixelAllocator.h b/3rdparty/include/pcl/PixelAllocator.h new file mode 100644 index 0000000..0d2f1ea --- /dev/null +++ b/3rdparty/include/pcl/PixelAllocator.h @@ -0,0 +1,251 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PixelAllocator.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_PixelAllocator_h +#define __PCL_PixelAllocator_h + +/// \file pcl/PixelAllocator.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +template class PCL_CLASS GenericImage; + +// ---------------------------------------------------------------------------- + +/*! + * \class PixelAllocator + * \brief Manages transparent allocation and deallocation of shared and local + * pixel data. + * + * %PixelAllocator is responsible for allocation and deallocation of pixel data + * blocks in PCL. The template argument P corresponds to an instantiation of + * GenericPixelTraits for a specific pixel sample type. + * + * Unless you are implementing geometrical transformations, or processes that + * perform direct substitutions of pixel data blocks in images, such as a whole + * channel, you usually should not have to use the %PixelAllocator template + * class directly in your code. The SharedPixelData and GenericImage classes + * can perform all the necessary allocations transparently. + * + * When you have to allocate or deallocate pixel data blocks, however, you + * should \e never use the \c new and \c delete operators, or the \c malloc, + * \c calloc and \c free standard C functions. You must use %PixelAllocator for + * all allocations and deallocations of pixel data \e exclusively. Among other + * good reasons for this, pixel data blocks cannot be allocated in your + * module's local heap if they are being used with shared images, i.e. images + * living in the PixInsight core application. + * + * The \e only safe way to allocate and deallocate pixel data in PCL is by + * using %PixelAllocator's member functions. Note that you cannot allocate + * %PixelAllocator directly. For an existing image, you get a reference to a + * %PixelAllocator instance by calling the Allocator() member function of + * %GenericImage. This member function returns a reference to the image's + * internal allocator, which will perform all pixel allocation tasks that you + * may need transparently, irrespective of whether the object represents a + * local or shared image. + * + * \sa GenericPixelTraits, GenericImage, SharedPixelData + */ +template +class PCL_CLASS PixelAllocator : public SharedPixelData +{ +public: + + /*! + * Represents the pixel traits class used by this instantiation of + * %PixelAllocator. + * + * The \c pixel_traits type should be an instantiation of + * GenericPixelTraits. It identifies a class implementing basic storage and + * functional primitives optimized for a particular pixel sample type. + */ + typedef P pixel_traits; + + /*! + * Represents the data type used to store pixel sample values in this + * template instantiation of %PixelAllocator. + */ + typedef typename pixel_traits::sample sample; + + /*! + * Returns true iff this allocator and another instance are working for the + * same shared image, or if both of them are working for local images. + * + * All local images share a unique internal allocator, but each shared image + * has its own, independent allocator object. This responds to the + * multithreaded nature of the PixInsight core application. + */ + bool operator ==( const PixelAllocator

& x ) const noexcept + { + return SharedPixelData::operator ==( x ); + } + + /*! + * Allocates a contiguous block of memory where at least \a n > 0 pixel + * samples can be optimally stored. + * + * Returns the starting address of the allocated block. + * + * This member function throws a \c std::bad_alloc exception if there is not + * enough memory available to allocate the required contiguous block. + */ + sample* AllocatePixels( size_type n ) const + { + PCL_PRECONDITION( n != 0 ) + return reinterpret_cast( SharedPixelData::Allocate( n*sizeof( sample ) ) ); + } + + /*! + * Allocates a contiguous block of memory where at least \a width * + * \a height pixel samples can be optimally stored. + * + * Returns the starting address of the allocated block. This is a + * convenience alias for: + * + * \code + * AllocatePixels( size_type( width )*size_type( height ) ); + * \endcode + */ + sample* AllocatePixels( int width, int height ) const + { + return AllocatePixels( size_type( width )*size_type( height ) ); + } + + /*! + * Allocates an array where at least \a n > 0 channel slots can be + * optimally stored. A channel slot is a pointer to a contiguous block of + * pixel samples, where an image can store a single channel. + * + * The allocated array is initialized to zero. Returns the starting address + * of the allocated array. + * + * This member function throws a \c std::bad_alloc exception if there is not + * enough memory available to allocate the required contiguous block. + */ + sample** AllocateChannelSlots( size_type n ) const + { + PCL_PRECONDITION( n != 0 ) + sample** cslots = reinterpret_cast( SharedPixelData::Allocate( n*sizeof( sample* ) ) ); + ::memset( cslots, 0, n*sizeof( sample* ) ); + return cslots; + } + + /*! + * Deallocates a previously allocated memory block. The deallocated block + * becomes available for subsequent allocations. + * + * \warning Do not use this function to deallocate memory that has + * not been allocated by \e this %PixelAllocator object. This includes + * memory blocks allocated by the global \c new operator, or by other + * %PixelAllocator objects. Failure to follow this rule will lead to severe + * heap corruption for the calling module. + */ + template + void Deallocate( T* p ) const + { + PCL_PRECONDITION( p != nullptr ) + SharedPixelData::Deallocate( reinterpret_cast( p ) ); + } + +private: + + PixelAllocator() = default; + + PixelAllocator( void* handle ) + : SharedPixelData( handle, P::BitsPerSample(), P::IsFloatSample(), P::IsComplexSample() ) + { + } + + PixelAllocator( const PixelAllocator

& x ) + : SharedPixelData( x ) + { + } + + PixelAllocator( int width, int height, int numberOfChannels, int colorSpace ) + : SharedPixelData( width, height, numberOfChannels, P::BitsPerSample(), P::IsFloatSample(), colorSpace ) + { + } + + PixelAllocator& operator =( const PixelAllocator

& x ) + { + (void)SharedPixelData::operator =( x ); + return *this; + } + + sample** GetSharedData() const + { + return reinterpret_cast( SharedPixelData::GetSharedData() ); + } + + void SetSharedData( sample** ptrToShared ) + { + SharedPixelData::SetSharedData( reinterpret_cast( ptrToShared ) ); + } + + friend class pcl::GenericImage

; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PixelAllocator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PixelAllocator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PixelInterpolation.h b/3rdparty/include/pcl/PixelInterpolation.h new file mode 100644 index 0000000..3175ffa --- /dev/null +++ b/3rdparty/include/pcl/PixelInterpolation.h @@ -0,0 +1,1132 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PixelInterpolation.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_PixelInterpolation_h +#define __PCL_PixelInterpolation_h + +/// \file pcl/PixelInterpolation.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning( push ) +# pragma warning( disable : 4267 ) // conversion from 'size_t' to ... +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PixelInterpolation + * \brief Abstract root base class for all pixel interpolation algorithms. + * + * %PixelInterpolation is the abstract base class of all pixel interpolation + * PCL classes. A pixel interpolation class is able to generate pixel + * interpolators (instances of PixelInterpolation::Interpolator), which + * are generic objects providing a common pixel interpolation interface that is + * independent on a particular interpolation algorithm. + * + * \sa NearestNeighborPixelInterpolation, BilinearPixelInterpolation, + * BicubicSplinePixelInterpolation, BicubicBSplinePixelInterpolation, + * BicubicFilterPixelInterpolation, LanczosPixelInterpolation, + * Lanczos3LUTPixelInterpolation, Lanczos4LUTPixelInterpolation, + * Lanczos5LUTPixelInterpolation + */ +class PCL_CLASS PixelInterpolation +{ +public: + + /*! + * \class pcl::PixelInterpolation::Interpolator + * \brief Generic two-dimensional pixel interpolator + * + * %Interpolator provides a common pixel interpolation interface that is + * independent on a particular interpolation algorithm. + */ + template + class PCL_CLASS Interpolator + { + public: + + /*! + * Represents a pixel sample value. + */ + typedef typename P::sample sample; + + /*! + * Constructs and initializes a new %Interpolator object. + * + * \param interpolation Pointer to a dynamically allocated instance of + * the two-dimensional interpolation algorithm. + * The instance will be owned by this object, + * which will destroy and deallocate it upon + * destruction. + * + * \param data Source matrix of pixel sample values that will + * be interpolated. + * + * \param width Horizontal dimension (most rapidly varying + * matrix subscript) of the source data matrix. + * Must be greater than zero. + * + * \param height Vertical dimension (most slowly varying matrix + * subscript) of the source data matrix. Must be + * greater than zero. + * + * \param unclipped If false (default value), the interpolation + * will constrain interpolated values to the + * native range of the pixel sample type + * represented by the template argument P. If + * true, interpolated pixel values will be + * returned unmodified. Note that this only makes + * sense for floating point pixel sample types. + */ + Interpolator( BidimensionalInterpolation* interpolation, + const sample* data, int width, int height, bool unclipped = false ) + : m_interpolation( interpolation ) + , m_unclipped( unclipped ) + { + if ( !m_interpolation.IsNull() ) + m_interpolation->Initialize( data, width, height ); + } + + /*! + * Disabled copy constructor. + */ + Interpolator( const Interpolator& ) = delete; + + /*! + * Move constructor. + */ + Interpolator( Interpolator&& ) = default; + + /*! + * Destroys an %Interpolator object and all internal working structures. + */ + virtual ~Interpolator() + { + } + + /*! + * Returns a reference to the immutable two-dimensional interpolation + * being used by this %Interpolator object. + */ + const BidimensionalInterpolation& Interpolation() const + { + PCL_PRECONDITION( !m_interpolation.IsNull() ) + return *m_interpolation; + } + + /*! + * Returns a reference to the mutable two-dimensional interpolation being + * used by this %Interpolator object. + */ + BidimensionalInterpolation& Interpolation() + { + PCL_PRECONDITION( !m_interpolation.IsNull() ) + return *m_interpolation; + } + + /*! + * Interpolates a pixel sample value at the specified \a x and \a y image + * coordinates. + * + * If this is an unclipped interpolator (see the class constructor), the + * interpolated value will be returned unmodified. If this is a clipped + * interpolator (default state), the returned value will be constrained + * to stay within the native range of the pixel sample type represented + * by the template argument P. Note that unclipped interpolation only + * makes sense for floating point pixel sample types. + */ + sample operator()( double x, double y ) const + { + PCL_PRECONDITION( !m_interpolation.IsNull() ) + double r = (*m_interpolation)( x, y ); + if ( !m_unclipped ) + { + if ( r > P::MaxSampleValue() ) + return P::MaxSampleValue(); + if ( r < P::MinSampleValue() ) + return P::MinSampleValue(); + } + return P::FloatToSample( r ); + } + + /*! + * Interpolates a pixel sample value at the specified \a p point. + * + * This is an overloaded member function, provided for convenience. It is + * equivalent to operator()( p.x, p.y ). + */ + template + sample operator()( const GenericPoint& p ) const + { + return operator()( p.x, p.y ); + } + + private: + + AutoPointer> m_interpolation; + bool m_unclipped; + }; + + // ------------------------------------------------------------------------- + + /*! + * Constructs a %PixelInterpolation object. + */ + PixelInterpolation() = default; + + /*! + * Copy constructor. + */ + PixelInterpolation( const PixelInterpolation& ) = default; + + /*! + * Destroys a %PixelInterpolation object. + */ + virtual ~PixelInterpolation() + { + } + + /*! + * Returns a descriptive text string for this pixel interpolation. + */ + virtual String Description() const = 0; + + /*! + * Returns true iff this interpolation can be safely used in multithreaded + * contexts. + * + * A thread-safe interpolator can be used concurrently by multiple threads + * without needing to lock access to the interpolated data. + * + * \note The default implementation returns true, so pixel interpolations + * are considered thread-safe by default. + */ + virtual bool IsThreadSafe() const + { + return true; + } + + /*! + * Creates a new Interpolator object specialized for a pixel sample type P. + * + * \param data Two-dimensional matrix of pixel sample values that will be + * interpolated. + * + * \param width Horizontal dimension (most rapidly varying matrix + * subscript) of the source data matrix. + * + * \param height Vertical dimension (most slowly varying matrix subscript) + * of the source data matrix. + */ + template + Interpolator

* NewInterpolator( const T* data, int width, int height, bool unclipped = false ) const + { + return new Interpolator

( NewInterpolation( data ), data, width, height, unclipped ); + } + +protected: + + virtual BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 32-bit floating point images" ); + } + + virtual BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 64-bit floating point images" ); + } + + virtual BidimensionalInterpolation* + NewInterpolation( const ComplexPixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 32-bit complex images" ); + } + + virtual BidimensionalInterpolation* + NewInterpolation( const DComplexPixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 64-bit complex images" ); + } + + virtual BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 8-bit integer images" ); + } + + virtual BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 16-bit integer images" ); + } + + virtual BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const + { + throw NotImplemented( *this, "Interpolate 32-bit integer images" ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class NearestNeighborPixelInterpolation + * \brief NearestNeighbor pixel interpolation. + * + * %NearestNeighborPixelInterpolation uses the nearest neighbor interpolation + * algorithm (NearestNeighborInterpolation) to interpolate pixel values as the + * nearest neighbor source pixels. + * + * \sa PixelInterpolation, NearestNeighborInterpolation, + * BilinearPixelInterpolation, BicubicSplinePixelInterpolation, + * BicubicBSplinePixelInterpolation, BicubicFilterPixelInterpolation + */ +class PCL_CLASS NearestNeighborPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %NearestNeighborPixelInterpolation object. + */ + NearestNeighborPixelInterpolation() = default; + + /*! + * Copy constructor. + */ + NearestNeighborPixelInterpolation( const NearestNeighborPixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + return "Nearest neighbor interpolation"; + } + +private: + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new NearestNeighborInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new NearestNeighborInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new NearestNeighborInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new NearestNeighborInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new NearestNeighborInterpolation; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BilinearPixelInterpolation + * \brief Bilinear pixel interpolation. + * + * %BilinearPixelInterpolation uses the bilinear interpolation algorithm + * (BilinearInterpolation) to interpolate pixel values from the nearest + * four neighbor pixels. + * + * \sa PixelInterpolation, BilinearInterpolation, + * NearestNeighborPixelInterpolation, BicubicSplinePixelInterpolation, + * BicubicBSplinePixelInterpolation, BicubicFilterPixelInterpolation + */ +class PCL_CLASS BilinearPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %BilinearPixelInterpolation object. + */ + BilinearPixelInterpolation() = default; + + /*! + * Copy constructor. + */ + BilinearPixelInterpolation( const BilinearPixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + return "Bilinear interpolation"; + } + +private: + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new BilinearInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new BilinearInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new BilinearInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new BilinearInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new BilinearInterpolation; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BicubicSplinePixelInterpolation + * \brief Bicubic spline pixel interpolation. + * + * %BicubicSplinePixelInterpolation uses the bicubic spline interpolation + * algorithm (BicubicSplineInterpolation) to interpolate pixel values from the + * nearest sixteen neighbor pixels. + * + * \sa PixelInterpolation, BicubicSplineInterpolation, + * NearestNeighborPixelInterpolation, BicubicPixelInterpolation, + * BicubicBSplinePixelInterpolation, BicubicFilterPixelInterpolation + */ +class PCL_CLASS BicubicSplinePixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %BicubicPixelInterpolation object. + * + * The optional \e clamp parameter is a linear clamping threshold + * for the bicubic spline interpolation algorithm. See the documentation for + * BicubicSplineInterpolation for a detailed description of the automatic + * linear clamping feature. + */ + BicubicSplinePixelInterpolation( double clamp = __PCL_BICUBIC_SPLINE_CLAMPING_THRESHOLD ) + : m_clamp( clamp ) + { + } + + /*! + * Copy constructor. + */ + BicubicSplinePixelInterpolation( const BicubicSplinePixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + return String().Format( "Bicubic spline interpolation, c=%.2f", m_clamp ); + } + +private: + + float m_clamp; + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new BicubicSplineInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new BicubicSplineInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new BicubicSplineInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new BicubicSplineInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new BicubicSplineInterpolation( m_clamp ); + } +}; + +/*! + * \class BicubicPixelInterpolation + * \brief Bicubic pixel interpolation - an alias for BicubicSplinePixelInterpolation. + * + * BicubicPixelInterpolation is a synonym for the + * BicubicSplinePixelInterpolation class. + * + * \sa BicubicSplinePixelInterpolation + */ +class PCL_CLASS BicubicPixelInterpolation : public BicubicSplinePixelInterpolation +{ +public: + + /*! + * Constructs a %BicubicPixelInterpolation object. + * + * The optional \e c parameter is a linear clamping threshold for + * the bicubic spline interpolation algorithm. See the documentation for + * BicubicSplineInterpolation for a detailed description of the automatic + * linear clamping feature. + */ + BicubicPixelInterpolation( double c = __PCL_BICUBIC_SPLINE_CLAMPING_THRESHOLD ) + : BicubicSplinePixelInterpolation( c ) + { + } + + /*! + * Copy constructor. + */ + BicubicPixelInterpolation( const BicubicPixelInterpolation& ) = default; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BicubicBSplinePixelInterpolation + * \brief Bicubic B-spline pixel interpolation. + * + * %BicubicBSplinePixelInterpolation uses the bicubic B-spline interpolation + * algorithm (BicubicBSplineInterpolation) to interpolate pixel values from the + * nearest sixteen neighbor pixels. + * + * \sa PixelInterpolation, BicubicBSplineInterpolation, + * NearestNeighborPixelInterpolation, BilinearPixelInterpolation, + * BicubicSplinePixelInterpolation, BicubicFilterPixelInterpolation + */ +class PCL_CLASS BicubicBSplinePixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %BicubicBSplinePixelInterpolation object. + */ + BicubicBSplinePixelInterpolation() = default; + + /*! + * Copy constructor. + */ + BicubicBSplinePixelInterpolation( const BicubicBSplinePixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + return "Bicubic B-spline interpolation"; + } + +private: + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new BicubicBSplineInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new BicubicBSplineInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new BicubicBSplineInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new BicubicBSplineInterpolation; + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new BicubicBSplineInterpolation; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BicubicFilterPixelInterpolation + * \brief Pixel interpolation based on Mitchell-Netravali parameterized bicubic + * filters. + * + * %BicubicFilterPixelInterpolation uses a \e cubic \e filter (an instance of + * CubicFilter or a derived class) to interpolate pixel values in a square + * pixel matrix of the specified \e radius. + * + * \sa PixelInterpolation, CubicFilter, BicubicFilterInterpolation, + * NearestNeighborPixelInterpolation, BilinearPixelInterpolation, + * BicubicSplinePixelInterpolation, BicubicBSplinePixelInterpolation + */ +class PCL_CLASS BicubicFilterPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %BicubicFilterPixelInterpolation object. + * + * \param rh,rv Horizontal and vertical interpolation radii, respectively, + * in pixels. Both radii must be >= 1. Interpolation will + * take place in a rectangular pixel matrix whose dimensions + * will be width = 2*rh + 1 and height = 2*rv + 1. + * + * \param filter Reference to a CubicFilter instance that will be used as + * the interpolation filter. + * + */ + BicubicFilterPixelInterpolation( int rh, int rv, const CubicFilter& filter ) + : m_rh( Max( 1, rh ) ) + , m_rv( Max( 1, rv ) ) + { + PCL_PRECONDITION( rh >= 1 ) + PCL_PRECONDITION( rv >= 1 ) + m_filter = filter.Clone(); + } + + /*! + * Copy constructor. + */ + BicubicFilterPixelInterpolation( const BicubicFilterPixelInterpolation& x ) + : m_rh( x.m_rh ) + , m_rv( x.m_rv ) + { + m_filter = x.m_filter->Clone(); + } + + /*! + * Move constructor. + */ + BicubicFilterPixelInterpolation( BicubicFilterPixelInterpolation&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~BicubicFilterPixelInterpolation() + { + } + + /*! + */ + String Description() const override + { + return "Bicubic interpolation, " + m_filter->Description().AppendFormat( " (%dx%d)", 2*m_rh + 1, 2*m_rv + 1 ); + } + + /*! + * Returns a reference to the immutable cubic filter being used by this + * interpolation. + */ + const CubicFilter& Filter() const + { + return *m_filter; + } + +private: + + int m_rh, m_rv; + AutoPointer m_filter; + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new BicubicFilterInterpolation( m_rh, m_rv, *m_filter ); + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new BicubicFilterInterpolation( m_rh, m_rv, *m_filter ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new BicubicFilterInterpolation( m_rh, m_rv, *m_filter ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new BicubicFilterInterpolation( m_rh, m_rv, *m_filter ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new BicubicFilterInterpolation( m_rh, m_rv, *m_filter ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class LanczosPixelInterpolation + * \brief Lanczos pixel interpolation. + * + * %LanczosPixelInterpolation uses the Lanczos interpolation algorithm + * (LanczosInterpolation) to interpolate pixel values from the + * nearest 2*n^2 neighbor pixels, where n is the filter order. + * + * \sa PixelInterpolation, LanczosInterpolation, + * BicubicBSplinePixelInterpolation, NearestNeighborPixelInterpolation, + * BilinearPixelInterpolation, BicubicSplinePixelInterpolation, + * BicubicFilterPixelInterpolation, Lanczos3LUTPixelInterpolation, + * Lanczos4LUTPixelInterpolation, Lanczos5LUTPixelInterpolation + */ +class PCL_CLASS LanczosPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %LanczosPixelInterpolation object. + * + * \param n Filter order (n >= 1). The Lanczos filter interpolates + * from the nearest (2*n)^2 mapped source pixels for each + * interpolation point. The default filter order is 3, which + * means that the interpolation uses a neighborhood of 36 + * source pixels. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggresive deringing effect is + * achieved. A negative threshold value disables the + * interpolation clamping feature. The default value is 0.3. + */ + LanczosPixelInterpolation( int n = 3, float clamp = 0.3 ) + : m_n( Max( 1, n ) ) + , m_clamp( clamp ) + { + PCL_PRECONDITION( n >= 1 ) + PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + LanczosPixelInterpolation( const LanczosPixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + String desc = String().Format( "Lanczos-%d interpolation", m_n ); + if ( m_clamp >= 0 ) + desc.AppendFormat( ", c=%.2f", m_clamp ); + return desc; + } + +private: + + int m_n; // filter order + float m_clamp; // clamping threshold (enabled if >= 0) + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new LanczosInterpolation( m_n, m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new LanczosInterpolation( m_n, m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new LanczosInterpolation( m_n, m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new LanczosInterpolation( m_n, m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new LanczosInterpolation( m_n, m_clamp ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Lanczos3LUTPixelInterpolation + * \brief Lanczos 3rd-order LUT-based pixel interpolation. + * + * %Lanczos3LUTPixelInterpolation uses a Lanczos 3rd-order LUT-based interpolation + * algorithm (Lanczos3LUTInterpolation) to interpolate pixel values from the + * nearest 36 neighbor pixels. LUT-based interpolations are about three times + * faster than interpolations using function evaluations. + * + * \sa PixelInterpolation, Lanczos3LUTInterpolation, LanczosInterpolation, + * BicubicBSplinePixelInterpolation, NearestNeighborPixelInterpolation, + * BilinearPixelInterpolation, BicubicSplinePixelInterpolation, + * BicubicFilterPixelInterpolation, LanczosPixelInterpolation, + * Lanczos4LUTPixelInterpolation, Lanczos5LUTPixelInterpolation + */ +class PCL_CLASS Lanczos3LUTPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %Lanczos3LUTPixelInterpolation object. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggresive deringing effect is + * achieved. A negative threshold value disables the + * interpolation clamping feature. The default value is 0.3. + */ + Lanczos3LUTPixelInterpolation( float clamp = 0.3F ) + : m_clamp( clamp ) + { + PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + Lanczos3LUTPixelInterpolation( const Lanczos3LUTPixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + String desc( "Lanczos-3 LUT interpolation" ); + if ( m_clamp >= 0 ) + desc.AppendFormat( ", c=%.2f", m_clamp ); + return desc; + } + +private: + + float m_clamp; // clamping threshold (enabled if >= 0) + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new Lanczos3LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new Lanczos3LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new Lanczos3LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new Lanczos3LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new Lanczos3LUTInterpolation( m_clamp ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Lanczos4LUTPixelInterpolation + * \brief Lanczos 3rd-order LUT-based pixel interpolation. + * + * %Lanczos4LUTPixelInterpolation uses a Lanczos 4th-order LUT-based + * interpolation algorithm (Lanczos4LUTInterpolation) to interpolate pixel + * values from the nearest 64 neighbor pixels. LUT-based interpolations are + * about three times faster than interpolations using function evaluations. + * + * \sa PixelInterpolation, Lanczos4LUTInterpolation, LanczosInterpolation, + * BicubicBSplinePixelInterpolation, NearestNeighborPixelInterpolation, + * BilinearPixelInterpolation, BicubicSplinePixelInterpolation, + * BicubicFilterPixelInterpolation, LanczosPixelInterpolation, + * Lanczos3LUTPixelInterpolation, Lanczos5LUTPixelInterpolation + */ +class PCL_CLASS Lanczos4LUTPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %Lanczos4LUTPixelInterpolation object. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggresive deringing effect is + * achieved. A negative threshold value disables the + * interpolation clamping feature. The default value is 0.3. + */ + Lanczos4LUTPixelInterpolation( float clamp = 0.3F ) + : m_clamp( Range( clamp, 0.0F, 1.0F ) ) + { + PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + Lanczos4LUTPixelInterpolation( const Lanczos4LUTPixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + String desc( "Lanczos-4 LUT interpolation" ); + if ( m_clamp >= 0 ) + desc.AppendFormat( ", c=%.2f", m_clamp ); + return desc; + } + +private: + + float m_clamp; // clamping threshold (enabled if >= 0) + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new Lanczos4LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new Lanczos4LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new Lanczos4LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new Lanczos4LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new Lanczos4LUTInterpolation( m_clamp ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Lanczos5LUTPixelInterpolation + * \brief Lanczos 5th-order LUT-based pixel interpolation. + * + * %Lanczos5LUTPixelInterpolation uses a Lanczos 5th-order LUT-based + * interpolation algorithm (Lanczos5LUTInterpolation) to interpolate pixel + * values from the nearest 100 neighbor pixels. LUT-based interpolations are + * about three times faster than interpolations using function evaluations. + * + * \sa PixelInterpolation, Lanczos5LUTInterpolation, LanczosInterpolation, + * BicubicBSplinePixelInterpolation, NearestNeighborPixelInterpolation, + * BilinearPixelInterpolation, BicubicSplinePixelInterpolation, + * BicubicFilterPixelInterpolation, LanczosPixelInterpolation, + * Lanczos3LUTPixelInterpolation, Lanczos4LUTPixelInterpolation + */ +class PCL_CLASS Lanczos5LUTPixelInterpolation : public PixelInterpolation +{ +public: + + /*! + * Constructs a %Lanczos5LUTPixelInterpolation object. + * + * \param clamp Clamping threshold. Clamping is applied to fix undershoot + * (aka ringing) artifacts. A value of this parameter within + * the [0,1] range enables clamping: The lower the clamping + * threshold, the more aggresive deringing effect is + * achieved. A negative threshold value disables the + * interpolation clamping feature. The default value is 0.3. + */ + Lanczos5LUTPixelInterpolation( float clamp = 0.3F ) + : m_clamp( Range( clamp, 0.0F, 1.0F ) ) + { + PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 ) + } + + /*! + * Copy constructor. + */ + Lanczos5LUTPixelInterpolation( const Lanczos5LUTPixelInterpolation& ) = default; + + /*! + */ + String Description() const override + { + String desc( "Lanczos-5 LUT interpolation" ); + if ( m_clamp >= 0 ) + desc.AppendFormat( ", c=%.2f", m_clamp ); + return desc; + } + +private: + + float m_clamp; // clamping threshold (enabled if >= 0) + + BidimensionalInterpolation* + NewInterpolation( const FloatPixelTraits::sample* ) const override + { + return new Lanczos5LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const DoublePixelTraits::sample* ) const override + { + return new Lanczos5LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt8PixelTraits::sample* ) const override + { + return new Lanczos5LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt16PixelTraits::sample* ) const override + { + return new Lanczos5LUTInterpolation( m_clamp ); + } + + BidimensionalInterpolation* + NewInterpolation( const UInt32PixelTraits::sample* ) const override + { + return new Lanczos5LUTInterpolation( m_clamp ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#ifdef _MSC_VER +# pragma warning( pop ) +#endif + +#endif // __PCL_PixelInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PixelInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PixelTraits.h b/3rdparty/include/pcl/PixelTraits.h new file mode 100644 index 0000000..6e0b652 --- /dev/null +++ b/3rdparty/include/pcl/PixelTraits.h @@ -0,0 +1,6294 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PixelTraits.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_PixelTraits_h +#define __PCL_PixelTraits_h + +/// \file pcl/PixelTraits.h + +#include +#include + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +struct PixelTraitsLUT +{ + const float* pFLUT8; // uint8 -> float + const float* pFLUTA; // i/255^2 (direct 8-bit normalization) + const float* p1FLUT8; // 1 - pFLUT8 + const float* pFLUT16; // uint16 -> float + const float* pFLUT20; // uint20 -> float + const double* pDLUT8; // uint8 -> double + const double* pDLUTA; // i/255^2 (direct 8-bit normalization) + const double* p1DLUT8; // 1- pDLUT8 + const double* pDLUT16; // uint16 -> double + const double* pDLUT20; // uint20 -> double + const uint8* p8LUT16; // uint16 -> uint8 + const uint8* p8LUT20; // uint20 -> uint8 + const uint16* p16LUT8; // uint8 -> uint16 + const uint16* p16LUT20; // uint20 -> uint16 + const uint32* p20LUT8; // uint8 -> uint20 + const uint32* p20LUT16; // uint16 -> uint20 + const uint32* p24LUT8; // uint8 -> uint24 + const uint32* p24LUT16; // uint16 -> uint24 + const uint32* p32LUT8; // uint8 -> uint32 + const uint32* p32LUT16; // uint16 -> uint32 + const uint32* p32LUT20; // uint20 -> uint32 +}; + +extern PCL_DATA const PixelTraitsLUT* PTLUT; + +#ifndef __PCL_DONT_USE_PIXTRAITS_LUT +# define pFLUT8 PTLUT->pFLUT8 +# define pFLUTA PTLUT->pFLUTA +# define p1FLUT8 PTLUT->p1FLUT8 +# define pFLUT16 PTLUT->pFLUT16 +# define pFLUT20 PTLUT->pFLUT20 +# define pDLUT8 PTLUT->pDLUT8 +# define pDLUTA PTLUT->pDLUTA +# define p1DLUT8 PTLUT->p1DLUT8 +# define pDLUT16 PTLUT->pDLUT16 +# define pDLUT20 PTLUT->pDLUT20 +# define p8LUT16 PTLUT->p8LUT16 +# define p8LUT20 PTLUT->p8LUT20 +# define p16LUT8 PTLUT->p16LUT8 +# define p16LUT20 PTLUT->p16LUT20 +# define p20LUT8 PTLUT->p20LUT8 +# define p20LUT16 PTLUT->p20LUT16 +# define p24LUT8 PTLUT->p24LUT8 +# define p24LUT16 PTLUT->p24LUT16 +# define p32LUT8 PTLUT->p32LUT8 +# define p32LUT16 PTLUT->p32LUT16 +# define p32LUT20 PTLUT->p32LUT20 +#endif + +#define EPSILON_D 1.0e-16 +#define EPSILON_F 1.0e-8F + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericPixelTraits + * \brief Base class of all pixel traits classes. + * + * %GenericPixelTraits defines fundamental properties and functionality common + * to pixel sample types. + * + * The purpose of a pixel traits class is to characterize a data type + * to represent a single component of a pixel, or pixel sample. For + * example, a pixel traits class must provide primitive routines to copy + * samples between pixels and images, and to transform sample values between + * different numeric data types, among many other critical, low-level tasks. + * + * %GenericPixelTraits is in the core of PixInsight's scalable design: + * by isolating low-level pixel sample manipulations from medium-level pixel + * management and high-level image transformations, the whole platform achieves + * optimum efficiency and versatility for multiple pixel data types. + * + * %GenericPixelTraits is a template class that must be instantiated for + * suitable data types. Seven instantiations of %GenericPixelTraits have + * already been predefined in PCL, namely: + * + * + * + * + * + * + * + * + * + *
FloatPixelTraits 32-bit IEEE 754 floating point real pixel samples
DoublePixelTraits 64-bit IEEE 754 floating point real pixel samples
ComplexPixelTraits 32-bit IEEE 754 floating point complex pixel samples
DComplexPixelTraits 64-bit IEEE 754 floating point complex pixel samples
UInt8PixelTraits 8-bit unsigned integer pixel samples
UInt16PixelTraits 16-bit unsigned integer pixel samples
UInt32PixelTraits 32-bit unsigned integer pixel samples
+ * + * In coordination with the GenericImage

class, these template + * instantiations originate the corresponding seven fundamental two-dimensional + * image classes that have been predefined in PCL: + * + * + * + * + * + * + * + * + * + *
Image 32-bit IEEE 754 floating point real image
DImage 64-bit IEEE 754 floating point real image
ComplexImage 32-bit IEEE 754 floating point complex image
DComplexImage 64-bit IEEE 754 floating point complex image
UInt8Image 8-bit unsigned integer image
UInt16Image 16-bit unsigned integer image
UInt32Image 32-bit unsigned integer image
+ * + * \sa FloatPixelTraits, DoublePixelTraits, ComplexPixelTraits, DComplexPixelTraits, + * UInt8PixelTraits, UInt16PixelTraits, UInt32PixelTraits, GenericImage, SharedPixelData + */ +template +class PCL_CLASS GenericPixelTraits +{ +public: + + /*! + * Represents a pixel sample value. + */ + typedef S sample; + + enum { bytesPerSample = sizeof( sample ) }; + enum { bitsPerSample = bytesPerSample << 3 }; + + /*! + * Returns the number of bytes necessary to store a pixel sample. + */ + static constexpr int BytesPerSample() noexcept + { + return bytesPerSample; + } + + /*! + * Returns the number of bits in a pixel sample. + */ + static constexpr int BitsPerSample() noexcept + { + return bitsPerSample; + } + + /*! + * Returns the minimum valid sample value. This is usually a value of zero + * in the numeric data type represented by \c sample. + */ + static constexpr sample MinSampleValue() noexcept + { + return sample( 0 ); + } +}; + +#define IMPLEMENT_TRANSFER_OPERATIONS \ + \ + template \ + static void Fill( sample* __restrict__ f, T x, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr ) \ + sample v = ToSample( x ); \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f ) \ + *f = v; \ + } \ + \ + static void Fill( sample* __restrict__ f, sample x, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f ) \ + *f = x; \ + } \ + \ + template \ + static void Get( T* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + FromSample( *f, *g ); \ + } \ + \ + static void Get( sample* __restrict__ f, const sample* __restrict__ g, size_type n ) \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + *f = *g; \ + } \ + \ + template \ + static void Copy( sample* __restrict__ f, const T* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + *f = ToSample( *g ); \ + } \ + \ + static void Copy( sample* __restrict__ f, const sample* __restrict__ g, size_type n ) \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + *f = *g; \ + } \ + \ + template \ + static void GetMin( T* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + { \ + T h; FromSample( h, *g ); \ + if ( h < *f ) \ + *f = h; \ + } \ + } \ + \ + static void GetMin( sample* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + if ( *g < *f ) \ + *f = *g; \ + } \ + \ + template \ + static void CopyMin( sample* __restrict__ f, const T* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + { \ + sample h = ToSample( *g ); \ + if ( h < *f ) \ + *f = h; \ + } \ + } \ + \ + static void CopyMin( sample* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + if ( *g < *f ) \ + *f = *g; \ + } \ + \ + template \ + static void GetMax( T* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + { \ + T h; FromSample( h, *g ); \ + if ( *f < h ) \ + *f = h; \ + } \ + } \ + \ + static void GetMax( sample* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + if ( *f < *g ) \ + *f = *g; \ + } \ + \ + template \ + static void CopyMax( sample* __restrict__ f, const T* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + { \ + sample h = ToSample( *g ); \ + if ( *f < h ) \ + *f = h; \ + } \ + } \ + \ + static void CopyMax( sample* __restrict__ f, const sample* __restrict__ g, size_type n ) noexcept \ + { \ + PCL_PRECONDITION( f != nullptr && g != nullptr ) \ + PCL_IVDEP \ + for ( ; n > 0; --n, ++f, ++g ) \ + if ( *f < *g ) \ + *f = *g; \ + } + +// ---------------------------------------------------------------------------- + +/*! + * \class FloatPixelTraits + * \brief 32-bit IEEE 754 normalized floating point real pixel traits. + * + * %FloatPixelTraits is a template instantiation of GenericPixelTraits for the + * \c float type. It defines the characteristic properties and functionality of + * 32-bit IEEE 754 floating point real pixel samples. + * + * \sa GenericPixelTraits, GenericImage, Image + */ +class PCL_CLASS FloatPixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %FloatPixelTraits, this is equivalent to + * \c float. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return true; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %FloatPixelTraits, this member function returns "Float32". + */ + static constexpr const char* SampleFormat() noexcept + { + return "Float32"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %FloatPixelTraits, this member function returns 1.0F. + */ + static constexpr sample MaxSampleValue() noexcept + { + return 1.0F; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %FloatPixelTraits, this member function returns + * std::numeric_limits::lowest(). + */ + static constexpr sample LowestSampleValue() noexcept + { + return std::numeric_limits::lowest(); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %FloatPixelTraits, this member function returns + * std::numeric_limits::max(). + */ + static constexpr sample HighestSampleValue() noexcept + { + return std::numeric_limits::max(); + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static constexpr sample FloatToSample( T x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )/uint8_max; +#else + return pFLUT8[x]; +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return (sample( x ) - int8_min)/uint8_max; +#else + return pFLUT8[int( x ) - int8_min]; +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )/uint16_max; +#else + return pFLUT16[x]; +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return (sample( x ) - int16_min)/uint16_max; +#else + return pFLUT16[int( x ) - int16_min]; +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static constexpr sample ToSample( uint32 x ) noexcept + { + return sample( double( x )/uint32_max ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static constexpr sample ToSample( int32 x ) noexcept + { + return sample( (double( x ) - int32_min)/uint32_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static constexpr sample ToSample( float x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static constexpr sample ToSample( double x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static constexpr sample ToSample( const Complex& x ) noexcept + { + return sample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( RoundInt( b*uint8_max ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { + a = int8( RoundInt( b*uint8_max ) + int8_min ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( RoundInt( b*uint16_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( RoundInt( b*uint16_max ) + int16_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { + a = uint32( Round( double( b )*uint32_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { + a = int32( Round( double( b )*uint32_max ) + int32_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { + a = float( b ); + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { + a = double( b ); + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + a = typename Complex::component( b ); + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a += ToSample( b ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a -= ToSample( b ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + a *= ToSample( b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a /= ToSample( b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + a = pcl::Pow( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = pcl::Abs( a - ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = pcl::Min( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = pcl::Max( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Or( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia | ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Nor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia | ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void And( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia & ib ) ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. Negation is + * performed after converting the operand to an 8-bit unsigned integer, + * then the result is converted to the pixel sample type before assignment. + */ + static void Not( sample& a ) noexcept + { + uint8 ia; FromSample( ia, a ); + a = ToSample( uint8( ~ia ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting both operands to 8-bit unsigned integers, then the result is + * converted to the pixel sample type and assigned to \a a. + */ + template + static void Not( sample& a, T b ) noexcept + { + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void Nand( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia & ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia ^ ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia ^ ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + a = 1 - pcl::Min( (1 - a)/pcl::Max( EPSILON_F, ToSample( b ) ), 1.0F ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + a = a + ToSample( b ) - 1; + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + a = 1 - (1 - a)*(1 - ToSample( b )); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + a = pcl::Min( a/pcl::Max( EPSILON_F, (1 - ToSample( b )) ), 1.0F ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + a = (a > 0.5F) ? 1 - ((1 - 2*(a - 0.5F)) * (1 - ToSample( b ))) : 2*a*ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5F) ? 1 - (1 - a)*(1 - fb - 0.5F) : a*(fb + 0.5F); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5F) ? 1 - (1 - a)*(1 - 2*(fb - 0.5F)) : 2*a*fb; + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5F) ? 1 - pcl::Max( (1 - a)/(fb - 0.5F)/2, 1.0F ) : pcl::Min( a/pcl::Max( EPSILON_F, 1 - 2*fb ), 1.0F ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5F) ? pcl::Max( a + 2*(fb - 0.5F), 1.0F ) : pcl::Max( a + 2*fb - 1, 1.0F ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5F) ? pcl::Max( a, 2*(fb - 0.5F) ) : pcl::Min( a, 2*fb ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + a = pcl::Range( 0.5F - 2*(a - 0.5F)*(ToSample( b ) - 0.5F), 0.0F, 1.0F ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class DoublePixelTraits + * \brief 64-bit IEEE 754 normalized floating point real pixel traits. + * + * %DoublePixelTraits is a template instantiation of GenericPixelTraits for the + * \c double type. It defines the characteristic properties and functionality + * of 64-bit IEEE 754 floating point real pixel samples. + * + * \sa GenericPixelTraits, GenericImage, DImage + */ +class PCL_CLASS DoublePixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %DoublePixelTraits, this is equivalent + * to \c double. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return true; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %DoublePixelTraits, this member function returns "Float64". + */ + static constexpr const char* SampleFormat() noexcept + { + return "Float64"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %DoublePixelTraits, this member function returns 1.0. + */ + static constexpr sample MaxSampleValue() noexcept + { + return 1.0; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %DoublePixelTraits, this member function returns + * std::numeric_limits::lowest(). + */ + static constexpr sample LowestSampleValue() noexcept + { + return std::numeric_limits::lowest(); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %DoublePixelTraits, this member function returns + * std::numeric_limits::max(). + */ + static constexpr sample HighestSampleValue() noexcept + { + return std::numeric_limits::max(); + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static constexpr sample FloatToSample( T x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )/uint8_max; +#else + return pDLUT8[x]; +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return (sample( x ) - int8_min)/uint8_max; +#else + return pDLUT8[int( x ) - int8_min]; +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )/uint16_max; +#else + return pDLUT16[x]; +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return (sample( x ) - int16_min)/uint16_max; +#else + return pDLUT16[int( x ) - int16_min]; +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static constexpr sample ToSample( uint32 x ) noexcept + { + return sample( x )/uint32_max; + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static constexpr sample ToSample( int32 x ) noexcept + { + return (sample( x ) - int32_min)/uint32_max; + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static constexpr sample ToSample( float x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static constexpr sample ToSample( double x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static constexpr sample ToSample( const Complex& x ) noexcept + { + return sample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( RoundInt( b*uint8_max ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { + a = int8( RoundInt( b*uint8_max ) + int8_min ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( RoundInt( b*uint16_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( RoundInt( b*uint16_max ) + int16_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { + a = uint32( Round( sample( b )*uint32_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { + a = int32( Round( sample( b )*uint32_max ) + int32_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { + a = float( b ); + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { + a = double( b ); + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + a = typename Complex::component( b ); + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a += ToSample( b ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a -= ToSample( b ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + a *= ToSample( b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a /= ToSample( b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + a = pcl::Pow( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = pcl::Abs( a - ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = pcl::Min( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = pcl::Max( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Or( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia | ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Nor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia | ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void And( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia & ib ) ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. Negation is + * performed after converting the operand to an 8-bit unsigned integer, + * then the result is converted to the pixel sample type before assignment. + */ + static void Not( sample& a ) noexcept + { + uint8 ia; FromSample( ia, a ); + a = ToSample( uint8( ~ia ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting both operands to 8-bit unsigned integers, then the result is + * converted to the pixel sample type and assigned to \a a. + */ + template + static void Not( sample& a, T b ) noexcept + { + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void Nand( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia & ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia ^ ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia ^ ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + a = 1 - pcl::Min( (1 - a)/pcl::Max( EPSILON_D, ToSample( b ) ), 1.0 ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + a = a + ToSample( b ) - 1; + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + a = 1 - (1 - a)*(1 - ToSample( b )); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + a = pcl::Min( a/pcl::Max( EPSILON_D, (1 - ToSample( b )) ), 1.0 ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + a = (a > 0.5) ? 1 - ((1 - 2*(a - 0.5)) * (1 - ToSample( b ))) : 2*a*ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5) ? 1 - (1 - a)*(1 - fb - 0.5) : a*(fb + 0.5); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5) ? 1 - (1 - a)*(1 - 2*(fb - 0.5)) : 2*a*fb; + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5) ? 1 - pcl::Max( (1 - a)/(fb - 0.5)/2, 1.0 ) : pcl::Min( a/pcl::Max( EPSILON_D, 1 - 2*fb ), 1.0 ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5) ? pcl::Max( a + 2*(fb - 0.5), 1.0 ) : pcl::Max( a + 2*fb - 1, 1.0 ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + sample fb = ToSample( b ); + a = (fb > 0.5) ? pcl::Max( a, 2*(fb - 0.5) ) : pcl::Min( a, 2*fb ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + a = pcl::Range( 0.5 - 2*(a - 0.5)*(ToSample( b ) - 0.5), 0.0, 1.0 ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ComplexPixelTraits + * \brief 32-bit IEEE 754 normalized floating point complex pixel traits. + * + * %ComplexPixelTraits is a template instantiation of GenericPixelTraits for + * the \c Complex type. It defines the characteristic properties and + * functionality of 32-bit IEEE 754 floating point complex pixel samples. + * + * \sa GenericPixelTraits, GenericImage, ComplexImage + */ +class PCL_CLASS ComplexPixelTraits : public GenericPixelTraits > +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits > traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample. For + * %ComplexPixelTraits, this is equivalent to \c float. + */ + typedef sample::component component; + + static constexpr int BitsPerSample() noexcept + { + return sizeof( component ) << 3; + } + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return true; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %ComplexPixelTraits, this member function returns "Complex32". + */ + static constexpr const char* SampleFormat() noexcept + { + return "Complex32"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %ComplexPixelTraits, this member function returns {1.0F, 0.0F}. + */ + static sample MaxSampleValue() noexcept + { + return sample( component( 1 ) ); + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %ComplexPixelTraits, this member function returns + * {std::numeric_limits::lowest(), 0.0F}. + */ + static sample LowestSampleValue() noexcept + { + return sample( component( std::numeric_limits::lowest() ) ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %ComplexPixelTraits, this member function returns + * {std::numeric_limits::max(), 0.0F}. + */ + static sample HighestSampleValue() noexcept + { + return sample( component( std::numeric_limits::max() ) ); + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { + return sample( component( x ) ); + } + + template + static sample FloatToSample( sample x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( component( x )/uint8_max ); +#else + return sample( component( pFLUT8[x] ) ); +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( (component( x ) - int8_min)/uint8_max ); +#else + return sample( component( pFLUT8[int( x ) - int8_min] ) ); +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( component( x )/uint16_max ); +#else + return sample( component( pFLUT16[x] ) ); +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( (component( x ) - int16_min)/uint16_max ); +#else + return sample( component( pFLUT16[int( x ) - int16_min] ) ); +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint32 x ) noexcept + { + return sample( component( double( x )/uint32_max ) ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int32 x ) noexcept + { + return sample( component( (double( x ) - int32_min)/uint32_max ) ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return sample( component( x ) ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return sample( component( x ) ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static sample ToSample( const Complex& x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( RoundInt( pcl::Abs( b )*uint8_max ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSampl( int8& a, sample b ) noexcept + { + a = int8( RoundInt( pcl::Abs( b )*uint8_max ) + int8_min ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( RoundInt( pcl::Abs( b )*uint16_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( RoundInt( pcl::Abs( b )*uint16_max ) + int16_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { + a = uint32( Round( double( pcl::Abs( b ) )*uint32_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { + a = int32( Round( double( pcl::Abs( b ) )*uint32_max ) + int32_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { + a = float( pcl::Abs( b ) ); + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { + a = double( pcl::Abs( b ) ); + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + a = Complex( b ); + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a += ToSample( b ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a -= ToSample( b ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + a *= ToSample( b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a /= ToSample( b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + a = pcl::Pow( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = pcl::Abs( a - ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = pcl::Min( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = pcl::Max( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Or( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia | ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Nor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia | ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void And( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia & ib ) ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. Negation is + * performed after converting the operand to an 8-bit unsigned integer, + * then the result is converted to the pixel sample type before assignment. + */ + static void Not( sample& a ) noexcept + { + uint8 ia; FromSample( ia, a ); + a = ToSample( uint8( ~ia ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting both operands to 8-bit unsigned integers, then the result is + * converted to the pixel sample type and assigned to \a a. + */ + template + static void Not( sample& a, T b ) noexcept + { + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void Nand( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia & ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia ^ ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia ^ ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_F, fb ), 1.0F ) ); + } + + static void ColorBurn( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_F, b ), 1.0F ) ); + } + + static void ColorBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa + fb - 1 ); + } + + static void LinearBurn( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + static void LinearBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - (1 - fa)*(1 - fb) ); + } + + static void Screen( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + static void Screen( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_F, 1 - fb ), 1.0F ) ); + } + + static void ColorDodge( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_F, 1 - b ), 1.0F ) ); + } + + static void ColorDodge( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fa > 0.5F) ? 1 - ((1 - 2*(fa - 0.5F)) * (1 - fb)) : 2*a*fb ); + } + + static void Overlay( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5F) ? 1 - ((1 - 2*(fa - 0.5F)) * (1 - b)) : 2*a*b ); + } + + static void Overlay( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - b)) : 2*a*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - (1 - fa)*(1 - fb - 0.5F) : a*(fb + 0.5F) ); + } + + static void SoftLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - (1 - fa)*(1 - b - 0.5F) : a*(b + 0.5F) ); + } + + static void SoftLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - b - 0.5) : a*(b + 0.5) ); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5F)) : 2*fa*fb ); + } + + static void HardLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - (1 - fa)*(1 - 2*(b - 0.5F)) : 2*fa*b ); + } + + static void HardLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - 2*(b - 0.5)) : 2*fa*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5F)/2, 1.0F ) : pcl::Min( fa/pcl::Max( EPSILON_F, 1 - 2*fb ), 1.0F ) ); + } + + static void VividLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - pcl::Max( (1 - fa)/(b - 0.5F)/2, 1.0F ) : pcl::Min( fa/pcl::Max( EPSILON_F, 1 - 2*b ), 1.0F ) ); + } + + static void VividLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - pcl::Max( (1 - fa)/(b - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? pcl::Max( fa + 2*(fb - 0.5F), 1.0F ) : pcl::Max( fa + 2*fb - 1, 1.0F ) ); + } + + static void LinearLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? pcl::Max( fa + 2*(b - 0.5F), 1.0F ) : pcl::Max( fa + 2*b - 1, 1.0F ) ); + } + + static void LinearLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa + 2*(b - 0.5), 1.0 ) : pcl::Max( fa + 2*b - 1, 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? pcl::Max( fa, 2*(fb - 0.5F) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? pcl::Max( fa, 2*(b - 0.5F) ) : pcl::Min( fa, 2*b ) ); + } + + static void PinLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa, 2*(b - 0.5) ) : pcl::Min( fa, 2*b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Range( 0.5F - 2*(fa - 0.5F)*(fb - 0.5F), 0.0F, 1.0F ) ); + } + + static void Exclusion( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5F - 2*(fa - 0.5F)*(b - 0.5F), 0.0F, 1.0F ) ); + } + + static void Exclusion( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(b - 0.5), 0.0, 1.0 ) ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class DComplexPixelTraits + * \brief 64-bit IEEE 754 normalized floating point complex pixel traits. + * + * %DComplexPixelTraits is a template instantiation of GenericPixelTraits for + * the \c Complex type. It defines the characteristic properties and + * functionality of 64-bit IEEE 754 floating point complex pixel samples. + * + * \sa GenericPixelTraits, GenericImage, DComplexImage + */ +class PCL_CLASS DComplexPixelTraits : public GenericPixelTraits > +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits > traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample. For + * %DComplexPixelTraits, this is equivalent to \c double. + */ + typedef sample::component component; + + /*! + */ + static constexpr int BitsPerSample() noexcept + { + return sizeof( component ) << 3; + } + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return true; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %DComplexPixelTraits, this member function returns "Complex64". + */ + static constexpr const char* SampleFormat() noexcept + { + return "Complex64"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %DComplexPixelTraits, this member function returns {1.0, 0.0}. + */ + static sample MaxSampleValue() noexcept + { + return sample( component( 1 ) ); + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %DComplexPixelTraits, this member function returns + * {std::numeric_limits::lowest(), 0.0F}. + */ + static sample LowestSampleValue() noexcept + { + return sample( component( std::numeric_limits::lowest() ) ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %DComplexPixelTraits, this member function returns + * {std::numeric_limits::max(), 0.0F}. + */ + static sample HighestSampleValue() noexcept + { + return sample( component( std::numeric_limits::max() ) ); + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { + return sample( component( x ) ); + } + + template + static sample FloatToSample( sample x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( component( x )/uint8_max ); +#else + return sample( component( pDLUT8[x] ) ); +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( (component( x ) - int8_min)/uint8_max ); +#else + return sample( component( pDLUT8[int( x ) - int8_min] ) ); +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( component( x )/uint16_max ); +#else + return sample( component( pDLUT16[x] ) ); +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( (component( x ) - int16_min)/uint16_max ); +#else + return sample( component( pDLUT16[int( x ) - int16_min] ) ); +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint32 x ) noexcept + { + return sample( component( x )/uint32_max ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int32 x ) noexcept + { + return sample( (component( x ) - int32_min)/uint32_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return sample( component( x ) ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return sample( component( x ) ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static sample ToSample( const Complex& x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( RoundInt( pcl::Abs( b )*uint8_max ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { + a = int8( RoundInt( pcl::Abs( b )*uint8_max ) + int8_min ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( RoundInt( pcl::Abs( b )*uint16_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( RoundInt( pcl::Abs( b )*uint16_max ) + int16_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { + a = uint32( Round( component( pcl::Abs( b ) )*uint32_max ) ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { + a = int32( Round( component( pcl::Abs( b ) )*uint32_max ) + int32_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { + a = float( pcl::Abs( b ) ); + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { + a = double( pcl::Abs( b ) ); + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + a = Complex( b ); + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a += ToSample( b ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a -= ToSample( b ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + a *= ToSample( b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a /= ToSample( b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + a = pcl::Pow( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = pcl::Abs( a - ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = pcl::Min( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = pcl::Max( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Or( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia | ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Nor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia | ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void And( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia & ib ) ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. Negation is + * performed after converting the operand to an 8-bit unsigned integer, + * then the result is converted to the pixel sample type before assignment. + */ + static void Not( sample& a ) noexcept + { + uint8 ia; FromSample( ia, a ); + a = ToSample( uint8( ~ia ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting both operands to 8-bit unsigned integers, then the result is + * converted to the pixel sample type and assigned to \a a. + */ + template + static void Not( sample& a, T b ) noexcept + { + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * both operands to 8-bit unsigned integers, then the result is converted to + * the pixel sample type and assigned to \a a. + */ + template + static void Nand( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia & ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ia ^ ib ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting both operands to 8-bit unsigned integers, then the + * result is converted to the pixel sample type and assigned to \a a. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + uint8 ia; FromSample( ia, a ); + uint8 ib; FromSample( ib, ToSample( b ) ); + a = ToSample( uint8( ~(ia ^ ib) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, fb ), 1.0 ) ); + } + + static void ColorBurn( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, double( b ) ), 1.0 ) ); + } + + static void ColorBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa + fb - 1 ); + } + + static void LinearBurn( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + double( b ) - 1 ); + } + + static void LinearBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - (1 - fa)*(1 - fb) ); + } + + static void Screen( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - double( b )) ); + } + + static void Screen( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - fb ), 1.0 ) ); + } + + static void ColorDodge( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - double( b ) ), 1.0 ) ); + } + + static void ColorDodge( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - fb)) : 2*a*fb ); + } + + static void Overlay( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - double( b ))) : 2*a*double( b ) ); + } + + static void Overlay( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - b)) : 2*a*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - fb - 0.5) : a*(fb + 0.5) ); + } + + static void SoftLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - fb - 0.5) : a*(fb + 0.5) ); + } + + static void SoftLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - b - 0.5) : a*(b + 0.5) ); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5)) : 2*fa*fb ); + } + + static void HardLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5)) : 2*fa*fb ); + } + + static void HardLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - 2*(b - 0.5)) : 2*fa*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*fb ), 1.0 ) ); + } + + static void VividLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*fb ), 1.0 ) ); + } + + static void VividLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - pcl::Max( (1 - fa)/(b - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa + 2*(fb - 0.5), 1.0 ) : pcl::Max( fa + 2*fb - 1, 1.0 ) ); + } + + static void LinearLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa + 2*(fb - 0.5), 1.0 ) : pcl::Max( fa + 2*fb - 1, 1.0 ) ); + } + + static void LinearLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa + 2*(b - 0.5), 1.0 ) : pcl::Max( fa + 2*b - 1, 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa, 2*(fb - 0.5) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa, 2*(fb - 0.5) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa, 2*(b - 0.5) ) : pcl::Min( fa, 2*b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(fb - 0.5), 0.0, 1.0 ) ); + } + + static void Exclusion( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(double( b ) - 0.5), 0.0, 1.0 ) ); + } + + static void Exclusion( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(b - 0.5), 0.0, 1.0 ) ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class UInt8PixelTraits + * \brief 8-bit unsigned integer pixel traits. + * + * %UInt8PixelTraits is a template instantiation of GenericPixelTraits for the + * \c uint8 type. It defines the characteristic properties and functionality of + * 8-bit unsigned integer pixel samples. + * + * \sa GenericPixelTraits, GenericImage, UInt8Image + */ +class PCL_CLASS UInt8PixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %UInt8PixelTraits, this is equivalent to + * \c uint8. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %UInt8PixelTraits, this member function returns "UInt8". + */ + static constexpr const char* SampleFormat() noexcept + { + return "UInt8"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %UInt8PixelTraits, this member function returns 255. + */ + static constexpr sample MaxSampleValue() noexcept + { + return uint8_max; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %UInt8PixelTraits, this member function returns 0. + */ + static constexpr sample LowestSampleValue() noexcept + { + return sample( 0 ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %UInt8PixelTraits, this member function returns 255. + */ + static constexpr sample HighestSampleValue() noexcept + { + return uint8_max; + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { +#ifdef __PCL_ENFORCE_PIXTRAITS_FLOAT_RANGE + return sample( pcl::Range( Round( x ), T( 0 ), T( uint8_max ) ) ); +#else + // ### N.B.: x must be in the range [0,uint8_max]. + return sample( RoundInt( x ) ); +#endif + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static constexpr sample ToSample( uint8 x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static constexpr sample ToSample( int8 x ) noexcept + { + return sample( int32( x ) - int32( int8_min ) ); + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( Round( double( x )*uint16_to_uint8 ) ); +#else + return p8LUT16[x]; +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( Round( (double( x ) - int16_min)*uint16_to_uint8 ) ); +#else + return p8LUT16[int( x ) - int16_min]; +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint32 x ) noexcept + { + return sample( Round( double( x )*uint32_to_uint8 ) ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int32 x ) noexcept + { + return sample( Round( (double( x ) - int32_min)*uint32_to_uint8 ) ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return FloatToSample( x*uint8_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( float x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0F, 1.0F )*uint8_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return FloatToSample( x*uint8_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( double x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0, 1.0 )*uint8_max ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static sample ToSample( const Complex& x ) noexcept + { + return ToSample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( b ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { + a = int8( int32( b ) + int32( int8_min ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint16( b )*uint8_to_uint16; +#else + a = p16LUT8[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int16( int32( uint16( b )*uint8_to_uint16 ) + int32( int16_min ) ); +#else + a = int16( int32( p16LUT8[b] ) + int32( int16_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint32( b )*uint8_to_uint32; +#else + a = p32LUT8[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int32( double( uint32( b )*uint8_to_uint32 ) + int32_min ); +#else + a = int32( int64( p32LUT8[b] ) + int64( int32_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = float( b )/uint8_max; +#else + a = pFLUT8[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = double( b )/uint8_max; +#else + a = pDLUT8[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + typename Complex::component c; + FromSample( c, b ); + a = c; + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a = sample( pcl::Range( uint32( a ) + uint32( ToSample( b ) ), + uint32( 0 ), uint32( uint8_max ) ) ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a = sample( pcl::Range( int32( a ) - int32( ToSample( b ) ), + int32( 0 ), int32( uint8_max ) ) ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa * fb ); + } + + /*! # + */ + static void Mul( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, pcl::Complex b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a = FloatToSample( float( a )/float( ToSample( b ) ) ); + } + + /*! # + */ + static void Div( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, pcl::Complex b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Pow( fa, fb ) ); + } + + /*! # + */ + static void Pow( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! # + */ + static void Pow( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! # + */ + static void Pow( sample& a, pcl::Complex b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! # + */ + static void Pow( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = sample( pcl::Range( pcl::Abs( int32( a ) - int32( ToSample( b ) ) ), + int32( 0 ), int32( uint8_max ) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = pcl::Min( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = pcl::Max( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Or( sample& a, T b ) noexcept + { + a |= ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Nor( sample& a, T b ) noexcept + { + a = ~(a | ToSample( b )); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * the right-hand side operand \a b to the pixel sample type. + */ + template + static void And( sample& a, T b ) noexcept + { + a &= ToSample( b ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. + */ + static void Not( sample& a ) noexcept + { + a = sample( ~a ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Not( sample& a, T b ) noexcept + { + a = sample( ~ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * the right-hand side operand \a b to the pixel sample type. + */ + template + static void Nand( sample& a, T b ) noexcept + { + a = sample( ~(a & ToSample( b )) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Xor( sample& a, T b ) noexcept + { + a ^= ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + a = sample( ~(a ^ ToSample( b )) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_F, fb ), 1.0F ) ); + } + + static void ColorBurn( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_F, b ), 1.0F ) ); + } + + static void ColorBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa + fb - 1 ); + } + + static void LinearBurn( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + static void LinearBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - (1 - fa)*(1 - fb) ); + } + + static void Screen( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + static void Screen( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_F, 1 - fb ), 1.0F ) ); + } + + static void ColorDodge( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_F, 1 - b ), 1.0F ) ); + } + + static void ColorDodge( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fa > 0.5F) ? 1 - ((1 - 2*(fa - 0.5F)) * (1 - fb)) : 2*a*fb ); + } + + static void Overlay( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5F) ? 1 - ((1 - 2*(fa - 0.5F)) * (1 - b)) : 2*a*b ); + } + + static void Overlay( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - b)) : 2*a*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - (1 - fa)*(1 - fb - 0.5F) : a*(fb + 0.5F) ); + } + + static void SoftLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - (1 - fa)*(1 - b - 0.5F) : a*(b + 0.5F) ); + } + + static void SoftLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - b - 0.5) : a*(b + 0.5) ); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5F)) : 2*fa*fb ); + } + + static void HardLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - (1 - fa)*(1 - 2*(b - 0.5F)) : 2*fa*b ); + } + + static void HardLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - 2*(b - 0.5)) : 2*fa*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5F)/2, 1.0F ) : pcl::Min( fa/pcl::Max( EPSILON_F, 1 - 2*fb ), 1.0F ) ); + } + + static void VividLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - pcl::Max( (1 - fa)/(b - 0.5F)/2, 1.0F ) : pcl::Min( fa/pcl::Max( EPSILON_F, 1 - 2*b ), 1.0F ) ); + } + + static void VividLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - pcl::Max( (1 - fa)/(b - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? pcl::Max( fa + 2*(fb - 0.5F), 1.0F ) : pcl::Max( fa + 2*fb - 1, 1.0F ) ); + } + + static void LinearLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? pcl::Max( fa + 2*(b - 0.5F), 1.0F ) : pcl::Max( fa + 2*b - 1, 1.0F ) ); + } + + static void LinearLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa + 2*(b - 0.5), 1.0 ) : pcl::Max( fa + 2*b - 1, 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? pcl::Max( fa, 2*(fb - 0.5F) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? pcl::Max( fa, 2*(b - 0.5F) ) : pcl::Min( fa, 2*b ) ); + } + + static void PinLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa, 2*(b - 0.5) ) : pcl::Min( fa, 2*b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Range( 0.5F - 2*(fa - 0.5F)*(fb - 0.5F), 0.0F, 1.0F ) ); + } + + static void Exclusion( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5F - 2*(fa - 0.5F)*(b - 0.5F), 0.0F, 1.0F ) ); + } + + static void Exclusion( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(b - 0.5), 0.0, 1.0 ) ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class UInt16PixelTraits + * \brief 16-bit unsigned integer pixel traits. + * + * %UInt16PixelTraits is a template instantiation of GenericPixelTraits for the + * \c uint16 type. It defines the characteristic properties and functionality + * of 16-bit unsigned integer pixel samples. + * + * \sa GenericPixelTraits, GenericImage, UInt16Image + */ +class PCL_CLASS UInt16PixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %UInt16PixelTraits, this is equivalent + * to \c uint16. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %UInt16PixelTraits, this member function returns "UInt16". + */ + static constexpr const char* SampleFormat() noexcept + { + return "UInt16"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %UInt16PixelTraits, this member function returns 65535. + */ + static constexpr sample MaxSampleValue() noexcept + { + return uint16_max; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %UInt16PixelTraits, this member function returns 0. + */ + static constexpr sample LowestSampleValue() noexcept + { + return sample( 0 ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %UInt16PixelTraits, this member function returns 255. + */ + static constexpr sample HighestSampleValue() noexcept + { + return uint16_max; + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { +#ifdef __PCL_ENFORCE_PIXTRAITS_FLOAT_RANGE + return sample( pcl::Range( Round( x ), T( 0 ), T( uint16_max ) ) ); +#else + // ### N.B.: x must be in the range [0,uint16_max]. + return sample( RoundInt( x ) ); +#endif + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )*sample( uint8_to_uint16 ); +#else + return p16LUT8[x]; +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( (int32( x ) - int32( int8_min ))*int32( uint8_to_uint16 ) ); +#else + return p16LUT8[int( x ) - int( int8_min )]; +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static constexpr sample ToSample( uint16 x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static constexpr sample ToSample( int16 x ) noexcept + { + return sample( int32( x ) - int32( int16_min ) ); + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint32 x ) noexcept + { + return sample( Round( double( x )*uint32_to_uint16 ) ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int32 x ) noexcept + { + return sample( Round( (double( x ) - int32_min)*uint32_to_uint16 ) ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return FloatToSample( x*uint16_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( float x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0F, 1.0F )*uint16_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return FloatToSample( x*uint16_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( double x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0, 1.0 )*uint16_max ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static constexpr sample ToSample( const Complex& x ) noexcept + { + return ToSample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint8( Round( double( b )*uint16_to_uint8 ) ); +#else + a = p8LUT16[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int8( Round( double( b )*uint16_to_uint8 ) + int8_min ); +#else + a = int8( int( p8LUT16[b] ) + int( int8_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( b ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( int32( b ) + int32( int16_min ) ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint32( b )*uint16_to_uint32; +#else + a = p32LUT16[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int32( double( uint32( b )*uint16_to_uint32 ) + int32_min ); +#else + a = int32( int64( p32LUT16[b] ) + int64( int32_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = float( b )/uint16_max; +#else + a = pFLUT16[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = double( b )/uint16_max; +#else + a = pDLUT16[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + typename Complex::component c; + FromSample( c, b ); + a = c; + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a = sample( pcl::Range( uint32( a ) + uint32( ToSample( b ) ), + uint32( 0 ), uint32( uint16_max ) ) ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a = sample( pcl::Range( int32( a ) - int32( ToSample( b ) ), + int32( 0 ), int32( uint16_max ) ) ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa * fb ); + } + + /*! # + */ + static void Mul( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a = FloatToSample( double( a )/double( ToSample( b ) ) ); + } + + /*! # + */ + static void Div( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Pow( fa, fb ) ); + } + + /*! # + */ + static void Pow( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, double( b ) ) ); + } + + /*! # + */ + static void Pow( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! # + */ + static void Pow( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, pcl::Complex( b ) ) ); + } + + /*! # + */ + static void Pow( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = sample( pcl::Range( pcl::Abs( int32( a ) - int32( ToSample( b ) ) ), + int32( 0 ), int32( uint16_max ) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = pcl::Min( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = pcl::Max( a, ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Or( sample& a, T b ) noexcept + { + a |= ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Nor( sample& a, T b ) noexcept + { + a = ~(a | ToSample( b )); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * the right-hand side operand \a b to the pixel sample type. + */ + template + static void And( sample& a, T b ) noexcept + { + a &= ToSample( b ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. + */ + static void Not( sample& a ) noexcept + { + a = sample( ~a ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Not( sample& a, T b ) noexcept + { + a = sample( ~ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * the right-hand side operand \a b to the pixel sample type. + */ + template + static void Nand( sample& a, T b ) noexcept + { + a = sample( ~(a & ToSample( b )) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Xor( sample& a, T b ) noexcept + { + a ^= ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + a = sample( ~(a ^ ToSample( b )) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_F, fb ), 1.0F ) ); + } + + static void ColorBurn( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_F, b ), 1.0F ) ); + } + + static void ColorBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa + fb - 1 ); + } + + static void LinearBurn( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + static void LinearBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - (1 - fa)*(1 - fb) ); + } + + static void Screen( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + static void Screen( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_F, 1 - fb ), 1.0F ) ); + } + + static void ColorDodge( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_F, 1 - b ), 1.0F ) ); + } + + static void ColorDodge( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fa > 0.5F) ? 1 - ((1 - 2*(fa - 0.5F)) * (1 - fb)) : 2*a*fb ); + } + + static void Overlay( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5F) ? 1 - ((1 - 2*(fa - 0.5F)) * (1 - b)) : 2*a*b ); + } + + static void Overlay( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - b)) : 2*a*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - (1 - fa)*(1 - fb - 0.5F) : a*(fb + 0.5F) ); + } + + static void SoftLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - (1 - fa)*(1 - b - 0.5F) : a*(b + 0.5F) ); + } + + static void SoftLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - b - 0.5) : a*(b + 0.5) ); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5F)) : 2*fa*fb ); + } + + static void HardLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - (1 - fa)*(1 - 2*(b - 0.5F)) : 2*fa*b ); + } + + static void HardLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - 2*(b - 0.5)) : 2*fa*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5F)/2, 1.0F ) : pcl::Min( fa/pcl::Max( EPSILON_F, 1 - 2*fb ), 1.0F ) ); + } + + static void VividLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? 1 - pcl::Max( (1 - fa)/(b - 0.5F)/2, 1.0F ) : pcl::Min( fa/pcl::Max( EPSILON_F, 1 - 2*b ), 1.0F ) ); + } + + static void VividLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - pcl::Max( (1 - fa)/(b - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? pcl::Max( fa + 2*(fb - 0.5F), 1.0F ) : pcl::Max( fa + 2*fb - 1, 1.0F ) ); + } + + static void LinearLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? pcl::Max( fa + 2*(b - 0.5F), 1.0F ) : pcl::Max( fa + 2*b - 1, 1.0F ) ); + } + + static void LinearLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa + 2*(b - 0.5), 1.0 ) : pcl::Max( fa + 2*b - 1, 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5F) ? pcl::Max( fa, 2*(fb - 0.5F) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( (b > 0.5F) ? pcl::Max( fa, 2*(b - 0.5F) ) : pcl::Min( fa, 2*b ) ); + } + + static void PinLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa, 2*(b - 0.5) ) : pcl::Min( fa, 2*b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + float fa; FromSample( fa, a ); + float fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Range( 0.5F - 2*(fa - 0.5F)*(fb - 0.5F), 0.0F, 1.0F ) ); + } + + static void Exclusion( sample& a, float b ) noexcept + { + float fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5F - 2*(fa - 0.5F)*(b - 0.5F), 0.0F, 1.0F ) ); + } + + static void Exclusion( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(b - 0.5), 0.0, 1.0 ) ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class UInt32PixelTraits + * \brief 32-bit unsigned integer pixel traits. + * + * %UInt32PixelTraits is a template instantiation of GenericPixelTraits for the + * \c uint32 type. It defines the characteristic properties and functionality + * of 32-bit unsigned integer pixel samples. + * + * \sa GenericPixelTraits, GenericImage, UInt32Image + */ +class PCL_CLASS UInt32PixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %UInt32PixelTraits, this is equivalent + * to \c uint32. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %UInt32PixelTraits, this member function returns "UInt32". + */ + static constexpr const char* SampleFormat() noexcept + { + return "UInt32"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %UInt32PixelTraits, this member function returns 4294967295. + */ + static constexpr sample MaxSampleValue() noexcept + { + return uint32_max; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %UInt32PixelTraits, this member function returns 0. + */ + static constexpr sample LowestSampleValue() noexcept + { + return sample( 0 ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %UInt32PixelTraits, this member function returns 4294967295. + */ + static constexpr sample HighestSampleValue() noexcept + { + return uint32_max; + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { +#ifdef __PCL_ENFORCE_PIXTRAITS_FLOAT_RANGE + return sample( pcl::Range( Round( x ), T( 0 ), T( uint32_max ) ) ); +#else + // ### N.B.: x must be in the range [0,uint32_max]. + return sample( RoundI64( x ) ); +#endif + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )*sample( uint8_to_uint32 ); +#else + return p32LUT8[x]; +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( uint32( int32( x ) - int32( int8_min ) )*uint8_to_uint32 ); +#else + return p32LUT8[int( x ) - int( int8_min )]; +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x )*sample( uint16_to_uint32 ); +#else + return p32LUT16[x]; +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( uint32( int32( x ) - int32( int16_min ) )*uint16_to_uint32 ); +#else + return p32LUT16[int( x ) - int( int16_min )]; +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static constexpr sample ToSample( uint32 x ) noexcept + { + return sample( x ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static constexpr sample ToSample( int32 x ) noexcept + { + return sample( double( x ) - double( int32_min ) ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return FloatToSample( double( x )*uint32_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( float x ) noexcept + { + return FloatToSample( pcl::Range( double( x ), 0.0, 1.0 )*uint32_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return FloatToSample( x*uint32_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( double x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0, 1.0 )*uint32_max ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static sample ToSample( const Complex& x ) noexcept + { + return ToSample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( RoundInt( double( b )*uint32_to_uint8 ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { + a = int8( RoundInt( double( b )*uint32_to_uint8 ) + int8_min ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( RoundInt( double( b )*uint32_to_uint16 ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( RoundInt( double( b )*uint32_to_uint16 ) + int16_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { + a = uint32( b ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { + a = TruncInt( double( b ) + int32_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { + a = float( double( b )/uint32_max ); + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { + a = double( b )/uint32_max; + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + typename Complex::component c; + FromSample( c, b ); + a = c; + } + + /*! + * Copies a T value \a b to a pixel sample variable \a a, with implicit + * conversion from the source data type T to the pixel sample type. + */ + template + static void Mov( sample& a, T b ) noexcept + { + a = ToSample( b ); + } + + /*! + * Adds a T value \a b to a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Add( sample& a, T b ) noexcept + { + a = sample( pcl::Range( double( a ) + double( ToSample( b ) ), + 0.0, double( uint32_max ) ) ); + } + + /*! + * Subtracts a T value \a b from a pixel sample variable \a a, with implicit + * data type conversion. + */ + template + static void Sub( sample& a, T b ) noexcept + { + a = sample( pcl::Range( double( a ) - double( ToSample( b ) ), + 0.0, double( uint32_max ) ) ); + } + + /*! + * Multiplies a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Mul( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa * fb ); + } + + /*! # + */ + static void Mul( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! # + */ + static void Mul( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa * b ); + } + + /*! + * Divides a pixel sample variable \a a by a T value \a b, with implicit + * data type conversion. + */ + template + static void Div( sample& a, T b ) noexcept + { + a = FloatToSample( double( a )/double( ToSample( b ) ) ); + } + + /*! # + */ + static void Div( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! # + */ + static void Div( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa / b ); + } + + /*! + * Raises a pixel sample variable \a a to a T exponent value \a b, with + * implicit data type conversion. + */ + template + static void Pow( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Pow( fa, fb ) ); + } + + /*! # + */ + static void Pow( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, double( b ) ) ); + } + + /*! # + */ + static void Pow( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! # + */ + static void Pow( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, pcl::Complex( b ) ) ); + } + + /*! # + */ + static void Pow( sample& a, pcl::Complex b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Pow( fa, b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a its absolute difference with a T + * value \a b, with implicit data type conversion. + */ + template + static void Dif( sample& a, T b ) noexcept + { + a = sample( pcl::Range( pcl::Abs( double( a ) - double( ToSample( b ) ) ), + 0.0, double( uint32_max ) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the minimum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Min( sample& a, T b ) noexcept + { + a = sample( pcl::Min( a, ToSample( b ) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the maximum of its current value + * and a T value \a b, with implicit data type conversion. + */ + template + static void Max( sample& a, T b ) noexcept + { + a = sample( pcl::Max( a, ToSample( b ) ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive OR + * operation with a T value \a b. The bitwise OR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Or( sample& a, T b ) noexcept + { + a |= ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise inclusive NOR + * operation with a T value \a b. The bitwise NOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Nor( sample& a, T b ) noexcept + { + a = ~(a | ToSample( b )); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise AND operation with a + * T value \a b. The bitwise AND operation is performed after converting + * the right-hand side operand \a b to the pixel sample type. + */ + template + static void And( sample& a, T b ) noexcept + { + a &= ToSample( b ); + } + + /*! + * Negates (bitwise NOT operation) a pixel sample variable \a a. + */ + static void Not( sample& a ) noexcept + { + a = sample( ~a ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise negation (NOT + * operation) of a T value \a b. Bitwise negation is performed after + * converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Not( sample& a, T b ) noexcept + { + a = sample( ~ToSample( b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise NAND operation with a + * T value \a b. The bitwise NAND operation is performed after converting + * the right-hand side operand \a b to the pixel sample type. + */ + template + static void Nand( sample& a, T b ) noexcept + { + a = sample( ~(a & ToSample( b )) ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive OR (XOR) + * operation with a T value \a b. The bitwise XOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Xor( sample& a, T b ) noexcept + { + a ^= ToSample( b ); + } + + /*! + * Assigns to a pixel sample variable \a a the bitwise exclusive NOR (XNOR) + * operation with a T value \a b. The bitwise XNOR operation is performed + * after converting the right-hand side operand \a b to the pixel sample type. + */ + template + static void Xnor( sample& a, T b ) noexcept + { + a = sample( ~(a ^ ToSample( b )) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorBurn( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, fb ), 1.0 ) ); + } + + static void ColorBurn( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, double( b ) ), 1.0 ) ); + } + + static void ColorBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - pcl::Min( (1 - fa)/pcl::Max( EPSILON_D, b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear burn standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void LinearBurn( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( fa + fb - 1 ); + } + + static void LinearBurn( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + double( b ) - 1 ); + } + + static void LinearBurn( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( fa + b - 1 ); + } + + /*! + * Assigns to a pixel sample variable \a a the screen standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Screen( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( 1 - (1 - fa)*(1 - fb) ); + } + + static void Screen( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - double( b )) ); + } + + static void Screen( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( 1 - (1 - fa)*(1 - b) ); + } + + /*! + * Assigns to a pixel sample variable \a a the color dodge standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void ColorDodge( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - fb ), 1.0 ) ); + } + + static void ColorDodge( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - double( b ) ), 1.0 ) ); + } + + static void ColorDodge( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Min( fa/pcl::Max( EPSILON_D, 1 - b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the overlay standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Overlay( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - fb)) : 2*a*fb ); + } + + static void Overlay( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - double( b ))) : 2*a*double( b ) ); + } + + static void Overlay( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (fa > 0.5) ? 1 - ((1 - 2*(fa - 0.5)) * (1 - b)) : 2*a*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the soft light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void SoftLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - fb - 0.5) : a*(fb + 0.5) ); + } + + static void SoftLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - fb - 0.5) : a*(fb + 0.5) ); + } + + static void SoftLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - b - 0.5) : a*(b + 0.5) ); + } + + /*! + * Assigns to a pixel sample variable \a a the hard light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void HardLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5)) : 2*fa*fb ); + } + + static void HardLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? 1 - (1 - fa)*(1 - 2*(fb - 0.5)) : 2*fa*fb ); + } + + static void HardLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - (1 - fa)*(1 - 2*(b - 0.5)) : 2*fa*b ); + } + + /*! + * Assigns to a pixel sample variable \a a the vivid light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void VividLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*fb ), 1.0 ) ); + } + + static void VividLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? 1 - pcl::Max( (1 - fa)/(fb - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*fb ), 1.0 ) ); + } + + static void VividLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? 1 - pcl::Max( (1 - fa)/(b - 0.5)/2, 1.0 ) : pcl::Min( fa/pcl::Max( EPSILON_D, 1 - 2*b ), 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the linear light + * standard composition operation of its current value and a T value \a b, + * with implicit data type conversion. + */ + template + static void LinearLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa + 2*(fb - 0.5), 1.0 ) : pcl::Max( fa + 2*fb - 1, 1.0 ) ); + } + + static void LinearLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa + 2*(fb - 0.5), 1.0 ) : pcl::Max( fa + 2*fb - 1, 1.0 ) ); + } + + static void LinearLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa + 2*(b - 0.5), 1.0 ) : pcl::Max( fa + 2*b - 1, 1.0 ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the pin light standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void PinLight( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa, 2*(fb - 0.5) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + double fb = double( b ); + a = ToSample( (fb > 0.5) ? pcl::Max( fa, 2*(fb - 0.5) ) : pcl::Min( fa, 2*fb ) ); + } + + static void PinLight( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( (b > 0.5) ? pcl::Max( fa, 2*(b - 0.5) ) : pcl::Min( fa, 2*b ) ); + } + + /*! + * Assigns to a pixel sample variable \a a the exclusion standard + * composition operation of its current value and a T value \a b, with + * implicit data type conversion. + */ + template + static void Exclusion( sample& a, T b ) noexcept + { + double fa; FromSample( fa, a ); + double fb; FromSample( fb, ToSample( b ) ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(fb - 0.5), 0.0, 1.0 ) ); + } + + static void Exclusion( sample& a, float b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(double( b ) - 0.5), 0.0, 1.0 ) ); + } + + static void Exclusion( sample& a, double b ) noexcept + { + double fa; FromSample( fa, a ); + a = ToSample( pcl::Range( 0.5 - 2*(fa - 0.5)*(b - 0.5), 0.0, 1.0 ) ); + } + + // ------------------------------------------------------------------------- + + IMPLEMENT_TRANSFER_OPERATIONS +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class UInt20PixelTraits + * \brief 20-bit unsigned integer pixel traits. + * + * %UInt20PixelTraits is a template instantiation of GenericPixelTraits for + * unsigned 20-bit integers (stored as \c uint32 values). + * + * This class does not represent an instantiable pixel sample type. It is used + * mainly for generation and management of 20-bit lookup tables (LUTs). + * + * \sa GenericPixelTraits + */ +class PCL_CLASS UInt20PixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %UInt20PixelTraits, this is equivalent + * to \c uint32. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %UInt20PixelTraits, this member function returns "UInt20". + */ + static constexpr const char* SampleFormat() noexcept + { + return "UInt20"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %UInt20PixelTraits, this member function returns 1048576. + */ + static constexpr sample MaxSampleValue() noexcept + { + return uint20_max; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %UInt20PixelTraits, this member function returns 0. + */ + static constexpr sample LowestSampleValue() noexcept + { + return sample( 0 ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %UInt20PixelTraits, this member function returns 1048576. + */ + static constexpr sample HighestSampleValue() noexcept + { + return uint20_max; + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { +#ifdef __PCL_ENFORCE_PIXTRAITS_FLOAT_RANGE + return sample( pcl::Range( Round( x ), T( 0 ), T( uint20_max ) ) ); +#else + // ### N.B.: x must be in the range [0,uint20_max]. + return sample( RoundInt( x ) ); +#endif + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( x * uint8_to_uint20 ) ); +#else + return p20LUT8[x]; +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( (int32( x ) - int32( int8_min ))*uint8_to_uint20 ) ); +#else + return p20LUT8[int( x ) - int( int8_min )]; +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( x * uint16_to_uint20 ) ); +#else + return p20LUT16[x]; +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( (int32( x ) - int32( int16_min ))*uint16_to_uint20 ) ); +#else + return p20LUT16[int( x ) - int( int16_min )]; +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint32 x ) noexcept + { + return sample( RoundInt( x * uint32_to_uint20 ) ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int32 x ) noexcept + { + return sample( RoundInt( (double( x ) - int32_min)*uint32_to_uint20 ) ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return FloatToSample( x*uint20_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( float x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0F, 1.0F )*uint20_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return FloatToSample( x*uint20_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( double x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0, 1.0 )*uint20_max ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static constexpr sample ToSample( const Complex& x ) noexcept + { + return ToSample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint8( RoundInt( b * uint20_to_uint8 ) ); +#else + a = p8LUT20[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int8( RoundInt( b * uint20_to_uint8 ) + int8_min ); +#else + a = int8( int( p8LUT20[b] ) + int( int8_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint16( RoundInt( b * uint20_to_uint16 ) ); +#else + a = p16LUT20[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int16( RoundInt( b * uint20_to_uint16 ) + int16_min ); +#else + a = int16( int( p16LUT20[b] ) + int( int16_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = uint32( RoundInt( b * uint20_to_uint32 ) ); +#else + a = p32LUT20[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = int32( RoundInt( b * uint20_to_uint32 ) + int32_min ); +#else + a = int32( int64( p32LUT20[b] ) + int64( int32_min ) ); +#endif + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = float( b )/uint20_max; +#else + a = pFLUT20[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + a = double( b )/uint20_max; +#else + a = pDLUT20[b]; +#endif + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + typename Complex::component c; + FromSample( c, b ); + a = c; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class UInt24PixelTraits + * \brief 24-bit unsigned integer pixel traits. + * + * %UInt24PixelTraits is a template instantiation of GenericPixelTraits for + * unsigned 24-bit integers (stored as \c uint32 values). + * + * This class does not represent an instantiable pixel sample type. It is used + * mainly for generation and management of 24-bit lookup tables (LUTs). + * + * \sa GenericPixelTraits + */ +class PCL_CLASS UInt24PixelTraits : public GenericPixelTraits +{ +public: + + /*! + * Represents this template instantiation. + */ + typedef GenericPixelTraits traits_type; + + /*! + * Represents a pixel sample value. + */ + typedef traits_type::sample sample; + + /*! + * Represents a component of a complex pixel sample, or a pixel sample value + * for real pixel sample types. For %UInt24PixelTraits, this is equivalent + * to \c uint32. + */ + typedef sample component; + + /*! + * Returns true iff this pixel traits class corresponds to a floating point + * real pixel sample type. + */ + static constexpr bool IsFloatSample() noexcept + { + return false; + } + + /*! + * Returns true if this pixel traits class corresponds to a complex pixel + * sample type; false if it represents a real pixel sample type. + */ + static constexpr bool IsComplexSample() noexcept + { + return false; + } + + /*! + * Returns the address of a static null-terminated string identifying the + * sample data type represented by this pixel traits class. + * + * For %UInt24PixelTraits, this member function returns "UInt24". + */ + static constexpr const char* SampleFormat() noexcept + { + return "UInt24"; + } + + /*! + * Returns the maximum valid pixel sample value. + * + * For %UInt24PixelTraits, this member function returns 16777216. + */ + static constexpr sample MaxSampleValue() noexcept + { + return uint24_max; + } + + /*! + * Returns the lowest finite value representable by this pixel sample type. + * + * For %UInt24PixelTraits, this member function returns 0. + */ + static constexpr sample LowestSampleValue() noexcept + { + return sample( 0 ); + } + + /*! + * Returns the highest finite value representable by this pixel sample type. + * + * For %UInt24PixelTraits, this member function returns 16777216. + */ + static constexpr sample HighestSampleValue() noexcept + { + return uint24_max; + } + + /*! + * Conversion of any floating point value to a pixel sample value. + */ + template + static sample FloatToSample( T x ) noexcept + { +#ifdef __PCL_ENFORCE_PIXTRAITS_FLOAT_RANGE + return sample( pcl::Range( Round( x ), T( 0 ), T( uint24_max ) ) ); +#else + // ### N.B.: x must be in the range [0,uint24_max]. + return sample( RoundInt( x ) ); +#endif + } + + /*! + * Conversion of an 8-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( x * uint8_to_uint24 ); +#else + return p24LUT8[x]; +#endif + } + + /*! + * Conversion of an 8-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int8 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( (int32( x ) - int32( int8_min ))*uint8_to_uint24 ) ); +#else + return p24LUT8[int( x ) - int( int8_min )]; +#endif + } + + /*! + * Conversion of a 16-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( x * uint16_to_uint24 ) ); +#else + return p24LUT16[x]; +#endif + } + + /*! + * Conversion of a 16-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int16 x ) noexcept + { +#ifdef __PCL_DONT_USE_PIXTRAITS_LUT + return sample( RoundInt( (int32( x ) - int32( int16_min ))*uint16_to_uint24 ) ); +#else + return p24LUT16[int( x ) - int( int16_min )]; +#endif + } + + /*! + * Conversion of a 32-bit unsigned integer value to a pixel sample value. + */ + static sample ToSample( uint32 x ) noexcept + { + return sample( RoundInt( x * uint32_to_uint24 ) ); + } + + /*! + * Conversion of a 32-bit signed integer value to a pixel sample value. + */ + static sample ToSample( int32 x ) noexcept + { + return sample( RoundInt( (double( x ) - int32_min)*uint32_to_uint24 ) ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. + */ + static sample ToSample( float x ) noexcept + { + return FloatToSample( double( x )*uint24_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( float x ) noexcept + { + return FloatToSample( pcl::Range( double( x ), 0.0, 1.0 )*uint24_max ); + } + + /*! + * Conversion of a 64-bit floating point value to a pixel sample value. + */ + static sample ToSample( double x ) noexcept + { + return FloatToSample( x*uint24_max ); + } + + /*! + * Conversion of a 32-bit floating point value to a pixel sample value. This + * function guarantees that the result will never overflow as a result of an + * out-of-range argument value. + */ + static sample ToSampleConstrained( double x ) noexcept + { + return FloatToSample( pcl::Range( x, 0.0, 1.0 )*uint24_max ); + } + + /*! + * Conversion of any complex value to a pixel sample value. + */ + template + static sample ToSample( const Complex& x ) noexcept + { + return ToSample( pcl::Abs( x ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit unsigned integer. + */ + static void FromSample( uint8& a, sample b ) noexcept + { + a = uint8( RoundInt( b * uint24_to_uint8 ) ); + } + + /*! + * Conversion of a pixel sample value to an 8-bit signed integer. + */ + static void FromSample( int8& a, sample b ) noexcept + { + a = int8( RoundInt( b * uint24_to_uint8 ) + int8_min ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit unsigned integer. + */ + static void FromSample( uint16& a, sample b ) noexcept + { + a = uint16( RoundInt( b * uint24_to_uint16 ) ); + } + + /*! + * Conversion of a pixel sample value to a 16-bit signed integer. + */ + static void FromSample( int16& a, sample b ) noexcept + { + a = int16( RoundInt( b * uint24_to_uint16 ) + int16_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit unsigned integer. + */ + static void FromSample( uint32& a, sample b ) noexcept + { + a = uint32( RoundInt( b * uint24_to_uint32 ) ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit signed integer. + */ + static void FromSample( int32& a, sample b ) noexcept + { + a = int32( RoundInt( b * uint24_to_uint32 ) + int32_min ); + } + + /*! + * Conversion of a pixel sample value to a 32-bit floating point real. + */ + static void FromSample( float& a, sample b ) noexcept + { + a = float( b )/uint24_max; + } + + /*! + * Conversion of a pixel sample value to a 64-bit floating point real. + */ + static void FromSample( double& a, sample b ) noexcept + { + a = double( b )/uint24_max; + } + + /*! + * Conversion of a pixel sample value to any complex type. + */ + template + static void FromSample( Complex& a, sample b ) noexcept + { + typename Complex::component c; + FromSample( c, b ); + a = c; + } +}; + +// ---------------------------------------------------------------------------- + +#undef IMPLEMENT_TRANSFER_OPERATIONS + +#undef EPSILON_D +#undef EPSILON_F + +#ifndef __PCL_DONT_USE_PIXTRAITS_LUT +#undef pFLUT8 +#undef pFLUTA +#undef p1FLUT8 +#undef pFLUT16 +#undef pFLUT20 +#undef pDLUT8 +#undef pDLUTA +#undef p1DLUT8 +#undef pDLUT16 +#undef pDLUT20 +#undef p8LUT16 +#undef p8LUT20 +#undef p16LUT8 +#undef p16LUT20 +#undef p20LUT8 +#undef p20LUT16 +#undef p24LUT8 +#undef p24LUT16 +#undef p32LUT8 +#undef p32LUT16 +#undef p32LUT20 +#endif + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PixelTraits_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PixelTraits.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PlateCarreeProjection.h b/3rdparty/include/pcl/PlateCarreeProjection.h new file mode 100644 index 0000000..23a7dbb --- /dev/null +++ b/3rdparty/include/pcl/PlateCarreeProjection.h @@ -0,0 +1,136 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PlateCarreeProjection.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_PlateCarreeProjection_h +#define __PCL_PlateCarreeProjection_h + +/// \file pcl/PlateCarreeProjection.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PlateCarreeProjection + * \brief Plate-Carree projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS PlateCarreeProjection: public ProjectionBase +{ +public: + + /*! + * Default constructor. + */ + PlateCarreeProjection() = default; + + /*! + * Copy constructor. + */ + PlateCarreeProjection( const PlateCarreeProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new PlateCarreeProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "CAR"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Plate-Carree"; + } + +protected: + + bool Project( DPoint& pW, const DPoint& pN ) const noexcept override + { + pW = pN; + return true; + } + + bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept override + { + pN = pW; + return true; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PlateCarreeProjection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PlateCarreeProjection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Point.h b/3rdparty/include/pcl/Point.h new file mode 100644 index 0000000..6d3de24 --- /dev/null +++ b/3rdparty/include/pcl/Point.h @@ -0,0 +1,1484 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Point.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_Point_h +#define __PCL_Point_h + +/// \file pcl/Point.h + +#include + +#include +#include + +#ifdef __PCL_QT_INTERFACE +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * ### NB: Template class GenericPoint cannot have virtual member functions. + * This is because internal PCL and core routines rely on + * GenericPoint, GenericPoint and GenericPoint to + * be directly castable to int*, float* and double*, respectively. See + * also the PCL_ASSERT_POINT_SIZE() macro. + */ + +#define PCL_ASSERT_POINT_SIZE() \ + static_assert( sizeof( *this ) == 2*sizeof( T ), "Invalid sizeof( GenericPoint<> )" ) + +/*! + * \class GenericPoint + * \brief A generic point in the two-dimensional space. + * + * %GenericPoint implements a point in the plane, specified by its \a x and + * \a y coordinates. The type T represents scalar point coordinates and can be + * any real or integer numerical type. + * + * The coordinates of %GenericPoint are accessed directly by its x and y data + * members. Given a %GenericPoint instance \a p, you can use \a p.x and \a p.y + * directly to get or set coordinate values. + * + * \sa \ref point_types_2d "2-D Point Types", + * \ref point_functions_2d "2-D Point Operators and Functions", + * GenericRectangle + */ +template +class PCL_CLASS GenericPoint +{ +public: + + /*! + * Represents the type of a point component. + */ + typedef T component; + + /* + * Point coordinates + */ + component x; //!< Abscissa (horizontal, or X-axis coordinate). + component y; //!< Ordinate (vertical, or Y-axis coordinate). + + /*! + * Constructs a default %GenericPoint instance. Point coordinates are not + * initialized, so they'll have unpredictable garbage values. + */ + constexpr GenericPoint() + { + PCL_ASSERT_POINT_SIZE(); + } + + /*! + * Constructs a %GenericPoint instance given its coordinates \a xPos and + * \a yPos in the plane. + * + * The type T1 can be any suitable real or integer numerical type, or a type + * with numeric conversion semantics. + */ + template + constexpr GenericPoint( T1 xPos, T1 yPos ) + : x( component( xPos ) ) + , y( component( yPos ) ) + { + PCL_ASSERT_POINT_SIZE(); + } + + /*! + * Constructs a %GenericPoint instance with both point coordinates equal to + * the specified scalar \a d. + */ + constexpr GenericPoint( component d ) + : GenericPoint( d, d ) + { + PCL_ASSERT_POINT_SIZE(); + } + + /*! + * Constructs a %GenericPoint instance from coordinates taken from the + * specified initializer list \a l. + * + * This constructor will copy 2, 1 or zero point coordinates, depending on + * the number of values in the initializer list. Coordinates that cannot be + * initialized from list values will be set to zero. For example, the + * following code: + * + * \code + * Point p1 = {}; + * Point p2 = { 1 }; + * Point p3 = { 1, 2 }; + * \endcode + * + * is functionally equivalent to: + * + * \code + * Point p1( 0, 0 ); + * Point p2( 1, 0 ); + * Point p3( 1, 2 ); + * \endcode + */ + template + GenericPoint( std::initializer_list l ) + { + PCL_ASSERT_POINT_SIZE(); + switch ( l.size() ) + { + default: + case 2: y = component( l.begin()[1] ); + case 1: x = component( l.begin()[0] ); + case 0: break; + } + switch ( l.size() ) + { + case 0: x = component( 0 ); + case 1: y = component( 0 ); + default: + case 2: break; + } + } + + /*! + * Nontrivial copy constructor. Constructs a %GenericPoint instance as a + * copy (possibly involving a conversion between different numerical types) + * of another point \a p with different template argument. + */ + template + GenericPoint( const GenericPoint& p ) + : GenericPoint( component( p.x ), component( p.y ) ) + { + PCL_ASSERT_POINT_SIZE(); + } + +#ifdef __PCL_QT_INTERFACE + GenericPoint( const QPoint& p ) + : GenericPoint( component( p.x() ), component( p.y() ) ) + { + PCL_ASSERT_POINT_SIZE(); + } +#endif + + /*! + * Returns the square of the Euclidian distance between this point and + * another point \a p in the plane. + * + * The Euclidian distance between two points p and q is the length of the + * straight line between both points: Sqrt( (p.x - q.x)^2 + (p.y - q.y)^2 ). + * + * This function returns just the radicand (p.x - q.x)^2 + (p.y - q.y)^2. + * This is useful because saves calculation of a square root, which is + * unnecessary in some practical cases. One of them is ordering of + * distances: Sqrt(A) < Sqrt(B) implies A < B. + * + * \sa DistanceTo(), ManhattanDistanceTo() + */ + template + double SquaredDistanceTo( const GenericPoint& p ) const noexcept + { + double dx = double( p.x ) - double( x ); + double dy = double( p.y ) - double( y ); + return dx*dx + dy*dy; + } + + /*! + * Returns the Euclidian distance between this point and another point \a p + * in the plane. + * + * The Euclidian distance between two points p and q is the length of the + * straight line between both points: Sqrt( (p.x - q.x)^2 + (p.y - q.y)^2 ). + * + * \sa SquaredDistanceTo(), ManhattanDistanceTo() + */ + template + double DistanceTo( const GenericPoint& p ) const noexcept + { + return pcl::Sqrt( SquaredDistanceTo( p ) ); + } + + /*! + * Returns the square of the Euclidian distance between this point and the + * origin of coordinates in the plane. In other words, this function returns + * the squared length of the two-dimensional vector represented by this + * point object. + * + * This function is equivalent to: + * + * \code SquaredDistanceTo( GenericPoint( 0 ) ) \endcode + * + * but potentially faster, depending mainly on compiler optimizations. + * + * \sa DistanceToOrigin() + */ + double SquaredDistanceToOrigin() const noexcept + { + return double( x )*double( x ) + double( y )*double( y ); + } + + /*! + * Returns the Euclidian distance between this point and the origin of + * coordinates in the plane. In other words, this function returns the + * length of the two-dimensional vector represented by this point object. + * + * This function is equivalent to: + * + * \code DistanceTo( GenericPoint( 0 ) ) \endcode + * + * but potentially faster, depending mainly on compiler optimizations. + * + * \sa SquaredDistanceToOrigin(), ManhattanDistanceToOrigin() + */ + double DistanceToOrigin() const noexcept + { + return pcl::Sqrt( SquaredDistanceToOrigin() ); + } + + /*! + * Returns the Manhattan distance between this point and another point \a p + * in the plane. + * + * The Manhattan distance between two points p and q is the sum of distances + * measured along axes at right angles: |p.x - q.x| + |p.y - q.y|. + * + * \sa DistanceTo(), ManhattanDistanceToOrigin() + */ + template + double ManhattanDistanceTo( const GenericPoint& p ) const noexcept + { + return Abs( double( p.x ) - double( x ) ) + Abs( double( p.y ) - double( y ) ); + } + + /*! + * Returns the Manhattan distance between this point and the origin of + * coordinates in the plane. In other words, this function returns the sum + * of the absolute values of this point's x and y coordinates. + * + * This function is equivalent to: + * + * \code ManhattanDistanceTo( GenericPoint( 0 ) ) \endcode + * + * but potentially faster, depending mainly on compiler optimizations. + * + * \sa ManhattanDistanceTo(), DistanceToOrigin() + */ + double ManhattanDistanceToOrigin() const noexcept + { + return Abs( double( x ) ) + Abs( double( y ) ); + } + + /*! + * Moves this point to the location of another point \a p. + * + * \sa MoveBy() + */ + template + void MoveTo( const GenericPoint& p ) noexcept + { + MoveTo( p.x, p.y ); + } + + /*! + * Moves this point to the specified absolute coordinates \a xPos and + * \a yPos in the plane. + * + * \sa MoveBy() + */ + template + void MoveTo( T1 xPos, T1 yPos ) noexcept + { + x = component( xPos ); y = component( yPos ); + } + +#ifdef __PCL_QT_INTERFACE + void MoveTo( const QPoint& p ) noexcept + { + MoveTo( p.x(), p.y() ); + } +#endif + + /*! + * Returns a point whose coordinates are equal to the coordinates of the + * specified point \a d. + */ + template + GenericPoint MovedTo( const GenericPoint& p ) const noexcept + { + return GenericPoint( component( p.x ), component( p.y ) ); + } + + /*! + * Returns a point at the specified \a xPos and \a yPos coordinates. + */ + template + GenericPoint MovedTo( T1 xPos, T1 yPos ) const noexcept + { + return GenericPoint( component( xPos ), component( yPos ) ); + } + + /*! + * Moves this point by equal increments in the X and Y directions, relative + * to its current position. + * + * \param d Increments in the X and Y directions, given by \a d.x and + * \a d.y, respectively. + * + * \sa MoveTo() + */ + template + void MoveBy( const GenericPoint& d ) noexcept + { + MoveBy( d.x, d.y ); + } + + /*! + * Moves this point by increments \a dx and \a dy in the X and Y directions, + * respectively, relative to its current position. + * + * For example, given the declaration: + * + * \code GenericPoint p; \endcode + * + * These two expressions are equivalent: + * + * \code + * p.MoveBy( -3, 7 ); + * p.MoveTo( p.x-3, p.y+7 ); + * \endcode + * + * \sa MoveTo() + */ + template + void MoveBy( T1 dx, T1 dy ) noexcept + { + x += component( dx ); y += component( dy ); + } + + /*! + * Moves this point by the same increment \a dxy in the X and Y directions, + * relative to its current position. + * + * This function is functionally equivalent to: + * + * \code MoveBy( dxy, dxy ); \endcode + * + * \sa MoveTo() + */ + template + void MoveBy( T1 dxy ) noexcept + { + x += component( dxy ); y += component( dxy ); + } + +#ifdef __PCL_QT_INTERFACE + void MoveBy( const QPoint& p ) + { + MoveBy( p.x(), p.y() ); + } +#endif + + /*! + * Returns a point whose coordinates are the coordinates of this point + * displaced by the increments specified as the point \a d. + */ + template + GenericPoint MovedBy( const GenericPoint& d ) const noexcept + { + return GenericPoint( x + component( d.x ), y + component( d.y ) ); + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * displaced by the specified increments \a dx and \a dy. + */ + template + GenericPoint MovedBy( T1 dx, T1 dy ) const noexcept + { + return GenericPoint( x + component( dx ), y + component( dy ) ); + } + + /*! + * Rotates this point in the plane by the specified \a angle in radians, + * with respect to a center of rotation given by its coordinates \a xc and + * \a yc. + */ + template + void Rotate( T1 angle, T2 xc, T2 yc ) noexcept + { + pcl::Rotate( x, y, angle, xc, yc ); + } + + /*! + * Rotates this point in the plane by the specified \a angle in radians, + * with respect to the specified \a center of rotation. + */ + template + void Rotate( T1 angle, const GenericPoint& center ) noexcept + { + Rotate( angle, center.x, center.y ); + } + + /*! + * Rotates this point in the plane by the specified angle, given by its sine + * and cosine, \a sa and \a ca respectively, with respect to a center of + * rotation given by its coordinates \a xc and \a yc. + */ + template + void Rotate( T1 sa, T1 ca, T2 xc, T2 yc ) noexcept + { + pcl::Rotate( x, y, sa, ca, xc, yc ); + } + + /*! + * Rotates this point in the plane by the specified angle, given by its sine + * and cosine, \a sa and \a ca respectively, with respect to the specified + * \a center of rotation. + */ + template + void Rotate( T1 sa, T1 ca, const GenericPoint& center ) noexcept + { + Rotate( sa, ca, center.x, center.y ); + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * rotated in the plane by the specified \a angle in radians, with respect + * to a center of rotation given by its coordinates \a xc and \a yc. + */ + template + GenericPoint Rotated( T1 angle, T2 xc, T2 yc ) const noexcept + { + GenericPoint p( *this ); + p.Rotate( angle, xc, yc ); + return p; + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * rotated in the plane by the specified \a angle in radians, with respect + * to the specified \a center of rotation. + */ + template + GenericPoint Rotated( T1 angle, const GenericPoint& center ) const noexcept + { + GenericPoint p( *this ); + p.Rotate( angle, center ); + return p; + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * rotated in the plane by the specified angle given by its sine and cosine, + * \a sa and \a ca respectively, with respect to a center of rotation given + * by its coordinates \a xc and \a yc. + */ + template + GenericPoint Rotated( T1 sa, T1 ca, T2 xc, T2 yc ) const noexcept + { + GenericPoint p( *this ); + p.Rotate( sa, ca, xc, yc ); + return p; + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * rotated in the plane by the specified angle given by its sine and cosine, + * \a sa and \a ca respectively, with respect to the specified \a center of + * rotation. + */ + template + GenericPoint Rotated( T1 sa, T1 ca, const GenericPoint& center ) const noexcept + { + GenericPoint p( *this ); + p.Rotate( sa, ca, center ); + return p; + } + + /*! + * Rounds the coordinates of this point to their corresponding nearest + * integer coordinates. + * + * \sa Round( int ), Rounded(), Truncate(), RoundedToInt(), TruncatedToInt() + */ + void Round() noexcept + { + x = component( pcl::Round( double( x ) ) ); + y = component( pcl::Round( double( y ) ) ); + } + + /*! + * Rounds the coordinates of this point to \a n fractional digits (\a n >= 0). + * + * \sa Round(), Rounded( int ), Truncate(), RoundedToInt(), TruncatedToInt() + */ + void Round( int n ) noexcept + { + PCL_PRECONDITION( n >= 0 ) + x = component( pcl::Round( double( x ), n ) ); + y = component( pcl::Round( double( y ), n ) ); + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * rounded to their nearest integers. + * + * \sa Round(), Rounded( int ), Truncated(), RoundedToInt(), TruncatedToInt() + */ + GenericPoint Rounded() const noexcept + { + return GenericPoint( component( pcl::Round( double( x ) ) ), component( pcl::Round( double( y ) ) ) ); + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * rounded to \a n fractional digits (\a n >= 0). + * + * \sa Round( int ), Rounded(), Truncated(), RoundedToInt(), TruncatedToInt() + */ + GenericPoint Rounded( int n ) const noexcept + { + PCL_PRECONDITION( n >= 0 ) + return GenericPoint( component( pcl::Round( double( x ), n ) ), component( pcl::Round( double( y ), n ) ) ); + } + + /*! + * Returns a point of integer template type whose coordinates are the + * coordinates of this point rounded to their nearest integers. + * + * \sa Round(), Rounded(), Truncated(), TruncatedToInt() + */ + GenericPoint RoundedToInt() const noexcept + { + return GenericPoint( pcl::RoundInt( double( x ) ), pcl::RoundInt( double( y ) ) ); + } + + /*! + * Integer truncation of coordinates. Sets the coordinates x, y of this + * point to the corresponding nearest integer coordinates i, j, such that + * i <= x and j <= y. + * + * \sa Truncated(), Round(), RoundedToInt(), TruncatedToInt() + */ + void Truncate() noexcept + { + x = component( pcl::Trunc( double( x ) ) ); + y = component( pcl::Trunc( double( y ) ) ); + } + + /*! + * Integer truncation of coordinates. Returns a point whose coordinates are + * the coordinates x, y of this point truncated to their corresponding + * nearest integer coordinates i, j, such that i <= x and j <= y. + * + * \sa Truncate(), Rounded(), RoundedToInt(), TruncatedToInt() + */ + GenericPoint Truncated() const noexcept + { + return GenericPoint( component( pcl::Trunc( double( x ) ) ), component( pcl::Trunc( double( y ) ) ) ); + } + + /*! + * Integer truncation of coordinates. Returns a point of integer template + * type whose coordinates are the coordinates x, y of this point truncated + * to the nearest integer coordinates i, j, such that i <= x and j <= y. + * + * \sa Truncate(), Truncated(), Rounded(), RoundedToInt() + */ + GenericPoint TruncatedToInt() const noexcept + { + return GenericPoint( pcl::TruncInt( double( x ) ), pcl::TruncInt( double( y ) ) ); + } + + /*! + * Assignment operator. Moves this point to the location specified as a + * point \a p. Returns a reference to this point. + * + * \sa MoveTo() + */ + template + GenericPoint& operator =( const GenericPoint& p ) noexcept + { + x = component( p.x ); + y = component( p.y ); + return *this; + } + + /*! + * Assignment operator. Given a coordinate \a v, moves this point to a + * location x = y = \a v. Returns a reference to this point. + * + * \sa MoveTo() + */ + GenericPoint& operator =( component v ) noexcept + { + x = y = v; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericPoint& operator =( const QPoint& p ) noexcept + { + x = component( p.x() ); + y = component( p.y() ); + return *this; + } +#endif + + /*! + * Adds each coordinate of a given point \a p to its homonym coordinate in + * this point. Returns a reference to this point. + * + * \sa MoveBy(), operator -=() + */ + template + GenericPoint& operator +=( const GenericPoint& p ) noexcept + { + x += component( p.x ); + y += component( p.y ); + return *this; + } + + /*! + * Adds a scalar \a d to both coordinates of this point. Returns a reference + * to this point. + * + * \sa MoveBy(), operator -=() + */ + GenericPoint& operator +=( component d ) noexcept + { + x += d; + y += d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericPoint& operator +=( const QPoint& p ) noexcept + { + x += component( p.x() ); + y += component( p.y() ); + return *this; + } +#endif + + /*! + * Subtracts each coordinate of a given point \a p from its homonym + * coordinate in this point. Returns a reference to this point. + * + * \sa MoveBy(), operator +=() + */ + template + GenericPoint& operator -=( const GenericPoint& p ) noexcept + { + x -= component( p.x ); + y -= component( p.y ); + return *this; + } + + /*! + * Subtracts a scalar \a d from both coordinates of this point. Returns a + * reference to this point. + * + * \sa MoveBy(), operator +=() + */ + GenericPoint& operator -=( component d ) noexcept + { + x -= d; + y -= d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericPoint& operator -=( const QPoint& p ) noexcept + { + x -= component( p.x() ); + y -= component( p.y() ); + return *this; + } +#endif + + /*! + * Multiplies each coordinate of this point by its homonym coordinate of a + * given point \a p. Returns a reference to this point. + * + * \sa operator /=(), operator +=() + */ + template + GenericPoint& operator *=( const GenericPoint& p ) noexcept + { + x *= component( p.x ); + y *= component( p.y ); + return *this; + } + + /*! + * Multiplies both coordinates of this point by a scalar \a d. Returns a + * reference to this point. + * + * \sa operator /=(), operator +=() + */ + GenericPoint& operator *=( component d ) noexcept + { + x *= d; + y *= d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericPoint& operator *=( const QPoint& p ) noexcept + { + x *= component( p.x() ); + y *= component( p.y() ); + return *this; + } +#endif + + /*! + * Divides each coordinate of this point by its homonym coordinate of a + * given point \a p. Returns a reference to this point. + * + * \sa operator *=(), operator -=() + */ + template + GenericPoint& operator /=( const GenericPoint& p ) noexcept + { + PCL_PRECONDITION( component( p.x ) != component( 0 ) && component( p.y ) != component( 0 ) ) + x /= component( p.x ); + y /= component( p.y ); + return *this; + } + + /*! + * Divides both coordinates of this point by a scalar \a d. Returns a + * reference to this point. + * + * \sa operator *=(), operator -=() + */ + GenericPoint& operator /=( component d ) noexcept + { + PCL_PRECONDITION( d != component( 0 ) ) + x /= d; + y /= d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericPoint& operator /=( const QPoint& p ) noexcept + { + PCL_PRECONDITION( component( p.x() ) != component( 0 ) && component( p.y() ) != component( 0 ) ) + x /= component( p.x() ); + y /= component( p.y() ); + return *this; + } +#endif + + /*! + * Returns a copy of this point. + */ + GenericPoint operator +() const noexcept + { + return *this; + } + + /*! + * Returns a point whose coordinates have the same magnitudes as the + * coordinates of this point, but opposite signs. The returned point so + * defined represents a vector diametrically opposed to this one. + */ + GenericPoint operator -() const noexcept + { + return GenericPoint( -x, -y ); + } + + /*! + * Reflects this point in the origin. This transformation changes the signs + * of both point coordinates. + */ + void Reflect() noexcept + { + x = -x; + y = -y; + } + + /*! + * Reflects this point across the X axis. This transformation changes the + * sign of this point's y-coordinate. + */ + void ReflectX() noexcept + { + y = -y; + } + + /*! + * Reflects this point across the Y axis. This transformation changes the + * sign of this point's x-coordinate. + */ + void ReflectY() noexcept + { + x = -x; + } + + /*! + * Returns the reflexion of this point in the origin. The returned point has + * the coordinates of this point with inverse signs. + */ + GenericPoint Reflected() const noexcept + { + return GenericPoint( -x, -y ); + } + + /*! + * Returns the reflexion of this point across the X axis. The returned point + * has the same x-coordinate as this point and the y-coordinate of this + * point with inverse sign. + */ + GenericPoint ReflectedX() const noexcept + { + return GenericPoint( x, -y ); + } + + /*! + * Returns the reflexion of this point across the Y axis. The returned point + * has the x-coordinate of this point with inverse sign and the same + * y-coordinate as this point. + */ + GenericPoint ReflectedY() const noexcept + { + return GenericPoint( -x, y ); + } + + /* + * Returns a point whose coordinates are the coordinates of this point + * converted to radians, assuming that this point has coordinates expressed + * in degrees. + */ + GenericPoint Rad() const noexcept + { + return GenericPoint( pcl::Rad( x ), pcl::Rad( y ) ); + } + + /*! + * Returns a point whose coordinates are the coordinates of this point + * converted to degrees, assuming that this point has coordinates expressed + * in radians. + */ + GenericPoint Deg() const noexcept + { + return GenericPoint( pcl::Deg( x ), pcl::Deg( y ) ); + } + + /*! + * Converts the coordinates of this point to radians, assuming that they are + * expressed in degrees before calling this function. Returns a reference to + * this object. + */ + GenericPoint& ToRad() noexcept + { + x = pcl::Rad( x ); + y = pcl::Rad( y ); + return *this; + } + + /*! + * Converts the coordinates of this point to degrees, assuming that they are + * expressed in radians before calling this function. Returns a reference to + * this object. + */ + GenericPoint& ToDeg() noexcept + { + x = pcl::Deg( x ); + y = pcl::Deg( y ); + return *this; + } + + /*! + * Returns a reference to a point component. Returns a reference to the X + * point coordinate if the specified index \a i is zero, or a reference to + * the Y coordinate otherwise. + */ + component& operator []( int i ) noexcept + { + return (i == 0) ? x : y; + } + + /*! + * Returns a copy of a point component. Returns the X point coordinate if + * the specified index \a i is zero, or the Y coordinate otherwise. + */ + component operator []( int i ) const noexcept + { + return (i == 0) ? x : y; + } + + /*! + * Returns the dot product of this point and another point given by its + * coordinates \a px and \a py. + */ + template + double Dot( T1 px, T2 py ) const noexcept + { + return double( x )*double( px ) + double( y )*double( py ); + } + + /*! + * Returns the dot product of this point and another point \a p. + */ + template + double Dot( const GenericPoint& p ) const noexcept + { + return Dot( p.x, p.y ); + } + +#ifdef __PCL_QT_INTERFACE + operator QPoint() const noexcept + { + return QPoint( int( x ), int( y ) ); + } +#endif +}; + +#undef PCL_ASSERT_POINT_SIZE + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup point_functions_2d Point Operators and Functions + */ + +/*! + * Returns true iff two points \a p1 and \a p2 are equal. Two points are equal + * if their homonym coordinates are equal. + * \ingroup point_functions_2d + */ +template inline +bool operator ==( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + return p1.x == p2.x && p1.y == p2.y; +} + +/*! + * Returns true iff a point \a p1 is equal to a scalar \a d2. A point \p is + * equal to a scalar \a d if both coordinates of \a p are equal to \a d. + * \ingroup point_functions_2d + */ +template inline +bool operator ==( const GenericPoint& p1, T d2 ) noexcept +{ + return p1.x == d2 && p1.y == d2; +} + +/*! + * Returns true iff a scalar \a d1 is equal to a point \a p2. A scalar \a d is + * equal to a point \a p if both coordinates of \a p are equal to \a d. + * \ingroup point_functions_2d + */ +template inline +bool operator ==( T d1, const GenericPoint& p2 ) noexcept +{ + return d1 == p2.x && d1 == p2.y; +} + +/*! + * Returns true iff a point \a p1 is less than another point \a p2. + * + * Points in the plane are sorted by ordinates in PCL. Given two points \a p + * and \a q in the plane, it holds that: + * + * \a p < \a q if \a p.y < \a q.y or \a p.y == \a q.y and \a p.x < \a q.x + * + * \ingroup point_functions_2d + */ +template inline +bool operator <( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + return p1.y < p2.y || p1.y == p2.y && p1.x < p2.x; +} + +/*! + * Returns true iff a point \a p1 is less than a scalar \a d2. + * + * Given a point \a p in the plane and a scalar \a d, it holds that: + * + * \a p < \a d if \a p.y < \a d or \a p.y == \a d and \a p.x < \a d + * + * \ingroup point_functions_2d + */ +template inline +bool operator <( const GenericPoint& p1, T d2 ) noexcept +{ + return p1.y < d2 || p1.y == d2 && p1.x < d2; +} + +/*! + * Returns true iff a scalar \a d1 is less than a point \a p2. + * + * Given a point \a p in the plane and a scalar \a d, it holds that: + * + * \a d < \a p if \a d < \a p.y or \a d == \a p.y and \a d < \a p.x + * + * \ingroup point_functions_2d + */ +template inline +bool operator <( T d1, const GenericPoint& p2 ) noexcept +{ + return d1 < p2.y || d1 == p2.y && d1 < p2.x; +} + +/*! + * Adds two points \a p1 and \a p2, and returns the resulting sum point. + * + * Point addition consists in adding homonym coordinates. Given two points + * \a p and \a q in the plane, the sum point \a s = \a p + \a q is given by: + * + * \a s.x = \a p.x + \a q.x \n + * \a s.y = \a p.y + \a q.y + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator +( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + return GenericPoint( T1( p1.x + p2.x ), T1( p1.y + p2.y ) ); +} + +/*! + * Adds a point \a p1 and a scalar \a d2, and returns the resulting sum point. + * + * Given a point \a p in the plane and a scalar \a d, the sum point + * \a s = \a p + \a d is given by: + * + * \a s.x = \a p.x + \a d \n + * \a s.y = \a p.y + \a d + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator +( const GenericPoint& p1, T d2 ) noexcept +{ + return GenericPoint( p1.x+d2, p1.y+d2 ); +} + +/*! + * Adds a scalar \a d1 and a point \a p2, and returns the resulting sum point. + * + * Point addition is a commutative operation, thus see + * pcl::operator +( const GenericPoint&, T ). + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator +( T d1, const GenericPoint& p2 ) noexcept +{ + return GenericPoint( p2.x+d1, p2.y+d1 ); +} + +/*! + * Subtracts two points \a p1 and \a p2, and returns the resulting difference + * point. + * + * Point subtraction consists in subtracting homonym coordinates. Given two + * points \a p and \a q in the plane, the difference point \a r = \a p - \a q + * is given by: + * + * \a r.x = \a p.x - \a q.x \n + * \a r.y = \a p.y - \a q.y + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator -( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + return GenericPoint( T1( p1.x - p2.x ), T1( p1.y - p2.y ) ); +} + +/*! + * Subtracts a scalar \a d2 from a point \a p1, and returns the resulting + * difference point. + * + * Given a point \a p in the plane and a scalar \a d, the difference point + * \a r = \a p - \a d is given by: + * + * \a r.x = \a p.x - \a d \n + * \a r.y = \a p.y - \a d + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator -( const GenericPoint& p1, T d2 ) noexcept +{ + return GenericPoint( p1.x-d2, p1.y-d2 ); +} + +/*! + * Subtracts a point \a p2 from a scalar \a d1, and returns the resulting + * difference point. + * + * Given a point \a p in the plane and a scalar \a d, the difference point + * \a r = \a d - \a p is given by: + * + * \a r.x = \a d - \a p.x \n + * \a r.y = \a d - \a p.y + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator -( T d1, const GenericPoint& p2 ) noexcept +{ + return GenericPoint( d1-p2.x, d1-p2.y ); +} + +/*! + * Multiplies two points \a p1 and \a p2, and returns the resulting product + * point. + * + * Point multiplication consists in multiplying homonym coordinates. Given two + * points \a p and \a q in the plane, the product point \a P = \a p * \a q is + * given by: + * + * \a P.x = \a p.x * \a q.x \n + * \a P.y = \a p.y * \a q.y + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator *( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + return GenericPoint( T1( p1.x * p2.x ), T1( p1.y * p2.y ) ); +} + +/*! + * Multiplies a point \a p1 by a scalar \a d2, and returns the resulting + * product point. + * + * Given a point \a p in the plane and a scalar \a d, the product point + * \a P = \a p * \a d is given by: + * + * \a P.x = \a p.x * \a d \n + * \a P.y = \a p.y * \a d + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator *( const GenericPoint& p1, T d2 ) noexcept +{ + return GenericPoint( p1.x*d2, p1.y*d2 ); +} + +/*! + * Multiplies a scalar \a d1 by a point \a p2, and returns the resulting + * product point. + * + * Point multiplication is a commutative operation, thus see + * pcl::operator *( const GenericPoint&, T ). + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator *( T d1, const GenericPoint& p2 ) noexcept +{ + return GenericPoint( p2.x*d1, p2.y*d1 ); +} + +/*! + * Divides two points \a p1 and \a p2, and returns the resulting quotient point. + * + * Given two points \a p and \a q in the plane, the quotient point + * \a Q = \a p / \a q is given by: + * + * \a Q.x = \a p.x / \a q.x \n + * \a Q.y = \a p.y / \a q.y + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator /( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + PCL_PRECONDITION( p2.x != T2( 0 ) && p2.y != T2( 0 ) ) + return GenericPoint( T1( p1.x / p2.x ), T1( p1.y / p2.y ) ); +} + +/*! + * Divides a point \a p1 by a scalar \a d2, and returns the resulting + * quotient point. + * + * Given a point \a p in the plane and a scalar \a d, the quotient point + * \a Q = \a p / \a d is given by: + * + * \a Q.x = \a p.x / \a d \n + * \a Q.y = \a p.y / \a d + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator /( const GenericPoint& p1, T d2 ) noexcept +{ + PCL_PRECONDITION( d2 != T( 0 ) ) + return GenericPoint( p1.x/d2, p1.y/d2 ); +} + +/*! + * Divides a scalar \a d1 by a point \a p2, and returns the resulting + * quotient point. + * + * Given a point \a p in the plane and a scalar \a d, the quotient point + * \a Q = \a d / \a q is given by: + * + * \a Q.x = \a d / \a p.x \n + * \a Q.y = \a d / \a p.y + * + * \ingroup point_functions_2d + */ +template inline +GenericPoint operator /( T d1, const GenericPoint& p2 ) noexcept +{ + PCL_PRECONDITION( p2.x != T( 0 ) && p2.y != T( 0 ) ) + return GenericPoint( d1/p2.x, d1/p2.y ); +} + +/*! + * Returns the distance between two points \a p1 and \a p2 in the plane. + * \ingroup point_functions_2d + */ +// ### FIXME: We cannot use two template arguments here due to a conflict with +// Distance( FI, FI ) defined in Iterator.h +//template inline +template inline +double Distance( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + double dx = double( p2.x ) - double( p1.x ); + double dy = double( p2.y ) - double( p1.y ); + return pcl::Sqrt( dx*dx + dy*dy ); +} + +/*! + * Returns the Manhattan distance between two points \a p1 and \a p2 in the + * plane. + * \ingroup point_functions_2d + */ +template inline +double ManhattanDistance( const GenericPoint& p1, const GenericPoint& p2 ) noexcept +{ + return Abs( double( p2.x ) - double( p1.x ) ) + Abs( double( p2.y ) - double( p1.y ) ); +} + +/*! + * Rotates a point in the plane, given a rotation angle and the coordinates of + * a center of rotation. + * + * \param p Reference to a point that will be rotated. + * \param a Rotation angle in radians. Positive angles are measured + * counter-clockwise. + * \param xc Abscissa (x coordinate) of the center of rotation. + * \param yc Ordinate (y coordinate) of the center of rotation. + * + * The coordinates \a p.x and \a p.y are replaced by their corresponding + * rotated values. + * + * \ingroup point_functions_2d + */ +template inline +void Rotate( GenericPoint& p, T1 a, T2 xc, T2 yc ) noexcept +{ + pcl::Rotate( p.x, p.y, a, xc, yc ); +} + +/*! + * Rotates a point in the plane, given a rotation angle and a rotation center + * point. + * + * \param p Reference to a point that will be rotated. + * \param a Rotation angle in radians. Positive angles are measured + * counter-clockwise. + * \param c Reference to a point that will be taken as the center of + * rotation. + * + * The coordinates \a p.x and \a p.y are replaced by their corresponding + * rotated values. + * + * \ingroup point_functions_2d + */ +template inline +void Rotate( GenericPoint& p, T1 a, const GenericPoint& c ) noexcept +{ + pcl::Rotate( p, a, c.x, c.y ); +} + +/*! + * Rotates a point in the plane, given a rotation angle by its sine and + * cosine, and the coordinates of a center of rotation. + * + * \param p Reference to a point that will be rotated. + * \param sa Sine of the rotation angle. + * \param ca Cosine of the rotation angle. + * \param xc Abscissa (x coordinate) of the center of rotation. + * \param yc Ordinate (y coordinate) of the center of rotation. + * + * The coordinates \a p.x and \a p.y are replaced by their corresponding + * rotated values. + * + * \ingroup point_functions_2d + */ +template inline +void Rotate( GenericPoint& p, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept +{ + pcl::Rotate( p.x, p.y, sa, ca, xc, yc ); +} + +/*! + * Rotates a point in the plane, given a rotation angle by its sine and + * cosine, and a rotation center point. + * + * \param p Reference to a point that will be rotated. + * \param sa Sine of the rotation angle. + * \param ca Cosine of the rotation angle. + * \param c Reference to a point that will be taken as the center of + * rotation. + * + * The coordinates \a p.x and \a p.y are replaced by their corresponding + * rotated values. + * + * \ingroup point_functions_2d + */ +template inline +void Rotate( GenericPoint& p, T1 sa, T1 ca, const GenericPoint& c ) noexcept +{ + pcl::Rotate( p, sa, ca, c.x, c.y ); +} + +/*! + * Exchanges two points \a p1 and \a p2 in the plane. Calling this function is + * equivalent to: + * + * \code Swap( p1.x, p2.x ); Swap( p1.y, p2.y ); \endcode + * + * \ingroup point_functions_2d + */ +template inline +void Swap( GenericPoint& p1, GenericPoint& p2 ) noexcept +{ + pcl::Swap( p1.x, p2.x ); + pcl::Swap( p1.y, p2.y ); +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_POINT_INSTANTIATE + +/*! + * \defgroup point_types_2d Point Types + */ + +/*! + * \class pcl::I32Point + * \ingroup point_types_2d + * \brief 32-bit integer point on the plane. + * + * %I32Point is a template instantiation of GenericPoint for the \c int32 type. + */ +typedef GenericPoint I32Point; + +/*! + * \class pcl::Point + * \ingroup point_types_2d + * \brief 32-bit integer point on the plane. + * + * %Point is an alias for I32Point. It is a template instantiation of + * GenericPoint for \c int32. + */ +typedef I32Point Point; + +/*! + * \class pcl::F32Point + * \ingroup point_types_2d + * \brief 32-bit floating-point point in the R^2 space. + * + * %F32Point is a template instantiation of GenericPoint for the \c float type. + */ +typedef GenericPoint F32Point; + +/*! + * \class pcl::FPoint + * \ingroup point_types_2d + * \brief 32-bit floating-point point in the R^2 space. + * + * %FPoint is an alias for F32Point. It is a template instantiation of + * GenericPoint for \c float. + */ +typedef F32Point FPoint; + +/*! + * \class pcl::F64Point + * \ingroup point_types_2d + * \brief 64-bit floating-point point in the R^2 space. + * + * %F64Point is a template instantiation of GenericPoint for \c double. + */ +typedef GenericPoint F64Point; + +/*! + * \class pcl::DPoint + * \ingroup point_types_2d + * \brief 64-bit floating-point point in the R^2 space. + * + * %DPoint is an alias for F64Point. It is a template instantiation of + * GenericPoint for \c double. + */ +typedef F64Point DPoint; + +#endif // !__PCL_NO_POINT_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Point_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Point.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PolarTransform.h b/3rdparty/include/pcl/PolarTransform.h new file mode 100644 index 0000000..47e717c --- /dev/null +++ b/3rdparty/include/pcl/PolarTransform.h @@ -0,0 +1,299 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PolarTransform.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_PolarTransform_h +#define __PCL_PolarTransform_h + +/// \file pcl/PolarTransform.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PolarTransformBase + * \brief Base class of polar transforms. + * + * %PolarTransformBase implements properties and functionality common to polar + * transform classes in PCL. + * + * A polar transform remaps pixel values in a two-dimensional image to encode + * polar coordinates on both image axes. Polar angle measured counter-clockwise + * with respect to the geometric center of the image is encoded linearly on the + * vertical (Y) axis. Radial distance to the center is encoded (linearly or + * not, depending on each particular transform) on the horizontal (X) axis. + * + * Polar transforms have important applications in FFT-based image registration + * algorithms (e.g. as part of Fourier-Mellin transforms). + * + * \sa PolarTransform, LogPolarTransform, FFTRegistrationEngine + */ +class PCL_CLASS PolarTransformBase : public InterpolatingGeometricTransformation, + public ParallelProcess +{ +public: + + /*! + * Constructs a %PolarTransformBase object using the specified \a p pixel + * interpolation. The referenced interpolation object \a p must remain valid + * while this %PolarTransformBase object exists. + */ + PolarTransformBase( PixelInterpolation& p ) + : InterpolatingGeometricTransformation( p ) + { + } + + /*! + * Copy constructor. + */ + PolarTransformBase( const PolarTransformBase& ) = default; + + /*! + * Returns the initial rotation angle in radians. The default initial + * rotation angle is zero. + */ + float InitialRotation() const + { + return m_initialAngle; + } + + /*! + * Sets the initial rotation \a angle in radians. + */ + void SetInitialRotation( float angle ) + { + PCL_PRECONDITION( angle >= 0 && angle <= pcl::Const::_2pi() ) + if ( (m_initialAngle = angle) > m_finalAngle ) + pcl::Swap( m_initialAngle, m_finalAngle ); + } + + /*! + * Returns the final rotation angle in radians. The default final rotation + * angle is 2*pi (360 degrees). + */ + float FinalRotation() const + { + return m_finalAngle; + } + + /*! + * Sets the final rotation \a angle in radians. + */ + void SetFinalRotation( float angle ) + { + PCL_PRECONDITION( angle >= 0 && angle <= pcl::Const::_2pi() ) + if ( (m_finalAngle = angle) < m_initialAngle ) + pcl::Swap( m_initialAngle, m_finalAngle ); + } + + /*! + * Sets the initial and final rotation angles, \a initialAngle and + * \a finalAngle respectively, in radians. If the specified initial angle is + * greater than the final angle, both values are swapped. + */ + void SetRotationRange( float initialAngle, float finalAngle ) + { + PCL_PRECONDITION( initialAngle >= 0 && initialAngle <= pcl::Const::_2pi() ) + PCL_PRECONDITION( finalAngle >= 0 && finalAngle <= pcl::Const::_2pi() ) + m_initialAngle = initialAngle; + m_finalAngle = finalAngle; + if ( m_finalAngle < m_initialAngle ) + pcl::Swap( m_initialAngle, m_finalAngle ); + } + + /*! + */ + void GetNewSizes( int& w, int& h ) const override + { + // No change + } + + /*! + * \internal + */ + virtual bool IsLogPolar() const + { + return false; + } + +protected: + + float m_initialAngle = 0; // in radians + float m_finalAngle = pcl::Const::_2pi(); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PolarTransform + * \brief In-place transformation to polar coordinates. + * + * This class implements a Cartesian to polar coordinate transform with the + * following properties: + * + * \li The origin of polar coordinates is located at the geometric center of + * the image. + * + * \li Rotation angles are encoded linearly on the vertical axis, growing from + * bottom to top. + * + * \li Distance to the origin is encoded linearly on the horizontal axis, + * growing from left to right. + * + * \li Transform pixels mapped outside the source image (in Cartesian + * coordinates) are set to zero. + * + * \sa LogPolarTransform, PolarTransformBase, FFTRegistrationEngine + */ +class PCL_CLASS PolarTransform : public PolarTransformBase +{ +public: + + /*! + * Constructs a %PolarTransform object using the specified pixel + * interpolation \a p. The referenced interpolation object \a p must remain + * valid while this %PolarTransform object exists. + */ + PolarTransform( PixelInterpolation& p ) + : PolarTransformBase( p ) + { + } + + /*! + * Copy constructor. + */ + PolarTransform( const PolarTransform& ) = default; + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class LogPolarTransform + * \brief In-place transformation to log-polar coordinates. + * + * This class implements a Cartesian to log-polar coordinate transform with the + * following properties: + * + * \li The origin of polar coordinates is located at the geometric center of + * the image. + * + * \li Rotation angles are encoded linearly on the vertical axis, growing from + * bottom to top. + * + * \li Distance to the origin is encoded logarithmically on the horizontal + * axis, growing from left to right. Natural (base e) logarithms are used. + * + * \li Transform pixels mapped outside the source image (in Cartesian + * coordinates) are set to zero. + * + * \sa PolarTransform, PolarTransformBase, FFTRegistrationEngine + */ +class PCL_CLASS LogPolarTransform : public PolarTransformBase +{ +public: + + /*! + * Constructs a %LogPolarTransform object using the specified pixel + * interpolation \a p. The referenced interpolation object \a p must remain + * valid while this %LogPolarTransform object exists. + */ + LogPolarTransform( PixelInterpolation& p ) + : PolarTransformBase( p ) + { + } + + /*! + * Copy constructor. + */ + LogPolarTransform( const LogPolarTransform& ) = default; + + /*! + * \internal + */ + bool IsLogPolar() const override + { + return true; + } + +protected: + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PolarTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PolarTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Position.h b/3rdparty/include/pcl/Position.h new file mode 100644 index 0000000..d4c000b --- /dev/null +++ b/3rdparty/include/pcl/Position.h @@ -0,0 +1,1522 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Position.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_Position_h +#define __PCL_Position_h + +/// \file pcl/Position.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \struct StarPosition + * \brief Positional data of a star. + * + * This structure provides the data necessary for reduction of star positions + * with the following member functions: + * + * Position::Geometric( const StarPosition& ) \n + * Position::Astrometric( const StarPosition& ) \n + * Position::Proper( const StarPosition& ) \n + * Position::Apparent( const StarPosition& ) \n + * Position::Intermediate( const StarPosition& ) + * + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS StarPosition +{ + double alpha = 0; //!< ICRS right ascension in degrees. + double delta = 0; //!< ICRS declination in degrees. + double muAlpha = 0; //!< Proper motion in right ascension, mas/year * cos( delta ). + double muDelta = 0; //!< Proper motion in declination, in mas/year. + double p = 0; //!< Parallax in arcseconds. + double v = 0; //!< Radial velocity in km/s, positive away from Earth. + TimePoint t0 = TimePoint::J2000(); //!< Epoch of coordinates. + + /*! + * Default constructor. See data members for default values. + */ + StarPosition() = default; + + /*! + * Copy constructor. + */ + StarPosition( const StarPosition& x ) + : alpha( x.alpha ) + , delta( x.delta ) + , muAlpha( x.muAlpha ) + , muDelta( x.muDelta ) + , p( x.p ) + , v( x.v ) + , t0( x.t0 ) + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + StarPosition& operator =( const StarPosition& x ) + { + alpha = x.alpha; + delta = x.delta; + muAlpha = x.muAlpha; + muDelta = x.muDelta; + p = x.p; + v = x.v; + t0 = x.t0; + return *this; + } + + /*! + * Memberwise constructor. + * + * \param ra Right ascension equatorial coordinate in degrees. + * Can be specified in the range [-180,+180] or + * [0,360) indistinctly. + * + * \param dec Declination equatorial coordinate in degrees. + * Should be in the [-90,+90] range. + * + * \param properMotionRA Proper motion in right ascension, in mas/year, + * measured on a great circle, that is, the + * specified value must be the proper motion in R.A. + * multiplied by the cosine of the declination. Zero + * by default. + * + * \param properMotionDec Proper motion in declination, in mas/year. Zero + * by default. + * + * \param parallax Parallax in arcseconds. Zero by default. + * + * \param radialVelocity Radial velocity in km/s, positive away from the + * Earth. Zero by default. + * + * \param epoch Epoch of catalog coordinates. J2000.0 by default. + * + * Positions and proper motions must be referred to ICRS/J2000.0. + * + * If out-of-range coordinates are specified, their values will be + * constrained to their proper ranges: right ascension to [0°,360°) + * and declination to [-90°,+90°]. + */ + StarPosition( double ra, double dec, + double properMotionRA = 0, double properMotionDec = 0, + double parallax = 0, + double radialVelocity = 0, + TimePoint epoch = TimePoint::J2000() ) + : alpha( ((ra = Mod( ra, 360.0 )) < 0) ? ra + 360 : ra ) + , delta( Range( dec, -90.0, +90.0 ) ) + , muAlpha( properMotionRA ) + , muDelta( properMotionDec ) + , p( parallax ) + , v( radialVelocity ) + , t0( epoch ) + { + } + +private: + + uint64 m_uniqueId = UniqueId(); + + static uint64 UniqueId(); + + friend class PCL_CLASS Position; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct ObserverPosition + * \brief Geodetic coordinates of a terrestrial observer. + * + * This structure provides the data necessary to calculate topocentric places + * of solar system bodies and stars. + * + * \ingroup solar_system_ephemerides + */ +struct PCL_CLASS ObserverPosition +{ + double lambda = 0; //!< Geodetic longitude in degrees. + double phi = 0; //!< Geodetic latitude in degrees. + double h = 0; //!< Geodetic height in meters. + double a = ea_eq_radius_IAU2009; //!< Equatorial radius of the reference spheroid in meters. + double f = ea_flattening_IERS2010; //!< Flattening of the reference spheroid. + Vector r0 = Vector( 0, 0, 0 ); //!< Geocentric rectangular coordinates of the center of the regional spheroid, in meters. + bool cioBased = false; //!< Whether to compute CIO-based or equinox-based topocentric coordinates. + + /*! + * Equatorial radius of Earth in meters, IAU 2009/2012. + */ + constexpr static double ea_eq_radius_IAU2009 = 6378136.6; + + /*! + * Flattening of Earth, IERS 2010. + */ + constexpr static double ea_flattening_IERS2010 = 1/298.25642; + + /*! + * Default constructor. + * + * Constructs an %ObserverPosition object for a fictitious observer at the + * geocenter. See data members for specific default values. + */ + ObserverPosition() = default; + + /*! + * Copy constructor. + */ + ObserverPosition( const ObserverPosition& ) = default; + + /*! + * Move constructor. + */ + ObserverPosition( ObserverPosition&& ) = default; + + /*! + * Copy assignment operator. + */ + ObserverPosition& operator =( const ObserverPosition& ) = default; + + /*! + * Move assignment operator. + */ + ObserverPosition& operator =( ObserverPosition&& ) = default; + + /*! + * Memberwise constructor. + * + * \param longitude Geodetic longitude in degrees. + * + * \param latitude Geodetic latitude in degrees. + * + * \param height Geodetic height in meters. Zero by default. + * + * \param equatorialRadius Equatorial radius of the reference spheroid in + * meters. The default value is the IAU 2009/2012 + * equatorial radius of Earth: 6,378,136.6 meters. + * + * \param flattening Flattening of the reference spheroid. The default + * value is the IERS 2010 flattening of Earth: + * 1/298.25642. + * + * \param regionalCenter Geocentric rectangular coordinates of the center + * of the regional spheroid, in meters. A zero 3-D + * vector (that is, the geocenter) by default. + * + * \param useCIO Whether to compute CIO-based or equinox-based + * topocentric coordinates. False (equinox-based) by + * default. + * + * Typically, the values used should be WGS84 coordinates (for example, as + * distributed by GPS) or ITRF coordinates (both systems close together at + * the level of a few centimeters). + * + * Geographic longitudes grow eastward, so longitudes are positive to the + * east and negative to the west of the central meridian. For ease of + * calculation, this constructor converts longitudes to the + * [0°,360°) range. + * + * If out-of-range coordinates are specified, their values will be + * constrained to their proper ranges: longitude to [0°,360°), and + * latitude to [-90°,+90°]. + */ + ObserverPosition( double longitude, double latitude, + double height = 0, + double equatorialRadius = ea_eq_radius_IAU2009, + double flattening = ea_flattening_IERS2010, + const Vector& regionalCenter = Vector( 0, 0, 0 ), + bool useCIO = false ) + : lambda( ((longitude = Mod( longitude, 360.0 )) < 0) ? longitude + 360 : longitude ) + , phi( Range( latitude, -90.0, +90.0 ) ) + , h( Max( 0.0, height ) ) + , a( Max( 0.0, equatorialRadius ) ) + , f( Max( 0.0, flattening ) ) + , r0( regionalCenter ) + , cioBased( useCIO ) + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Position + * \brief Reduction of planetary and stellar positions. + * + * This class implements algorithms for reduction of positions of solar system + * bodies and stars. It allows for calculation of geometric, astrometric, + * proper, apparent and intermediate places, including geocentric and + * topocentric coordinates. + * + * The implemented vector astrometry and ephemeris calculation algorithms are + * rigorous and compliant with current IAU and IERS resolutions. Both + * equinox-based and CIO-based paradigms have been implemented for calculation + * of positions that depend on Earth's rotation. The apparent and intermediate + * places include the following corrections: + * + * \li Light-travel time for solar system bodies. + * + * \li Space motion for stars, including parallax, radial velocity and proper + * motions, with corrections for the relativistic Doppler effect that takes + * into account the change in light-travel time for stars. + * + * \li Relativistic deflection of light due to solar gravitation. + * + * \li Aberration of light, relativistic model. + * + * \li %Frame bias, precession and nutation. (equinox-based and CIO-based). + * + * \li Accurate topocentric places with polar motion corrections. + * + * Vector components are expressed in astronomical units (au) for stars and all + * solar system bodies except the Moon, for which positions are given in + * kilometers. + * + * As of writing this documentation (October 2018), the IAU 2006/2000A + * precession-nutation theory is implemented (adjusted model with corrections + * to nutation angles, IAU 2006/2000AR). The standard fundamental + * ephemerides are JPL's DE438/LE438. + * + * Most of the reference publications and material used are cited in source + * code comments and the documentation. The main authoritative resource is: + * + * Urban, Sean E., Kenneth Seidelmann, P., ed. (2013), The Explanatory + * Supplement to the Astronomical Almanac 3rd Edition. + * + * \ingroup solar_system_ephemerides + */ +class PCL_CLASS Position +{ +public: + + /*! + * Constructs a %Position object initialized for the specified time of + * calculation \a t in the specified \a timescale. + * + * The supported time scales are: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
\b TT Terrestrial Time. This is the default + * timescale.
\b TDB Barycentric Dynamical Time.
\b Teph Ephemeris time, as defined by JPL DE/LE + * numerical integrations. For all purposes, this is + * equivalent to TDB.
\b UTC Coordinated Universal Time.
\b TAI Atomic International Time.
\b UT1 Universal Time.
\b UT Universal Time (same as UT1).
+ * + * \a timescale string values are considered case-sensitive. + * + * All necessary timescale conversions to compute ephemerides and reduction + * of positions are performed automatically. + */ + Position( TimePoint t, const IsoString& timescale = "TT" ); + + /*! + * Copy constructor. + */ + Position( const Position& ) = default; + + /*! + * Move constructor. + */ + Position( Position&& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Position& operator =( const Position& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Position& operator =( Position&& ) = default; + + /*! + * Computes the true position of a solar system body. + * + * The components of the returned vector are the geocentric or topocentric + * rectangular equatorial coordinates for the calculation instant defined by + * this object in the TT timescale, without accounting for light-travel + * time, for the body defined by the specified ephemeris handle \a H. + * + * This function calls Geometric( EphemerisFile::Handle& ) internally to + * compute, if necessary, the geometric position with correction for light + * time, that is, no separate calculation routine is implemented for true + * positions. The returned vector is only useful to compute the true + * geocentric or topocentric distance, and for verification purposes. + */ + Vector True( EphemerisFile::Handle& H ) + { + (void)Geometric( H ); + return m_U0; + } + + /*! + * Computes the geometric position of a star. + * + * This function has been implemented for completeness. It is a synonym for + * Geometric( const StarPosition& ). There are no known 'true' positions of + * stars, since their light-travel time is implicitly included in the space + * motion equations. + */ + Vector True( const StarPosition& S ) + { + (void)Geometric( S ); + return m_U0; + } + + /*! + * Computes the true distance of a solar system body. + * + * The true distance is the actual distance from the body to the observer, + * geocentric or topocentric, at the instant of calculation. This excludes + * the light-travel time correction. + */ + double TrueDistance( EphemerisFile::Handle& H ) + { + return True( H ).L2Norm(); + } + + /*! + * Computes the true distance of a star. + * + * The returned value is just the norm of the geometric position vector, + * that is: + * + * \code Geometric( S ).L2Norm() \endcode + * + * This should be an actual distance in au only for stars with known + * parallaxes. For stars where the parallax is unknown or undefined, this + * value is meaningless because in such cases position vectors are unit + * vectors, whose components are also known as direction cosines. + */ + double TrueDistance( const StarPosition& S ) + { + return True( S ).L2Norm(); + } + + /*! + * Computes the geometric position of a solar system body. + * + * The components of the returned vector are the geocentric or topocentric + * rectangular equatorial coordinates for the instant of calculation defined + * by this object in the TT timescale, accounting for light-travel time, for + * the body defined by the specified ephemeris handle \a H. + * + * The implemented reduction algorithm includes just the correction for + * light-travel time, but no corrections for light deflection, annual + * aberration, nutation, or precession. The position so calculated allows to + * plot the specified body directly on an existing sky chart referred to + * GCRS/J2000.0. Note however, that for generation of new graphical + * representations for a given date using star catalog data, astrometric or + * proper places should be used instead. + */ + Vector Geometric( EphemerisFile::Handle& H ); + + /*! + * Computes the geometric position of a star. + * + * The components of the returned vector are the geocentric or topocentric + * rectangular equatorial coordinates for the instant of calculation defined + * by this object in the TT timescale, for the positional star data defined + * by the specified object \a S. + * + * The implemented reduction algorithm includes just the corrections for + * space motion: parallax, radial velocity and proper motions, when the + * corresponding data items are nonzero in the specified object \a S. The + * space motion vector includes terms to account for the relativistic + * Doppler effect. + */ + Vector Geometric( const StarPosition& S ); + + /*! + * Computes the astrometric place of a solar system body. + * + * The returned vector is the astrometric place of the object defined by the + * specified ephemeris handle \a H in geocentric or topocentric rectangular + * equatorial coordinates, calculated for the instant defined by this object + * in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Light-travel time. + * + * \li Relativistic deflection of light due to solar gravitation (except + * for the Sun, the Moon, and any object closer from Earth than the Sun at + * the time of observation). + * + * An astrometric place does not include annual aberration, nutation and + * precession corrections. Hence it is referred to an 'hybrid' reference + * system, but similar to GCRS J2000.0. + */ + Vector Astrometric( EphemerisFile::Handle& H ); + + /*! + * Computes the astrometric place of a star. + * + * The returned vector is the astrometric place calculated for the + * positional star data defined by the specified object \a S. Its components + * are geocentric or topocentric rectangular equatorial coordinates, + * calculated for the instant defined by this object in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Space motion, including parallax, radial velocity and proper motions, + * with corrections for the relativistic Doppler effect. + * + * \li Relativistic deflection of light due to solar gravitation. + * + * An astrometric place does not include annual aberration, nutation and + * precession corrections. Hence it is referred to an 'hybrid' reference + * system, but similar to GCRS J2000.0. + */ + Vector Astrometric( const StarPosition& S ); + + /*! + * Computes the proper place of a solar system body. + * + * The returned vector is the proper place of the object defined by the + * specified ephemeris handle \a H in geocentric or topocentric rectangular + * equatorial coordinates, calculated for the instant defined by this object + * in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Light-travel time. + * + * \li Relativistic deflection of light due to solar gravitation (except + * for the Sun, the Moon, and any object closer from Earth than the Sun at + * the time of observation. + * + * \li Aberration of light, including relativistic terms. + * + * A proper place does not include nutation and precession corrections, + * hence it is referred to the reference coordinate system: GCRS J2000.0. + */ + Vector Proper( EphemerisFile::Handle& H ); + + /*! + * Computes the proper place of a star. + * + * The returned vector is the proper place calculated for the positional + * star data defined by the specified object \a S. Its components are + * geocentric or topocentric rectangular equatorial coordinates, calculated + * for the instant defined by this object in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Space motion, including parallax, radial velocity and proper motions, + * with corrections for the relativistic Doppler effect. + * + * \li Relativistic deflection of light due to solar gravitation. + * + * \li Aberration of light, including relativistic terms. + * + * A proper place does not include nutation and precession corrections, + * hence it is referred to the reference coordinate system: GCRS J2000.0. + */ + Vector Proper( const StarPosition& S ); + + /*! + * Computes the apparent place of a solar system body. + * + * The returned vector is the apparent place of the object defined by the + * specified ephemeris handle \a H in geocentric or topocentric rectangular + * equatorial coordinates, calculated for the instant defined by this object + * in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Light-travel time. + * + * \li Relativistic deflection of light due to solar gravitation (except + * for the Sun, the Moon, and any object closer from Earth than the Sun at + * the time of observation. + * + * \li Aberration of light, including relativistic terms. + * + * \li %Frame bias, precession and nutation. The origin of right ascension is + * the true equinox of date. + * + * \note The declination coordinate is identical in both equinox-based + * (apparent) and CIO-based (intermediate) positions. Only the origin of + * right ascensions differs between both systems. + * + * \warning If a valid observer location has been defined by calling the + * SetObserver() member function, and the specified ObserverPosition + * structure requires CIO-based transformations (see the + * ObserverPosition::cioBased member), this function will throw an Error + * exception. + */ + Vector Apparent( EphemerisFile::Handle& H ); + + /*! + * Computes the apparent place of a star. + * + * The returned vector is the apparent place calculated for the positional + * star data defined by the specified object \a S. Its components are + * geocentric or topocentric rectangular equatorial coordinates, calculated + * for the instant defined by this object in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Space motion, including parallax, radial velocity and proper motions, + * with corrections for the relativistic Doppler effect. + * + * \li Relativistic deflection of light due to solar gravitation. + * + * \li Aberration of light, including relativistic terms. + * + * \li %Frame bias, precession and nutation. The origin of right ascension is + * the true equinox of date. + * + * \note The declination coordinate is identical in both equinox-based + * (apparent) and CIO-based (intermediate) positions. Only the origin of + * right ascensions differs between both systems. + * + * \warning If a valid observer location has been defined by calling the + * SetObserver() member function, and the specified ObserverPosition + * structure requires CIO-based transformations (see the + * ObserverPosition::cioBased member), this function will throw an Error + * exception. + */ + Vector Apparent( const StarPosition& S ); + + /*! + * Computes the intermediate place of a solar system body. + * + * The returned vector is the intermediate place of the object defined by + * the specified ephemeris handle \a H in geocentric or topocentric + * rectangular equatorial coordinates, calculated for the instant defined by + * this object in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Light-travel time. + * + * \li Relativistic deflection of light due to solar gravitation (except + * for the Sun, the Moon, and any object closer from Earth than the Sun at + * the time of observation. + * + * \li Aberration of light, including relativistic terms. + * + * \li %Frame bias, precession and nutation. The origin of right ascension is + * the Celestial Intermediate Origin (CIO), following the IAU + * recommendations since January 2003. + * + * \note The declination coordinate is identical in both equinox-based + * (apparent) and CIO-based (intermediate) positions. Only the origin of + * right ascensions differs between both systems. + * + * \warning If a valid observer location has been defined by calling the + * SetObserver() member function, and the specified ObserverPosition + * structure requires equinox-based transformations (see the + * ObserverPosition::cioBased member), this function will throw an Error + * exception. + */ + Vector Intermediate( EphemerisFile::Handle& H ); + + /*! + * Computes the intermediate place of a star. + * + * The returned vector is the intermediate place calculated for the + * positional star data defined by the specified object \a S. Its components + * are geocentric or topocentric rectangular equatorial coordinates, + * calculated for the instant defined by this object in the TT timescale. + * + * The implemented reduction algorithm includes the following corrections: + * + * \li Space motion, including parallax, radial velocity and proper motions, + * with corrections for the relativistic Doppler effect. + * + * \li Relativistic deflection of light due to solar gravitation. + * + * \li Aberration of light, including relativistic terms. + * + * \li %Frame bias, precession and nutation. The origin of right ascension is + * the Celestial Intermediate Origin (CIO), following the IAU + * recommendations since January 2003. + * + * \note The declination coordinate is identical in both equinox-based + * (apparent) and CIO-based (intermediate) positions. Only the origin of + * right ascensions differs between both systems. + * + * \warning If a valid observer location has been defined by calling the + * SetObserver() member function, and the specified ObserverPosition + * structure requires equinox-based transformations (see the + * ObserverPosition::cioBased member), this function will throw an Error + * exception. + */ + Vector Intermediate( const StarPosition& S ); + + /*! + * Defines the geodetic positional and reference data necessary for + * calculation of topocentric positions of solar system objects and stars. + * + * By default, an instance of the %Position class calculates geocentric + * coordinates. After calling this member function, subsequently calculated + * geometric, proper, astrometric, apparent and intermediate places will be + * topocentric, that is, will be referred to the location of the observer + * with respect to the center of the Earth. + * + * By calling this member function, all previously computed positional data + * will be erased with the exception of fundamental ephemerides and existing + * bias-precession-nutation matrices, which can always be preserved. + * + * The ObserverPosition::cioBased data member of the specified \a observer + * structure selects the celestial system and paradigm to be used in the + * calculation of positions that depend on Earth's rotation. If the cioBased + * member is true, equinox-based places cannot be calculated, and any of the + * Apparent() member functions will throw an exception if called. + * Conversely, if cioBased is false, CIO-based places cannot be calculated + * and no call to an Intermediate() member function will be allowed. + * + * If polar motion corrections are enabled, the position of the CIP with + * respect to the ITRS is interpolated from the global CIP_ITRS database, if + * it provides data for the current time of calculation. In such case, polar + * motion is taken into account in the calculation of the observer's + * geocentric position and velocity. For the geocentric velocity a standard + * constant value for the rotation rate of the Earth is used; the velocity + * component due to precession and nutation is not taken into account since + * its effect is negligible. See the IsPolarMotionEnabled() and CIP_ITRS() + * member functions for more information and additional references. + */ + void SetObserver( const ObserverPosition& observer ); + + /*! + * Removes the current observer, if a valid one has been defined by a + * previous call to SetObserver(). In such case, all previously computed + * positional data will be invalidated, with the exception of fundamental + * ephemerides and existing bias-precession-nutation matrices. + * + * If no observer has been defined for this object, calling this member + * function has no effect. + * + * After calling this member function, all subsequently calculated + * geometric, proper, astrometric, apparent and intermediate places will be + * geocentric. + */ + void SetGeocentric(); + + /*! + * Returns the current observer. If no observer has been defined for this + * object, returns a default-constructed structure for a fictitious observer + * at the geocenter. + */ + ObserverPosition Observer() const + { + if ( m_observer ) + return *m_observer; + return ObserverPosition(); + } + + /*! + * Returns true iff a valid observer location has been defined for this + * object in a previous call to SetObserver(). + */ + bool IsTopocentric() const + { + return m_observer; + } + + /*! + * Returns true iff topocentric places take into account polar motion + * corrections to compute the geocentric position and velocity of the + * observer. This involves calculation of CIP coordinates with respect to + * the ITRS, as well as access to a database of CIP/ITRS positions. See the + * CIP_ITRS() member function for more details. + * + * Polar motion introduces changes at the mas level for calculation of + * topocentric coordinates of the Moon. For the rest of objects, the effect + * of polar motion corrections is completely negligible. For topocentric + * positions of the Moon, polar motion can be necessary to achieve the + * highest accuracy, but in such case one may also have to take into account + * a regional geoid referred to the Earth's reference ellipsoid. See the + * ObserverPosition structure. + */ + bool IsPolarMotionEnabled() const + { + return m_usePolarMotion; + } + + /*! + * Enables polar motion corrections for calculation of topocentric places. + * See the CIP_ITRS() and IsPolarMotionEnabled() functions for more details. + */ + void EnablePolarMotion( bool enable = true ) + { + m_usePolarMotion = enable; + } + + /*! + * Disables polar motion corrections for calculation of topocentric places. + * See the CIP_ITRS() and IsPolarMotionEnabled() functions for more details. + */ + void DisablePolarMotion( bool disable = true ) + { + EnablePolarMotion( !disable ); + } + + /*! + * Returns the time of calculation for this object in the Barycentric + * Dynamical Time (TDB) timescale. + * + * The times of calculation in different timescales are calculated by the + * class constructor. + */ + TimePoint TDB() const + { + return m_t; + } + + /*! + * Returns the time of calculation for this object in the ephemeris + * timescale defined by the JPL DE/LE numerical integration. For all + * purposes this is equivalent to TDB. + * + * The times of calculation in different timescales are calculated by the + * class constructor. + */ + TimePoint Teph() const + { + return m_t; + } + + /*! + * Returns the time of calculation for this object in the Terrestrial Time + * (TT) timescale. + * + * The times of calculation in different timescales are calculated by the + * class constructor. + */ + TimePoint TT() const + { + return m_tt; + } + + /*! + * Returns the time of calculation for this object in the Universal Time + * (UT1) timescale. + * + * The times of calculation in different timescales are calculated by the + * class constructor. + */ + TimePoint UT1() const + { + return m_ut1; + } + + /*! + * Returns the ICRS barycentric position of the Earth (barycentric + * rectangular equatorial coordinates), computed for the TDB time of + * calculation by the class constructor. The components of the + * returned vector are expressed in au. + */ + Vector BarycentricPositionOfEarth() const + { + return m_Eb; + } + + /*! + * Returns the ICRS barycentric velocity of the Earth (barycentric + * rectangular equatorial coordinates), computed for the TDB time of + * calculation by the class constructor. The components of the + * returned vector are expressed in au/day. + */ + Vector BarycentricVelocityOfEarth() const + { + return m_Edb; + } + + /*! + * Returns the ICRS barycentric position of the Sun (barycentric rectangular + * equatorial coordinates), computed for the TDB time of calculation by the + * class constructor. The components of the returned vector are in au. + */ + Vector BarycentricPositionOfSun() const + { + return m_Sb; + } + + /*! + * Returns the ICRS heliocentric position of the Earth (heliocentric + * rectangular equatorial coordinates), computed for the TDB time of + * calculation by the class constructor. The components of the + * returned vector are expressed in au. + */ + Vector HeliocentricPositionOfEarth() const + { + return m_Eh; + } + + /*! + * Calculates all parameters and data structures necessary for equinox-based + * reduction of positions. + * + * This member function calculates the following structures: + * + * \li Precession+bias angles, IAU 2006 precession model, Fukushima-Williams + * parameterization. See ESAsA sections 6.6.2.2 and 7.2.5.1. + * + * \li Mean obliquity of the ecliptic, IAU 2006 precession model. See ESAsA + * section 7.2.5.1. + * + * \li Nutation angles, IAU 2006/2000A_R nutation model. See ESAsA section + * 6.6.1. + * + * \li Combined bias-precession-nutation matrix, equinox-based. See ESAsA + * sections 6.7 and 7.2.5.1. + * + * \li Position of the Celestial Intermediate Pole (CIP). ESAsA section 6.7. + * + * \li Celestial Intermediate Origin (CIO) locator. ESAsA section 6.7. + * + * \li Equation of the origins (EO). See Wallace, P. & Capitaine, N., 2006, + * Astron.Astrophys. 459, 981, and ESAsA section 6.4. + * + * \li Earth rotation angle (ERA) for the UT1 time of calculation. See IERS + * Technical Note No. 32, 2003, Section 5.4.4. + * + * \li Greenwich Apparent Sidereal Time (GAST), IAU 2006. ESAsA 6.8.5. + * + * Since all of these items depend exclusively on time, they are computed + * only once in the first call to this function, and subsequent calls will + * have no effect. + * + * Normally, you don't have to call this function directly because it is + * invoked automatically when necessary by the different position reduction + * routines. + */ + void InitEquinoxBasedParameters(); + + /*! + * Calculates all parameters and data structures necessary for CIO-based + * reduction of positions. + * + * This member function starts by calling InitEquinoxBasedParameters(), so + * it implicitly calculates all equinox-based parameters. Then it calculates + * the CIO-based combined bias-precession-nutation matrix. See ESAsA + * sections 6.7 and 7.2.5.2. + * + * Since all of these items depend exclusively on time, they are computed + * only once in the first call to this function, and subsequent calls will + * have no effect. + * + * Normally, you don't have to call this function directly because it is + * invoked automatically when necessary by the different position reduction + * routines. + */ + void InitCIOBasedParameters(); + + /*! + * Returns the equinox-based combined bias-precession-nutation matrix. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + Matrix EquinoxBiasPrecessionNutationMatrix() + { + InitEquinoxBasedParameters(); + return m_M; + } + + /*! + * Returns the inverse of the equinox-based combined + * bias-precession-nutation matrix. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + Matrix EquinoxBiasPrecessionNutationInverseMatrix() + { + InitEquinoxBasedParameters(); + return m_Minv; + } + + /*! + * Returns the CIO-based combined bias-precession-nutation matrix. + * + * This member function calls InitCIOBasedParameters() to ensure that + * all data required for equinox-based and CIO-based reduction of positions + * is available. + */ + Matrix CIOBiasPrecessionNutationMatrix() + { + InitCIOBasedParameters(); + return m_C; + } + + /*! + * Returns the inverse of the CIO-based combined bias-precession-nutation + * matrix. + * + * This member function calls InitCIOBasedParameters() to ensure that + * all data required for equinox-based and CIO-based reduction of positions + * is available. + */ + Matrix CIOBiasPrecessionNutationInverseMatrix() + { + InitCIOBasedParameters(); + return m_Cinv; + } + + /*! + * Coordinates of the Celestial Intermediate Pole (CIP) in the GCRS, in + * radians. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + Vector CIP() + { + InitEquinoxBasedParameters(); + return Vector( m_X, m_Y ); + } + + /*! + * Coordinates of the Celestial Intermediate Pole (CIP) in the ITRS. + * + * If possible, this member function returns an interpolated value from the + * global CIP_ITRS database, which will be loaded and parsed upon the first + * call to this function as a thread-safe procedure. See + * EphemerisFile::CIP_ITRSDataFilePath() and + * EphemerisFile::OverrideCIP_ITRSDataFilePath() for more information. See + * also IsPolarMotionEnabled() for some practical considerations. + * + * Otherwise, if the time of calculation for this object falls outside the + * CIP_ITRS database time span, this function will return a two-dimensional + * vector with zero components. + * + * The components of the returned 2-D vector are the coordinates + * xp, yp of the CIP with respect to the ITRS, + * expressed in radians. + */ + Vector CIP_ITRS() const; + + /*! + * The Celestial Intermediate Origin (CIO) locator, in radians. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + double CIO() + { + InitEquinoxBasedParameters(); + return m_s; + } + + /*! + * Equation of the origins, expressed in radians. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + double EO() + { + InitEquinoxBasedParameters(); + return m_EO; + } + + /*! + * Earth rotation angle, expressed in radians. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + double ERA() + { + InitEquinoxBasedParameters(); + return m_ERA; + } + + /*! + * Greenwich apparent sidereal time, expressed in radians. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + double GAST() + { + InitEquinoxBasedParameters(); + return m_GAST; + } + + /*! + * Mean obliquity of the ecliptic, in radians. + */ + double EpsA() const + { + // Mean obliquity of the ecliptic, IAU 2006 precession model. + if ( m_M.IsEmpty() ) + return AsRad( Poly( m_TT, { 84381.406, -46.836769, -0.0001831, 0.00200340, -0.000000576, -0.0000000434 } ) ); + return m_epsa; + } + + /*! + * Returns the nutation angles in radians as a point p, where \e p.x is the + * nutation in longitude and \e p.y is the nutation in obliquity. + * + * This member function calls InitEquinoxBasedParameters() to ensure that + * all data required for equinox-based reduction of positions is available. + */ + DPoint NutationAngles() + { + InitEquinoxBasedParameters(); + return DPoint( m_dpsi, m_deps ); + } + + /*! + * Returns true iff the apparent visual magnitude of the object represented + * by the specified handle \a H can be calculated with the current + * implementation, at the calculation time defined by this instance. + * + * Currently apparent visual magnitudes can be calculated for the following + * solar system bodies: + * + * \li Objects providing valid H and G parameters (absolute magnitude and + * slope coefficient). This happens for most asteroids included in standard + * XEPH files. + * + * \li Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune and Pluto. + * + * \li The four Galilean satellites of Jupiter: Io, Europa, Ganymede and + * Callisto. + * + * \sa ApparentVisualMagnitude() + */ + bool CanComputeApparentVisualMagnitude( const EphemerisFile::Handle& H ) const; + + /*! + * Returns the observed visual magnitude of a solar system body. + * + * For objects with known H and G values (absolute magnitude and slope + * parameters, respectively; see EphemerisFile::Handle::H() and + * EphemerisFile::Handle::G()), the apparent visual magnitude is calculated + * applying the algorithm for minor planets described in Bowell et al. + * (1989). See also The Explanatory Supplement, Section 10.4.3. + * + * For Mercury, Venus, Mars, Jupiter, Saturn and Neptune, we apply the + * equations described in the following paper: + * + * Anthony Mallama, James L. Hilton, Computing Apparent Planetary + * Magnitudes for The Astronomical Almanac, revised 2018 June 21. + * + * As of writing this documentation, the above paper is available online at: + * https://arxiv.org/pdf/1808.01973.pdf + * + * For Saturn, we compute the apparent visual magnitude taking into account + * the planet's rings. + * + * For Uranus, Pluto and the Galilean satellites of Jupiter, data from + * various sources are taken from Table 10.6 of the Explanatory Supplement. + * + * If the required data are not available, or if no algorithm is known for + * the calculation of the apparent visual magnitude of the specified object, + * this member function returns an undefined Optional object. + * + * An undefined object is also returned when the phase angle of the object + * at the time of calculation is beyond the limits of the set of + * observations used to generate the underlying models. For Mercury, + * apparent magnitudes are only calculated for phase angles + * 2° ≤ \e i ≤ 170°. For Venus, the magnitude is only + * calculated for 0° < \e i ≤ 163°.7. The valid range for Mars is + * \e i ≤ 50°. + * + * \sa CanComputeApparentVisualMagnitude() + */ + Optional ApparentVisualMagnitude( EphemerisFile::Handle& H ); + + /*! + * Conversion from rectangular equatorial to rectangular ecliptic + * coordinates. + * + * \param q Rectangular equatorial coordinates. + * + * \param se Sine of the obliquity of the ecliptic. + * + * \param ce Cosine of the obliquity of the ecliptic. + * + * Returns a vector whose components are the rectangular ecliptic + * coordinates corresponding to the specified equatorial position \a q at + * the epoch where the specified obliquity has been calculated. + */ + static Vector EquatorialToEcliptic( const Vector& q, double se, double ce ) + { + // Rx(eps)*q + return Vector( q[0], q[1]*ce + q[2]*se, q[2]*ce - q[1]*se ); + } + + /*! + * Conversion from rectangular equatorial to rectangular ecliptic + * coordinates. + * + * \param q Rectangular equatorial coordinates. + * + * \param eps Oliquity of the ecliptic in radians. + * + * Returns a vector whose components are the rectangular ecliptic + * coordinates corresponding to the specified equatorial position \a q at + * the epoch where the specified obliquity has been calculated. + */ + static Vector EquatorialToEcliptic( const Vector& q, double eps ) + { + double se, ce; SinCos( eps, se, ce ); + return EquatorialToEcliptic( q, se, ce ); + } + + /*! + * Conversion from spherical equatorial to spherical ecliptic coordinates. + * + * \param q Spherical equatorial coordinates in radians, where \a q.x is + * the right ascension and \a q.y is the declination. + * + * \param se Sine of the obliquity of the ecliptic. + * + * \param ce Cosine of the obliquity of the ecliptic. + * + * Returns the ecliptic coordinates in radians as a point \e p, where \e p.x + * is the longitude in the range [0,2pi) and \e p.y is the latitude in + * [-pi/2,+pi/2]. + */ + static DPoint EquatorialToEcliptic( const DPoint& q, double se, double ce ) + { + DPoint e; + EquatorialToEcliptic( Vector::FromSpherical( q.x, q.y ), se, ce ).ToSpherical2Pi( e.x, e.y ); + return e; + } + + /*! + * Conversion from spherical equatorial to spherical ecliptic coordinates. + * + * \param q Spherical equatorial coordinates in radians, where \a q.x is + * the right ascension and \a q.y is the declination. + * + * \param eps Oliquity of the ecliptic in radians. + * + * Returns the ecliptic coordinates in radians as a point \e p, where \e p.x + * is the longitude in the range [0,2pi) and \e p.y is the latitude in + * [-pi/2,+pi/2]. + */ + static DPoint EquatorialToEcliptic( const DPoint& q, double eps ) + { + double se, ce; SinCos( eps, se, ce ); + return EquatorialToEcliptic( q, se, ce ); + } + + /*! + * Conversion from rectangular ecliptic to rectangular equatorial + * coordinates. + * + * \param q Rectangular ecliptic coordinates. + * + * \param se Sine of the obliquity of the ecliptic. + * + * \param ce Cosine of the obliquity of the ecliptic. + * + * Returns a vector whose components are the rectangular equatorial + * coordinates corresponding to the specified ecliptic position \a q at + * the epoch where the specified obliquity has been calculated. + */ + static Vector EclipticToEquatorial( const Vector& q, double se, double ce ) + { + // Rx(eps)*q + return Vector( q[0], q[1]*ce - q[2]*se, q[2]*ce + q[1]*se ); + } + + /*! + * Conversion from rectangular ecliptic to rectangular equatorial + * coordinates. + * + * \param q Rectangular ecliptic coordinates. + * + * \param eps Oliquity of the ecliptic in radians. + * + * Returns a vector whose components are the rectangular equatorial + * coordinates corresponding to the specified ecliptic position \a q at + * the epoch where the specified obliquity has been calculated. + */ + static Vector EclipticToEquatorial( const Vector& q, double eps ) + { + double se, ce; SinCos( eps, se, ce ); + return EclipticToEquatorial( q, se, ce ); + } + + /*! + * Conversion from spherical ecliptic to spherical equatorial coordinates. + * + * \param q Spherical ecliptic coordinates in radians, where \a q.x is + * the longitude and \a q.y is the latitude. + * + * \param se Sine of the obliquity of the ecliptic. + * + * \param ce Cosine of the obliquity of the ecliptic. + * + * Returns the equatorial coordinates in radians as a point \e p, where \e p.x + * is the right ascension in the range [0,2pi) and \e p.y is the declination + * in [-pi/2,+pi/2]. + */ + static DPoint EclipticToEquatorial( const DPoint& q, double se, double ce ) + { + DPoint e; + EclipticToEquatorial( Vector::FromSpherical( q.x, q.y ), se, ce ).ToSpherical2Pi( e.x, e.y ); + return e; + } + + /*! + * Conversion from spherical ecliptic to spherical equatorial coordinates. + * + * \param q Spherical ecliptic coordinates in radians, where \a q.x is + * the longitude and \a q.y is the latitude. + * + * \param eps Oliquity of the ecliptic in radians. + * + * Returns the equatorial coordinates in radians as a point \e p, where \e p.x + * is the right ascension in the range [0,2pi) and \e p.y is the declination + * in [-pi/2,+pi/2]. + */ + static DPoint EclipticToEquatorial( const DPoint& q, double eps ) + { + double se, ce; SinCos( eps, se, ce ); + return EclipticToEquatorial( q, se, ce ); + } + + /*! + * Conversion from ICRS rectangular equatorial to rectangular galactic + * coordinates. + * + * \param q Rectangular equatorial coordinates in the ICRS. + * + * Returns a vector whose components are the calculated rectangular galactic + * coordinates. + * + * In this routine we adopt the proposed ICRS coordinates of the + * galactic pole in: + * + * Jia-Cheng Liu, Zi Zhu, and Hong Zhang, Reconsidering the galactic + * coordinate system, Astronomy & Astrophysics manuscript no. AA2010, + * October 26, 2018. + * + * The applied conventional definitions are as follows. The ICRS equatorial + * coordinates of the zero point of galactic coordinates are: + * + * α = 17h45m40s.0400 + * δ = –29°00'28".138 + * + * The equatorial coordinates of the galactic pole, coherent with the ICRS, + * are: + * + * αp = 12h51m36s.7151981 + * δp = +27°06'11".193172 + * + * Note that these definitions are not consistent with the conventional + * values currently accepted by the IAU. The current (as of October 2018) + * galactic coordinate system was defined by the IAU in 1959 in the FK4 + * B1950.0 reference system. + */ + static Vector ICRSEquatorialToGalactic( const Vector& q ) + { + return Matrix( +0.494055821648, -0.054657353964, -0.445679169947, + -0.872844082054, -0.484928636070, +0.746511167077, + -0.867710446378, -0.198779490637, +0.455593344276 )*q; + } + + /*! + * Conversion from ICRS spherical equatorial to spherical galactic + * coordinates. + * + * \param q Spherical ICRS equatorial coordinates in radians, where + * \a q.x is the right ascension and \a q.y is the declination. + * + * Returns the galactic coordinates in radians as a point \e p, where \e p.x + * is the longitude in the range [0,2pi) and \e p.y is the latitude in + * [-pi/2,+pi/2]. + * + * See the documentation for ICRSEquatorialToGalactic( const Vector& ) for + * critical information on the adopted galactic coordinate system. + */ + static DPoint ICRSEquatorialToGalactic( const DPoint& q ) + { + DPoint g; + ICRSEquatorialToGalactic( Vector::FromSpherical( q.x, q.y ) ).ToSpherical2Pi( g.x, g.y ); + return g; + } + +private: + + // TDB + TimePoint m_t; + // TT + TimePoint m_tt; + // UT1 + TimePoint m_ut1; + // TT in Julian centuries since J2000.0. + double m_TT; + // Barycentric ICRS position and velocity of the Earth. + Vector m_Eb, m_Edb; + // Geocentric ICRS position and velocity of the observer, in km and km/day. + Vector m_G, m_Gd; + // Barycentric ICRS position of the Sun. + Vector m_Sb; + // Heliocentric position of the Earth. + Vector m_Eh; + // Distance Earth-Sun. + double m_E; + // Heliocentric position of the observer (au). + Vector m_Oh; + // Distance observer-Sun (au). + double m_O; + // Bias+precession angles. + double m_gamb, m_phib, m_psib, m_epsa; + // Nutation angles. + double m_dpsi, m_deps; + // Position of the Celestial Intermediate Pole (CIP) in GCRS. + double m_X, m_Y; + // CIO locator. + double m_s; + // Combined bias-precession-nutation matrix (NPB). + Matrix m_M, m_Minv; + // Combined bias-precession-nutation matrix (NPB_CIO). + Matrix m_C, m_Cinv; + // Equation of the origins. + double m_EO; + // Earth rotation angle. + double m_ERA; + // Greenwich apparent sidereal time. + double m_GAST; + // Light-travel time in days. + double m_tau = 0; + // Barycentric position. + Vector m_ub; + // True geocentric position. + Vector m_U0; + // Geocentric position. + Vector m_U; + // Astrometric place. + Vector m_u1; + // Proper place. + Vector m_u2; + // Apparent place. + Vector m_u3e; + // Intermediate place. + Vector m_u3i; + + // Handles for calculation of fundamental ephemerides and nutation angles. + AutoPointerCloner m_TT_TDB, m_HE, m_HS, m_HN; + + // Current observer for calculation of topocentric coordinates. + AutoPointerCloner m_observer; + + // Special case flags. + bool m_isMoon = false, m_isSun = false, m_isStar = false; + + // Whether to account for polar motion (CIP->ITRS) in calculation of + // topocentric positions. + bool m_usePolarMotion = true; + + // Unique identifier of the object whose positions are being calculated. + uint64 m_uniqueObjectId = 0; + + template + bool Validate( const T& obj ) + { + if ( obj.m_uniqueId != m_uniqueObjectId ) + { + m_U0 = m_U = m_ub = m_u1 = m_u2 = m_u3e = m_u3i = Vector(); + m_tau = 0; + m_isMoon = m_isSun = m_isStar = false; + m_uniqueObjectId = obj.m_uniqueId; + return false; + } + return true; + } + + Vector Deflection(); + Vector Aberration(); + + static double CIOLocator( double T, double X, double Y ); + + /* + * Astronomical constants, IAU 2009/2012 and IERS 2003/2010. + */ + constexpr static double au_km = 149597870.7; // astronomical unit (km) + constexpr static double c_km_s = 299792.458; // speed of light (km/s) + constexpr static double c_km_day = c_km_s*86400; // speed of light (km/day) + constexpr static double c_au_day = (c_km_s/au_km)*86400; // speed of light (au/day) + constexpr static double earth_omega = 7.292115e-5; // angular velocity of Earth in radians/s +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Position_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Position.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PreviewSelectionDialog.h b/3rdparty/include/pcl/PreviewSelectionDialog.h new file mode 100644 index 0000000..4026836 --- /dev/null +++ b/3rdparty/include/pcl/PreviewSelectionDialog.h @@ -0,0 +1,130 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PreviewSelectionDialog.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 __PreviewSelectionDialog_h +#define __PreviewSelectionDialog_h + +/// \file pcl/PreviewSelectionDialog.h + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PreviewSelectionDialog + * \brief A simple dialog box to select an existing preview. + * + * %PreviewSelectionDialog consists of a ViewList control populated with all + * existing previews, and standard OK and Cancel push buttons. This class is a + * useful helper whenever a process needs access to a user-selected preview. + * + * \sa ViewSelectionDialog, MultiViewSelectionDialog, Dialog + */ +class PreviewSelectionDialog : public Dialog +{ +public: + + /*! + * Constructs a %PreviewSelectionDialog object. If the optional \a id + * argument is specified and a preview exists with that identifier, the + * dialog will select the corresponding preview upon execution. + */ + PreviewSelectionDialog( const IsoString& id = IsoString() ); + + PreviewSelectionDialog( const IsoString::ustring_base& id ) + : PreviewSelectionDialog( IsoString( id ) ) + { + } + + /*! + * Destroys a %PreviewSelectionDialog object. + */ + virtual ~PreviewSelectionDialog() + { + } + + /*! + * Returns the identifier of the selected preview. + */ + IsoString Id() const + { + return m_id; + } + +private: + + IsoString m_id; + + VerticalSizer Global_Sizer; + ViewList Images_ViewList; + HorizontalSizer Buttons_Sizer; + PushButton OK_PushButton; + PushButton Cancel_PushButton; + + void ViewSelected( ViewList& sender, View& view ); + void ButtonClick( Button& sender, bool checked ); + void ControlShow( Control& sender ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PreviewSelectionDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PreviewSelectionDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Process.h b/3rdparty/include/pcl/Process.h new file mode 100644 index 0000000..66f5c15 --- /dev/null +++ b/3rdparty/include/pcl/Process.h @@ -0,0 +1,365 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Process.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_Process_h +#define __PCL_Process_h + +/// \file pcl/Process.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class ProcessPrivate; + +/*! + * \class Process + * \brief High-level interface to an installed process. + * + * %Process instances are high-level, managed objects that represent + * installed processes in the PixInsight platform. A module creates an + * instance of %Process to gain access to an installed process through + * intermodule communication. + * + * %Process and %MetaProcess + * + * %Process provides a description of the functionality and properties of an + * already installed process. Contrarily, by subclassing the + * MetaProcess class a module can define and implement a new process that can + * be installed in the PixInsight platform. %MetaProcess is a formal + * description of a process, while %Process describes an existing (and + * installed) process. + * + * As a %MetaProcess subclass describes how a process can be instantiated, + * %Process allows a module to create new instances of a process that can be + * edited and executed. %Process does not provide any process execution + * functionality; executable processes are represented by the ProcessInstance + * class. + * + * \sa ProcessBase, MetaProcess, ProcessInstance + */ +class PCL_CLASS Process : public ProcessBase +{ +public: + + /*! + * A list of process parameters. + * + * This type is returned by the Parameters() member function to describe and + * identify the set of parameters of a process. + */ + typedef Array parameter_list; + + /*! + * Constructs a %Process object. + * + * \param classId Identifier of an installed process in the PixInsight + * core application. + * + * If successful, this constructor creates a managed alias to an installed + * process in the PixInsight core application. + * + * If there is no installed process with the specified identifier, if + * \a classId is not a valid identifier, or if the alias object cannot be + * generated for some reason, this constructor throws an Error exception + * with the corresponding error message. Your code should guarantee that + * these exceptions are always caught and handled appropriately. + */ + Process( const IsoString& classId ); + + Process( const IsoString::ustring_base& classId ) + : Process( IsoString( classId ) ) + { + } + + /*! + * Copy constructor. Constructs an \e alias %Process object that refers to + * the same process as the specified object \a proc. + */ + Process( const Process& proc ); + + /*! + * Destroys this %Process object. + * + * \note This destructor does not destroy or uninstall the actual process it + * refers to, which is part of the PixInsight core application. Only the + * managed alias object living in the caller module is destroyed. + */ + virtual ~Process(); + + /*! + */ + IsoString Id() const override; + + /*! + * Returns a list of alias identifiers for this process. + * + * A process can have one or more alias identifiers. Aliases are + * useful to maintain compatibility with previous versions of a process. + * + * When the PixInsight core application imports a process instance (e.g., + * from a process icon) it automatically replaces alias process identifiers + * with actual (current) identifiers. This allows a developer to change the + * identifier of a process without breaking compatibility with process + * instances in existing icon collections or projects. + * + * The returned object is a list of distinct identifiers that are treated as + * synonyms to the actual identifier of this process, which is returned by + * the Id() member function. Two installed processes can't have the same + * alias, so each identifier included in the returned list must be unique + * among all installed processes on the entire PixInsight platform. + */ + IsoStringList Aliases() const; + + /*! + * Returns the identifiers of one or more categories to which this process + * belongs. + * + * Processes are organized hierarchically by categories in PixInsight. All + * installed processes appear classified by their categories on the %Process + * Explorer window, and also under the %Process main menu item. + * + * This function returns a list of category names. Each category name must + * be a valid C identifier. If the returned list is empty, then this process + * is not associated with any particular category. In such case this process + * appears under a special, fallback pseudo-category identified as + * <Etc> on both the %Process Explorer window and the %Process main + * menu item. + */ + IsoStringList Categories() const; + + /*! + */ + uint32 Version() const override; + + /*! + */ + String Description() const override; + + /*! + */ + String ScriptComment() const override; + + /*! + */ + Bitmap Icon() const override; + + /*! + */ + Bitmap SmallIcon() const override; + + /*! + */ + bool CanProcessViews() const override; + + /*! + */ + bool CanProcessGlobal() const override; + + /*! + */ + bool CanProcessImages() const override; + + /*! + */ + bool CanProcessCommandLines() const override; + + /*! + */ + bool CanEditPreferences() const override; + + /*! + */ + bool CanBrowseDocumentation() const override; + + /*! + */ + bool IsAssignable() const override; + + /*! + */ + bool NeedsInitialization() const override; + + /*! + */ + bool NeedsValidation() const override; + + /*! + */ + bool PrefersGlobalExecution() const override; + + /*! + */ + bool EditPreferences() const override; + + /*! + */ + bool BrowseDocumentation() const override; + + /*! + * Invokes the command line execution routine for this process. + * + * \param arguments A string with the list of arguments that will be passed + * to the command line execution routine. Multiple + * arguments must be separated with white space characters. + * + * If this process supports command line execution, then the corresponding + * command line execution routine is invoked with the specified arguments. + * Otherwise, this member function calls Launch(), and the specified command + * line arguments are ignored. + * + * On the PixInsight platform, command line option arguments are customarily + * specified with leading dash characters, following the common UNIX style. + * Argument values are separated with equal signs. However, command line + * syntax and the meaning of each argument are specific to each process. + * + * This function returns the exit code of the command line execution routine + * of the process. By convention, exit code zero means successful execution, + * and nonzero exit codes are returned to signal errors. + */ + int RunCommandLine( const String& arguments ) const; + + /*! + * Launches this process. + * + * If this process has an associated default interface, then its top level + * window is shown and activated in its current state. + * + * If this process has no default interface, then the core application + * attempts to generate a default instance of the process and execute it. If + * the process prefers global execution (see the PrefersGlobalExecution() + * member function), then the default instance is executed in the global + * context; otherwise it is executed on the current view, if there is at + * least one image available. + * + * Returns true if the process was successfully launched; false in the event + * of error, or if the core application was unable to launch or execute it. + */ + bool Launch() const; + + /*! + * Returns the list of parameters of this process. The list can be empty for + * processes that don't have parameters. + */ + parameter_list Parameters() const; + + /*! + * Returns true iff this process has a parameter with the specified + * identifier \a paramId. + */ + bool HasParameter( const IsoString& paramId ) const; + + /*! + * Returns true iff this process has a table parameter \a tableId with the + * specified column parameter \a colId. + */ + bool HasTableColumn( const IsoString& tableId, const IsoString& colId ) const; + + /*! + * Returns a list of all the currently defined process categories in the + * PixInsight core application. + */ + static IsoStringList AllProcessCategories(); + + /*! + * Returns a list of all the currently installed processes on the PixInsight + * core application. + */ + static Array AllProcesses(); + + /*! + * Returns a list of all the currently installed processes pertaining to the + * specified \a category. Pass an empty string to obtain a list of all + * uncategorized processes (i.e. the \ fallback category). + * + * Returns an empty list if no currently installed process pertains to the + * specified category. + */ + static Array ProcessesByCategory( const IsoString& category ); + + static Array ProcessesByCategory( const IsoString::ustring_base& category ) + { + return ProcessesByCategory( IsoString( category ) ); + } + +private: + + AutoPointer m_data; + + Process( const void* ); + + const void* Handle() const; + + friend class ProcessInstance; + friend class ProcessParameter; + friend class ProcessParameterPrivate; + friend class InternalProcessEnumerator; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Process_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Process.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProcessBase.h b/3rdparty/include/pcl/ProcessBase.h new file mode 100644 index 0000000..5cd64ef --- /dev/null +++ b/3rdparty/include/pcl/ProcessBase.h @@ -0,0 +1,303 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProcessBase.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_ProcessBase_h +#define __PCL_ProcessBase_h + +/// \file pcl/ProcessBase.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ProcessBase + * \brief Abstract base class for process descriptions. + * + * %ProcessBase defines a number of descriptive properties of a process in the + * PixInsight platform. + * + * %ProcessBase is an abstract base class of the MetaProcess and Process + * instantiable classes. %MetaProcess describes an installable process, while + * the %Process class provides direct access to an installed process through + * intermodule communication. + * + * In more practical terms, modules defining new processes must implement + * derived classes of %MetaProcess, while %Process is used by modules requiring + * direct access to process instances through installed processes. + * + * Note that the %ProcessBase, %MetaProcess, %Process, ProcessImplementation + * and ProcessInstance classes are conceptually parallel to the FileFormatBase, + * MetaFileFormat, FileFormat, FileFormatImplementation and FileFormatInstance + * classes, respectively. This is just a reflection of the strong object + * orientation and modularity that characterize the PixInsight platform. + * + * \sa MetaProcess, Process, ProcessImplementation, ProcessInstance + */ +class PCL_CLASS ProcessBase +{ +public: + + /*! + * Constructs a %ProcessBase object. + */ + ProcessBase() + { + } + + /*! + * Destroys this %ProcessBase object. + */ + virtual ~ProcessBase() noexcept( false ) + { + } + + /*! + * Returns an identifier for this process. + * + * %Process identifiers are unique C identifiers. + */ + virtual IsoString Id() const = 0; + + /*! + * Returns a version number for this process, encoded as a hexadecimal + * number. + * + * For example, version 1.0.5 should be returned as 0x105, and version + * 3.11.5 as 0x3B5. + */ + virtual uint32 Version() const = 0; + + /*! + * Returns a descriptive text for this process. + * + * This function should provide a brief but sufficiently informative + * description of this process. The returned description appears on the + * %Process Explorer window, and should provide information about what this + * process does and how it can be used, avoiding too exhaustive descriptions + * that are better reserved for a technical manual. + * + * %Process descriptions are always printed on PixInsight consoles. This + * means that the text output functionality of the Console class can be used + * to format the string returned by this function. Refer to that class and + * its documentation for further information. + */ + virtual String Description() const = 0; + + /*! + * Returns a brief description for generated scripts. + * + * The returned text is intended to provide a brief comment to describe this + * process and its parameters, for quick reference on generated scripts. + * When writing these comments, think as you do when you're commenting your + * own source code. + */ + virtual String ScriptComment() const = 0; + + /*! + * Returns a large icon image that identifies this process. + * + * The returned image is used to identify all instances of this process in + * the core application's GUI. It is used on the Process Explorer window, on + * all icons transporting instances of this process, and in general for + * every graphical item related to this process or to an instance of this + * process. + */ + virtual Bitmap Icon() const = 0; + + /*! + * Returns a small icon image that identifies this process. + * + * For details on process icon images, see the documentation for Icon(). + * + * Small icons are used on interface elements where screen space must be + * preserved. Two good examples are the Process Explorer window and the + * ProcessContainer interface. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * Small icons are deprecated because all process and interface icons must + * now be specified in SVG format. SVG icons can be resized automatically to + * the required dimensions. + */ + virtual Bitmap SmallIcon() const = 0; + + /*! + * Returns true iff this process is able to process views. + */ + virtual bool CanProcessViews() const = 0; + + /*! + * Returns true iff this process can be executed globally. + */ + virtual bool CanProcessGlobal() const = 0; + + /*! + * Returns true iff this process is able to process standalone images. + */ + virtual bool CanProcessImages() const = 0; + + /*! + * Returns true iff this process is able to process specific command-line + * invocations. + */ + virtual bool CanProcessCommandLines() const = 0; + + /*! + * Returns true iff this process is able to edit specific preferences. + */ + virtual bool CanEditPreferences() const = 0; + + /*! + * Returns true iff this process is able to open a documentation browser with + * specific documentation contents. + * + * Starting from version 1.7, the PixInsight core application implements an + * integrated documentation system. The core application provides automatic + * documentation browsing and searching functionality, so normally this + * member function returns true for all processes. + */ + virtual bool CanBrowseDocumentation() const = 0; + + /*! + * Returns true iff the instances of this process are \e assignable. + * + * Assignable processes allow copying the parameters of one instance (and + * possibly more module-dependent data) to another. + */ + virtual bool IsAssignable() const = 0; + + /*! + * Returns true iff the instances of this process require special + * initialization. + * + * Special initialization takes place just after instance creation. + * Sometimes, there are actions that cannot be implemented in the + * constructor of a process instance class. For example, this often happens + * when an instance must be initialized by calling reimplemented virtual + * functions from a base class constructor. Reimplemented virtual functions + * cannot be resolved from a base class constructor in C++. + */ + virtual bool NeedsInitialization() const = 0; + + /*! + * Returns true iff the instances of this process require special + * validation. + * + * Some processes may require validation of their instances just before they + * are executed. This is known as special validation. The core + * application will never execute an instance of a process if its validation + * function fails. + */ + virtual bool NeedsValidation() const = 0; + + /*! + * Returns true iff the instances of this process prefer execution in the + * global context, instead of being executed on views. + * + * Note that the option indicated by this function is just a \e hint to the + * PixInsight core application, not necessarily observed. This means that + * the fact that this member function returns true for a process does not + * mean that the process cannot be executed on views. + */ + virtual bool PrefersGlobalExecution() const = 0; + + /*! + * Handles a request to edit process preferences. Returns true if the + * preferences were successfully edited. + * + * By calling this member function for a process able to edit preferences + * (that is, when CanEditPreferences() returns true), the user is allowed to + * define a set of preferences specific to this process. Usually this task + * is implemented on a modal dialog box. In such case, if the user closes + * the dialog box without accepting the new preferences settings (e.g. by + * clicking the dialog's Cancel button) this member function should return + * false. This member function should only return true if the user has + * edited and accepted a new set of preferences for this process. + */ + virtual bool EditPreferences() const = 0; + + /*! + * Handles a request to browse documentation specific for this process. + * Returns true iff the documentation was loaded successfully. + * + * Since version 1.7 of the PixInsight core application, the integrated + * documentation system works in a completely automatic and standardized way + * to provide documentation browsing and searching functionality. + * + * The default implementation of this member function automatically launches + * and loads the integrated documentation browser with the documentation for + * this process, if it exists and has been installed. For more information, + * please read the documentation for the CanBrowseDocumentation() function. + */ + virtual bool BrowseDocumentation() const = 0; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ProcessBase_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProcessBase.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProcessImplementation.h b/3rdparty/include/pcl/ProcessImplementation.h new file mode 100644 index 0000000..90c1f9e --- /dev/null +++ b/3rdparty/include/pcl/ProcessImplementation.h @@ -0,0 +1,813 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProcessImplementation.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_ProcessImplementation_h +#define __PCL_ProcessImplementation_h + +/// \file pcl/ProcessImplementation.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS MetaParameter; +class PCL_CLASS ProcessInterface; +class PCL_CLASS View; +class PCL_CLASS ImageWindow; + +// ---------------------------------------------------------------------------- + +/*! + * \class ProcessImplementation + * \brief Implementation of a PixInsight process instance. + * + * %Process instances are the main actors in the PixInsight environment, since + * they are responsible for all of the actual processing work. For example, + * process instances can be executed on views, on images and on the global + * context, edited through process interfaces, parsed by script interpreters, + * stored in processing histories and process containers, and managed as + * process icons and projects that can be transferred to and from special disk + * files (XPSM and XOSM formats). + * + * In the PixInsight/PCL framework, a process class is formally + * defined as a descendant of the MetaProcess class, along with several + * descendants of MetaParameter classes. %ProcessImplementation defines the + * behavior and functionality of an instance of a process class. + * + * \sa MetaProcess, MetaParameter + */ +class PCL_CLASS ProcessImplementation +{ +public: + + /*! + * Constructs a process instance. + * + * \param m Pointer to a metaprocess that identifies the process class + * that this process instance belongs to. + */ + ProcessImplementation( const MetaProcess* m ); + + /*! + * Copy constructor. Constructs a new process instance as a duplicate of an + * existing instance. + */ + ProcessImplementation( const ProcessImplementation& x ); + + /*! + * Destroys this process instance. + */ + virtual ~ProcessImplementation(); + + /*! + * Returns a pointer to the metaprocess of this process instance. + * + * The metaprocess defines the process class this instance belongs to. + */ + const MetaProcess* Meta() const + { + return meta; + } + + /*! + * Initializes this process instance after construction. This is knwon as + * special initialization of process instances. + * + * The PixInsight core application calls this function to initialize an + * instance just after it has been created by its class constructor. + * + * There are cases where the entire initialization work required for a + * process instance cannot be accomplished in the instance class constructor + * (e.g., because it requires calling reimplemented virtual functions from a + * base class). In such cases, this function can be reimplemented to perform + * the pending initialization tasks immediately after instance construction. + * + * This function is only called if the associated metaprocess class + * reimplements MetaProcess::NeedsInitialization() to return true. + */ + virtual void Initialize(); + + /*! + * Returns true iff this process instance is currently valid for execution. + * + * \param[out] info If this function returns false, it should return also a + * brief text (128 characters maximum) in this string, + * describing why this is an invalid instance. + * + * The PixInsight core application calls this function to validate an + * instance just before attempting to execute it, either on a view or in the + * global context. + * + * This function is only called if the associated metaprocess class + * reimplements MetaProcess::NeedsValidation() to return true. + * + * If this function returns false, giving a brief description of the reasons + * in the \a info string is not mandatory, but neglecting it is considered + * bad programming practice. + */ + virtual bool Validate( String& info ); + + /*! + * Assigns an existing instance \a i to this instance, if it belongs to an + * assignable process class. + * + * The PixInsight core application calls this function each time a process + * instance has to be replaced with a copy of another existing instance. + * This happens under a wide variety of situations. A good example is + * copying a process icon by dragging it to another icon. Another, less + * visible example is when a view's processing history is being copied as + * the initial processing of a duplicate view. + * + * Assignment only occurs for \e assignable processes. A process is + * assignable unless its defining MetaProcess descendant class reimplements + * the MetaProcess::IsAssignable() member function to return false. + * + * Assignable process instance implementation classes must reimplement this + * function, or a runtime exception will be thrown. This means that + * virtually \e all descendants classes of %ProcessImplementation must + * reimplement this function. A plausible reason to define a non-assignable + * process (perhaps the only one) is because its instances have no data at + * all that could be assigned - an example is the standard Invert process. + */ + virtual void Assign( const ProcessImplementation& i ); + + /*! + * Returns true iff this process instance could be successfully executed on a + * given \a view. + * + * \param view Reference to a view on which this process is being tested + * to validate execution. + * + * \param[out] whyNot If this function returns false, it should return + * also a brief text (128 characters maximum) in this string, + * explaining why this instance cannot be executed on the + * passed \a view. + * + * In general, among many other possible reasons, a process instance class + * should reimplement this function if: + * + * \li It is a process that cannot be executed on views. In this case, the + * reimplementation of this function should always return false. + * + * \li It cannot be executed on \e all views. For example, some processes + * can only be executed on main views, but not on previews. Or perhaps this + * process cannot be executed on color images, but only on grayscale images. + * + * \li Some instances, perhaps depending on specific parameter values or + * user-selectable options, may have limitations or cannot be executed on + * some types of views or images. + * + * If this function returns false, giving a brief description of the reasons + * in the \a whyNot string is not mandatory, but neglecting it is considered + * bad programming practice. + * + * \note The default implementation of this function returns true, so by + * default a process instance can be executed on any view. + */ + virtual bool CanExecuteOn( const View& view, String& whyNot ) const; + + /*! + * Returns true iff this process instance would require a history update for + * the specified \a view, if it was executed on it. + * + * A history update would be required if this instance was modifying the + * \a view or its image in \e any way. By any way we mean not only + * changing pixel values, but to alter whatever property of the view or its + * image. + * + * \note The default implementation of this function returns true, so by + * default a process instance is supposed to update all views. + */ + virtual bool IsHistoryUpdater( const View& view ) const + { + return true; // by default, all processes are supposed to update images. + } + + /*! + * Returns true iff this is a maskable process instance for the + * specified \a view. + * + * \param view Reference to a view on which this process is being tested to + * validate maskable execution. + * + * \param mask Reference to an image window whose image would act as a mask + * after execution of this process instance. + * + * A maskable instance is one whose resulting processed image can be masked. + * When a target image is masked after execution of a process instance, + * white mask pixels allow replacement of target pixels with fully processed + * values, and black mask pixels preserve original target pixel values. Gray + * mask pixel values yield proportional combinations of original and + * processed target pixels. + * + * If a process cannot be masked, or if some process instances can't be + * masked sometimes, then this function should be reimplemented to return + * false, or an appropriate value depending on the execution context. + * + * \note The default implementation of this function returns true, so by + * default a process instance is supposed to be maskable for all views. + */ + virtual bool IsMaskable( const View& view, const ImageWindow& mask ) const + { + return true; // by default, all processes are supposed to be maskable. + } + + /*! + * Returns a combination of flags indicating the required contents of a + * history update record for the specified \a view if this instance was + * executed on it. + * + * The returned value is an OR'ed combination of flags that must be + * specified with the symbolic constants defined in the UndoFlag namespace. + * + * When reimplementing this function, you should include flags for all data + * items that your process instances modify in target views. For example, if + * a process instance modifies the FITS header keywords of target images, + * the reimplementation of this function should include the + * UndoFlag::Keywords flag. + * + * \note The default implementation of this function returns + * UndoFlag::DefaultMode. This value selects a default set of items, + * including pixel data, that will be stored in a history record for the + * specified \a view before executing this process instance on it. You + * normally won't need to reimplement this function, since the default + * history data set is appropriate for most processes. + */ + virtual UndoFlags UndoMode( const View& view ) const + { + return UndoFlag::DefaultMode; + } + + /*! + * This function is called just before execution of this process instance on + * the specified \a view. Returns true if execution can continue. + * + * This function is the last chance for a process instance to prevent + * execution on a particular view. + * + * For example, a process that destroys the previews defined in the image + * window of a target view should always ask the user if it is OK to do so + * before execution. In this case, this function would be reimplemented to + * open a standard yes/no message box asking something like "About to + * destroy all previews in this image window. Are you sure?" to the + * user. False should be returned if the user answered "No". + * + * \note The default implementation of this function returns true, so by + * default execution on views is not stopped by this function. + */ + virtual bool BeforeExecution( View& view ) + { + return true; + } + + /*! + * View execution routine. Executes this process instance on the specified + * target \a view. Returns true if execution took place successfully; false + * in the event of error. + * + * This function must be reimplemented in process instance classes that can + * be executed on views. By default, all instances are supposed to be + * executable on views. To prevent view execution, an instance class should + * reimplement the CanExecuteOn() member function. + * + * Exceptions can be freely thrown from this function; they will be caught + * and handled automatically by core PCL routines. For this reason, + * reimplementations of this function rarely return false when an error + * occurs; they prefer throwing exceptions instead. + * + * \note The default implementation of this function throws a runtime + * exception. This has been done on purpose to recall you that this function + * must be reimplemented for processes with view execution capabilities. + */ + virtual bool ExecuteOn( View& view ); + + /*! + * This function is called just after execution of this process instance on + * the specified \a view. + * + * %ProcessImplementation instance classes rarely reimplement this function. + * It can be useful as a place to perform some cleanup work after execution. + * + * When this function is invoked, the specified \a view has been completely + * processed. This includes a full history update (if appropriate), all + * involved notifications sent, and its screen rendition fully regenerated. + */ + virtual void AfterExecution( View& view ) + { + } + + /*! + * Returns true iff this process instance could be successfully executed on + * the passed \a image. + * + * \param image Reference to an ImageVariant object on which this process + * is being tested to validate execution. + * + * \param[out] whyNot If this function returns false, it should return + * also a brief text (128 characters maximum) in this string, + * explaining why this instance be executed on the + * passed \a image. + * + * This function will only be called for processes able to be executed on + * standalone images, that is, for processes that reimplement the following + * member function: + * + * bool MetaProcess::CanProcessImages() const + * + * to return true. Note that the default implementation of the above + * function returns false, so a process cannot be executed on %ImageVariant + * instances by default. + * + * Don't confuse standalone \e image execution with \e view execution, which + * corresponds to the ExecuteOn( View& ) member function. + * + * \note The default implementation of this function returns true, so by + * default an instance of a process able to be executed on standalone images + * can be executed on any image. + */ + virtual bool CanExecuteOn( const ImageVariant& image, String& whyNot ) const; + + /*! + * Image execution routine. Executes this process instance on the specified + * target \a image. Returns true if execution was successful; false in the + * event of error. + * + * \param image Reference to an ImageVariant object that transports the + * image to be processed. + * + * \param hints A string containing a (possibly empty) list of \e hints + * intended to modify the way an image is processed. A process can + * simply ignore all of these hints, or just look for one or more + * hints that it recognizes and supports, ignoring others. When two + * or more hints are specified, they must be separated by space + * characters (0x20). File formats also support hints in a similar + * way; see for example the FileFormatInstance::Open() member + * function for more information. + * + * This function must be reimplemented by processes that can be executed on + * standalone images. To enable this functionality, the following member + * function: + * + * bool MetaProcess::CanProcessImages() const + * + * must be reimplemented to return true, since it returns false by default. + * Otherwise this function will never be called. + * + * By default, an instance of a process able to be executed on standalone + * images is supposed to be executable on \e any image. To prevent image + * execution selectively, for example as a function of image properties, an + * instance class should reimplement: + * + * bool ProcessImplementation::CanExecuteOn( const ImageVariant&, String& ) const + * + * Exceptions can be freely thrown from this function; they will be caught + * and handled automatically by core PCL routines. For this reason, + * reimplementations of this function rarely return false when an error + * occurs; they prefer throwing exceptions instead. + * + * \note The default implementation of this function throws a runtime + * exception. This has been done on purpose to recall you that this function + * must be reimplemented for processes with image execution capabilities. + */ + virtual bool ExecuteOn( ImageVariant& image, const IsoString& hints ); + + /*! + * Returns true iff this process instance could be successfully executed in + * the global context. + * + * \param[out] whyNot If this function returns false, it should return + * also a brief text (128 characters maximum) in this string, + * explaining why this instance couldn't be executed in the + * global context. + * + * Execution in the global context occurs when a process instance is + * executed without any specific target view. In such cases we say that a + * global process is being executed. + * + * A good example of a \e pure global process is the GlobalPreferences + * process. This process allows the user modifying a number of global + * application options, but it does not apply to any image. + * + * Other processes can perform as global processes sometimes, depending on + * specific parameter values. An example is the RGBWorkingSpaceParameters + * process, which can be applied to change a view's RGB working space + * (RGBWS), or to set the parameters of the global RGBWS. + * + * Processes willing to perform global execution, either on a regular basis + * or under specific circumstances, must reimplement this function. + * + * \note The default implementation of this function returns false and + * assigns a standard message to the \a whyNot string (something like + * "The xxx process cannot be executed in the global context"). So + * by default a process instance cannot be executed in the global context. + */ + virtual bool CanExecuteGlobal( String& whyNot ) const; + + /*! + * This function is called just before execution of this process instance in + * the global context. Returns true if global execution can continue. + * + * This function is the last chance for a process instance to cancel + * execution in the global context. Reimplement it if you need to do + * something that the user should be aware of before global execution, + * giving her an opportunity to stop this process. + * + * \note The default implementation of this function returns true, so by + * default global execution is not stopped by this function. + */ + virtual bool BeforeGlobalExecution() + { + return true; + } + + /*! + * Global execution routine. Executes this process instance in the global + * context. Returns true if execution took place successfully; false in + * the event of error. + * + * This function must be reimplemented in process instance classes that can + * be executed globally. By default, instances cannot be executed globally. + * To allow global execution, an instance class should reimplement the + * CanExecuteGlobal() member function. + * + * Exceptions can be freely thrown from this function; they will be caught + * and handled automatically by core PCL routines. For this reason, + * reimplementations of this function rarely return false when an error + * occurs; they prefer throwing exceptions instead. + * + * \note The default implementation of this function throws a runtime + * exception. This has been done on purpose to recall you that this function + * must be reimplemented for processes with global execution capabilities. + */ + virtual bool ExecuteGlobal(); + + /*! + * This function is called just after execution of this process instance in + * the global context. + * + * %ProcessImplementation instance classes rarely reimplement this function. + * It can be useful as a place to perform some cleanup work after execution. + */ + virtual void AfterGlobalExecution() + { + } + + /*! + * Returns the address of an interface appropriate to edit this process + * instance. Returns zero if there is no available interface for this + * process instance. + * + * This function is called when an existing instance is activated in the + * core application's GUI (e.g., by double-clicking a process icon). When + * the process is selected in a generic way (e.g., from the %ProcessImplementation + * Explorer window), MetaProcess::DefaultInterface() is called instead. + * + * This function must be reimplemented if multiple interfaces are + * available for this process class that are selectable on a per-instance + * basis. + * + * \note Reimplementing this function is very infrequent. This is because + * the default implementation just returns MetaProcess::DefaultInterface(), + * which is adequate for processes associated to a single interface, as are + * the majority of them. + */ + virtual ProcessInterface* SelectInterface() const + { + return meta->DefaultInterface(); // by default, process instances use + // their default interfaces. + } + + /*! + * Returns true iff the specified interface is a valid interface for this + * process instance. + * + * This function is called when this instance is about to be imported by a + * process interface, to validate the import operation. + * + * \note This function is rarely reimplemented, for similar reasons to those + * exposed in the documentation for SelectInterface(). The default + * implementation of this function returns true if the specified interface + * is the same one that is returned by SelectInterface(). + */ + virtual bool IsValidInterface( const ProcessInterface* i ) const + { + return i == SelectInterface(); + } + + /*! + * This function is called just before reading this process instance from an + * input stream, as a disk file. Returns true if the reading procedure can + * continue. + * + * This function is not intended to allow or disallow instance reading + * operations based on source data contents. For that reason, this function + * doesn't receive a reference to the input stream from which this instance + * is about to be read. + * + * The purpose of this function is preparing process instances to receive + * new parameters. This allows for a high degree of optimization in the + * implementation of actual parameter data and their acquisition. + * + * \note The default implementation of this function returns true, so by + * default instance reading is not stopped by this function. + */ + virtual bool BeforeReading() + { + return true; + } + + /*! + * This function is called just after this process instance has been read + * from an input stream, as a disk file. + * + * You usually should need a reimplementation of this function if you also + * reimplemented BeforeReading(). Read the documentation for that member + * function for more information. + * + * \note The default implementation of this function does nothing. + */ + virtual void AfterReading() + { + } + + /*! + * This function is called just before writing this process instance to an + * output stream, as a disk file. Returns true if the writing procedure can + * continue. + * + * This function is not intended to allow or disallow instance writing + * operations based on target stream contents or properties. For that + * reason, this function doesn't receive a reference to the output stream + * to which this instance is about to be written. + * + * The purpose of this function is preparing process instances to export + * their parameters. This allows for a high degree of optimization in the + * implementation of actual parameter data and their availability. + * + * \note The default implementation of this function returns true, so by + * default instance writing is not stopped by this function. + */ + virtual bool BeforeWriting() const + { + return true; + } + + /*! + * This function is called just after this process instance has been written + * to an output stream, as a disk file. + * + * You usually should need a reimplementation of this function if you also + * reimplemented BeforeWriting(). Read the documentation for that member + * function for more information. + * + * \note The default implementation of this function does nothing. + */ + virtual void AfterWriting() const + { + } + + /*! + * Returns the fixed address of an actual parameter in this process + * instance, and locks it while the core application requires direct access + * to its data. + * + * \param p The address of a metaparameter that identifies the parameter + * being locked. + * + * \param tableRow The index of a table row where the requested parameter + * is defined. For parameters not belonging to tables, this + * parameter must be ignored. + * + * The PixInsight core application calls this function to get the actual + * address of a parameter in this process instance. The parameter should not + * be destroyed, changed or moved physically in memory until the + * UnlockParameter() member function is invoked for this instance with the + * same \a p and \a tableRow arguments. + * + * Once UnlockParameter() has been called for a specific parameter, it can + * be freely moved, allocated or deallocated by this process instance. + * + * \note Reimplementing this function is \e mandatory for processes defining + * parameters. + */ + virtual void* LockParameter( const MetaParameter* p, size_type tableRow ); + + /*! + * This function is called by the core application after LockParameter(), + * when direct access to an specified actual parameter is no longer needed. + * + * \param p The address of a metaparameter that identifies the parameter + * being unlocked. + * + * \param tableRow The index of a table row where the requested parameter + * is defined. For parameters not belonging to tables, this + * parameter must be ignored. + * + * When this function is invoked, the instance is free to move or change the + * parameter, until the next call to LockParameter() with the same \a p and + * \a tableRow arguments. + * + * \note This function is not called if the corresponding + * MetaParameter::NeedsUnlocking() member function has not been + * reimplemented to return true in the derived class that the specified + * parameter \a *p is an instance of. + */ + virtual void UnlockParameter( const MetaParameter* p, size_type tableRow ); + + /*! + * This function is called to validate a parameter value for an actual + * parameter in this process instance. Returns true if the specified value + * is a valid value for the specified parameter in this instance. + * + * \param value Pointer to the parameter value being tested. + * + * \param p The address of a metaparameter that identifies the + * parameter being validated. + * + * \param tableRow The index of a table row where the requested parameter + * is defined. For parameters not belonging to tables, this + * parameter must be ignored. + * + * \note This function is not called if the corresponding + * MetaParameter::NeedsValidation() member function has not been + * reimplemented to return true in the derived class that the specified + * parameter \a *p is an instance of. + */ + virtual bool ValidateParameter( void* value, const MetaParameter* p, size_type tableRow ) const; + + /*! + * Allocates the required space to store a variable-length parameter value + * of the specified length or size. Returns true if the necessary space was + * successfully allocated. + * + * \param sizeOrLength Requested size in bytes or length in elements of the + * parameter value being allocated. + * + * \param p The address of a metaparameter that identifies the + * variable-length parameter being allocated. + * + * \param tableRow The index of a table row where the requested parameter + * is defined. For parameters not belonging to tables, this + * parameter must be ignored. + * + * For table parameters, \a sizeOrLength is a row count. For a string + * parameter, \a sizeOrLength is a string length in characters. For a block + * parameter, \a sizeOrLength is a block size in bytes. + * + * \note Reimplementing this function is \e mandatory for processes defining + * variable-length parameters. + */ + virtual bool AllocateParameter( size_type sizeOrLength, const MetaParameter* p, size_type tableRow ); + + /*! + * Returns the length or size of an actual variable-length parameter in this + * process instance. + * + * \param p The address of a metaparameter that identifies the + * variable-length parameter. + * + * \param tableRow The index of a table row where the requested parameter + * is defined. For parameters not belonging to tables, this + * parameter must be ignored. + * + * For tables, you must reimplement this function to return the current + * number of rows. For strings, you must return the string length in + * characters (\e not bytes). For blocks, you must return the size in bytes. + * + * \note Reimplementing this function is \e mandatory for processes defining + * variable-length parameters. + */ + virtual size_type ParameterLength( const MetaParameter* p, size_type tableRow ) const; + + /*! + * Launches this process instance. + * + * This function will lead to one of the following actions, in decreasing + * order of priority: + * + * \li The SelectInterface() member function will be called for this + * instance. If the returned interface is valid, it will be activated and + * a copy of this instance will be imported. + * + * \li If the MetaProcess::PrefersGlobalExecution() member function of the + * metaprocess associated to this instance returns true, or if no current + * view is available, a new thread will be created to execute this instance + * in the global context. + * + * \li If the MetaProcess::PrefersGlobalExecution() member function of the + * metaprocess associated to this instance returns false, and there is a + * current view available, a new thread will be created to execute this + * instance on the current view. + * + * \li A run-time exception will be thrown indicating that this instance + * cannot be executed. + */ + void Launch() const; + + /*! + * Launches a process interface for this process instance. + * + * The SelectInterface() member function will be called for this instance. + * The returned interface will be activated, and a copy of this instance + * will be imported. + */ + void LaunchInterface() const; + + /*! + * Execute this instance in the global context. + */ + void LaunchGlobal() const; + + /*! + * Executes this instance on the current view. + */ + void LaunchOnCurrentView() const; + + /*! + * Executes this instance in the current window or, more precisely, on its + * main view. + */ + void LaunchOnCurrentWindow() const; + + /*! + * Executes this instance on the specified view. + */ + void LaunchOn( View& ) const; + + /*! + * Executes this instance on the main view of the specified image window. + */ + void LaunchOn( ImageWindow& ) const; + +protected: + + const MetaProcess* meta = nullptr; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ProcessImplementation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProcessImplementation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProcessInstance.h b/3rdparty/include/pcl/ProcessInstance.h new file mode 100644 index 0000000..6cc8e9f --- /dev/null +++ b/3rdparty/include/pcl/ProcessInstance.h @@ -0,0 +1,701 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProcessInstance.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_ProcessInstance_h +#define __PCL_ProcessInstance_h + +/// \file pcl/ProcessInstance.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS Process; +class PCL_CLASS ImageWindow; +class PCL_CLASS View; + +/*! + * \class ProcessInstance + * \brief High-level interface to a process instance. + * + * %ProcessInstance, along with %Process, provides access to any installed + * process through intermodule communication. + * + * %ProcessInstance represents a live instance of an installed process that can + * be edited (by setting parameter values) and executed. + * + * \sa Process + */ +class PCL_CLASS ProcessInstance : public UIObject +{ +public: + + /*! + * Constructs this object as a reference to a new instance of the specified + * \a process. The newly created instance has a set of default parameter + * values. + */ + ProcessInstance( const Process& process ); + + /*! + * Copy constructor. The newly constructed object references the same + * server-side process instance as the specified object \a p. + * + * \note Note that this constructor does not generate a new process + * instance. It just constructs a high-level reference to an existing + * process instance. + */ + ProcessInstance( const ProcessInstance& p ) : UIObject( p ) + { + } + + /*! + * Destroys a process instance. + * + * After destruction of this object, the server-side process instance is + * also destroyed (garbage-collected) if it is no longer referenced by other + * %ProcessInstance objects. + */ + virtual ~ProcessInstance() + { + } + + /*! + * Returns a reference to a null process instance. A null + * %ProcessInstance object does not correspond to an existing process + * instance in the PixInsight core application. + */ + static ProcessInstance& Null(); + + /*! + * Returns a Process object that represents the installed process that + * this instance belongs to. + */ + Process ParentProcess() const; + + /*! + * Assignment operator. Returns a reference to this object. + * + * Makes this object reference the same server-side process instance as the + * specified object \a p. If the previous instance becomes unreferenced, it + * will be garbage-collected by the PixInsight core application. + */ + ProcessInstance& operator =( const ProcessInstance& p ) + { + SetHandle( p.handle ); + return *this; + } + + /*! + * Generates a uniquely referenced, newly created process instance as a + * duplicate of the instance referenced by this object, and returns a + * high-level reference to it as a new %ProcessInstance object. + */ + ProcessInstance Clone() const; + + /*! + * Assigns the parameters of a process instance referenced by the specified + * object \a p to the instance referenced by this object. Returns true if + * the assignment operation was successful; false in the event of error. + * + * Note that this member function does \e not do the same as an assignment + * operator or a copy constructor, because the latter two operations simply + * cause this object to reference an existing server-side instance (and + * possibly leave a previous instance unreferenced). This member function + * does not generate a new process instance and does not change existing + * references to server-side objects; it just copies process parameters (and + * probably other module-dependent data) from one existing instance to + * another. + * + * \note For this member function to success, the parent Process has to be + * an assignable process. Assignable processes return true from + * reimplemented Process::IsAssignable() virtual functions. + */ + bool Assign( const ProcessInstance& p ); + + /*! + * Requests the parent process to validate this process instance. Returns + * true upon successful validation; false if the instance is not valid, or + * in the event of error. + * + * If this member function returns false, the process should return a + * description of the reasons to not validate the instance in the string + * \a whyNot. If the function returns true, the string \a whyNot will be + * cleared (so it will be empty and its previous contents will be lost). + */ + bool Validate( String& whyNot ); + + /*! + * Returns true iff this process instance will modify the process history of + * the specified \a view, in case it is executed on it. + * + * If this member function returns false, then this instance can be safely + * executed on the \a view as a read-only process; the view won't be + * modified in any way. + */ + bool IsHistoryUpdater( const View& view ) const; + + /*! + * Returns true iff this process instance can be masked with the specified + * image \a window when executed on the specified \a view. + * + * When a process is masked, its result is mixed with the image in the state + * it was before execution, according to the values of a mask image. This + * process is carried out automatically by the PixInsight core application. + */ + bool IsMaskable( const View& view, const ImageWindow& mask ) const; + + /*! + * Validates execution of this process instance on the specified \a view. + * Returns true iff this instance can be executed on the view. + * + * If this member function returns false, the process should return in the + * string \a whyNot a description of the reasons why this instance cannot be + * executed on the specified \a view. If the function returns true, the + * string \a whyNot will be cleared (so it will be empty and its previous + * contents will be lost). + */ + bool CanExecuteOn( const View& view, String& whyNot ) const; + + /*! + * Executes this process instance on the specified \a view. Returns true + * upon successful execution; false in the event of error. + * + * The optional \a swapFile argument allows the caller to control generation + * of swap data as part of the instance execution. If \a swapFile is true + * (the default value), the PixInsight core application will save the + * previous state of the target \a view before instance execution. In this + * case the executed instance will be appended to the view's process history + * in the usual way, and the process will be undoable. + * + * If \a swapFile is false, the previous state of the view is not saved, the + * instance is not added to the view's history, and the process cannot be + * undone after execution. In this case the caller module is responsible for + * leaving the image transported by \a view in a valid and predictable + * state. Keep in mind that if no swap data are generated before excution, + * the user has no way to restore the previous state of the image, and also + * has no way to control the sequence of processes that have given rise to + * the current state of the image. If these side effects are not correctly + * controlled and handled by the calling module, they will violate basic + * design principles of the PixInsight platform, and hence they can be a + * good reason for denying certification of a module. + * + * This member function is typically called with the \a swapFile argument + * set to false by processes that execute other processes to implement their + * own tasks. For example, the standard %ProcessContainer process (which is + * internal to the core application) does exactly this to execute a sequence + * of processes as a unique step in a view's process history. Another case + * where \a swapFile should be set to false is when a process generates a + * new image as a result of running a sequence of processes, but it wants to + * appear as the unique process in the initial state element of the + * view's process history. + */ + bool ExecuteOn( View& view, bool swapFile = true ); + + /*! + * Returns true iff this process instance can be executed in the global + * context. + * + * If this member function returns false, the process should return in the + * string \a whyNot a description of the reasons why this instance cannot be + * executed on the global context. If the function returns true, the string + * \a whyNot will be cleared (so it will be empty and its previous contents + * will be lost). + * + * A process is executed in the global context when it is not explicitly + * executed on a particular view. Two well-known examples of global + * processes are Preferences and ReadoutOptions. Note that a process can + * work both globally and on views. For example, the PixelMath process can + * work globally to generate new images, or locally when it is executed on a + * target view. + */ + bool CanExecuteGlobal( String& whyNot ) const; + + /*! + * Executes this process instance on the global context. Returns true upon + * successful execution; false in the event of error. + * + * See the documentation for CanExecuteGlobal() for additional comments on + * process execution contexts. + */ + bool ExecuteGlobal(); + + /*! + * Validates execution of this process instance on the specified \a image. + * Returns true iff this instance can be executed on the image. + * + * If this member function returns false, the process should return in the + * string \a whyNot a description of the reasons why this instance cannot be + * executed on the specified \a image. If the function returns true, the + * string \a whyNot will be cleared (so it will be empty and its previous + * contents will be lost). + */ + bool CanExecuteOn( const ImageVariant& image, String& whyNot ) const; + + /*! + * Executes this process instance on the specified \a image. Returns true + * upon successful execution; false in the event of error. + * + * \param image Reference to an ImageVariant object that transports the + * image to be processed. + * + * \param hints A string containing a (possibly empty) list of \e hints + * intended to modify the way an image is processed. A process can + * simply ignore all of these hints, or just look for one or more + * hints that it recognizes and supports, ignoring others. When two + * or more hints are specified, they must be separated by space + * characters (0x20). File formats also support hints in a similar + * way; see for example the FileFormatInstance::Open() member + * function for more information. The default value is an empty + * string. + */ + bool ExecuteOn( ImageVariant& image, const IsoString& hints = IsoString() ); + + bool ExecuteOn( ImageVariant& image, const IsoString::ustring_base& hints ) + { + return ExecuteOn( image, IsoString( hints ) ); + } + + /*! + * Launches this process instance. + * + * If this process has an associated default interface, then its top level + * window is shown and activated, and this instance is \e imported by the + * interface. After importing this instance, the interface will show its + * parameter values. + * + * If this process has no default interface, then the core application + * attempts to execute this instance. If the process prefers global + * execution (see the Process::PrefersGlobalExecution() member function), + * then this instance will be executed in the global context; otherwise it + * will be executed on the current view, if there is at least one image + * available. + * + * Returns true if this instance was successfully launched; false in the + * event of error, or if the core application was unable to launch or + * execute the instance. + */ + bool Launch(); + + /*! + * Returns true iff this process instance is able to open and activate a + * process interface. + * + * Normally, each process has an associated interface that can always be + * launched through any existing (and valid) instance of the appropriate + * process class. However, there are some processes for which an interface + * does not make sense. A well-known example is the Invert process. + */ + bool CanLaunchInterface() const; + + /*! + * Opens and activates the interface associated to this process, and causes + * it to import this instance. After importing this instance, the interface + * will show its parameter values. Returns true if the interface could be + * successfully launched; false in the event of error. + */ + bool LaunchInterface(); + + /*! + * Returns the descriptive text currently associated with this process + * instance, or an empty string if this instance has no description. + * + * In PixInsight, each process instance has an associated text that the user + * can edit to describe the purpose and conditions of the applied processes. + * This feature is an extremely useful and efficient way to document a + * processing procedure. + */ + String Description() const; + + /*! + * Sets the descriptive text for this process instance. + * + * Instance descriptions can make use of the whole formating capabilities of + * PixInsight consoles; see the Console class for more information. + */ + void SetDescription( const String& text ); + + /*! + * Gets the running times for the latest execution of this process instance. + * + * \param[out] startJD Starting execution time as a Julian day number. + * + * \param[out] elapsedSecs Total elapsed execution time in seconds. + * + * If this instance has never been executed, or if the execution times have + * not been recorded for some reason, both output values are set to zero. + */ + void GetExecutionTimes( double& startJD, double& elapsedSecs ) const; + + /*! + * Returns the time when this process instance was last executed as a Julian + * day number. If this instance has never been executed, or if the execution + * time has not been recorded for some reason, this function returns zero. + */ + double StartJD() const + { + double startJD, dum; + GetExecutionTimes( startJD, dum ); + return startJD; + } + + /*! + * Returns the total elapsed time in seconds for the latest execution of + * this process instance, or zero if either this instance has never been + * executed, or if the execution time has not been recorded for some reason. + */ + double ElapsedTime() const + { + double dum, elapsedSecs; + GetExecutionTimes( dum, elapsedSecs ); + return elapsedSecs; + } + + /*! + * Returns a source code representation of this process instance. + * + * \param language The language to use for the source code representation. + * Currently the only languages supported are "JavaScript" + * and "XPSM 1.0". The default language is JavaScript. + * + * \param varId The identifier of a variable that will be used to + * represent this instance. If an empty string is + * specified (which is the default value), the PixInsight + * core application wll assign a default identifier. This + * identifier only applies to JavaScript source code + * representations, not to XML representations. + * + * \param indent Indentation distance in characters. This is a constant + * number of white space characters (0x20) that will be + * prepended to each source code line. The default value + * is zero. + * + * The source code generated by this function can be used directly for + * serialization of process instances in the specified language. + */ + String ToSource( const IsoString& language = "JavaScript", + const IsoString& varId = IsoString(), int indent = 0 ) const; + + /*! + * Returns a process instance generated from the specified \a source code. + * + * \note This member function is still not implemented; it will be + * implemented in a future version of PCL. For now, this function always + * returns a null process instance. + */ + static ProcessInstance FromSource( const String& source, + const IsoString& language = "JavaScript" ); + + /*! + * Returns a process instance generated as a duplicate of the instance + * transported by a process icon with the specified identifier \a iconId. + * + * Returns a null instance if the specified icon does not exist, or if an + * icon exists with the specified identifier but it is not a process icon + * (e.g., an image icon). + */ + static ProcessInstance FromIcon( const IsoString& iconId ); + + static ProcessInstance FromIcon( const IsoString::ustring_base& iconId ) + { + return FromIcon( IsoString( iconId ) ); + } + + /*! + * Returns a string list with the identifiers of all existing process icons, + * or an empty list if there are no process icons. + */ + static IsoStringList Icons(); + + /*! + * Returns a string list with the identifiers of all existing process icons + * transporting instances of the specified process, or an empty list if no + * such icons exist. + */ + static IsoStringList IconsByProcessId( const IsoString& processId ); + + static IsoStringList IconsByProcessId( const IsoString::ustring_base& processId ) + { + return IconsByProcessId( IsoString( processId ) ); + } + + /*! + * Returns the value of a process parameter. + * + * \param parameter Reference to an existing parameter in the parent + * process of this instance (see Process::Parameters()). + * + * \param rowIndex Zero-based index of the table row, when the specified + * \a parameter is a table column parameter. Must be + * within the range of existing rows for the corresponding + * table parameter in this instance, that is, from zero to + * the number of table rows minus one. If \a parameter is + * not a table column parameter this argument is ignored. + * + * If the specified \a parameter is a table process parameter, this member + * function throws an Error exception. A table process parameter does not + * have a value, and its contents cannot be retrieved directly as a whole. + * + * Note that the default value of the \a rowIndex argument is an impossible + * row index number: ~size_type(0). This value has been selected on purpose + * in order to force the caller to specify a row index when \a parameter is + * a table column parameter. This is a simple but effective security + * mechanism to robustify parameter access code: if no row index is + * specified for a table column parameter, this member function will always + * return an invalid %Variant object (see below). + * + * This member function returns a Variant object with the current value of + * the specified parameter or table cell parameter in this instance. An + * invalid %Variant object is returned in the following cases: + * + * \li If the specified \a parameter is not a valid parameter of the parent + * process. + * + * \li If \a parameter is a table column parameter and the specified + * \a rowIndex is larger than or equal to the number of existing rows for + * the parent table parameter in this instance. + * + * The calling process should always check Variant::IsValid() for the + * objects returned by this function. + */ + Variant ParameterValue( const ProcessParameter& parameter, size_type rowIndex = ~size_type( 0 ) ) const; + + /*! + * Returns the value of a process parameter. + * + * This is an overloaded member function, provided for convenience. It + * allows retrieving parameter values using parameter identifiers instead of + * references to ProcessParameter objects. Otherwise this member function + * behaves exactly like + * ParameterValue( const ProcessParameter&, size_type ) const + */ + Variant ParameterValue( const IsoString& parameterId, size_type rowIndex = ~size_type( 0 ) ) const + { + return ParameterValue( ProcessParameter( ParentProcess(), parameterId ), rowIndex ); + } + + Variant ParameterValue( const IsoString::ustring_base& parameterId, size_type rowIndex = ~size_type( 0 ) ) const + { + return ParameterValue( IsoString( parameterId ), rowIndex ); + } + + /*! + * Sets the value of a process parameter. + * + * \param value New parameter value. The specified Variant object must + * transport an object of either the same type as the + * \a parameter whose value will be changed, or of a type + * that can legally be converted to the corresponding + * parameter type. The value must also observe the limits + * imposed by the parent process regarding acceptable + * values, numeric ranges, etc. + * + * \param parameter Reference to an existing parameter in the parent + * process of this instance (see Process::Parameters()). + * + * \param rowIndex Zero-based index of the table row, when the specified + * \a parameter is a table column parameter. Must be + * within the range of existing rows for the corresponding + * table parameter in this instance, that is, from zero to + * the number of table rows minus one. If \a parameter is + * not a table column parameter this argument is ignored. + * + * If the specified \a parameter is a table process parameter, this member + * function throws an Error exception. A table process parameter does not + * have a value, and its contents cannot be set directly as a whole. + * + * Note that the default value of the \a rowIndex argument is an impossible + * row index number: ~size_type(0). This value has been selected on purpose + * in order to force the caller to specify a row index when \a parameter is + * a table column parameter. This is a simple but effective security + * mechanism to robustify parameter access code: if no row index is + * specified for a table column parameter, this member function will always + * return false. + * + * The \a value must observe the limits imposed by the parent process + * regarding valid numeric ranges, length limits, acceptable characters, + * etc., depending on parameter types. This member function returns true iff + * the parameter value could be set correctly. If the type of \a value + * cannot be converted to the required parameter type, an Error exception is + * thrown with the appropriate error message. + * + * \note To set the values of table column parameters, the necessary table + * rows must be allocated \e before calling this member function. To + * allocate table rows, use the AllocateTableRows() member function. + */ + bool SetParameterValue( const Variant& value, + const ProcessParameter& parameter, size_type rowIndex = ~size_type( 0 ) ); + + /*! + * Sets the value of a process parameter. + * + * This is an overloaded member function, provided for convenience. It + * allows changing parameter values using parameter identifiers instead of + * references to ProcessParameter objects. Otherwise this member function + * behaves exactly like + * SetParameterValue( const Variant&, const ProcessParameter&, size_type ) + */ + bool SetParameterValue( const Variant& value, const IsoString& parameterId, size_type rowIndex = ~size_type( 0 ) ) + { + return SetParameterValue( value, ProcessParameter( ParentProcess(), parameterId ), rowIndex ); + } + + bool SetParameterValue( const Variant& value, const IsoString::ustring_base& parameterId, size_type rowIndex = ~size_type( 0 ) ) + { + return SetParameterValue( value, IsoString( parameterId ), rowIndex ); + } + + /*! + * Returns the number of existing rows in a table process parameter. + * + * \param table Reference to a table parameter in the parent process. + * + * If the specified parameter is not a table process parameter of the parent + * process, this member function returns zero. + */ + size_type TableRowCount( const ProcessParameter& table ) const; + + /*! + * Returns the number of existing rows in a table process parameter. + * + * This is an overloaded member function, provided for convenience. It + * returns the number of existing table rows using parameter identifiers + * instead of references to ProcessParameter objects. Otherwise this member + * function behaves exactly like + * TableRowCount( const ProcessParameter& ) const + */ + size_type TableRowCount( const IsoString& tableId ) const + { + return TableRowCount( ProcessParameter( ParentProcess(), tableId ) ); + } + + size_type TableRowCount( const IsoString::ustring_base& tableId ) const + { + return TableRowCount( IsoString( tableId ) ); + } + + /*! + * Allocates table rows for a table process parameter. + * + * \param table Reference to a table parameter in the parent process. + * + * \param rowCount Number of table rows to allocate. If the parameter has + * table row limitations, this value must be within the + * acceptable range. + * + * Calling this member function deallocates all previously existing table + * rows in this instance, if there were any. Table rows cannot be appended + * neither deleted selectively; the whole table parameter is reallocated as + * a whole each time this member function is called. Calling this function + * with \a rowCount set to zero (if zero rows are acceptable for the + * specified \a table parameter) effectively deallocates the whole table + * parameter in this instance. + * + * Returns true if the specified number of rows could be allocated + * successfully in this process instance; false in the event of error. + */ + bool AllocateTableRows( const ProcessParameter& table, size_type rowCount ); + + /*! + * Allocates table rows for a table process parameter. + * + * This is an overloaded member function, provided for convenience. It + * allows reallocating a table parameter rows using a parameter identifier + * instead of a reference to a ProcessParameter object. Otherwise this + * member function behaves exactly like + * AllocateTableRows( const ProcessParameter&, size_type ) + */ + bool AllocateTableRows( const IsoString& tableId, size_type rowCount ) + { + return AllocateTableRows( ProcessParameter( ParentProcess(), tableId ), rowCount ); + } + + bool AllocateTableRows( const IsoString::ustring_base& tableId, size_type rowCount ) + { + return AllocateTableRows( IsoString( tableId ), rowCount ); + } + +private: + + ProcessInstance( void* h ) : UIObject( h ) + { + } + + ProcessInstance( const void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class ProcessInstancePrivate; + friend class InterfaceDispatcher; + friend class InternalIconEnumerator; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ProcessInstance_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProcessInstance.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProcessInterface.h b/3rdparty/include/pcl/ProcessInterface.h new file mode 100644 index 0000000..ebd255b --- /dev/null +++ b/3rdparty/include/pcl/ProcessInterface.h @@ -0,0 +1,2618 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProcessInterface.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_ProcessInterface_h +#define __PCL_ProcessInterface_h + +/// \file pcl/ProcessInterface.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::InterfaceFeature + * \brief Provides symbolic constants defining feature flags to customize + * process interfaces. + * + * Besides defining their specific GUI components and behavior, process + * interfaces can be customized in a standardized way by means of a series of + * flags that control the contents and functionality of their interface + * control bars. Those flags are defined through symbolic constants in the + * InterfaceFeature namespace. + * + * An interface control bar is a managed control located at its parent + * interface window's bottom side. It is a relatively small panel where a + * number of standard tool buttons and a one-line text area can be customized. + * + * A standard process interface window has the following layout in PixInsight: + * + *

+ *    +---------------------------------+
+ *    |      Interface Title Bar        +
+ *    +---------------------------------+
+ *    |                                 |
+ *    |     Module-Defined              |
+ *    |     Interface Client Area       |
+ *    |                                 |
+ *    +---------------------------------+
+ *    | Info Area                       |
+ *    +---------------------------------+
+ *    | D A G T E X             B V P R |
+ *    +---------------------------------+
+ * 
+ * + * Where the two sections at the bottom form the interface's + * control bar: + * + * \li Info Area is a one-line text label that can be used to provide + * some feedback and information to the user. The contents of the info area can + * be modified programmatically, but cannot be changed by the user. + * + * \li D = %Process Drag %Object, used to create a new process instance + * by dragging it with the mouse. The new instance can be dragged for execution + * on selected views, to create process icons, to add instances to a process + * container, etc. + * + * \li A = Apply button, used for execution of a new process instance on + * the current view or window. + * + * \li G = Apply Global button, used for execution of a new process + * instance in the global context. + * + * \li T = Real-Time %Preview button, to attach this interface to the + * real-time previewing system. + * + * \li E = Execute button, used to commit execution of a dynamic + * interface. + * + * \li X = Cancel button, used to cancel execution of a dynamic + * interface. + * + * \li B = Browse Documentation button. When this button is activated, + * the default behavior is to open the Documentation Browser interface and load + * it with the documentation for the process for which this open the %Process + * Explorer window and show the . + * + * \li V = Track %View check box. When this check box is checked, the + * interface should modify its behavior in some way as a function of the + * current view. This check box generates calls to + * ProcessInterface::TrackViewUpdated(). Interfaces using this feature + * also need receiving ProcessInterface::ImageFocused() notifications. + * + * \li P = Preferences button, to open a modal dialog box where + * process and interface-specific preferences can be edited. + * + * \li R = Reset button, to reset the current instance to a default + * state. + * + * The following symbolic constants have been publicly defined for interface + * feature flags: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
InterfaceFeature::None This effectively suppresses a interface's control bar
InterfaceFeature::DragObject %Process drag object - To generate new process instances
InterfaceFeature::ApplyToViewButton Apply button - To execute a process on the active view
InterfaceFeature::ApplyGlobalButton Apply Global button - To execute a process in the global context
InterfaceFeature::RealTimeButton Real-Time Preview button - To activate the real-time preview interface
InterfaceFeature::ExecuteButton Execute button - To commit a dynamic interface
InterfaceFeature::CancelButton Cancel button - To cancel a dynamic interface
InterfaceFeature::BrowseDocumentationButton Browse documentation button - Browse process-specific documentation
InterfaceFeature::TrackViewButton Track View check box - To activate/deactivate tracking of the current view
InterfaceFeature::PreferencesButton Preferences button - To edit process and interface-specific preferences
InterfaceFeature::ResetButton Reset button - To reset process instance parameters
InterfaceFeature::InfoArea Info Area - To create a single-line text area
InterfaceFeature::Default A default set of flags for static interfaces
InterfaceFeature::DefaultGlobal A default set of flags for static interfaces that execute globally
InterfaceFeature::DefaultDynamic A default set of flags for dynamic interfaces
+ * + * More functionality can be added to interface control bars in future + * PixInsight and PCL releases. + */ +namespace InterfaceFeature +{ + enum mask_type + { + None = 0x00000000, // This effectively suppresses a interface's control bar + DragObject = 0x00000001, // Process drag object - To generate new process instances + ApplyToViewButton = 0x00000002, // Apply button - To execute a process on the active view + ApplyGlobalButton = 0x00000004, // Apply Global button - To execute a process in the global context + RealTimeButton = 0x00000008, // Real-Time Preview button - To activate the real-time preview interface + ExecuteButton = 0x00000010, // Execute button - To commit a dynamic interface + CancelButton = 0x00000020, // Cancel button - To cancel a dynamic interface + BrowseDocumentationButton = 0x00000080, // Browse Documentation button - To browse process-specific documentation + TrackViewButton = 0x00000100, // Track View check box - To activate/deactivate tracking of the current view + PreferencesButton = 0x00000400, // Preferences button - To edit process and interface-specific preferences + ResetButton = 0x00000800, // Reset button - To reset process instance parameters + InfoArea = 0x00010000, // Info Area - To create a single-line text area + Default = DragObject | ApplyToViewButton | BrowseDocumentationButton | ResetButton, // A default set of flags for static interfaces + DefaultGlobal = DragObject | ApplyGlobalButton | BrowseDocumentationButton | ResetButton, // A default set of flags for static interfaces that execute globally + DefaultDynamic = DragObject | ExecuteButton | CancelButton | BrowseDocumentationButton | ResetButton // A default set of flags for dynamic interfaces + }; +} + +/*! + * \class pcl::InterfaceFeatures + * \brief A collection of interface feature flags. + */ +typedef Flags InterfaceFeatures; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +class PCL_CLASS MetaProcess; +class PCL_CLASS ProcessImplementation; +class PCL_CLASS ProcessInstance; +class PCL_CLASS VectorGraphics; +class PCL_CLASS View; + +// ---------------------------------------------------------------------------- + +/*! + * \class ProcessInterface + * \brief Client-side interface to a PixInsight process interface window. + * + * ### TODO: PCL 2.1.x: Rename this class to %ProcessInterfaceImplementation + * ### TODO: PCL 2.2: New %ProcessInterface class for intermodule communication + * + * ### TODO: Write a detailed description for %ProcessInterface. + */ +class PCL_CLASS ProcessInterface : public Control, public MetaObject +{ +public: + + /*! + * Constructs a process interface window. + */ + ProcessInterface(); + + /*! + * Destroys a %ProcessInterface object. + */ + virtual ~ProcessInterface() noexcept( false ) + { + } + + /*! + * Returns a reference to a null %ProcessInterface instance. A null + * %ProcessInterface does not correspond to an existing interface window in + * the PixInsight core application. + */ + static ProcessInterface& Null(); + + /*! + * Returns an identifier for this interface. + * + * Interface identifiers must be unique (within the set of installed + * interfaces), valid C identifiers. + * + * \note Although an arbitrary identifier can be used for a process + * interface, it is customary (and also a good idea, for the sake of + * clarity) to assign the same identifier to both a process and its + * standard interface. For example, \c FastRotation is used as the + * identifier of the FastRotation process and its interface window. + */ + virtual IsoString Id() const = 0; + + /*! + * Returns a list of alias identifiers for this interface. + * + * An interface can have one or more alias identifiers. Aliases are + * useful to maintain compatibility with previous versions of an interface. + * + * When the PixInsight core application loads a project, it automatically + * replaces alias interface identifiers with actual (current) identifiers. + * This allows a developer to change the identifier of a process interface + * without breaking compatibility with existing projects. + * + * The returned string is a comma-separated list of distinct identifiers + * that will be treated as synonyms to the actual identifier of this + * interface, which is returned by the Id() member function. Two installed + * interfaces can't have the same alias, so each identifier included in the + * list must be unique across all process interfaces on the entire + * PixInsight platform. + * + * \note The default implementation of this member function returns an empty + * string (no aliases). + * + * \sa Id() + */ + virtual IsoString Aliases() const + { + return IsoString(); + } + + /*! + * Returns a pointer to the process associated with this interface. + * + * In general, each interface window works mainly for a particular process. + * This is what is known as the standard interface of a process in + * PixInsight. + */ + virtual MetaProcess* Process() const = 0; + + /*! + * Returns a version number for this interface, encoded as a hexadecimal + * number. + * + * For example, version 1.0.5 should be returned as 0x105, and version + * 3.11.5 as 0x3B5. The default return value is 0x100, corresponding to + * version 1.0.0. + * + * \deprecated This function has been deprecated and should not be used. + * Interfaces no longer need version numbers. The value returned by this + * member function is always ignored by the PixInsight core application. + */ + virtual uint32 Version() const + { + return 0x100; + } + + /*! + * Returns a description of this interface. + * + * This function must provide a brief description of the functionality and + * purpose of this process interface. This should include which + * process(es) can be interfaced, and how. + * + * \deprecated This function has been deprecated and should not be used. + * Interfaces must be described by the process(es) that use them. The value + * returned by this member function is always ignored by the PixInsight core + * application. + */ + virtual String Description() const + { + return String(); + } + + /*! + * Returns the icon image of this process interface as a document in SVG + * format. + * + * The specified image will be used as an icon appearing on the interface + * window's title bar. To facilitate the visual identification of processes + * and their interfaces, most reimplementations of this function should + * normally return the same SVG document returned by its interfaced process' + * reimplementation of MetaProcess::IconImageSVG(). + * + * The returned string must be the source code of a valid SVG document + * representing the icon image, encoded in UTF-8. + * + * Since core version 1.8.8-6, all process, interface and file format icons + * should be specified in SVG format. Raster formats, such as XPM and PNG, + * have been deprecated for this purpose. + * + * If both this function and IconImageSVGFile() return an empty string, or + * if the specified SVG document does not exist or is not valid, a default + * icon will be assigned to this process interface automatically by the + * PixInsight core application. + * + * \note The default implementation of this function returns an empty + * string. + * + * \sa IconImageSVGFile() + */ + virtual IsoString IconImageSVG() const + { + return IsoString(); + } + + /*! + * Returns the icon image of this process interface as a document in SVG + * format, stored as an external file. + * + * The specified image will be used as an icon appearing on the interface + * window's title bar. To facilitate the visual identification of processes + * and their interfaces, most reimplementations of this function should + * normally return the same SVG document returned by its interfaced process' + * reimplementation of MetaProcess::IconImageSVGFile(). + * + * The returned string must be a path to an existing file in the local + * file system (remote resources are not supported in current PCL versions), + * which must store a valid SVG document representing the icon image. The + * SVG source code must be encoded in UTF-8. + * + * Since core version 1.8.8-6, all process, interface and file format icons + * should be specified in SVG format. Raster formats, such as XPM and PNG, + * have been deprecated for this purpose. + * + * If both this function and IconImageSVG() return an empty string, or if + * the specified SVG document does not exist or is not valid, a default icon + * will be assigned to this process interface automatically by the + * PixInsight core application. + * + * Automatic Resource Location + * + * See MetaProcess::IconImageSVGFile() for important information that is + * equally applicable to this member function. + * + * \note The default implementation of this function returns an empty + * string. + * + * \sa IconImageSVG() + */ + virtual String IconImageSVGFile() const + { + return String(); + } + + /*! + * Returns a large icon for this interface as an image in the + * standard XPM format. + * + * The specified image will be used as an icon appearing on the interface + * window's title bar. To facilitate the visual identification of processes + * and their interfaces, most reimplementations of this function should + * normally return the same SVG document returned by its interfaced process' + * reimplementation of MetaProcess::IconImageXPM(). + * + * 32-bit RGBA color images (including an alpha channel) are fully + * supported. + * + * If this function returns nullptr, a default icon will be assigned to this + * interface automatically. + * + * \note The default implementation of this function returns nullptr. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process interface icons in SVG format. Existing modules should + * also be refactored in the same way to support scalable icons. + * + * \sa IconImageFile() + */ + virtual const char** IconImageXPM() const + { + return nullptr; + } + + /*! + * Returns a large icon for this interface as a path specification + * to an existing image file. + * + * Supported image file formats include PNG, XPM, JPG and BMP. + * + * For details on interface icon images, see the documentation for + * IconImageXPM(). + * + * \note The default implementation of this function returns an empty + * string. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process interface icons in SVG format. Existing modules should + * also be refactored in the same way to support scalable icons. + * + * \sa IconImageXPM() + */ + virtual String IconImageFile() const + { + return String(); + } + + /*! + * Returns a small icon for this interface as an image in the + * standard XPM format. + * + * For details on interface icon images, see the documentation for + * IconImageXPM(). + * + * Small icons are used on interface elements where screen space must be + * preserved. This may include iconized interface windows. When this + * function is not reimplemented in a derived class, the PixInsight core + * application automatically generates a small icon by resampling down the + * large icon provided by IconImageXPM(). + * + * You normally should not need to reimplement this function; the core + * application usually does a fine work resampling large icons to generate + * reduced versions. + * + * \note The default implementation of this function returns nullptr. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process interface icons in SVG format. Existing modules should + * also be refactored in the same way to support scalable icons. + * + * \sa SmallIconImageFile() + */ + virtual const char** SmallIconImageXPM() const + { + return nullptr; + } + + /*! + * Returns a small icon for this interface as a path specification + * to an existing image file. + * + * Supported image file formats include PNG, XPM, JPG and BMP. + * + * For details on small interface icon images, see the documentation for + * SmallIconImageXPM(). + * + * \note The default implementation of this function returns an empty + * string. + * + * \deprecated This member function has been deprecated since core version + * 1.8.8-6. It is still available for compatibility with existing modules + * that depend on it, but it will be removed in a future version of PCL. + * All newly produced code must use IconImageSVG() or IconImageSVGFile() to + * define process interface icons in SVG format. Existing modules should + * also be refactored in the same way to support scalable icons. + * + * \sa SmallIconImageXPM() + */ + virtual String SmallIconImageFile() const + { + return String(); + } + + /*! + * Returns a combination of flags defining the contents and functionality of + * the interface control bar in this process interface. + * + * The returned value must be an OR'ed combination of flags defined by + * symbolic constants in the InterfaceFeature namespace. + * + * \note The default implementation of this function returns + * InterfaceFeature::Default, which is a default set of flags appropriate + * for most interfaces working for processes that execute on views. + * + * \sa InterfaceFeature + */ + virtual InterfaceFeatures Features() const + { + return InterfaceFeature::Default; + } + + /*! + * Function called when the user clicks the Apply button on the interface + * control bar. + * + * For this function to be invoked, the InterfaceFeature::ApplyToViewButton + * flag must be included in the set of feature flags returned by the + * Features() member function, or a reimplementation of it, as appropriate. + * + * \note The default implementation of this function obtains a new process + * instance by calling NewProcess() for this interface, then executes it on + * the active view, if there is one. + */ + virtual void ApplyInstance() const; + + /*! + * Function called when the user clicks the Apply Global button on the + * interface control bar. + * + * For this function to be invoked, the InterfaceFeature::ApplyGlobalButton + * flag must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * \note The default implementation of this function obtains a new process + * instance by calling NewProcess() for this interface, then executes it in + * the global context. + */ + virtual void ApplyInstanceGlobal() const; + + /*! + * Function called when the user clicks the Execute button on the interface + * control bar. + * + * For this function to be invoked, the InterfaceFeature::ExecuteButton flag + * must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * \note The default implementation of this function does nothing. It is + * reimplemented by derived classes implementing dynamic interfaces, to + * commit the active dynamic session. An example is the standard DynamicCrop + * interface. The reimplementation of this function in the DynamicCrop + * interface executes the defined crop/rotate/rescale operation on the + * interface's dynamic target image and terminates the dynamic session. + */ + virtual void Execute() + { + } + + /*! + * Function called when the user clicks the Cancel button on the + * interface control bar. + * + * For this function to be invoked, the InterfaceFeature::CancelButton + * flag must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * \note The default implementation of this function terminates the active + * dynamic session, if there is one. It is unlikely that this function needs + * a reimplementation in a derived class, unless a nonstandard interface + * behavior is desired. + */ + virtual void Cancel(); + + /*! + * Function called when the user toggles the pushed state of the Real Time + * Preview control bar button. + * + * \param active True if the Real Time Preview button is currently + * active (or pushed down); false if the button is + * unpushed. + * + * For this function to be invoked, the InterfaceFeature::RealTimeButton + * flag must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * Derived classes for interfaces that use the real time previewing system + * must reimplement this function to control ownership of the Real Time + * Preview window and provide real-time preview images, as necessary. + * + * \note The default implementation of this function does nothing. + */ + virtual void RealTimePreviewUpdated( bool active ) + { + } + + /*! + * Function called when the user clicks the Browse Documentation button on + * the interface control bar. Returns true if the documentation was loaded + * successfully. + * + * For this function to be invoked, the + * InterfaceFeature::BrowseDocumentationButton flag must be included in the + * set of feature flags returned by a reimplementation of the Features() + * member function in a derived class. + * + * The default implementation of this member function is a wrapper for the + * MetaProcess::BrowseDocumentation() virtual member function of the process + * class associated with this interface. In other words, it basically does + * the following: + * + * \code + * const MetaProcess* P = Process(); + * if ( P != nullptr ) + * if ( P->CanBrowseDocumentation() ) + * P->BrowseDocumentation(); + * \endcode + * + * In general, a derived class should not need to reimplement this member + * function, as the default behavior is appropriate in most cases. + */ + virtual bool BrowseDocumentation() const; + + /*! + * Function called when the user toggles the pushed state of the Track %View + * control bar button. + * + * \param active True if the Track %View button is currently active + * (pushed down); false if the button is unpushed. + * + * For this function to be invoked, the InterfaceFeature::TrackViewButton + * flag must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * %View tracking is used by interfaces that modify their behavior + * and/or information contents as a function of the current view in the + * PixInsight application's GUI. When a view is selected, the interface + * receives an ImageFocused() notification and, if view tracking is active, + * it takes the opportune actions. + * + * \note The default implementation of this function does nothing. + * + * \sa Control::IsTrackViewActive(), Control::SetTrackViewActive(), + * ImageFocused() + */ + virtual void TrackViewUpdated( bool active ) + { + } + + /*! + * Function called when the user clicks the Preferences control bar button. + * + * For this function to be invoked, the InterfaceFeature::PreferencesButton + * flag must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * If you reimplement this function, its standard behavior is launching a + * modal dialog to allow editing preferences and options pertaining to the + * process(es) associated to this interface. + * + * \note Note that along with this function, a process should reimplement + * the MetaProcess::EditPreferences() member in its MetaProcess subclass, + * and that both implementations should be coherent. The default + * implementation of this function does nothing. + * + * \sa MetaProcess::CanEditPreferences(), MetaProcess::EditPreferences() + */ + virtual void EditPreferences() + { + } + + /*! + * Function called when the user clicks the Reset control bar button. + * + * For this function to be invoked, the InterfaceFeature::ResetButton + * flag must be included in the set of feature flags returned by a + * reimplementation of the Features() member function in a derived class. + * + * If you reimplement this function, its standard behavior is performing a + * reset of the current process instance in this interface, loading its + * default parameter values, and updating interface elements in consequence. + * + * \note The default implementation of this function does nothing. + */ + virtual void ResetInstance() + { + } + + /*! + * Interface initialization routine. + * + * This member function is called when the control handle of this interface + * becomes valid, that is, just after the window holding this interface has + * been created. + * + * You can reimplement this function to create all child controls of this + * interface, as well as to set up a number of important control features, + * like a window title, colors, fonts, and so on. + * + * \deprecated This function has been deprecated and should not be used. + * Interface initialization should be carried out using the \e deferred + * \e initialization technique by reimplementing the Launch() virtual member + * function. See the documentation for these functions for more detailed + * information. + * + * \note The default implementation of this function does nothing. + * + * \sa Launch( const MetaProcess&, const ProcessImplementation*, bool&, unsigned& ), + * Launch( unsigned ) + */ + virtual void Initialize() + { + } + + /*! + * %Process interface launch routine. + * + * \param process Reference to the metaprocess describing the process + * class that is launching this interface, either directly + * as its default interface, or through an existing + * process instance. + * + * \param instance Address of a process instance that is trying to launch + * this interface, or zero if it is being launched + * directly as the default interface of the \a process. + * + * \param[out] dynamic True if this interface wants to be launched in + * dynamic mode; false if this interface will launch as a + * static interface. + * + * \param flags Reserved for future extensions - must not be modified. + * + * This function is called whenever an interface is about to be \e launched. + * An interface can be launched either directly as the default interface of + * a process class (e.g., from PixInsight's %Process Explorer window), or + * through an existing process instance (e.g., by double-clicking a process + * icon). The argument values identify the process class and, if nonzero, + * the process instance. + * + * This function must return true if it accepts to be launched under the + * conditions specified by the arguments. After successfully launching an + * interface from a process instance (i.e., if \a instance is nonzero), the + * ValidateProcess() member function is invoked with a reference to the + * instance. If the instance is validated, the ImportProcess() function is + * finally called. + * + * If this function returns true, the \a dynamic referenced argument + * variable must be set to \c true if this interface wants to start in + * dynamic mode. If an interface launches in dynamic mode, a final call to + * EnterDynamicMode() will occur before the interface window is shown and/or + * activated. Note that the actual dynamic session will not really + * start until a first view is selected by the user to serve as a + * dynamic target. + * + * Interface Initialization + * + * Initializing an interface means building its sub-controls and setting up + * a number of important control features, such as a window title, colors, + * fonts, adjusting sizes, and so on. This job can be done by reimplementing + * the Initialize() member function, which the PixInsight core application + * calls as soon as the control handle of this interface becomes valid, that + * is, just after the window holding this interface has been created. + * + * However, the Initialize() function is now deprecated and the standard way + * to initialize an interface is by reimplementing its %Launch() function to + * perform the initialization work the first time the interface is + * launched. This technique is known as deferred initialization + * of a process interface, and has the important advantage that it minimizes + * resources and memory usage because an interface is only initialized if it + * is ever used. Most interfaces are almost never launched by the user, + * except on special occasions, so investing resources for them continually + * is inefficient in general. All standard PixInsight interfaces use the + * deferred initialization technique for that reason. + * + * However, developers using the deferred initialization technique must be + * very careful to ensure that their interfaces will never try to access any + * child controls and other interface elements prior to initializing them. + * This is particularly important if an interface responds to platform + * notifications or events generated by other controls. + * + * \note The default implementation of this function sets \a dynamic = false + * and returns true, so all process interfaces are static by default. + * + * \sa Initialize(), LaunchCount(), Launch( unsigned ) + */ + virtual bool Launch( const MetaProcess& process, + const ProcessImplementation* instance, bool& dynamic, unsigned& flags ) + { + dynamic = false; // interfaces are static by default + return true; + } + + /*! + * Launches this interface with its default process. + * + * \param flags Reserved for future extensions - must be zero. + * + * Returns true if the interface could be launched successfully; false in + * the event of error. + * + * This is a convenience function to launch an interface without a process + * instance. It is functionally equivalent to the following code: + * + * \code + * bool Launch( ProcessInterface& iface, unsigned flags = 0 ) + * { + * const MetaProcess* process = iface.Process(); + * if ( process == nullptr ) + * return false; + * bool notUsed; + * return iface.Launch( *process, nullptr, notUsed, flags ); + * } + * \endcode + * + * \sa Launch( const MetaProcess&, const ProcessImplementation*, bool&, unsigned& ), + */ + bool Launch( unsigned flags = 0 ); + + /*! + * Returns the number of times this interface has been launched since the + * beginning of the current PixInsight session. + * + * \sa Launch() + */ + size_type LaunchCount() const + { + return m_launchCount; + } + + /*! + * %Process instantiation function. + * + * Interfaces capable of generating process instances must reimplement this + * function to create a new process instance, whose address is returned. + * + * The newly created instance should reflect the current state of this + * interface. Interfaces usually maintain a private process instance, whose + * parameters are modifiable through the interface's controls. Then a + * reimplementation of this function simply creates a duplicate of the + * private instance and returns its address. + * + * Returning \e arbitrary instances that have no logical connection with + * the \e visible state of this interface is considered bad practice, and is + * a main reason to deny certification of a PixInsight module. This is + * because the user has always the right to know exactly what she or he can + * expect to get, based on the information shown by an interface on its + * controls. + * + * \note If an interface does not reimplement this function, then it will be + * a plain tool with no processing capabilities. This is because the default + * implementation of this function returns nullptr, meaning that no process + * instance can be generated. In this case, it is \e mandatory that the + * interface reimplements the IsInstanceGenerator() member function to + * return false. + * + * \sa IsInstanceGenerator(), NewTestProcess(), MetaProcess::Clone() + */ + virtual ProcessImplementation* NewProcess() const + { + return nullptr; + } + + /*! + * Test instantiation function. + * + * This function is invoked when a new instance is necessary for strict + * testing purposes exclusively, not to perform actual processing. + * + * In certain situations, the core application needs a \e temporary process + * instance exclusively for testing purposes. This happens, for example, to + * verify if a given instance can be executed on a given view, or in the + * global context, during complex GUI operations. The core application tries + * to optimize GUI performance by calling this function when possible. + * + * For example, the PixInsight core application tries to create temporary + * test instances each time the user drags a process icon over an image, to + * learn if the instance that the icon encapsulates can be executed on the + * view that holds the image. If the user drops the icon, then a regular, + * non-test instance is generated by calling NewProcess(), then it is + * executed, if possible. If the checks carried out by the dragged test + * instances take significant time, PixInsight's user interface can suffer + * from a severe performace degradation. + * + * If your process can provide a substantially simplified version of an + * existing instance, and such a simplified version still is able to know if + * it can be executed globally or on a given view, then reimplement this + * function. + * + * If your process requires (or may require) some megabytes of data to work, + * but these data are not needed for testing purposes, then it is a pretty + * good candidate to reimplement this function. In practice, however, + * requiring a reimplementation of this function is quite infrequent. + * + * \note The default implementation of this function just returns + * NewProcess(). + * + * \sa DistinguishesTestInstances(), NewProcess(), MetaProcess::TestClone() + */ + virtual ProcessImplementation* NewTestProcess() const + { + return NewProcess(); + } + + /*! + * Returns true iff this interface can generate new process instances. + * + * If your interface has no actual processing capabilities, then reimplement + * this function to return false. This helps the PixInsight core application + * to save resources and improve GUI performance. + * + * An interface has no processing capabilities if its NewProcess() member + * function returns zero. This happens if NewProcess() is not reimplemented. + * Although quite infrequent, an interface can be an instance generator + * \e sometimes, as a function of process parameters or other circumstances. + * In this case both NewProcess() and IsInstanceGenerator() must be + * reimplemented to provide coherent values. + * + * \note The default implementation of this function returns true, so all + * interfaces are instance generators by default. + * + * \sa NewProcess() + */ + virtual bool IsInstanceGenerator() const + { + return true; + } + + /*! + * Returns true iff this interface can provide simplified versions of process + * instances for strict testing purposes. + * + * For example, the PixInsight core application tries to create \e temporary + * test instances each time the user drags a process icon over an image, to + * learn if the instance that the icon encapsulates can be executed on the + * view that holds the image. If the user drops the icon, then a regular, + * non-test instance is generated and executed, if possible. If the checks + * carried out by the dragged test instances take significant time, + * PixInsight's user interface can suffer from a performace degradation. + * + * If you can provide substantially simplified instances, but still able to + * know if they can be used in the context of a particular view, then + * reimplement this function to return true, and also NewTestProcess() to + * return simplified test instances. + * + * \note The default implementation of this function returns false, so + * interfaces don't distinguish between normal (executable) and test + * instances by default. + * + * \sa NewTestProcess() + */ + virtual bool DistinguishesTestInstances() const + { + return false; + } + + /*! + * Instance validation function. + * + * \param instance Reference to a process instance that is being validated + * before being imported by this interface. + * + * \param[out] whyNot If this function returns false, it should return also + * a brief text (256 characters maximum) in this string, + * explaining why the specified \a instance is not a valid + * instance to be imported by this interface. + * + * This function will not be called unless the RequiresInstanceValidation() + * member function is reimplemented to return true in a derived class. + * + * Instance validation takes place when an instance is about to be imported + * by this interface. Importing a process instance means that its parameters + * and data will be acquired by this interface, to edit them through the + * available controls and GUI resources. + * + * \note The default implementation of this function returns false. This is + * because it should be reimplemented if RequiresInstanceValidation() has + * already been reimplemented to return true. + * + * \sa RequiresInstanceValidation(), ImportProcess() + */ + virtual bool ValidateProcess( const ProcessImplementation& instance, String& whyNot ) const + { + whyNot.Clear(); + return false; // Force a reimplementation if RequiresInstanceValidation() = true + } + + /*! + * Returns true iff this interface requires validation of a process instance + * before acquisition via ImportProcess(). + * + * If you actually need this kind of validation, reimplement this function + * to return true, and also the ValidateProcess() function to perform the + * instance validation. + * + * \note The default implementation of this function returns false, so + * instances are not validated before acquiring them with ImportProcess(). + * + * \sa ValidateProcess(), ImportProcess() + */ + virtual bool RequiresInstanceValidation() const + { + return false; + } + + /*! + * Instance import function. + * + * This function is called when a process instance is being acquired by this + * interface. For example, this happens when the user drags a process icon + * to the control bar panel of this interface, or when an instance has been + * launched and it has selected this interface from a reimplementation of + * ProcessImplementation::SelectInterface(). + * + * When an instance is imported by an interface, instance parameters and + * data items are usually acquired by the interface to edit them through its + * available controls and GUI resources. + * + * This function returns true iff the specified instance is accepted and + * successfully imported. + * + * This function is never called if CanImportInstances() has been + * reimplemented to return false. + * + * Note that ValidateProcess() has been called just before this function, + * with a reference to the same instance, only if a reimplementation of + * RequiresInstanceValidation() returns true. In this case, this function is + * not called if ValidateProcess() does not return true. + * + * You must reimplement this function if your interface has processing + * capabilities. Only plain tools don't need to reimplement this function, + * since they know nothing about process instances. + * + * \note The default implementation of this function returns false, so by + * default an interface cannot import instances. + * + * \sa ValidateProcess(), CanImportInstances(), + * ProcessImplementation::SelectInterface() + */ + virtual bool ImportProcess( const ProcessImplementation& ) + { + return false; + } + + /*! + * Returns true iff this interface is able to import process instances. + * + * If your interface has no processing capabilities, you should + * reimplement this function to return false. + * + * \note The default implementation of this function returns true. + * + * \sa ImportProcess() + */ + virtual bool CanImportInstances() const + { + return true; + } + + /*! + * Function called when the real-time preview image needs an update, and + * this interface is the owner of the Real-Time Preview system. + * + * \param[in,out] image Reference to a shared image where the real-time + * rendition would be generated. This image contains pixel + * data of a view selected for real-time previewing. A + * subsequent call to GenerateRealTimePreview() would + * receive a reference to an image with the same pixel + * data, for effective real-time preview generation. + * + * \param view Reference to a view that is currently selected in the + * Real-Time Preview system of the core application. The + * passed \a image contains a representation of the image + * in this view. + * + * \param rect Current real-time region in \a view image coordinates. + * If a nonempty rectangle is received through this + * parameter, then the input \a image contains a + * representation of the corresponding rectangular region + * of the \a view's image. If this parameter is an empty + * rectangle, it must be ignored and \a image is a + * representation of the entire \a view's image. + * + * \param zoomLevel Indicates the integer zoom ratio that has been applied + * to the specified \a image, with respect to the original + * view's image. If this parameter is a negative number, + * it represents a reduction factor; for example, -2 + * corresponds to a 1:2 reduction ratio, meaning that each + * pixel of \a image corresponds to 4 source pixels in the + * view being previewed. If this parameter is a positive + * number, it can only be equal to 1, indicating that each + * pixel in \a image corresponds to one source pixel. In + * other words, real-time preview images can be scaled + * down, but are never magnified or scaled up. + * + * Returns true if the real-time preview requires an update for the + * specified image; false if no update is required. + * + * If this function returns true, a subsequent call to + * GenerateRealTimePreview() will occur when appropriate. + * + * The passed \a image, \a view and \a rect objects cannot be + * modified in any way by this function. + * + * \note The default implementation of this function returns false. + * + * \sa GenerateRealTimePreview(), CancelRealTimePreview(), RealTimePreview + */ + virtual bool RequiresRealTimePreviewUpdate( const UInt16Image& image, const View& view, + const Rect& rect, int zoomLevel ) const + { + return false; + } + + /*! + * Function called to generate a new real-time preview rendition. + * + * \param[in,out] image Reference to a shared image where the real-time + * rendition must be generated. On input, this image + * contains pixel data of a view selected for real-time + * previewing. On output, this image must be transformed + * to represent a preview of the current process instance + * being edited on this process interface. + * + * \param view Reference to a view that is currently selected in the + * Real-Time Preview system of the core application. The + * passed \a image contains a representation of the image + * in this view. + * + * \param rect Current real-time region in \a view image coordinates. + * If a nonempty rectangle is received through this + * parameter, then the input \a image contains a + * representation of the corresponding rectangular region + * of the \a view's image. If this parameter is an empty + * rectangle, it must be ignored and \a image is a + * representation of the entire \a view's image. + * + * \param zoomLevel Indicates the integer zoom ratio that has been applied + * to the specified \a image, with respect to the original + * view's image. If this parameter is a negative number, + * it represents a reduction factor; for example, -2 + * corresponds to a 1:2 reduction ratio, meaning that each + * pixel of \a image corresponds to 4 source pixels in the + * view being previewed. If this parameter is a positive + * number, it can only be equal to 1, indicating that each + * pixel in \a image corresponds to one source pixel. In + * other words, real-time preview images can be scaled + * down, but are never magnified or scaled up. + * + * \param[out] info Reference to a string where a brief informative text + * (256 characters maximum) can optionally be stored to + * describe some special circumstances about the generated + * rendition. Typically, this string can be used to inform + * about an inexact or partial rendition, for example + * because the applied reduction ratio (\a zoomLevel) + * does not allow a reasonably accurate representation of + * some process features. + * + * Returns true to signal that the passed \a image has been modified and can + * now be used to update the current real-time preview. Returns false to + * indicate that the \a image has not been altered by this function, and + * hence that the current real-time preview update should be aborted. + * + * The passed \a view and \a rect objects cannot be modified in any + * way by this function. A reimplementation of this function cannot be + * used to modify a view indirectly - we mean it! + * + * \note The default implementation of this function returns false without + * modifying the passed \a image. + * + * \sa RequiresRealTimePreviewUpdate(), CancelRealTimePreview(), + * RealTimePreview + */ + virtual bool GenerateRealTimePreview( UInt16Image& image, const View& view, + const Rect& rect, int zoomLevel, String& info ) const + { + return false; + } + + /*! + * Function called to request cancellation of the ongoing real-time preview + * generation process. + * + * The core application may call this member function when the current + * real-time generation process (which is being carried out by a + * reimplemented GenerateRealTimePreview() function) should be aborted + * immediately and unconditionally. + * + * The core application can make such a request at its own discretion---and + * your interface should be ready to honor it during a real-time generation + * task---, but currently (as of PixInsight core version 1.8.0) this only + * happens if the real-time progress dialog has been made visible and the + * user has closed it prematurely (e.g., by clicking its Cancel button). + * + * \note The default implementation of this function simulates a manual + * deactivation of the Real-Time Preview button of this interface by calling + * Control::DeactivateRealTimePreview(). If your real-time generation code + * is coherent with the current state of your interface, you normally should + * not need to reimplement this member function. + * + * \sa RequiresRealTimePreviewUpdate(), GenerateRealTimePreview(), + * RealTimePreview::ShowProgressDialog(), RealTimePreview + */ + virtual void CancelRealTimePreview() + { + DeactivateRealTimePreview(); + } + + /*! + * Returns true iff this interface can be a dynamic interface. + * + * A dynamic interface is a process interface working in dynamic + * mode. In dynamic mode, an interface provides a high degree of + * interaction with the user through a set of special functions that allow + * direct, real-time communication with the core application's GUI. This + * includes the possibility of generating arbitrary graphical contents on + * image views, and receiving pointing device (mouse, tablet) messages. + * + * Note that an interface can work in both static and dynamic modes (not + * simultaneously, of course), depending on the value returned by the + * Launch() function. However, dynamic interface semantics will not be + * available to an interface unless it reimplements this function to return + * true. This has been done in this way to help saving platform resources, + * which is a design principle of PCL. + * + * If this function returns false (as it does by default), dynamic process + * semantics will not be available for this interface. + * + * \note The default implementation of this function returns false, so + * dynamic interface semantics are disabled by default. + * + * \sa Launch() + */ + virtual bool IsDynamicInterface() const + { + return false; + } + + /*! + * Function called when a new dynamic mode session is about to + * start. Returns true if the new dynamic session can continue; false if it + * should be interrupted. + * + * \note The default implementation of this function returns true. + * + * \sa ExitDynamicMode() + */ + virtual bool EnterDynamicMode() + { + return true; + } + + /*! + * Function called just after a dynamic session has been terminated. + * + * \note The default implementation of this function does nothing. + * + * \sa EnterDynamicMode() + */ + virtual void ExitDynamicMode() + { + } + + /*! + * Function called when the mouse cursor enters the viewport of a \a view, + * during an active dynamic session. + * + * \note The default implementation of this function does nothing. + * + * \sa DynamicMouseLeave(), DynamicMouseMove(), DynamicMousePress(), + * DynamicMouseRelease(), DynamicMouseDoubleClick(), DynamicMouseWheel() + */ + virtual void DynamicMouseEnter( View& view ) + { + } + + /*! + * Function called when the mouse cursor leaves the viewport of a \a view, + * during an active dynamic session. + * + * \note The default implementation of this function does nothing. + * + * \sa DynamicMouseEnter(), DynamicMouseMove(), DynamicMousePress(), + * DynamicMouseRelease(), DynamicMouseDoubleClick(), DynamicMouseWheel() + */ + virtual void DynamicMouseLeave( View& view ) + { + } + + /*! + * Function called when the mouse cursor is displaced on a view, during an + * active dynamic session. + * + * \param view Reference to a view over which the mouse cursor has + * been displaced. + * + * \param cursorPos New mouse cursor position in image coordinates. + * + * \param buttons Indicates the current states of all mouse buttons. This + * value is an OR'ed combination of MouseButton flags. A + * flag set indicates a pressed mouse button. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * \note The default implementation of this function does nothing. + * + * \sa DynamicMouseEnter(), DynamicMouseLeave(), DynamicMousePress(), + * DynamicMouseRelease(), DynamicMouseDoubleClick(), DynamicMouseWheel() + */ + virtual void DynamicMouseMove( View& view, const DPoint& cursorPos, + unsigned buttons, unsigned modifiers ) + { + } + + /*! + * Function called when a mouse button is pressed on a view, during an + * active dynamic session. + * + * \param view Reference to a view over which a mouse button has been + * pressed. + * + * \param cursorPos Current mouse cursor position in image coordinates. + * + * \param button Identifies the mouse button that has been pressed. This + * value is a unique MouseButton flag. + * + * \param buttons Indicates the current states of all mouse buttons. This + * value is an OR'ed combination of MouseButton flags. A + * flag set indicates a pressed mouse button. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * \note The default implementation of this function does nothing. + * + * \sa DynamicMouseEnter(), DynamicMouseLeave(), DynamicMouseMove(), + * DynamicMouseRelease(), DynamicMouseDoubleClick(), DynamicMouseWheel() + */ + virtual void DynamicMousePress( View& view, const DPoint& cursorPos, + int button, unsigned buttons, unsigned modifiers ) + { + } + + /*! + * Function called when a mouse button is released on a view, during an + * active dynamic session. + * + * \param view Reference to a view over which a mouse button has been + * released. + * + * \param cursorPos Current mouse cursor position in image coordinates. + * + * \param button Identifies the mouse button that has been released. + * This value is a unique MouseButton flag. + * + * \param buttons Indicates the current states of all mouse buttons. This + * value is an OR'ed combination of MouseButton flags. A + * flag set indicates a pressed mouse button. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * \note The default implementation of this function does nothing. + * + * \sa DynamicMouseEnter(), DynamicMouseLeave(), DynamicMouseMove(), + * DynamicMousePress(), DynamicMouseDoubleClick(), DynamicMouseWheel() + */ + virtual void DynamicMouseRelease( View& view, const DPoint& cursorPos, + int button, unsigned buttons, unsigned modifiers ) + { + } + + /*! + * Function called when the primary mouse button is double-clicked on a + * view, during an active dynamic session. + * + * \param view Reference to a view over which the primary mouse button + * has been double-clicked. + * + * \param cursorPos Current mouse cursor position in image coordinates. + * + * \param buttons Indicates the current states of all mouse buttons. This + * value is an OR'ed combination of MouseButton flags. A + * flag set indicates a pressed mouse button. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * \note The default implementation of this function does nothing. + * + * \sa DynamicMouseEnter(), DynamicMouseLeave(), DynamicMouseMove(), + * DynamicMousePress(), DynamicMouseRelease(), DynamicMouseWheel() + */ + virtual void DynamicMouseDoubleClick( View& view, const DPoint& cursorPos, + unsigned buttons, unsigned modifiers ) + { + } + + /*! + * Function called if a key is pressed when a view has the keyboard focus, + * during an active dynamic session. + * + * \param view Reference to the view that had the keyboard focus when + * a key was pressed. + * + * \param key A KeyCode code identifying the keyboard key that has + * been pressed. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * This function returns true if it processes the keyboard press event. If + * false is returned, then the keyboard event may propagate to other + * elements in the PixInsight core application GUI. + * + * \note The default implementation of this function returns false. + * + * \sa DynamicKeyRelease() + */ + virtual bool DynamicKeyPress( View& view, int key, unsigned modifiers ) + { + return false; + } + + /*! + * Function called if a key is released when a view has the keyboard focus, + * during an active dynamic session. + * + * \param view Reference to the view that had the keyboard focus when + * a key was released. + * + * \param key A KeyCode code identifying the keyboard key that has + * been released. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * This function returns true if it processes the keyboard release event. If + * false is returned, then the keyboard event may propagate to other + * elements in the PixInsight core application GUI. + * + * \note The default implementation of this function returns false. + * + * \sa DynamicKeyPress() + */ + virtual bool DynamicKeyRelease( View& view, int key, unsigned modifiers ) + { + return false; + } + + /*! + * Function called when the mouse wheel is rotated while the mouse cursor is + * over a view, during an active dynamic session. + * + * \param view Reference to a view over which the mouse cursor was + * located when the mouse wheel was rotated. + * + * \param cursorPos Current mouse cursor position in image coordinates. + * + * \param wheelDelta Wheel rotation increment. A positive increment + * indicates that the wheel has been rotated in the + * forward direction; negative increments correspond to + * backwards rotation. For example, negative increments + * should be used to scroll down a scrollable area, as a + * document browser. + * + * \param buttons Indicates the current states of all mouse buttons. This + * value is an OR'ed combination of MouseButton flags. A + * flag set indicates a pressed mouse button. + * + * \param modifiers Indicates the current states of all keyboard modifiers. + * This value is an OR'ed combination of KeyModifier + * flags. A flag set indicates a pressed modifier key. + * + * This function returns true if it processes the wheel rotation event. If + * false is returned, then the wheel event will propagate to other elements + * in the PixInsight core application GUI. + * + * \note The default implementation of this function returns false. + * + * \sa DynamicMouseEnter(), DynamicMouseLeave(), DynamicMouseMove(), + * DynamicMousePress(), DynamicMouseRelease(), DynamicMouseDoubleClick() + */ + virtual bool DynamicMouseWheel( View& view, const DPoint& cursorPos, + int wheelDelta, unsigned buttons, unsigned modifiers ) + { + return false; + } + + /*! + * Function called when a view's screen rendition needs to be updated, + * during an active dynamic session. + * + * \param view Reference to a view that requires a screen update. + * + * \param rect Update region in image coordinates. + * + * This function \e must be reimplemented by dynamic interfaces that + * maintain their own graphical content over image views. + * + * This function must return false if this interface requires no screen + * update for the specified update region. + * + * If this function returns true, then a subsequent call to DynamicPaint() + * will occur as soon as possible, including this update region, probably + * into a wider region, due to optimization of screen updates. + * + * \note The default implementation of this function returns false. + * + * \sa DynamicPaint() + */ + virtual bool RequiresDynamicUpdate( const View& view, const DRect& rect ) const + { + return false; + } + + /*! + * Function called when a view's screen rendition has been updated. + * + * \param view Reference to a view where the specified update region + * should be redrawn by this interface. + * + * \param graphics Reference to a vector graphics context, where all + * screen drawing work must be performed. + * + * \param rect Update region in image coordinates. + * + * This function \e must be reimplemented by dynamic interfaces that + * maintain their own graphical content over image views. + * + * When this function is invoked, the update region will contain just the + * screen rendition of the target \a view's image, with display functions + * and color management transformations applied as appropriate, but without + * any additional vectorial contents such as preview rectangles, selections, + * auxiliary geometric items, cursors, etc, which are always rendered + * \e after this function returns. + * + * When this function is called, the update region has already been set as + * the current clipping region of the \a graphics context in viewport + * coordinates. The module being invoked can only define a clipping region + * as an intersection with the update rectangle, but not outside it. In + * other words, this function can only paint \e inside the specified update + * rectangle. Any attempt to define a larger clipping region, for example by + * calling Graphics::SetClipRect(), is illegal and will be blocked by the + * PixInsight core application. + * + * \note The default implementation of this function does nothing. + * + * \sa RequiresDynamicUpdate(), VectorGraphics + */ + virtual void DynamicPaint( const View& view, VectorGraphics& graphics, const DRect& rect ) const + { + } + + /*! + * \defgroup image_notifications Image Notification Functions + * + * The PixInsight core application calls image notification functions to + * keep interfaces informed about changes and events involving views and + * their images. + * + * For a process interface to receive image notifications, the corresponding + * ProcessInterface subclass must reimplement + * ProcessInterface::WantsImageNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive image notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive image notifications by default. + * + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual bool WantsImageNotifications() const + { + return false; + } + + /*! + * Notification sent when a new view has been created. + * + * \param view Reference to the view that has been created. Can be + * either a main view or a preview. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageCreated( const View& view ) + { + } + + /*! + * Notification sent when the image in a view has been modified. + * + * \param view Reference to the view whose image has been modified. + * Can be either a main view or a preview. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageUpdated( const View& view ) + { + } + + /*! + * Notification sent when the identifier of a view has been changed. + * + * \param view Reference to the view whose identifier has been + * changed. Can be either a main view or a preview. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageRenamed( const View& view ) + { + } + + /*! + * Notification sent when an existing view is about to be destroyed. + * + * \param view Reference to the view that will be destroyed. Can be + * either a main view or a preview. + * + * When an image window is closed and it has one or more previews defined, + * an ImageDeleted() notification is sent for each of its previews, then a + * final notification is sent for its main view. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageDeleted( const View& view ) + { + } + + /*! + * Notification sent when a view has been activated and has received the + * input focus. + * + * \param view Reference to the view that has been activated and + * focused. This is from now on the current active + * view in the core application's GUI. \a view can be + * either a main view or a preview. + * + * If the \a view is a preview, this notification implicitly means that its + * parent image window has been activated and is now the topmost, active + * window in the current workspace. In this case, however, a notification + * for the window's main view is not sent; only the active view is notified. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageFocused( const View& view ) + { + } + + /*! + * Notification sent when a view has been locked for read and/or write + * operations. + * + * \param view Reference to the view that has been locked. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageLocked( const View& view ) + { + } + + /*! + * Notification sent when a view has been unlocked for read and/or write + * operations. + * + * \param view Reference to the view that has been unlocked. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageUnlocked( const View& view ) + { + } + + /*! + * Notification sent when the screen transfer functions (STF) have + * been enabled for a view. + * + * \param view Reference to a view whose STF have been enabled. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageSTFEnabled( const View& view ) + { + } + + /*! + * Notification sent when the screen transfer functions (STF) have + * been disabled for a view. + * + * \param view Reference to a view whose STF have been disabled. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageSTFDisabled( const View& view ) + { + } + + /*! + * Notification sent when the screen transfer functions (STF) of a + * view have been updated. + * + * \param view Reference to a view whose STF have been updated. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageSTFUpdated( const View& view ) + { + } + + /*! + * Notification sent when the parameters of the RGB working space + * (RGBWS) of a view have been updated. + * + * \param view Reference to a view whose RGBWS has been updated. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageRGBWSUpdated( const View& view ) + { + } + + /*! + * Notification sent when color management (CM) has been enabled + * for a view. + * + * \param view Reference to a view for which color management has been + * enabled. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageCMEnabled( const View& view ) + { + } + + /*! + * Notification sent when color management (CM) has been disabled + * for a view. + * + * \param view Reference to a view for which color management has been + * disabled. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageCMDisabled( const View& view ) + { + } + + /*! + * Notification sent when the color management (CM) parameters of a + * view have been updated. + * + * \param view Reference to a view whose color management data or + * working parameters have been modified. + * + * This notification is sent when a view's ICC profile is changed or + * deleted, and when some color management features are modified, as + * soft-proofing or gamut check, among others. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageCMUpdated( const View& view ) + { + } + + /*! + * Notification sent when an image has been saved to a disk file. + * + * \param view Reference to a view whose image has been successfully + * written to a file. + * + * \ingroup image_notifications + * \sa \ref image_notifications "Image Notification Functions" + */ + virtual void ImageSaved( const View& view ) + { + } + + /*! + * \defgroup mask_notifications Mask Notification Functions + * + * The PixInsight core application calls mask notification functions to + * keep interfaces informed about changes and events involving masks of + * image windows. + * + * For a process interface to receive mask notifications, the corresponding + * ProcessInterface subclass must reimplement + * ProcessInterface::WantsMaskNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive mask notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive mask notifications by default. + * + * \sa \ref mask_notifications "Mask Notification Functions" + */ + virtual bool WantsMaskNotifications() const + { + return false; + } + + /*! + * Notification sent when a mask has been selected for (or removed from) an + * image window. + * + * \param view Reference to the main view of an image window for which + * either a new mask has been selected, or an existing + * mask has been removed. + * + * \ingroup mask_notifications + * \sa \ref mask_notifications "Mask Notification Functions" + */ + virtual void MaskUpdated( const View& view ) + { + } + + /*! + * Notification sent when masking has been enabled for an image window. + * + * \param view Reference to the main view of an image window for which + * masking has been enabled. + * + * \ingroup mask_notifications + * \sa \ref mask_notifications "Mask Notification Functions" + */ + virtual void MaskEnabled( const View& view ) + { + } + + /*! + * Notification sent when masking has been disabled for an image window. + * + * \param view Reference to the main view of an image window for which + * masking has been disabled. + * + * \ingroup mask_notifications + * \sa \ref mask_notifications "Mask Notification Functions" + */ + virtual void MaskDisabled( const View& view ) + { + } + + /*! + * Notification sent when mask visibility has been enabled for an image + * window. + * + * \param view Reference to the main view of an image window whose + * mask is now visible. + * + * \ingroup mask_notifications + * \sa \ref mask_notifications "Mask Notification Functions" + */ + virtual void MaskShown( const View& view ) + { + } + + /*! + * Notification sent when mask visibility has been disabled for an image + * window. + * + * \param view Reference to the main view of an image window whose + * mask is now hidden. + * + * \ingroup mask_notifications + * \sa \ref mask_notifications "Mask Notification Functions" + */ + virtual void MaskHidden( const View& view ) + { + } + + /*! + * \defgroup transparency_notifications Image Transparency \ + * Notification Functions + * + * The PixInsight core application calls transparency notification functions + * to keep interfaces informed about changes in transparency rendering modes + * of image windows. + * + * For a process interface to receive transparency notifications, the + * corresponding ProcessInterface subclass must reimplement + * ProcessInterface::WantsTransparencyNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive transparency notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive transparency notifications by default. + * + * \sa \ref transparency_notifications + * "Image Transparency Notification Functions" + */ + virtual bool WantsTransparencyNotifications() const + { + return false; + } + + /*! + * Notification sent when transparency rendering has been disabled for an + * image window. + * + * \param view Reference to the main view of an image window for which + * transparency rendering has been disabled. + * + * \ingroup transparency_notifications + * \sa \ref transparency_notifications + * "Image Transparency Notification Functions" + */ + virtual void TransparencyHidden( const View& view ) + { + } + + /*! + * Notification sent when the current transparency rendering mode has been + * updated for an image window. + * + * \param view Reference to the main view of an image window whose + * transparency rendering mode has been updated. + * + * \ingroup transparency_notifications + * \sa \ref transparency_notifications + * "Image Transparency Notification Functions" + */ + virtual void TransparencyModeUpdated( const View& view ) + { + } + + /*! + * \defgroup view_property_notifications View Property Notification \ + * Functions + * + * The PixInsight core application calls view property notification + * functions to keep interfaces informed about changes and events involving + * view properties. + * + * For a process interface to receive view property notifications, the + * corresponding ProcessInterface subclass must reimplement + * ProcessInterface::WantsViewPropertyNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive view property notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive view property notifications by default. + * + * \sa \ref view_property_notifications "View Property Notification Functions" + */ + virtual bool WantsViewPropertyNotifications() const + { + return false; + } + + /*! + * Notification sent when a view property has been created or modified. + * + * \param view Reference to a view where a new property has been + * created, or an existing property has been modified. + * + * \param property Identifier of the view property that has been created + * or modified. + * + * \ingroup view_property_notifications + * \sa \ref view_property_notifications "View Property Notification Functions" + */ + virtual void ViewPropertyUpdated( const View& view, const IsoString& property ) + { + } + + /*! + * Notification sent when a view property has been deleted. + * + * \param view Reference to a view where a property has been deleted. + * + * \param property Identifier of the view property that has been deleted. + * + * \ingroup view_property_notifications + * \sa \ref view_property_notifications "View Property Notification Functions" + */ + virtual void ViewPropertyDeleted( const View& view, const IsoString& property ) + { + } + + /*! + * \defgroup readout_notifications Readout Notification Functions + * + * The PixInsight core application calls readout notification functions to + * send real-time readout pixel values to interfaces. + * + * Readout operations take place when the user clicks and drags the mouse + * over a view in readout mode (ImageMode::Readout). During a + * readout procedure, RGBA values are read from a view's image (according to + * global readout options) and sent to interfaces via readout notifications. + * + * For example, an interface can receive readout notifications to let the + * user select a color by clicking directly over an image. The NewImage + * standard interface does exactly this to select an initial color for newly + * created images. + * + * For a process interface to receive readout notifications, the + * corresponding ProcessInterface subclass must reimplement + * ProcessInterface::WantsReadoutNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive readout notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive readout notifications by default. + * + * \sa \ref readout_notifications "Readout Notification Functions" + */ + virtual bool WantsReadoutNotifications() const + { + return false; + } + + /*! + * Notification sent to signal the beginning of a new readout procedure. + * + * \param view Reference to a view from which new readout data + * notifications will be sent from now on. + * + * \ingroup readout_notifications + * \sa \ref readout_notifications "Readout Notification Functions" + */ + virtual void BeginReadout( const View& view ) + { + } + + /*! + * Notification sent when new readout data are available. + * + * \param view Reference to a view from which new readout data is + * being sent. + * + * \param position Readout position in image coordinates. + * + * \param R,G,B,A New readout red, green, blue and alpha values, + * respectively, in the normalized real range [0,1]. + * + * \note Although images can have an unlimited number of alpha channels in + * PixInsight, only readout values from the first alpha channel (which + * defines transparency) are sent to interfaces. + * + * \ingroup readout_notifications + * \sa \ref readout_notifications "Readout Notification Functions" + */ + virtual void UpdateReadout( const View& view, const DPoint& position, double R, double G, double B, double A ) + { + } + + /*! + * Notification sent to signal the end of an active readout procedure. + * + * \param view Reference to the view from which new readout data + * notifications will no longer be sent. + * + * \ingroup readout_notifications + * \sa \ref readout_notifications "Readout Notification Functions" + */ + virtual void EndReadout( const View& view ) + { + } + + /*! + * \defgroup process_notifications Process Instance Notification Functions + * + * The PixInsight core application calls process instance notification + * functions to keep interfaces informed about changes and events involving + * process instances. + * + * For a process interface to receive process instance notifications, the + * corresponding ProcessInterface subclass must reimplement + * ProcessInterface::WantsProcessNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive process instance + * notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive instance notifications by default. + * + * \sa \ref process_notifications "Process Instance Notification Functions" + */ + virtual bool WantsProcessNotifications() const + { + return false; + } + + /*! + * Notification sent when a new process instance has been created. + * + * \param instance Reference to a process instance that has been newly + * created. + * + * \ingroup process_notifications + * \sa \ref process_notifications "Process Instance Notification Functions" + */ + virtual void ProcessCreated( const ProcessInstance& instance ) + { + } + + /*! + * Notification sent when an existing process instance has been updated. + * + * \param instance Reference to a process instance that has been modified. + * + * \ingroup process_notifications + * \sa \ref process_notifications "Process Instance Notification Functions" + */ + virtual void ProcessUpdated( const ProcessInstance& instance ) + { + } + + /*! + * Notification sent when a process instance is about to be destroyed. + * + * \param instance Reference to a process instance that will be destroyed. + * + * \ingroup process_notifications + * \sa \ref process_notifications "Process Instance Notification Functions" + */ + virtual void ProcessDeleted( const ProcessInstance& instance ) + { + } + + /*! + * Notification sent when a process instance has been saved to a disk file. + * + * \param instance Reference to a process instance that has been written + * successfully to a disk file (for example, as part of a + * .xpsm file). + * + * \ingroup process_notifications + * \sa \ref process_notifications "Process Instance Notification Functions" + */ + virtual void ProcessSaved( const ProcessInstance& instance ) + { + } + + /*! + * \defgroup rtpreview_notifications Real Time Preview Notification \ + * Functions + * + * The PixInsight core application calls real time preview notification + * functions to keep interfaces informed about changes and events involving + * the PixInsight real time previewing system. + * + * For a process interface to receive real time preview notifications, the + * corresponding ProcessInterface subclass must reimplement + * ProcessInterface::WantsRealTimePreviewNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive notifications from the + * real-time previewing system. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive real-time previewing notifications by default. + * + * \sa \ref rtpreview_notifications "Real Time Preview Notification Functions" + */ + virtual bool WantsRealTimePreviewNotifications() const + { + return false; + } + + /*! + * Notification sent when the owner of the real time previewing system has + * been changed. + * + * \param iface Reference to a process interface that is now the owner + * of the real-time previewing system. + * + * \ingroup rtpreview_notifications + * \sa \ref rtpreview_notifications "Real Time Preview Notification Functions" + */ + virtual void RealTimePreviewOwnerChanged( ProcessInterface& iface ) + { + } + + /*! + * Notification sent when a real time preview LUT structure has been + * generated. + * + * \param colorModel Identifies the LUT structure that has been recalculated + * and is now available. + * + * \ingroup rtpreview_notifications + * \sa \ref rtpreview_notifications "Real Time Preview Notification Functions" + * + * \deprecated This function has been deprecated and should not be used. The + * real-time previewing system no longer depends on look up table (LUT) + * structures. + */ + virtual void RealTimePreviewLUTUpdated( int colorModel ) + { + } + + /*! + * Notification sent when a new real-time rendition has started being + * generated. + * + * \ingroup rtpreview_notifications + * \sa \ref rtpreview_notifications "Real Time Preview Notification Functions" + */ + virtual void RealTimePreviewGenerationStarted() + { + } + + /*! + * Notification sent when a new real-time rendition has finished being + * generated. + * + * \ingroup rtpreview_notifications + * \sa \ref rtpreview_notifications "Real Time Preview Notification Functions" + */ + virtual void RealTimePreviewGenerationFinished() + { + } + + /*! + * \defgroup global_notifications Global Notification Functions + * + * The PixInsight core application calls global notification functions to + * keep interfaces informed about changes and events occurring in the global + * core application context. + * + * For a process interface to receive global notifications, the + * corresponding ProcessInterface subclass must reimplement + * ProcessInterface::WantsGlobalNotifications() to return true. + */ + + /*! + * Returns true iff this interface will receive global notifications. + * + * \note The default implementation of this function returns false, so + * interfaces don't receive global notifications by default. + * + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual bool WantsGlobalNotifications() const + { + return false; + } + + /*! + * Notification sent when the parameters of the global RGB working space + * (RGBWS) have been modified. + * + * \ingroup global_notifications + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual void GlobalRGBWSUpdated() + { + } + + /*! + * Notification sent when color management (CM) has been globally enabled. + * + * \ingroup global_notifications + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual void GlobalCMEnabled() + { + } + + /*! + * Notification sent when color management (CM) has been globally disabled. + * + * \ingroup global_notifications + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual void GlobalCMDisabled() + { + } + + /*! + * Notification sent when global color management (CM) data or working + * parameters have been modified. This includes selecting a new default ICC + * profile, or changing some global color management parameters, such as + * default profile mismatching policies or rendering intents. + * + * \ingroup global_notifications + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual void GlobalCMUpdated() + { + } + + /*! + * Notification sent when global readout options have been modified. + * + * \ingroup global_notifications + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual void ReadoutOptionsUpdated() + { + } + + /*! + * Notification sent when one or more global preferences settings have been + * modified. + * + * \ingroup global_notifications + * \sa \ref global_notifications "Global Notification Functions" + */ + virtual void GlobalPreferencesUpdated() + { + } + + /*! + * Returns a settings key that should be used for storage of all settings + * data associated to this interface. + * + * The returned settings key string will be equal to "Interfaces/<id>/", + * where <id> is the identifier of this interface, as returned by the + * Id() member function. + * + * \note Interfaces must only use the keys returned by this function for + * storage of all their settings data. Using different keys is allowed, but + * it is considered bad practice in most cases. + * + * \sa Settings, SaveSettings(), LoadSettings() + */ + IsoString SettingsKey() const + { + return IsoString( "Interfaces/" ) + Id() + '/'; + } + + /*! + * Saves settings data for this process interface. + * + * This function is called automatically for all process interfaces upon + * module unload. If your interface needs storing and retrieving + * configuration data to remember them across sessions, then you should + * reimplement this function. + * + * See the documentation for the LoadSettings() member function for detailed + * information about saving and loading settings data for process + * interfaces. + * + * \note This function is only invoked for interfaces that have been + * launched at least once. This is because if an interface has not been used + * during a session, there is no plausible reason to modify its associated + * configuration data. This policy has been adopted to maximize user control + * over interface preferences and configuration settings. + * + * \sa Settings, LoadSettings(), SettingsKey() + */ + virtual void SaveSettings() const + { + } + + /*! + * Retrieves stored settings data for this process interface. + * + * This function is called automatically for all process interfaces the + * first time they are launched. If your interface needs storing and + * retrieving configuration data to remember them across sessions, then you + * should reimplement this function. + * + * When saving and loading settings data, your code must use the key + * returned by SettingsKey() as a prefix for the subkeys corresponding to + * each settings data item. For example, the following code snippet: + * + * \code + * IsoString key = SettingsKey() + "Geometry/"; + * // ... + * Settings::Write( key + "Width", Width() ); + * \endcode + * + * would save the current width of this interface to the + * "Interfaces/<id>/Geometry/Width" subkey in the global settings + * space assigned to the current module. This is the recommended behavior. + * + * \sa Settings, SaveSettings(), SettingsKey() + */ + virtual void LoadSettings() + { + } + + /*! + * Saves the current position and dimensions of this interface in global + * settings variables. + * + * Call this function to save the geometry of an interface window across + * sessions. The RestoreGeometry() member function can be invoked to restore + * previously saved position and size data. + * + * Before calling this function, all interface child controls and interface + * elements should have been completely initialized. If this interface is + * not resizable (e.g. because the SetFixedSize() function has been called), + * size data are not stored. + * + * This function stores geometry data in the following settings keys: + * + * Interfaces/<id>/Geometry/Left \n + * Interfaces/<id>/Geometry/Top \n + * Interfaces/<id>/Geometry/Width \n + * Interfaces/<id>/Geometry/Height + * + * where <id> is the identifier of this interface, as returned by the + * Id() member function. + * + * \note Normally, you should not need to call this function, unless you + * have explicitly disabled the auto save geometry feature by + * calling the DisableAutoSaveGeometry() member function. + * + * \sa RestoreGeometry(), SetDefaultPosition(), IsAutoSaveGeometryEnabled() + */ + void SaveGeometry() const; + + /*! + * Restores previously saved position and dimensions of this interface from + * global settings variables. Returns true if stored geometry data could be + * successfully retrieved and established for this interface. + * + * Call this function to restore the geometry of an interface window as it + * was previously saved by SaveGeometry(). This allows an interface to + * \e remember its size and position on the core application's work space + * across sessions. + * + * \note Normally, you should not need to call this function, unless you + * have explicitly disabled the auto save geometry feature by + * calling the DisableAutoSaveGeometry() member function. + * + * \sa SaveGeometry() + */ + bool RestoreGeometry(); + + /*! + * Moves this interface window to a default position on the PixInsight core + * application's work space. + * + * The default position is calculated to place the interface window centered + * on the primary monitor. + * + * \sa SaveGeometry(), RestoreGeometry() + */ + void SetDefaultPosition(); + + /*! + * Returns true iff the auto save geometry feature is currently + * active for this interface. + * + * When auto save geometry is active, the interface \e remembers + * its size and position on the PixInsight core application's worspace + * across sessions. Geometry data are saved to and retrieved from global + * settings variables automatically. Geometry is only saved for interfaces + * that have been launched at least once. + * + * \note By default, the auto save geometry feature is active for + * every process interface. To avoid this automatic behavior, it must be + * explicitly disabled. + * + * \sa EnableAutoSaveGeometry(), DisableAutoSaveGeometry(), + * SaveGeometry(), RestoreGeometry(), SetDefaultPosition() + */ + bool IsAutoSaveGeometryEnabled() const + { + return m_autoSaveGeometry; + } + + /*! + * Enables (or disables) the auto save geometry feature. For more + * information on this feature, see the documentation for the + * IsAutoSaveGeometryEnabled() member function. + * + * \sa DisableAutoSaveGeometry(), IsAutoSaveGeometryEnabled() + */ + void EnableAutoSaveGeometry( bool enable = true ) + { + m_autoSaveGeometry = enable; + } + + /*! + * Disables (or enables) the auto save geometry feature. For more + * information on this feature, see the documentation for the + * IsAutoSaveGeometryEnabled() member function. + * + * \sa EnableAutoSaveGeometry(), IsAutoSaveGeometryEnabled() + */ + void DisableAutoSaveGeometry( bool disable = true ) + { + EnableAutoSaveGeometry( !disable ); + } + + /*! + * Issues an %ImageUpdated notification for a view. + * + * \param view Reference to the view for which an ImageUpdated + * notification will be sent. + * + * The PixInsight core application will send ImageUpdated() notifications to + * all objects that listen image notifications on the entire PixInsight + * platform. This includes not only other process interfaces (including the + * emitter), but also a large number of interface objects and processing + * resources whose states can be automatically updated in response to the + * notification received. + * + * Broadcasting is typically used by dynamic interfaces that modify images + * as a function of direct user interaction. A good example of this is the + * CloneStamp interface, which broadcasts ImageUpdated notifications to + * keep the whole platform consistent with image changes due to clone stamp + * actions performed by the user. + * + * \note This member function must \e not be used on a regular basis without + * having a \e really good reason to do so. An abusive use of this function, + * such as too frequent calls performed during intensive real-time + * operations, may degrade the performance of the whole platform due to + * excessive overhead. + */ + static void BroadcastImageUpdated( const View& view ); + + /*! + * Processes pending user interface events. + * + * Call this function to let the PixInsight core application process pending + * user interface events, which may accumulate while your code is running. + * + * Modules typically call this function during real-time preview generation + * procedures. Calling this function ensures that the GUI remains responsive + * during long, calculation-intensive operations. + * + * If the \a excludeUserInputEvents parameter is set to true, no user input + * events will be processed by calling this function. This includes mainly + * mouse and keyboard events. Unprocessed input events will remain pending + * and will be processed as appropriate when execution returns to + * PixInsight's main event handling loop, or when this function is called + * again with \a excludeUserInputEvents set to false. + * + * \note Do not call this function too frequently, as doing so may degrade + * the performance of the whole PixInsight graphical interface. For example, + * calling this function at 250 ms intervals is reasonable and more than + * sufficient in most cases. Normally, you should only need to call this + * function during real-time image and graphics generation procedures, or + * from time-consuming processes. + */ + static void ProcessEvents( bool excludeUserInputEvents = false ); + +protected: + + /*! + * \internal + */ + ProcessInterface( int ); + +private: + + size_type m_launchCount = 0; + bool m_autoSaveGeometry = true; + + void PerformAPIDefinitions() const override; + + friend class InterfaceDispatcher; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_ProcessInterface_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProcessInterface.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProcessParameter.h b/3rdparty/include/pcl/ProcessParameter.h new file mode 100644 index 0000000..92b3252 --- /dev/null +++ b/3rdparty/include/pcl/ProcessParameter.h @@ -0,0 +1,695 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProcessParameter.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_ProcessParameter_h +#define __PCL_ProcessParameter_h + +/// \file pcl/ProcessParameter.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ProcessParameterType + * \brief %Process parameter data types. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ProcessParameterType::Invalid Represents an invalid process parameter type
ProcessParameterType::UInt8 Unsigned 8-bit integer (unsigned char)
ProcessParameterType::Int8 Signed 8-bit integer (char)
ProcessParameterType::UInt16 Unsigned 16-bit integer (unsigned short)
ProcessParameterType::Int16 Signed 16-bit integer (short)
ProcessParameterType::UInt32 Unsigned 32-bit integer (unsigned int)
ProcessParameterType::Int32 Signed 32-bit integer (int)
ProcessParameterType::UInt64 Unsigned 64-bit integer (unsigned long long)
ProcessParameterType::Int64 Signed 64-bit integer (long long)
ProcessParameterType::Float IEEE 754 single precision (float, 32-bit floating point)
ProcessParameterType::Double IEEE 754 double precision (double, 64-bit floating point)
ProcessParameterType::Boolean Boolean (implemented as uint32, where true=1 and false=0)
ProcessParameterType::Enumeration Enumerated (implemented as int32)
ProcessParameterType::String String (Unicode string encoded as UTF-16)
ProcessParameterType::Block Block (implemented as ByteArray)
ProcessParameterType::Table Table process parameter
+ */ +namespace ProcessParameterType +{ + enum value_type + { + Invalid = -1, + UInt8 = 0, + Int8, + UInt16, + Int16, + UInt32, + Int32, + UInt64, + Int64, + Float, + Double, + Boolean, + Enumeration, + String, + Block, + Table, + NumberOfTypes + }; + + /*! + * \defgroup process_parameter_classification Process Parameter \ + * Classification + */ + + /*! + * Returns true ifff the specified \a type corresponds to a numeric + * parameter data type. + * \ingroup process_parameter_classification + */ + inline bool IsNumeric( int type ) + { + return type >= UInt8 && type <= Double; + } + + /*! + * Returns true ifff the specified \a type corresponds to an integer + * parameter data type. + * \ingroup process_parameter_classification + */ + inline bool IsInteger( int type ) + { + return type >= UInt8 && type <= Int64; + } + + /*! + * Returns true ifff the specified \a type corresponds to a floating point + * real parameter data type. + * \ingroup process_parameter_classification + */ + inline bool IsReal( int type ) + { + return type == Float || type == Double; + } + + /*! + * Returns true ifff the specified \a type corresponds to a variable-length + * parameter data type. + * \ingroup process_parameter_classification + */ + inline bool IsVariableLength( int type ) + { + return type == String || type == Block || type == Table; + } +} + +// ---------------------------------------------------------------------------- + +class Process; +class ProcessParameterPrivate; + +/*! + * \class ProcessParameter + * \brief Identifies and describes a process parameter. + * + * The %ProcessParameter class describes and identifies process parameters + * through intermodule communication with the Process and ProcessInstance + * classes. + * + * As happens with the Process / MetaProcess and ProcessInstance / + * ProcessImplementation pairs, %ProcessParameter is the concrete counterpart + * to MetaParameter. %ProcessParameter represents a parameter of an already + * installed process, while %MetaParameter is a formal description of a + * parameter of a process implemented by subclassing %MetaProcess and + * %ProcessImplementation. + * + * Note that an instance of %ProcessParameter represents an existing parameter + * of an installed process, so you cannot create or define new parameters using + * this class. You can only use this class to get a complete description of a + * parameter, including its identifier, range of valid values, allowed lengths, + * default values, etc. You can also use %ProcessParameter to identify a + * parameter to get or set its current value in an existing process instance, + * which you can manipulate with the ProcessInstance class. + * + * \sa Process, ProcessInstance, MetaProcess, MetaParameter, ProcessImplementation + */ +class PCL_CLASS ProcessParameter +{ +public: + + /*! + * Represents a parameter data type. + */ + typedef ProcessParameterType::value_type data_type; + + /*! + * A list of process parameters. + * + * This type is returned by the TableColumns() member function to describe + * and identify the set of column parameters of a table process parameter. + */ + typedef Array parameter_list; + + /*! + * \struct EnumerationElement + * \brief Structure used to describe an enumeration element. + */ + struct EnumerationElement + { + IsoString id; //!< Element identifier + IsoStringList aliases; //!< Alias identifiers + int value; //!< Element value + }; + + /*! + * A list of enumeration elements. + * + * This type is returned by the EnumerationElements() member function to + * describe an enumeration process parameter. + */ + typedef Array enumeration_element_list; + + /*! + * Constructs a %ProcessParameter object. + * + * \param process Reference to a the process from which you want to gain + * access to one of its parameters. + * + * \param paramId Identifier of the process parameter. It can be the + * primary identifier of a parameter, or one of its alias + * identifiers. + * + * If successful, this constructor creates a managed alias to a process + * parameter of an installed process in the PixInsight core application. + * + * If there is no parameter of \a process with the specified identifier, if + * \a paramId is not a valid identifier, or if the alias object cannot be + * generated for some reason, this constructor throws an Error exception + * with the corresponding error message. Your code should guarantee that + * these exceptions are always caught and handled appropriately. + * + * \note Note that this constructor does not 'create' a new process + * parameter. It only gives access to a parameter of an existing process. + */ + ProcessParameter( const Process& process, const IsoString& paramId ); + + ProcessParameter( const Process& process, const IsoString::ustring_base& paramId ) + : ProcessParameter( process, IsoString( paramId ) ) + { + } + + /*! + * Constructs a %ProcessParameter object that identifies a table column + * parameter. + * + * \param table Reference to a valid table parameter. + * + * \param colId Identifier of the column parameter. It can be the + * primary identifier of a column parameter, or one of its + * alias identifiers. + * + * If successful, this constructor creates a managed alias to a table column + * parameter of an installed process in the PixInsight core application. + * + * If there is no column parameter of \a table with the specified + * identifier, if \a table is not a table parameter, if \a colId is not a + * valid identifier, or if the alias object cannot be generated for some + * reason, this constructor throws an Error exception with the corresponding + * error message. Your code should guarantee that these exceptions are + * always caught and handled appropriately. + * + * \note Note that this constructor does not 'create' a new process + * parameter. It only gives access to a parameter of an existing process. + */ + ProcessParameter( const ProcessParameter& table, const IsoString& colId ); + + ProcessParameter( const ProcessParameter& table, const IsoString::ustring_base& colId ) + : ProcessParameter( table, IsoString( colId ) ) + { + } + + /*! + * Copy constructor. The newly constructed object references the same + * server-side process parameter as the specified object \a p. + * + * \note Note that this constructor does not 'create' a new process + * parameter. It only gives access to a parameter of an existing process. + */ + ProcessParameter( const ProcessParameter& p ); + + /*! + * Destroys this %ProcessParameter object. + */ + virtual ~ProcessParameter(); + + /*! + * Returns true iff this is a \e null %ProcessParameter object. + * + * A null %ProcessParameter does not correspond to an existing parameter of + * an installed process in the PixInsight core application. + */ + bool IsNull() const; + + /*! + * Returns a reference to a null %ProcessParameter object. A null + * %ProcessParameter does not correspond to an existing parameter of an + * installed process in the PixInsight core application. + */ + static ProcessParameter& Null(); + + /*! + * Returns a reference to a Process object that represents the installed + * process this parameter belongs to. + */ + Process& ParentProcess() const; + + /*! + * If this parameter is a table column parameter, this function returns a + * %ProcessParameter object that represents the table process parameter this + * table column belongs to. + * + * If this parameter is not a table column parameter, this function returns + * a null %ProcessParameter object. + */ + ProcessParameter ParentTable() const; + + /*! + * Returns the identifier of this process parameter. + * + * Each process parameter has a valid and unique (within its parent process) + * identifier. All object identifiers follow the C syntax rules for variable + * identifiers in PixInsight. + * + * \sa Aliases() + */ + IsoString Id() const; + + /*! + * Returns a list of alias identifiers for this process parameter. + * + * A process parameter can have one or more alias identifiers. + * Aliased parameters are useful to maintain compatibility with previous + * versions of a process. + * + * When the PixInsight core application imports a process instance (e.g. + * from a process icon) it automatically replaces alias parameter + * identifiers with actual (current) identifiers. This allows a developer to + * change the identifiers of some process parameters without breaking + * compatibility with process instances in existing icon collections or + * projects. + * + * This function returns a list of identifiers that are treated as synonyms + * to the actual identifier of this parameter, which is returned by the Id() + * member function. If this parameter has no aliases, an empty list is + * returned. Two parameters of a process can't have the same alias, so each + * identifier in the list should be unique within its parent process. + * + * \sa Id() + */ + IsoStringList Aliases() const; + + /*! + * Returns true iff this process parameter is required to build new process + * instances. Returns false if a default value can be valid for this process + * parameter when an actual value is not available. + * + * When a new instance is being constructed and the process parameter that + * this object represents is not present (for example, because it is not + * defined in a serialized representation of the instance), the PixInsight + * core application has to decide whether a default, automatically generated + * value may be acceptable, or if the explicit presence of an actual value + * for this parameter is imprescindible. This member function allows a + * module to know this in advance. + */ + bool IsRequired() const; + + /*! + * Returns true if this object represents a read-only process parameter. + * Otherwise full read/write access is granted for this parameter. + * + * Read-only process parameters, also known as output properties, + * cannot be changed by external processes. For example, a script running on + * the core application can retrieve an output property from a process + * instance, but it cannot change its value. The same happens with PCL's + * implementation represented by the Process and ProcessInstance classes. + * + * Read-only parameters are often used to provide resulting values or + * process status information after instance execution. For example, the + * standard ImageIntegration process includes several read-only parameters + * that can be accessed from a script or module to know the identifiers of + * the views generated to store the integrated image and the rejection map + * images. This improves versatility and usability of processes, and + * provides more accurate and extensive information to developers. + */ + bool IsReadOnly() const; + + /*! + * Returns a brief (and hopefully useful) description of this process + * parameter. + */ + String Description() const; + + /*! + * Returns a script comment for this process parameter. + * + * The returned string is intended to be used as a source code comment to + * document process parameters in automatically generated scripts. + */ + String ScriptComment() const; + + /*! + * Returns the data type of this process parameter. For a list of valid + * parameter types, see the ProcessParameterType namespace. + * + * For a null %ProcessParameter object, this member function returns + * ProcessParameterType::Invalid. + */ + data_type Type() const; + + /*! + * Returns the appropriate data type to interpret this block process + * parameter. + * + * If this object does not represent a block parameter, or if this is a null + * object, this member function returns ProcessParameterType::Invalid. + */ + data_type DataInterpretation() const; + + /*! + * Returns true iff this object represents a Boolean process parameter. + */ + bool IsBoolean() const + { + return Type() == ProcessParameterType::Boolean; + } + + /*! + * Returns true iff this object represents a numeric process parameter. + */ + bool IsNumeric() const + { + return ProcessParameterType::IsNumeric( Type() ); + } + + /*! + * Returns true iff this object represents an integer process parameter. + */ + bool IsInteger() const + { + return ProcessParameterType::IsInteger( Type() ); + } + + /*! + * Returns true iff this object represents a floating point real process + * parameter. + */ + bool IsReal() const + { + return ProcessParameterType::IsReal( Type() ); + } + + /*! + * Returns true iff this object represents an enumerated process parameter. + */ + bool IsEnumeration() const + { + return Type() == ProcessParameterType::Enumeration; + } + + /*! + * Returns true iff this object represents a variable-length process + * parameter. + */ + bool IsVariableLength() const + { + return ProcessParameterType::IsVariableLength( Type() ); + } + + /*! + * Returns true iff this object represents a string process parameter. + */ + bool IsString() const + { + return Type() == ProcessParameterType::String; + } + + /*! + * Returns true iff this object represents a block process parameter. + */ + bool IsBlock() const + { + return Type() == ProcessParameterType::Block; + } + + /*! + * Returns true iff this object represents a table process parameter. + */ + bool IsTable() const + { + return Type() == ProcessParameterType::Table; + } + + /*! + * Returns the default value of this process parameter. + * + * This function returns a Variant object with the default parameter value. + * The type of the %Variant object depends on the type of this parameter. + * + * Default values are directly available for Boolean, numeric and string + * parameters. + * + * For enumerated parameters, this function returns the index of the default + * enumeration element. The returned integer can be used as an index on the + * list of elements returned by EnumerationElements(). + * + * For a block parameter an empty ByteArray is always returned, since block + * parameters don't have default values. + * + * For table parameters this function throws an Error exception. + * + * For a null %ProcessParameter object, this member function returns an + * invalid Variant object; see Variant::IsValid(). + */ + Variant DefaultValue() const; + + /*! + * Gets the valid range of values for a numeric process parameter. + * + * \param[out] minValue Minimum valid value of this numeric parameter. + * \param[out] maxValue Maximum valid value of this numeric parameter. + * + * If this parameter is not of a numeric type, or if this is a null object, + * this member function will set both output values to zero. + * + * If this numeric parameter does not impose a specific range of valid + * values, this member function will set the following output values: + * + * \a minValue = -DBL_MAX \n + * \a maxValue = +DBL_MAX. + * + * \sa MinimumValue(), MaximumValue() + */ + void GetNumericRange( double& minValue, double& maxValue ) const; + + /*! + * Returns the minimum valid value of a numeric process parameter. + * \sa GetNumericRange(), MaximumValue() + */ + double MinimumValue() const + { + double min, dum; + GetNumericRange( min, dum ); + return min; + } + + /*! + * Returns the maximum valid value of a numeric process parameter. + * \sa GetNumericRange(), MinimumValue() + */ + double MaximumValue() const + { + double dum, max; + GetNumericRange( dum, max ); + return max; + } + + /*! + * Returns the number of decimal digits used for literal representations of + * this floating point process parameter. + * + * If this parameter is not of a floating point numeric type, or if this is + * a null object, this function returns zero. Otherwise, this function + * returns a positive or negative integer value with the following meanings: + * + * If a value >= 0 is returned, literal representations are always rounded + * to the nearest value with the specified amount of decimal digits. If this + * function returns zero, output values corresponding to this parameter will + * always be rounded to the nearest integer. + * + * If this function returns a negative integer, literal representations will + * use the standard printf's \e g-format. In this format, numerical values + * are represented in a compact fashion, with automatic selection of + * exponential or fixed representations, depending on the value's magnitude + * and fractional accuracy. + * + * \sa ScientificNotation() + */ + int Precision() const; + + /*! + * Returns true iff this floating point process parameter requires scientific + * notation for literal representations. Returns false if this parameter + * requires fixed point notation, or if this is a null object. + * + * \sa Precision() + */ + bool ScientificNotation() const; + + /*! + * Gets the valid range of lengths for this variable length process + * parameter. + * + * \param[out] minLength Minimum valid length of this parameter. + * \param[out] maxLength Maximum valid length of this parameter. + * + * If this parameter is not of a variable length type, or if this is a null + * object, this member function will set both output values to zero. + * + * If this parameter does not impose a specific range of valid lengths, this + * member function will set the following output values: + * + * \a minValue = 0 \n + * \a maxValue = ~size_type( 0 ). + * + * \sa MinimumLength(), MaximumLength() + */ + void GetLengthLimits( size_type& minLength, size_type& maxLength ) const; + + /*! + * Returns the minimum valid length of a variable length process parameter. + * \sa GetLengthLimits(), MaximumLength() + */ + size_type MinimumLength() const + { + size_type min, dum; + GetLengthLimits( min, dum ); + return min; + } + + /*! + * Returns the maximum valid length of a variable length process parameter. + * \sa GetLengthLimits(), MinimumLength() + */ + size_type MaximumLength() const + { + size_type dum, max; + GetLengthLimits( dum, max ); + return max; + } + + /*! + * Returns a list of EnumerationElement structures describing all the + * elements of this enumeration process parameter. + * + * If this parameter is not of an enumerated type, or if this is a null + * object, this member function returns an empty list. + */ + enumeration_element_list EnumerationElements() const; + + /*! + * Returns a string with the valid characters of this string process + * parameter. + * + * If this parameter is not of a string type, if this string parameter does + * not impose a specific set of valid characters, or if this is a null + * object, this member function returns an empty string. + */ + String AllowedCharacters() const; + + /*! + * Returns the list of column parameters in this table process parameter. + * + * If this object does not represent a table parameter, or if this is a null + * object, this member function returns an empty list. + */ + parameter_list TableColumns() const; + + // ------------------------------------------------------------------------- + +private: + + AutoPointer m_data; + + ProcessParameter( const void* ); + + const void* Handle() const; + + friend class ProcessInstance; + friend class InternalParameterEnumerator; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ProcessParameter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProcessParameter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProgressBarStatus.h b/3rdparty/include/pcl/ProgressBarStatus.h new file mode 100644 index 0000000..1fba3a8 --- /dev/null +++ b/3rdparty/include/pcl/ProgressBarStatus.h @@ -0,0 +1,143 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProgressBarStatus.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_ProgressBarStatus_h +#define __PCL_ProgressBarStatus_h + +/// \file pcl/ProgressBarStatus.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS ProgressDialog; + +/*! + * \class ProgressBarStatus + * \brief A status monitoring callback that shows a modal progress dialog. + * + * %ProgressBarStatus is a StatusCallback derived class that opens a modal + * ProgressDialog to provide visual feedback about a running process, without + * freezing the graphical user interface dugin potentially long tasks. It + * allows the user to interrupt the process by activating a standard Cancel + * button on the progress dialog. This class supports both bounded and + * unbounded status monitors. + * + * \sa StatusCallback, StatusMonitor, StandardStatus, SpinStatus, MuteStatus + */ +class PCL_CLASS ProgressBarStatus : public StatusCallback +{ +public: + + /*! + * Constructs a %ProgressBarStatus object. + * + * \param title The window title for the modal progress bar dialog box. + * + * \param parent The parent control of the modal progress bar dialog box. + * The default value is Control::Null(), which creates a + * child top-level window of the current workspace. + */ + ProgressBarStatus( const String& title, Control& parent = Control::Null() ); + + /*! + * Virtual destructor. + */ + virtual ~ProgressBarStatus(); + + /*! + * This function is called by a status \a monitor object when a new + * monitored process is about to start. + */ + int Initialized( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object to signal an update of the + * progress count for the current process. + */ + int Updated( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object to signal that the current + * process has finished. + */ + int Completed( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object when the progress + * information for the current process has been changed. + */ + void InfoUpdated( const StatusMonitor& monitor ) const override; + +private: + + mutable AutoPointer m_progressDialog; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ProgressBarStatus_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProgressBarStatus.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProgressDialog.h b/3rdparty/include/pcl/ProgressDialog.h new file mode 100644 index 0000000..abfc87b --- /dev/null +++ b/3rdparty/include/pcl/ProgressDialog.h @@ -0,0 +1,275 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProgressDialog.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_ProgressDialog_h +#define __PCL_ProgressDialog_h + +/// \file pcl/ProgressDialog.h + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ProgressDialog + * \brief A simple progress bar dialog box. + * + * %ProgressDialog is a specialized modal dialog box to provide visual feedback + * about an ongoing task during potentially long processes. It includes a + * progress bar indicator that can change its graphical appearance to show the + * percentage of the total work already done (\e bounded progress bar), or just + * to inform the user that the task is still being done (unbounded case). The + * dialog also provides a customizable text label and an optional Cancel button + * that the user can activate to interrupt the process. + * + * \sa ProgressBarStatus + */ +class PCL_CLASS ProgressDialog : public Dialog +{ +public: + + /*! + * Constructs a %ProgressDialog. + * + * \param text The text that will be shown on the informative label above + * the progress bar. The default text is an empty string, + * which hides the informative label. + * + * \param title The title of the dialog box window. The default value is + * an empty string, which causes the window to show a default + * title defined by the PixInsight core application. + * + * \param lowerBound The minimum value of the progress bar. The default + * value is zero. + * + * \param upperBound The maximum value of the progress bar. The default + * value is 100, which is appropriate to show progress values + * as a percentage of the total work. + * + * \param parent The parent control of this dialog. The default value + * is Control::Null(), which creates a child top-level window + * of the current workspace. + */ + ProgressDialog( const String& text = String(), + const String& title = String(), + size_type lowerBound = 0, size_type upperBound = 100, + Control& parent = Control::Null() ); + + /*! + * Sets the window title for this dialog box. + */ + void SetTitle( const String& title ); + + /*! + * Sets the range of values for the progress bar indicator. + * + * \param lowerBound The minimum value of the progress bar. + * + * \param upperBound The maximum value of the progress bar. + * + * If both bounds are set to the same value, e.g. \a lowerBound = + * \a upperBound = 0, the progress bar will be \e unbounded. Unbounded + * progress bars change their appearance in a special way to show that the + * running process is still working, but without any specific information + * about the amount of the total work already done. + */ + void SetRange( size_type lowerBound, size_type upperBound ); + + /*! + * Causes the progress bar to be \e unbounded. + * + * Bounded progress bars show information about the amount of the total work + * already done. Unbounded progress bars change their appearance to inform + * that the process is still running, but without any specific hint about + * the amount of pending work. Calling this function is equivalent to: + * + * \code SetRange( 0, 0 ); \endcode + */ + void SetUnbounded() + { + SetRange( 0, 0 ); + } + + /*! + * Returns the lower bound of the progress bar indicator, or zero if the + * progress bar is unbounded. + */ + size_type LowerBound() const + { + return m_lowerBound; + } + + /*! + * Returns the upper bound of the progress bar indicator, or zero if the + * progress bar is unbounded. + */ + size_type UpperBound() const + { + return m_upperBound; + } + + /*! + * Sets the informative text shown on a label above the progress bar. + */ + void SetText( const String& text ); + + /*! + * Sets the current value of the progress bar indicator. + * + * If the progress bar is bounded, the specified \a value will be + * constrained to the current limits, as reported by LowerBound() and + * UpperBound(). + * + * If the progress bar is unbounded, the \a value argument will be ignored + * and the progress bar indicator will change graphically to provide + * feedback about a running process, but without any specific information + * about the amount of work already done. + * + * In all cases the progress bar will be updated on the screen as soon as + * possible after returning from this function. + */ + void SetValue( size_type value ); + + /*! + * Increments the value of the progress bar indicator. + * + * Calling this function is equivalent to: + * + * \code SetValue( m_value + 1 ); \endcode + */ + void Increment() + { + SetValue( m_value + 1 ); + } + + /*! + * Returns true if the Cancel button has been activated by the user, if it + * is enabled. + */ + bool IsCanceled() const + { + return m_canceled; + } + + /*! + * Enables the Cancel button of this progress dialog. When the Cancel button + * is enabled, the user can activate it to interrupt the running process. + */ + void EnableCancelButton( bool enable = true ); + + /*! + * Disables the Cancel button of this progress dialog. When the Cancel + * button is disabled, the user has no way to interrupt the running process. + */ + void DisableCancelButton( bool disable = true ) + { + EnableCancelButton( !disable ); + } + + /*! + * Returns true if the Cancel button is currently enabled. + */ + bool IsCancelButtonEnabled() const + { + return m_cancelButton.IsVisible(); + } + +protected: + + /*! + * \class ProgressDialog::ProgressBar + * \internal + */ + class ProgressBar : public Control + { + public: + + ProgressBar(); + + private: + + double m_value = 0; // only if bounded, in [0,1] + size_type m_step = 0; // only if unbounded, in [0,Width()-1] + bool m_bounded = true; + + void e_Paint( Control&, const Rect& ); + + friend class ProgressDialog; + }; + + size_type m_lowerBound = 0; + size_type m_upperBound = 100; + size_type m_value = 0; + bool m_canceled = false; + Label m_infoLabel; + ProgressBar m_progressBar; + PushButton m_cancelButton; + + void e_Click( Button& sender, bool checked ); + void e_Close( Control& sender, bool& allowClose ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ProgressDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProgressDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProjectionBase.h b/3rdparty/include/pcl/ProjectionBase.h new file mode 100644 index 0000000..d116fb1 --- /dev/null +++ b/3rdparty/include/pcl/ProjectionBase.h @@ -0,0 +1,231 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProjectionBase.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_ProjectionBase_h +#define __PCL_ProjectionBase_h + +/// \file pcl/ProjectionBase.h + +#include + +#include +#include +#include +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ProjectionBase + * \brief Base class of all projection systems + * + * \ingroup astrometry_support + */ +class PCL_CLASS ProjectionBase +{ +public: + + /*! + * Virtual destructor. + */ + virtual ~ProjectionBase() + { + } + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + virtual ProjectionBase* Clone() const = 0; + + /*! + * Returns the WCS projection identifier for this projection system. + */ + virtual IsoString ProjCode() const = 0; + + /*! + * Returns the readable name of this projection system. + */ + virtual IsoString Name() const = 0; + + /*! + * Updates the specified WCS metadata with field values corresponding to + * this projection. + */ + virtual void GetWCS( WCSKeywords& wcs ) const; + + /*! + * + */ + void InitFromRefPoint( double lng0, double lat0, const Optional& phip = Optional() ); + + /*! + * Transforms from celestial coordinates to world coordinates. + */ + virtual bool Direct( DPoint& pW, const DPoint& pRD ) const noexcept + { + DPoint pN = m_sph.CelestialToNative( pRD ); + return IsFinite( pN.x ) && IsFinite( pN.y ) && Project( pW, pN ); + } + + /*! + * Transforms from world coordinates to celestial coordinates. + */ + virtual bool Inverse( DPoint& pRD, const DPoint& pW ) const noexcept + { + DPoint pN; + if ( Unproject( pN, pW ) ) + if ( IsFinite( pN.x ) ) + if ( IsFinite( pN.y ) ) + { + pRD = m_sph.NativeToCelestial( pN ); + return true; + } + return false; + } + + /*! + * + */ + virtual bool CheckBrokenLine( const DPoint& cp1, const DPoint& cp2 ) const noexcept + { + return DistanceFast( m_sph.CelestialToNative( cp1 ), m_sph.CelestialToNative( cp2 ) ) < 150; + } + + /*! + * Returns the equatorial coordinates of the projection origin. + */ + virtual DPoint ProjectionOrigin() const + { + return DPoint( Deg( m_ra0 ), Deg( m_dec0 ) ); + } + + /*! + * Returns the distance in degrees between two locations in equatorial + * coordinates. + */ + static double Distance( const DPoint& p1, const DPoint& p2 ) + { + double sinX, cosX; + SinCos( Rad( Abs( p1.x - p2.x ) ), sinX, cosX ); + double sinY1, cosY1; + SinCos( Rad( p1.y ), sinY1, cosY1 ); + double sinY2, cosY2; + SinCos( Rad( p2.y ), sinY2, cosY2 ); + double K = cosY1*sinY2 - sinY1*cosY2*cosX; + return Deg( ArcTan( Sqrt( cosY2*sinX*cosY2*sinX + K*K ), sinY1*sinY2 + cosY1*cosY2*cosX ) ); + }; + + /*! + * Returns the distance in degrees between two locations in equatorial + * coordinates. Uses an approximate, faster algorithm. + */ + static double DistanceFast( const DPoint& p1, const DPoint& p2 ) + { + double sinY1, cosY1; + SinCos( Rad( p1.y ), sinY1, cosY1 ); + double sinY2, cosY2; + SinCos( Rad( p2.y ), sinY2, cosY2 ); + return Deg( ArcCos( sinY1*sinY2 + cosY1*cosY2*Cos( Rad( p1.x - p2.x ) ) ) ); + } + +protected: + + double m_ra0 = 0; // radians + double m_dec0 = 0; // radians + double m_theta0 = 0; // degrees + double m_phi0 = 0; // degrees + Optional m_lonpole; // degrees + Optional m_latpole; // degrees + SphericalRotation m_sph; + + /*! + * Default constructor. + */ + ProjectionBase() = default; + + /*! + * Copy constructor. + */ + ProjectionBase( const ProjectionBase& ) = default; + + /*! + * Initialization from WCS metadata. + */ + void InitFromWCS( const WCSKeywords& ); + + /*! + * Transforms from world coordinates to native spherical coordinates. + */ + virtual bool Project( DPoint& pW, const DPoint& pN ) const noexcept = 0; + + /*! + * Transforms from native spherical coordinates to world coordinates. + */ + virtual bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept = 0; + + friend class ProjectionFactory; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ProjectionBase_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProjectionBase.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ProjectionFactory.h b/3rdparty/include/pcl/ProjectionFactory.h new file mode 100644 index 0000000..c1fa815 --- /dev/null +++ b/3rdparty/include/pcl/ProjectionFactory.h @@ -0,0 +1,146 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ProjectionFactory.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_ProjectionFactory_h +#define __PCL_ProjectionFactory_h + +/// \file pcl/ProjectionFactory.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ProjectionFactory + * \brief Selectable projection system + * + * %ProjectionFactory implements a projection system that can be selected upon + * construction among all of the projections implemented in the PixInsight/PCL + * platform. + * + * \ingroup astrometry_support + */ +class PCL_CLASS ProjectionFactory +{ +public: + + /*! + * Creates a new projection for the specified WCS projection \a code and + * origin equatorial coordinates \a ra and \a dec in degrees. + * + * The following WCS projection codes are supported in current PCL versions: + * + * TAN\n + * STG\n + * CAR\n + * MER\n + * AIT\n + * ZEA\n + * SIN + * + * The specified WCS projection \a code is case insensitive and can contain + * leading and trailing spaces. + */ + static ProjectionBase* CreateByWCSCode( const IsoString& code, double ra, double dec ); + + static ProjectionBase* CreateByWCSCode( const IsoString::ustring_base& code, double ra, double dec ) + { + return CreateByWCSCode( IsoString( code ), ra, dec ); + } + + /*! + * Creates a new projection for the specified projection \a name and origin + * equatorial coordinates \a ra and \a dec in degrees. + * + * The following projection names are supported in current PCL versions: + * + * Gnomonic\n + * Stereographic\n + * PlateCarree\n + * Mercator\n + * HammerAitoff\n + * ZenithalEqualArea\n + * Orthographic + * + * The specified projection \a name is case insensitive and can contain + * leading and trailing spaces. + */ + static ProjectionBase* CreateByName( const IsoString& name, double ra, double dec ); + + static ProjectionBase* CreateByName( const IsoString::ustring_base& name, double ra, double dec ) + { + return CreateByName( IsoString( name ), ra, dec ); + } + + /*! + * Creates a new projection with data acquired from the specified WCS + * keywords. + */ + static ProjectionBase* Create( const WCSKeywords& wcs ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ProjectionFactory_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ProjectionFactory.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Property.h b/3rdparty/include/pcl/Property.h new file mode 100644 index 0000000..c6a202b --- /dev/null +++ b/3rdparty/include/pcl/Property.h @@ -0,0 +1,278 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Property.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_Property_h +#define __PCL_Property_h + +/// \file pcl/Property.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Property + * \brief An identifier-value association + * + * %Property is a simple identifier-value association, useful to transport + * properties associated with views and images on the PixInsight platform. + * + * The View and FileFormatInstance classes include member functions to generate + * PropertyArray containers, namely View::Properties(), + * FileFormatInstance::ReadProperties() and + * FileFormatInstance::ReadImageProperties(). + */ +class PCL_CLASS Property +{ +public: + + /*! + * Represents the string class used to transport property identifiers. + */ + typedef IsoString identifier_type; + + /*! + * Represents the class used to transport property values. + */ + typedef Variant value_type; + + /*! + * Represents the data type of a property value. + */ + typedef value_type::data_type data_type; + + /*! + * Default constructor. Constructs an invalid %Property object with an empty + * property identifier and an invalid property value. + */ + Property() = default; + + /*! + * Copy constructor. + */ + Property( const Property& ) = default; + + /*! + * Move constructor. + */ + Property( Property&& ) = default; + + /*! + * Constructs a %Property object with the specified property \a identifier + * and property \a value. + */ + Property( const identifier_type& identifier, const value_type& value ) + : m_id( identifier ) + , m_value( value ) + { + } + + /*! + * Constructs a %Property object with the specified property \a identifier + * and an undefined (invalid) property value. + */ + Property( const identifier_type& identifier ) + : m_id( identifier ) + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Property& operator =( const Property& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + Property& operator =( Property&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~Property() + { + } + + /*! + * Returns the property identifier. + */ + const identifier_type& Identifier() const + { + return m_id; + } + + /*! + * Returns the property identifier. This function is a convenience synonym + * for Identifier(). + */ + const identifier_type& Id() const + { + return Identifier(); + } + + /*! + * Returns the property value. + */ + const value_type& Value() const + { + return m_value; + } + + /*! + * Assigns the specified \a value to this property. The previous value will + * be replaced with the new one and hence will be lost. + */ + void SetValue( const value_type& value ) + { + m_value = value; + } + + /*! + * Returns the data type of this property, which is the data type of its + * value. + */ + data_type Type() const + { + return m_value.Type(); + } + + /*! + * Returns a description of this property, including its identifier and + * value data type. + */ + PropertyDescription Description() const + { + return PropertyDescription( m_id, m_value.Type() ); + } + + /*! + * Returns true iff the specified string \a id is a valid property + * identifier. Refer to XISF::IsValidPropertyId() for property identifier + * syntax rules. + */ + static bool IsValidIdentifier( const IsoString& id ) + { + if ( id.IsEmpty() ) + return false; + IsoStringList tokens; + id.Break( tokens, ':' ); + for ( const IsoString& token : tokens ) + if ( !token.IsValidIdentifier() ) + return false; + return true; + } + + static bool IsValidIdentifier( const IsoString::ustring_base& id ) + { + return IsValidIdentifier( IsoString( id ) ); + } + + /*! + * Returns true iff this property is valid. A valid property has a valid + * identifier and a valid value. + */ + bool IsValid() const + { + return IsValidIdentifier( m_id ) && m_value.IsValid(); + } + + /*! + * Equality operator. Returns true iff this property is equal to \a other + * property. + * + * Two %Property objects are equal if their identifiers are equal. Keep in + * mind that this operator compares properties, not their values. + */ + bool operator ==( const Property& other ) const + { + return m_id == other.m_id; + } + + /*! + * Less than operator. Returns true iff this property precedes \a other + * property. + * + * For comparisons of %Property objects, only their identifiers are taken + * into account. Keep in mind that this operator compares properties, not + * their values. + */ + bool operator <( const Property& other ) const + { + return m_id < other.m_id; + } + +protected: + + identifier_type m_id; + value_type m_value; +}; + +/*! + * \class pcl::PropertyArray + * \brief Dynamic array of Property objects + * + * %PropertyArray is a template instantiation of Array<> for Property. + */ +typedef Array PropertyArray; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Property_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Property.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PropertyDescription.h b/3rdparty/include/pcl/PropertyDescription.h new file mode 100644 index 0000000..62e8d73 --- /dev/null +++ b/3rdparty/include/pcl/PropertyDescription.h @@ -0,0 +1,164 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PropertyDescription.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_PropertyDescription_h +#define __PCL_PropertyDescription_h + +/// \file pcl/PropertyDescription.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PropertyDescription + * \brief A structure to describe a data property + * + * This structure is used (instantiated in PropertyDescriptionArray + * containers) by the FileFormatImplementation and FileFormaInstance classes to + * describe data properties stored in image files, among other classes. + * + * \sa FileFormatImplementation, FileFormatInstance + */ +struct PCL_CLASS PropertyDescription +{ + /*! + * An enumeration of supported property data types. + */ + typedef VariantType::value_type data_type; + + IsoString id; //!< Identifier of this property. + data_type type = VariantType::Invalid; //!< Property data type. + + /*! + * Default constructor. Constructs an %PropertyDescription object with + * an empty property identifier and unspecified (invalid) data type. + */ + PropertyDescription() = default; + + /*! + * Constructs an %PropertyDescription object with the specified + * property identifier and data type. + */ + PropertyDescription( const IsoString& s, data_type t = VariantType::Invalid ) + : id( s ) + , type( t ) + { + } + + /*! + * Copy constructor. + */ + PropertyDescription( const PropertyDescription& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PropertyDescription& operator =( const PropertyDescription& ) = default; + + /*! + * Returns true iff this object represents a valid data property. + */ + bool IsValid() const + { + return type != VariantType::Invalid; + } + + /*! + * Less-than relational operator. Returns true if this object precedes the + * specified object \a x; otherwise returns false. + * + * Since property identifiers are unique within a property's scope (within + * an image file, for example), comparisons of %PropertyDescription + * structures only take into account the PropertyDescription::id member. + */ + bool operator <( const PropertyDescription& x ) const + { + return id < x.id; + } + + /*! + * Equality operator. Returns true if this object refers to the same + * property as the specified object \a x; otherwise returns false. + * + * Since property identifiers are unique within a property's scope (within + * an image file, for example), comparisons of %PropertyDescription + * structures only take into account the PropertyDescription::id member. + */ + bool operator ==( const PropertyDescription& x ) const + { + return id == x.id; + } +}; + +/*! + * \class pcl::PropertyDescriptionArray + * \brief Dynamic array of PropertyDescription structures + * + * %PropertyDescriptionArray is a template instantiation of Array for + * PropertyDescription. + */ +typedef Array PropertyDescriptionArray; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PropertyDescription_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PropertyDescription.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PushButton.h b/3rdparty/include/pcl/PushButton.h new file mode 100644 index 0000000..c8facd6 --- /dev/null +++ b/3rdparty/include/pcl/PushButton.h @@ -0,0 +1,136 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PushButton.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_PushButton_h +#define __PCL_PushButton_h + +/// \file pcl/PushButton.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class PushButton + * \brief Client-side interface to a PixInsight %PushButton control. + * + * ### TODO: Write a detailed description for %PushButton + */ +class PCL_CLASS PushButton : public Button +{ +public: + + /*! + * Constructs a %PushButton with the specified \a text and \a icon, as a + * child control of \a parent. + */ + PushButton( const String& text = String(), + const pcl::Bitmap& icon = Bitmap::Null(), + Control& parent = Control::Null() ); + + /*! + * Destroys a %PushButton control. + */ + virtual ~PushButton() + { + } + + /*! + * Returns true, since push buttons are pushable buttons. + */ + bool IsPushable() const override + { + return true; + } + + /*! + * Returns false, since push buttons are not checkable buttons. + */ + bool IsCheckable() const override + { + return false; + } + + /*! + * Returns true iff this button has been selected as the default + * button of its parent dialog. + * + * The default button is activated when the user presses the Return or Enter + * keys while a modal dialog has the keyboard focus (and these keys are not + * captured by other sibling controls). + */ + bool IsDefault() const; + + /*! + * Selectes this button as the default button of its parent dialog. + * If this button is not a child control of a modal dialog, caling this + * member function has no effect. + */ + void SetDefault( bool = true ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_PushButton_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PushButton.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/PyramidalWaveletTransform.h b/3rdparty/include/pcl/PyramidalWaveletTransform.h new file mode 100644 index 0000000..bb88557 --- /dev/null +++ b/3rdparty/include/pcl/PyramidalWaveletTransform.h @@ -0,0 +1,517 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/PyramidalWaveletTransform.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_PyramidalWaveletTransform_h +#define __PCL_PyramidalWaveletTransform_h + +/// \file pcl/PyramidalWaveletTransform.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class WaveletFilter + * \brief Abstract base class of all orthogonal wavelet filters. + * + * ### TODO: Write a detailed description for %WaveletFilter. + * + * \ingroup multiscale_transforms + */ +class PCL_CLASS WaveletFilter +{ +public: + + /*! + * Constructs a default %WaveletFilter object. + */ + WaveletFilter() = default; + + /*! + * Destroys a %WaveletFilter object. + */ + virtual ~WaveletFilter() + { + } + + /*! + * Returns an identifying name for this wavelet filter. + */ + virtual String Name() const = 0; + + /*! + * Performs an in-place one-dimensional wavelet transform. + * + * \param[in,out] f Starting address of the vector to be transformed. + * + * \param n Length of the input vector. + * + * \param inverse True to perform an inverse wavelet transform. False + * (the default value) to perform a direct wavelet + * transform. + */ + template + void operator ()( T* f, size_type n, bool inverse = false ) const + { + Apply( f, n, inverse ); + } + +protected: + + const double* Kc = nullptr; // wavelet filter coefficients + Vector Kr; // transpose of filter coefficients + int N = 0; // number of coefficients + int ioff = 0; + int joff = 0; + + void Initialize() + { + PCL_CHECK( Kc != nullptr && N > 0 ) + Kr = Vector( N ); + for ( int k = 0, sig = -1; k < N; ++k ) + { + Kr[N-1-k] = sig*Kc[k]; + sig = -sig; + } + // ioff = joff = -(N >> 1); + ioff = -2; + joff = -N + 2; + } + +private: + + void Apply( float*, size_type, bool ) const; + void Apply( double*, size_type, bool ) const; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class Daubechies4Filter + * \brief Daubechies-4 wavelet filter. + * \ingroup multiscale_transforms + */ +class PCL_CLASS Daubechies4Filter : public WaveletFilter +{ +public: + + /*! + * Default constructor. + */ + Daubechies4Filter(); + + /*! + */ + String Name() const override + { + return "Daubechies-4"; + } +}; + +extern PCL_DATA Daubechies4Filter Daubechies4; + +// ---------------------------------------------------------------------------- + +/*! + * \class Daubechies6Filter + * \brief Daubechies-6 wavelet filter. + * \ingroup multiscale_transforms + */ +class PCL_CLASS Daubechies6Filter : public WaveletFilter +{ +public: + + /*! + * Default constructor. + */ + Daubechies6Filter(); + + /*! + */ + String Name() const override + { + return "Daubechies-6"; + } +}; + +extern PCL_DATA Daubechies6Filter Daubechies6; + +// ---------------------------------------------------------------------------- + +/*! + * \class Daubechies8Filter + * \brief Daubechies-8 wavelet filter. + * \ingroup multiscale_transforms + */ +class PCL_CLASS Daubechies8Filter : public WaveletFilter +{ +public: + + /*! + * Default constructor. + */ + Daubechies8Filter(); + + /*! + */ + String Name() const override + { + return "Daubechies-8"; + } +}; + +extern PCL_DATA Daubechies8Filter Daubechies8; + +// ---------------------------------------------------------------------------- + +/*! + * \class Daubechies10Filter + * \brief Daubechies-10 wavelet filter. + * \ingroup multiscale_transforms + */ +class PCL_CLASS Daubechies10Filter : public WaveletFilter +{ +public: + + /*! + * Default constructor. + */ + Daubechies10Filter(); + + /*! + */ + String Name() const override + { + return "Daubechies-10"; + } +}; + +extern PCL_DATA Daubechies10Filter Daubechies10; + +// ---------------------------------------------------------------------------- + +/*! + * \class Daubechies12Filter + * \brief Daubechies-12 wavelet filter. + * \ingroup multiscale_transforms + */ +class PCL_CLASS Daubechies12Filter : public WaveletFilter +{ +public: + + /*! + * Default constructor. + */ + Daubechies12Filter(); + + /*! + */ + String Name() const override + { + return "Daubechies-12"; + } +}; + +extern PCL_DATA Daubechies12Filter Daubechies12; + +// ---------------------------------------------------------------------------- + +/*! + * \class Daubechies20Filter + * \brief Daubechies-20 wavelet filter. + * \ingroup multiscale_transforms + */ +class PCL_CLASS Daubechies20Filter : public WaveletFilter +{ +public: + + /*! + * Default constructor. + */ + Daubechies20Filter(); + + /*! + */ + String Name() const override + { + return "Daubechies-20"; + } +}; + +extern PCL_DATA Daubechies20Filter Daubechies20; + +// ---------------------------------------------------------------------------- + +/*! + * \class PyramidalWaveletTransform + * \brief Discrete two-dimensional wavelet transforms by the pyramidal + * algorithms. + * + * \note The dimensions of transformed images must be integer powers of two. + * + * References + * + * Partially based on Numerical Recipes in C, 2nd Ed., by W. H. Press + * et al. + * + * ### TODO: Write a detailed description for %PyramidalWaveletTransform. + * + * \ingroup multiscale_transforms + */ +class PCL_CLASS PyramidalWaveletTransform : public BidirectionalImageTransformation +{ +public: + + /*! + * Default constructor. + * + * \note This constructor yields an uninitialized instance that cannot be + * used prior to initializing it with a reference to a WaveletFilter, which + * will be used as the scaling function of the wavelet transform. + */ + PyramidalWaveletTransform() = default; + + /*! + * Constructs a %PyramidalWaveletTransform instance with the specified + * wavelet filter \a f. + */ + PyramidalWaveletTransform( const WaveletFilter& f ) + : m_scalingFunction( &f ) + { + PCL_CHECK( m_scalingFunction != nullptr ) + } + + /*! + * Copy constructor. + */ + PyramidalWaveletTransform( const PyramidalWaveletTransform& ) = default; + + /*! + * Move constructor. + */ + PyramidalWaveletTransform( PyramidalWaveletTransform&& ) = default; + + /*! + * Destroys this %PyramidalWaveletTransform object. The existing wavelet + * transform is destroyed and deallocated. + */ + virtual ~PyramidalWaveletTransform() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PyramidalWaveletTransform& operator =( const PyramidalWaveletTransform& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PyramidalWaveletTransform& operator =( PyramidalWaveletTransform&& ) = default; + + /*! + * Returns a reference to the scaling function (or + * wavelet filter) used by this wavelet transform. + */ + const WaveletFilter& ScalingFunction() const + { + PCL_PRECONDITION( m_scalingFunction != nullptr ) + return *m_scalingFunction; + } + + /*! + * Sets the scaling function (or wavelet filter) used by + * this wavelet transform. + */ + void SetScalingFunction( const WaveletFilter& f ) + { + Clear(); + m_scalingFunction = &f; + PCL_CHECK( m_scalingFunction != nullptr ) + } + + /*! + * Returns true iff this object applies standard wavelet transforms; + * false if it applies nonstandard wavelet transforms. + */ + bool IsStandard() const + { + return !m_nonstandard; + } + + /*! + * Returns true if this object applies nonstandard wavelet + * transforms; false if it applies nstandard wavelet + * transforms. + * + * This is a convenience member function, equivalent to !IsStandard(). + */ + bool IsNonstandard() const + { + return m_nonstandard; + } + + /*! + * Enables or disables standard wavelet transforms for this + * %PyramidalWaveletTransform object. + * + * Calling this member function implicitly destroys the existing wavelet + * transform. + */ + void SetStandard( bool b = true ) + { + Clear(); + m_nonstandard = !b; + } + + /*! + * Enables or disables nonstandard wavelet transforms for this + * %PyramidalWaveletTransform object. + * + * Calling this member function implicitly destroys the existing wavelet + * transform. + * + * This is a convenience member function, equivalent to SetStandard( !b ). + */ + void SetNonstandard( bool b = true ) + { + Clear(); + m_nonstandard = b; + } + + /*! + * Returns a reference to the wavelet transform in this + * %PyramidalWaveletTransform object. + * + * The returned image is empty if no transform has been performed by this + * %PyramidalWaveletTransform object. + */ + const Image& Transform() const + { + return m_transform; + } + + /*! + * Returns a reference to the wavelet transform in this + * %PyramidalWaveletTransform object. + * + * The returned image is empty if no transform has been performed by this + * %PyramidalWaveletTransform object. + */ + Image& Transform() + { + return m_transform; + } + + /*! + * Destroys and deallocates the existing wavelet transform. + */ + void Clear() + { + m_transform.FreeData(); + } + +protected: + + /* + * Scaling function, or wavelet filter. + */ + const WaveletFilter* m_scalingFunction = nullptr; + + /* + * Flag true if nonstandard transforms are being used. + * Standard transforms are used otherwise (and by default). + */ + bool m_nonstandard = true; + + /* + * Wavelet transform + */ + pcl::Image m_transform; + + void Validate() const; + void DoTransform( StatusMonitor& ); + + // Transform (decomposition) + void Transform( const pcl::Image& ) override; + void Transform( const pcl::DImage& ) override; + void Transform( const pcl::ComplexImage& ) override; + void Transform( const pcl::DComplexImage& ) override; + void Transform( const pcl::UInt8Image& ) override; + void Transform( const pcl::UInt16Image& ) override; + void Transform( const pcl::UInt32Image& ) override; + + // Inverse transform (reconstruction) + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_PyramidalWaveletTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/PyramidalWaveletTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/QuadTree.h b/3rdparty/include/pcl/QuadTree.h new file mode 100644 index 0000000..cda5b4d --- /dev/null +++ b/3rdparty/include/pcl/QuadTree.h @@ -0,0 +1,1453 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/QuadTree.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_QuadTree_h +#define __PCL_QuadTree_h + +/// \file pcl/QuadTree.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * Default bucket capacity for point region quadtree generation. + */ +#define __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY 40 + +/* + * Default minimum allowed dimension of a quadtree node region. + */ +#define __PCL_QUADTREE_DEFAULT_EPSILON 1.0e-08 + +// ---------------------------------------------------------------------------- + +/*! + * \class QuadTree + * \brief Bucket PR quadtree for two-dimensional point data. + * + * A quadtree is a specialized binary search tree for partitioning of a set of + * points in two dimensions. Quadtrees have important applications in + * computational geometry problems requiring efficient rectangular range + * searching and nearest neighbor queries. + * + * This class implements a bucket point region quadtree structure + * (see Reference 2). + * + * The template type argument T represents the type of a \e point object stored + * in a %QuadTree structure. The type T must have the following properties: + * + * \li The standard default and copy constructors are required:\n + * \n + * T::T() \n + * T::T( const T& ) + * + * \li The \c T::component subtype must be defined. It represents a component + * of an object of type T. For example, if T is a vector type, T::component + * must be the type of a vector component. + * + * \li The array subscript operator must be defined as follows:\n + * \n + * component T::operator []( int i ) const \n + * \n + * This operator must return the value of the first or second component of an + * object being stored in the quadtree. The subindex i will be either 0 or 1 + * for the first or second point component, respectively. + * + * \b References + * + * 1. Mark de Berg et al, Computational Geometry: Algorithms and + * Applications Third Edition, Springer, 2010, Chapter 14. + * + * 2. Hanan Samet, Foundations of Multidimensional and Metric Data + * Structures, Morgan Kaufmann, 2006, Section 1.4. + * + * \sa KDTree + */ +template +class QuadTree +{ +public: + + /*! + * Represents a two-dimensional point stored in this quadtree. + */ + typedef T point; + + /*! + * Represents a point component. + */ + typedef typename point::component component; + + /*! + * A list of points. Used for tree build and search operations. + */ + typedef Array point_list; + + /*! + * A rectangular region. Used for rectangular range search operations. + */ + typedef DRect rectangle; + + /*! + * The type of rectangular region coordinates. + */ + typedef rectangle::component coordinate; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::QuadTree::Node + * \brief Quadtree node structure + */ + struct Node + { + rectangle rect = 0.0; //!< The rectangular region represented by this node. + Node* nw = nullptr; //!< North-West child node, representing the top-left subregion. + Node* ne = nullptr; //!< North-East child node, representing the top-right subregion. + Node* sw = nullptr; //!< South-West child node, representing the bottom-left subregion. + Node* se = nullptr; //!< South-East child node, representing the bottom-right subregion. + +#ifdef __PCL_QUADTREE_STRUCTURAL_NODE_HAS_DATA + void* data = nullptr; +#endif + + /*! + * Default constructor. Constructs an uninitialized quadtree node. + */ + Node() = default; + + /*! + * Constructs a quadtree node for the specified rectangular region \a r. + */ + Node( const rectangle& r ) + : rect( r ) + { + } + + /*! + * Returns true iff this is a leaf quadtree node. A leaf node does not + * contain child nodes, that is, there is no further subdivision of the + * domain space beyond a leaf quadtree node. + * + * In a healthy quadtree (as any QuadTree structure should be under + * normal working conditions), you can expect any leaf node to be an + * instance of QuadTree::LeafNode containing a nonempty list of points. + */ + bool IsLeaf() const + { + return nw == nullptr && ne == nullptr && sw == nullptr && se == nullptr; + } + + /*! + * Returns true iff the rectangular region represented by this node + * intersects the specified rectangle \a r. + */ + bool Intersects( const rectangle& r ) const + { + return rect.x1 >= r.x0 && rect.x0 <= r.x1 && + rect.y1 >= r.y0 && rect.y0 <= r.y1; + } + + /*! + * Returns true iff the rectangular region represented by this node + * includes a point in the plane specified by its coordinates \a x, \a y. + */ + bool Includes( coordinate x, coordinate y ) const + { + return x >= rect.x0 && x <= rect.x1 && + y >= rect.y0 && y <= rect.y1; + } + + /*! + * Returns true iff the rectangular region represented by this node + * includes the specified point \a p in the plane. + */ + bool Includes( const rectangle::point& p ) const + { + return Includes( p.x, p.y ); + } + + /*! + * Returns the Northwest (top left) splitting rectangle for this node. + */ + rectangle NWRect() const + { + return rectangle( rect.TopLeft(), rect.Center() ); + } + + /*! + * Returns the Northeast (top right) splitting rectangle for this node. + */ + rectangle NERect() const + { + return rectangle( rect.CenterTop(), rect.CenterRight() ); + } + + /*! + * Returns the Southwest (bottom left) splitting rectangle for this node. + */ + rectangle SWRect() const + { + return rectangle( rect.CenterLeft(), rect.CenterBottom() ); + } + + /*! + * Returns the Southeast (bottom right) splitting rectangle for this + * node. + */ + rectangle SERect() const + { + return rectangle( rect.Center(), rect.BottomRight() ); + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \class pcl::QuadTree::LeafNode + * \brief Quadtree leaf node structure + */ + struct LeafNode : public Node + { + /*! + * The list of points contained by this leaf node. + * + * In a healthy quadtree (as any QuadTree structure should be under + * normal working conditions), every existing leaf node should contain a + * nonempty point list. + */ + point_list points; + +#ifndef __PCL_QUADTREE_STRUCTURAL_NODE_HAS_DATA + + /*! + * Pointer to an arbitrary data structure that can be associated with + * this leaf node. Its default value is \c nullptr. + * + * The quadtree structure does not access this pointer in any way. + * Destruction of the object pointed to by this member, if required, is + * the sole responsibility of the external code that has defined it. + */ + void* data = nullptr; + +#endif + + /*! + * Constructs a new leaf node representing the specified rectangular + * region \a r and storing a nonempty point list \a p. + */ + LeafNode( const rectangle& r, const point_list& p ) + : Node( r ) + , points( p ) + { + PCL_CHECK( !points.IsEmpty() ) + } + + /*! + * Constructs a new leaf node representing the specified rectangular + * region \a r and storing the specified point \a p. + */ + LeafNode( const rectangle& r, const point& p ) + : Node( r ) + { + points << p; + } + + /*! + * Returns the number of points contained by this leaf node. Under normal + * conditions, the returned value must be > 0. + */ + int Length() const + { + return int( points.Length() ); + } + }; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty quadtree. + */ + QuadTree() = default; + + /*! + * Constructs a quadtree and builds it for the specified list of \a points. + * + * \param points A list of points that will be stored in this + * quadtree. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be ≥ 1. The default value is 40. + * + * \param epsilon The minimum allowed dimension of a quadtree node + * region. Must be larger than or equal to twice the + * machine epsilon for the \c coordinate type. The + * default value is 1e-8. + * + * If the specified list of \a points is empty, this constructor yields an + * empty quadtree. + */ + QuadTree( const point_list& points, + int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, + double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON ) + { + Build( points, bucketCapacity, epsilon ); + } + + /*! + * Constructs a quadtree and builds it for the specified list of \a points + * and a prescribed rectangular search region. + * + * \param rect The rectangular search region. + * + * \param points A list of points that will be stored in this + * quadtree. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be ≥ 1. The default value is 40. + * + * \param epsilon The minimum allowed dimension of a quadtree node + * region. Must be larger than or equal to twice the + * machine epsilon for the \c coordinate type. The + * default value is 1e-8. + * + * If the specified list of \a points is empty, or if no points lie within + * the \a rect region, this constructor yields an empty quadtree. + */ + QuadTree( const rectangle& rect, const point_list& points, + int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, + double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON ) + { + Build( rect, points, bucketCapacity, epsilon ); + } + + /*! + * Copy constructor. Copy construction is disabled because this class uses + * internal data structures that cannot be copy-constructed. However, + * %QuadTree implements move construction and move assignment. + */ + QuadTree( const QuadTree& ) = delete; + + /*! + * Copy assignment operator. Copy assignment is disabled because this class + * uses internal data structures that cannot be copy-assigned. However, + * %QuadTree implements move assignment and move construction. + */ + QuadTree& operator =( const QuadTree& ) = delete; + + /*! + * Move constructor. + */ + QuadTree( QuadTree&& x ) + : m_root( x.m_root ) + , m_bucketCapacity( x.m_bucketCapacity ) + , m_epsilon( x.m_epsilon ) + , m_length( x.m_length ) + { + x.m_root = nullptr; + x.m_length = 0; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + QuadTree& operator =( QuadTree&& x ) + { + if ( &x != this ) + { + DestroyTree( m_root ); + m_root = x.m_root; + m_bucketCapacity = x.m_bucketCapacity; + m_epsilon = x.m_epsilon; + m_length = x.m_length; + x.m_root = nullptr; + x.m_length = 0; + } + return *this; + } + + /*! + * Destroys a quadtree. All the stored point objects are deleted. + */ + ~QuadTree() + { + Clear(); + } + + /*! + * Removes all the stored point objects, yielding an empty quadtree. + */ + void Clear() + { + DestroyTree( m_root ); + m_root = nullptr; + m_length = 0; + } + + /*! + * Builds a new quadtree for the specified list of \a points. + * + * \param points A list of points that will be stored in this + * quadtree. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be ≥ 1. The default value is 40. + * + * \param epsilon The minimum allowed dimension of a quadtree node + * region. Must be larger than or equal to twice the + * machine epsilon for the \c coordinate type. The + * default value is 1e-8. + * + * If the tree stores point objects before calling this function, they are + * destroyed and removed before building a new tree. + * + * If the specified list of \a points is empty, this member function yields + * an empty quadtree. + */ + void Build( const point_list& points, + int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, + double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON ) + { + Clear(); + m_bucketCapacity = Max( 1, bucketCapacity ); + m_epsilon = Max( 2*std::numeric_limits::epsilon(), epsilon ); + + if ( !points.IsEmpty() ) + { + component x = points[0][0]; + component y = points[0][1]; + rectangle rect( x, y, x, y ); + for ( const point& p : points ) + { + x = p[0]; + y = p[1]; + if ( x < rect.x0 ) + rect.x0 = x; + if ( y < rect.y0 ) + rect.y0 = y; + if ( x > rect.x1 ) + rect.x1 = x; + if ( y > rect.y1 ) + rect.y1 = y; + } + m_root = BuildTree( rect, points ); + } + } + + /*! + * Builds a new quadtree with the specified list of \a points and a + * prescribed rectangular search region. + * + * \param rect The rectangular search region. + * + * \param points A list of points to be stored in this quadtree. + * Only points included in the specified \a rect + * search region will be inserted in the tree. + * All points outside \a rect will be ignored. + * + * \param bucketCapacity The maximum number of points in a leaf tree node. + * Must be ≥ 1. The default value is 40. + * + * \param epsilon The minimum allowed dimension of a quadtree node + * region. Must be larger than or equal to twice the + * machine epsilon for the \c coordinate type. The + * default value is 1e-8. + * + * If the tree stores point objects before calling this function, they are + * destroyed and removed before building a new tree. + * + * If the specified list of \a points is empty, or if no points lie within + * the \a rect region, this member function yields an empty quadtree. + */ + void Build( const rectangle& rect, const point_list& points, + int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, + double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON ) + { + Clear(); + m_bucketCapacity = Max( 1, bucketCapacity ); + m_epsilon = Max( 2*std::numeric_limits::epsilon(), epsilon ); + if ( !points.IsEmpty() ) + m_root = BuildTree( rect.Ordered(), points ); + } + + /*! + * Performs a rectangular range search in this quadtree. + * + * \param rect The rectangular search region. + * + * Returns a (possibly empty) list with all the points found in this tree + * within the specified search range. + */ + point_list Search( const rectangle& rect ) const + { + point_list found; + SearchTree( found, rect.Ordered(), m_root ); + return found; + } + + /*! + * Performs a rectangular range search in this quadtree. + * + * \param rect The rectangular search region. + * + * \param callback Callback functional. + * + * \param data Callback data. + * + * The callback function prototype should be: + * + * \code void callback( const point& pt, void* data ) \endcode + * + * The callback function will be called once for each point found in the + * tree within the specified search range. + */ + template + void Search( const rectangle& rect, F callback, void* data ) const + { + SearchTree( rect.Ordered(), callback, data, m_root ); + } + + /*! + * Inserts a point in this quadtree. + */ + void Insert( const point& pt ) + { + if ( m_root != nullptr ) + InsertTree( pt, m_root ); + else + { + component x = pt[0]; + component y = pt[1]; + m_root = new LeafNode( rectangle( x, y, x, y ), pt ); + } + } + + /*! + * Deletes all points in this quadtree equal to the specified point. + */ + void Delete( const point& pt ) + { + DeleteTree( pt, m_root ); + } + + /*! + * Deletes all points in this quadtree included in the specified rectangular + * region \a rect. + */ + void Delete( const rectangle& rect ) + { + DeleteTree( rect.Ordered(), m_root ); + } + + /*! + * Returns the bucket capacity of this quadtree, or the maximum number of + * points that can be stored in a leaf tree node. This parameter is + * specified when a new tree is built. + */ + int BucketCapacity() const + { + return m_bucketCapacity; + } + + /*! + * Returns the total number of points stored in this quadtree. + */ + size_type Length() const + { + return m_length; + } + + /*! + * Returns true iff this quadtree is empty. + */ + bool IsEmpty() const + { + return m_root == nullptr; + } + + /*! + * Returns a pointer to the root node of this quadtree, or nullptr if this + * quadtree is empty. + * + * The returned pointer is const qualified to forbid uncontrolled + * alterations that might invalidate the quadtree structure. + */ + const Node* Root() const + { + return m_root; + } + + /*! + * Returns a pointer to the (mutable) root node of this quadtree, or nullptr + * if this quadtree is empty. + */ + Node* Root() + { + return m_root; + } + + /*! + * Returns a pointer to the (immutable) leaf node of this quadtree that + * includes the specified point \a p in the plane, or nullptr if no such + * leaf node exists in this quadtree. + */ + const LeafNode* LeafNodeAt( rectangle::point p ) const + { + return SearchLeafNode( p, m_root ); + } + + /*! + * Returns a pointer to the leaf node of this quadtree that includes the + * specified point \a p in the plane, or nullptr if no such leaf node exists + * in this quadtree. + */ + LeafNode* LeafNodeAt( rectangle::point p ) + { + return SearchLeafNode( p, m_root ); + } + + /*! + * Returns a pointer to the (immutable) node of this quadtree that includes + * the specified point \a p in the plane, or nullptr if no such node exists + * in this quadtree. + * + * The returned node can be a leaf node or a structural node. This function + * should only return nullptr if the specified point \a p is exterior to the + * root rectangular region of this quadtree, or if this quadtree is empty. + */ + const Node* NodeAt( rectangle::point p ) const + { + return SearchNode( p, m_root ); + } + + /*! + * Returns a pointer to the node of this quadtree that includes the + * specified point \a p in the plane, or nullptr if no such node exists in + * this quadtree. + * + * The returned node can be a leaf node or a structural node. This function + * should only return nullptr if the specified point \a p is exterior to the + * root rectangular region of this quadtree, or if this quadtree is empty. + */ + Node* NodeAt( rectangle::point p ) + { + return SearchNode( p, m_root ); + } + + /*! + * Forces a quadtree subdivision of the leaf node that includes the + * specified point \a p in the plane. + * + * Returns the newly created structural node. This function should only + * return nullptr if the specified point \a p is exterior to the root + * rectangular region of this quadtree, or if this quadtree is empty. It + * could also return nullptr in degenerate cases where no further + * subdivision of the plane would be possible because of numerical limits. + */ + Node* SplitAt( rectangle::point p ) + { + Node* node = SearchDeepestStructuralNodeAt( p, m_root ); + if ( node != nullptr ) + { + Node** leaf = nullptr; + if ( node->nw != nullptr && node->nw->Includes( p ) ) + leaf = &node->nw; + else if ( node->ne != nullptr && node->ne->Includes( p ) ) + leaf = &node->ne; + else if ( node->sw != nullptr && node->sw->Includes( p ) ) + leaf = &node->sw; + else if ( node->se != nullptr && node->se->Includes( p ) ) + leaf = &node->se; + + if ( leaf != nullptr ) // cannot be false! + { + Node* newNode = SplitLeafNode( *leaf ); + if ( newNode != nullptr ) // should be true + { + delete static_cast( *leaf ); + *leaf = newNode; + } + return newNode; + } + } + + return nullptr; + } + + /*! + * Performs a recursive left-to-right, depth-first traversal of the subtree + * rooted at the specified \a node, invoking the specified function \a f + * successively for each leaf node. + * + * The function \a f must be compatible with the form: + * + * \code void f( const rectangle& r, const point_list& p, void*& d ) \endcode + * + * where \a r is the plane region covered by the current leaf node, \a p is + * the list of points in the current leaf node, and \a d is the optional + * pointer to arbitrary data associated with the current leaf node. + * + * The sequence of calls for the subtrees in each non-leaf node is: NW, NE, + * SW, SE. Only non-empty leaf nodes are included in the traversal, hence + * the function \a f will be invoked exclusively for non-empty point lists. + * + * If the specified \a node is nullptr, this function takes no action. + */ + template + static void Traverse( const Node* node, F f ) + { + if ( node != nullptr ) + if ( node->IsLeaf() ) + f( node->rect, + static_cast( node )->points, + static_cast( node )->data ); + else + { + Traverse( node->nw, f ); + Traverse( node->ne, f ); + Traverse( node->sw, f ); + Traverse( node->se, f ); + } + } + + /*! + * Performs a recursive left-to-right, depth-first traversal of the subtree + * rooted at the specified (mutable) \a node, invoking the specified + * function \a f successively for each leaf node. + * + * The function \a f must be compatible with the form: + * + * \code void f( const rectangle& r, point_list& p, void*& d ) \endcode + * + * where \a r is the plane region covered by the current leaf node, \a p is + * the list of points in the current leaf node, and \a d is the optional + * pointer to arbitrary data associated with the current leaf node. + * + * The sequence of calls for the subtrees in each non-leaf node is: NW, NE, + * SW, SE. Only non-empty leaf nodes are included in the traversal, hence + * the function \a f will be invoked exclusively for non-empty point lists. + * + * If the specified \a node is nullptr, this function takes no action. + */ + template + static void Traverse( Node* node, F f ) + { + if ( node != nullptr ) + if ( node->IsLeaf() ) + f( node->rect, static_cast( node )->points, + static_cast( node )->data ); + else + { + Traverse( node->nw, f ); + Traverse( node->ne, f ); + Traverse( node->sw, f ); + Traverse( node->se, f ); + } + } + + /*! + * Performs a recursive left-to-right, depth-first traversal of the entire + * quadtree, invoking the specified function \a f successively for each leaf + * node. Calling this function is equivalent to: + * + * \code Traverse( Root(), f ) \endcode + * + * If this quadtree is empty, this function takes no action. + */ + template + void Traverse( F f ) const + { + Traverse( m_root, f ); + } + + /*! + * Performs a recursive left-to-right, depth-first traversal of the entire + * (mutable) quadtree, invoking the specified function \a f successively for + * each leaf node. Calling this function is equivalent to: + * + * \code Traverse( Root(), f ) \endcode + * + * If this quadtree is empty, this function takes no action. + */ + template + void Traverse( F f ) + { + Traverse( m_root, f ); + } + + /*! + * Returns the total number of existing nodes in the subtree rooted at the + * specified \a node, including structural and leaf nodes. + */ + static size_type NumberOfNodes( const Node* node ) + { + size_type N = 0; + GetNumberOfNodes( N, node ); + return N; + } + + /*! + * Returns the total number of existing nodes in this quadtree, including + * structural and leaf nodes. + */ + size_type NumberOfNodes() const + { + return NumberOfNodes( m_root ); + } + + /*! + * Returns the total number of existing leaf nodes in the subtree rooted at + * the specified \a node. + */ + static size_type NumberOfLeafNodes( const Node* node ) + { + size_type N = 0; + GetNumberOfLeafNodes( N, node ); + return N; + } + + /*! + * Returns the total number of existing leaf nodes in this quadtree. + */ + size_type NumberOfLeafNodes() const + { + return NumberOfLeafNodes( m_root ); + } + + /*! + * Returns the height of the subtree rooted at the specified \a node. + */ + static int Height( const Node* node ) + { + return TreeHeight( node, 0 ); + } + + /*! + * Returns the height of this quadtree. + */ + int Height() const + { + return Height( m_root ); + } + + /*! + * Exchanges two %QuadTree objects \a x1 and \a x2. + */ + friend void Swap( QuadTree& x1, QuadTree& x2 ) + { + pcl::Swap( x1.m_root, x2.m_root ); + pcl::Swap( x1.m_bucketCapacity, x2.m_bucketCapacity ); + pcl::Swap( x1.m_epsilon, x2.m_epsilon ); + pcl::Swap( x1.m_length, x2.m_length ); + } + +private: + + Node* m_root = nullptr; + int m_bucketCapacity = 0; + double m_epsilon = 0; + size_type m_length = 0; + + Node* NewLeafNode( const rectangle& rect, const point_list& points ) + { + m_length += points.Length(); + return new LeafNode( rect, points ); + } + + LeafNode* SearchLeafNode( const rectangle::point& p, const Node* node ) const + { + if ( node != nullptr ) + if ( node->Includes( p ) ) + { + if ( node->IsLeaf() ) + return const_cast( static_cast( node ) ); + + LeafNode* child = SearchLeafNode( p, node->nw ); + if ( child == nullptr ) + { + child = SearchLeafNode( p, node->ne ); + if ( child == nullptr ) + { + child = SearchLeafNode( p, node->sw ); + if ( child == nullptr ) + child = SearchLeafNode( p, node->se ); + } + } + return child; + } + + return nullptr; + } + + Node* SearchNode( const rectangle::point& p, const Node* node ) const + { + if ( node != nullptr ) + if ( node->Includes( p ) ) + { + if ( node->IsLeaf() ) + return const_cast( node ); + + Node* child = SearchNode( p, node->nw ); + if ( child == nullptr ) + { + child = SearchNode( p, node->ne ); + if ( child == nullptr ) + { + child = SearchNode( p, node->sw ); + if ( child == nullptr ) + { + child = SearchNode( p, node->se ); + if ( child == nullptr ) + return const_cast( node ); + } + } + } + return child; + } + + return nullptr; + } + + Node* SearchDeepestStructuralNodeAt( const rectangle::point& p, const Node* node ) const + { + if ( node != nullptr ) + if ( !node->IsLeaf() ) + if ( node->Includes( p ) ) + { + Node* child = SearchDeepestStructuralNodeAt( p, node->nw ); + if ( child == nullptr ) + { + child = SearchDeepestStructuralNodeAt( p, node->ne ); + if ( child == nullptr ) + { + child = SearchDeepestStructuralNodeAt( p, node->sw ); + if ( child == nullptr ) + { + child = SearchDeepestStructuralNodeAt( p, node->se ); + if ( child == nullptr ) + return const_cast( node ); + } + } + } + return child; + } + + return nullptr; + } + + Node* BuildTree( const rectangle& rect, const point_list& points ) + { + if ( points.IsEmpty() ) + return nullptr; + + if ( points.Length() <= size_type( m_bucketCapacity ) ) + return NewLeafNode( rect, points ); + + double x2 = (rect.x0 + rect.x1)/2; + double y2 = (rect.y0 + rect.y1)/2; + // Prevent geometrically degenerate subtrees. For safety, we enforce + // minimum region dimensions larger than twice the machine epsilon for + // the rectangle coordinate type. + if ( x2 - rect.x0 < m_epsilon || rect.x1 - x2 < m_epsilon || + y2 - rect.y0 < m_epsilon || rect.y1 - y2 < m_epsilon ) + { + return NewLeafNode( rect, points ); + } + + point_list nw, ne, sw, se; + for ( const point& p : points ) + { + component x = p[0]; + component y = p[1]; + if ( x <= x2 ) + { + if ( y <= y2 ) + nw << p; + else + sw << p; + } + else + { + if ( y <= y2 ) + ne << p; + else + se << p; + } + } + + Node* node = new Node( rect ); + node->nw = BuildTree( rectangle( rect.x0, rect.y0, x2, y2 ), nw ); + node->ne = BuildTree( rectangle( x2, rect.y0, rect.x1, y2 ), ne ); + node->sw = BuildTree( rectangle( rect.x0, y2, x2, rect.y1 ), sw ); + node->se = BuildTree( rectangle( x2, y2, rect.x1, rect.y1 ), se ); + + // Further degeneracies may result, e.g. if the point class is not + // behaving as expected. Do not allow them. + if ( node->IsLeaf() ) + { + delete node; + return NewLeafNode( rect, points ); + } + + return node; + } + + Node* SplitLeafNode( const Node* node ) + { + if ( node == nullptr || !node->IsLeaf() ) + return nullptr; + + double x2 = (node->rect.x0 + node->rect.x1)/2; + double y2 = (node->rect.y0 + node->rect.y1)/2; + // Prevent geometrically degenerate subtrees. For safety, we enforce + // minimum region dimensions larger than twice the machine epsilon for + // the rectangle coordinate type. + if ( x2 - node->rect.x0 < m_epsilon || node->rect.x1 - x2 < m_epsilon || + y2 - node->rect.y0 < m_epsilon || node->rect.y1 - y2 < m_epsilon ) + { + return nullptr; + } + + const LeafNode* leaf = static_cast( node ); + point_list nw, ne, sw, se; + for ( const point& p : leaf->points ) + { + component x = p[0]; + component y = p[1]; + if ( x <= x2 ) + { + if ( y <= y2 ) + nw << p; + else + sw << p; + } + else + { + if ( y <= y2 ) + ne << p; + else + se << p; + } + } + + size_type savedLength = m_length; + Node* newNode = new Node( node->rect ); + newNode->nw = BuildTree( rectangle( node->rect.x0, node->rect.y0, x2, y2 ), nw ); + newNode->ne = BuildTree( rectangle( x2, node->rect.y0, node->rect.x1, y2 ), ne ); + newNode->sw = BuildTree( rectangle( node->rect.x0, y2, x2, node->rect.y1 ), sw ); + newNode->se = BuildTree( rectangle( x2, y2, node->rect.x1, node->rect.y1 ), se ); + m_length = savedLength; + + // Further degeneracies may result, e.g. if the point class is not + // behaving as expected. Do not allow them. + if ( newNode->IsLeaf() ) + { + delete newNode; + return nullptr; + } + + return newNode; + } + + void SearchTree( point_list& found, const rectangle& rect, const Node* node ) const + { + if ( node != nullptr ) + if ( node->Intersects( rect ) ) + if ( node->IsLeaf() ) + { + const LeafNode* leaf = static_cast( node ); + for ( const point& p : leaf->points ) + { + component x = p[0]; + if ( x >= rect.x0 ) + if ( x <= rect.x1 ) + { + component y = p[1]; + if ( y >= rect.y0 ) + if ( y <= rect.y1 ) + found << p; + } + } + } + else + { + SearchTree( found, rect, node->nw ); + SearchTree( found, rect, node->ne ); + SearchTree( found, rect, node->sw ); + SearchTree( found, rect, node->se ); + } + } + + template + void SearchTree( const rectangle& rect, F callback, void* data, const Node* node ) const + { + if ( node != nullptr ) + if ( node->Intersects( rect ) ) + if ( node->IsLeaf() ) + { + const LeafNode* leaf = static_cast( node ); + for ( const point& p : leaf->points ) + { + component x = p[0]; + if ( x >= rect.x0 ) + if ( x <= rect.x1 ) + { + component y = p[1]; + if ( y >= rect.y0 ) + if ( y <= rect.y1 ) + callback( p, data ); + } + } + } + else + { + SearchTree( rect, callback, data, node->nw ); + SearchTree( rect, callback, data, node->ne ); + SearchTree( rect, callback, data, node->sw ); + SearchTree( rect, callback, data, node->se ); + } + } + + void InsertTree( const point& pt, Node*& node ) + { + PCL_CHECK( node != nullptr ) + + component x = pt[0]; + component y = pt[1]; + + if ( x < node->rect.x0 ) + node->rect.x0 = x; + else if ( x > node->rect.x1 ) + node->rect.x1 = x; + + if ( y < node->rect.y0 ) + node->rect.y0 = y; + else if ( y > node->rect.y1 ) + node->rect.y1 = y; + + if ( node->IsLeaf() ) + { + LeafNode* leaf = static_cast( node ); + if ( leaf->Length() < m_bucketCapacity ) + leaf->points << pt; + else + { + rectangle rect = leaf->rect; + double x2 = (rect.x0 + rect.x1)/2; + double y2 = (rect.y0 + rect.y1)/2; + // Prevent geometrically degenerate subtrees. For safety, we + // enforce minimum region dimensions larger than twice the + // machine epsilon for the rectangle coordinate type. + if ( x2 - rect.x0 < m_epsilon || rect.x1 - x2 < m_epsilon || + y2 - rect.y0 < m_epsilon || rect.y1 - y2 < m_epsilon ) + { + leaf->points << pt; + } + else + { + point_list nw, ne, sw, se; + for ( const point& p : leaf->points ) + { + component x = p[0]; + component y = p[1]; + if ( x <= x2 ) + { + if ( y <= y2 ) + nw << p; + else + sw << p; + } + else + { + if ( y <= y2 ) + ne << p; + else + se << p; + } + } + + if ( x <= x2 ) + { + if ( y <= y2 ) + nw << pt; + else + sw << pt; + } + else + { + if ( y <= y2 ) + ne << pt; + else + se << pt; + } + + delete leaf; + + node = new Node( rect ); + + if ( !nw.IsEmpty() ) + node->nw = new LeafNode( rectangle( rect.x0, rect.y0, x2, y2 ), nw ); + if ( !ne.IsEmpty() ) + node->ne = new LeafNode( rectangle( x2, rect.y0, rect.x1, y2 ), ne ); + if ( !sw.IsEmpty() ) + node->sw = new LeafNode( rectangle( rect.x0, y2, x2, rect.y1 ), sw ); + if ( !se.IsEmpty() ) + node->se = new LeafNode( rectangle( x2, y2, rect.x1, rect.y1 ), se ); + } + } + + ++m_length; + } + else + { + rectangle rect = node->rect; + double x2 = (rect.x0 + rect.x1)/2; + double y2 = (rect.y0 + rect.y1)/2; + if ( pt[0] <= x2 ) + { + if ( pt[1] <= y2 ) + { + if ( node->nw == nullptr ) + node->nw = new LeafNode( rectangle( rect.x0, rect.y0, x2, y2 ), pt ); + else + InsertTree( pt, node->nw ); + } + else + { + if ( node->sw == nullptr ) + node->sw = new LeafNode( rectangle( rect.x0, y2, x2, rect.y1 ), pt ); + else + InsertTree( pt, node->sw ); + } + } + else + { + if ( pt[1] <= y2 ) + { + if ( node->ne == nullptr ) + node->ne = new LeafNode( rectangle( x2, rect.y0, rect.x1, y2 ), pt ); + else + InsertTree( pt, node->ne ); + } + else + { + if ( node->se == nullptr ) + node->se = new LeafNode( rectangle( x2, y2, rect.x1, rect.y1 ), pt ); + else + InsertTree( pt, node->se ); + } + } + } + } + + void DeleteTree( const rectangle& rect, Node*& node ) + { + if ( node != nullptr ) + if ( node->Intersects( rect ) ) + { + if ( node->IsLeaf() ) + { + LeafNode* leaf = static_cast( node ); + point_list points; + for ( const point& p : leaf->points ) + { + component x = p[0]; + if ( x >= rect.x0 ) + if ( x <= rect.x1 ) + { + component y = p[1]; + if ( y >= rect.y0 ) + if ( y <= rect.y1 ) + { + --m_length; + continue; + } + } + points << p; + } + + if ( points.IsEmpty() ) + { + delete leaf; + node = nullptr; + } + else + leaf->points = points; + } + else + { + DeleteTree( rect, node->nw ); + DeleteTree( rect, node->ne ); + DeleteTree( rect, node->sw ); + DeleteTree( rect, node->se ); + + if ( node->IsLeaf() ) + { + delete node; + node = nullptr; + } + } + } + } + + void DeleteTree( const point& pt, Node*& node ) + { + if ( node != nullptr ) + { + component x = pt[0]; + component y = pt[1]; + if ( node->Includes( x, y ) ) + if ( node->IsLeaf() ) + { + LeafNode* leaf = static_cast( node ); + point_list points; + for ( const point& p : leaf->points ) + { + if ( p[0] == x ) + if ( p[1] == y ) + { + --m_length; + continue; + } + points << p; + } + + if ( points.IsEmpty() ) + { + delete leaf; + node = nullptr; + } + else + leaf->points = points; + } + else + { + DeleteTree( pt, node->nw ); + DeleteTree( pt, node->ne ); + DeleteTree( pt, node->sw ); + DeleteTree( pt, node->se ); + + if ( node->IsLeaf() ) + { + delete node; + node = nullptr; + } + } + } + } + + void DestroyTree( Node* node ) + { + if ( node != nullptr ) + if ( node->IsLeaf() ) + delete static_cast( node ); + else + { + DestroyTree( node->nw ); + DestroyTree( node->ne ); + DestroyTree( node->sw ); + DestroyTree( node->se ); + delete node; + } + } + + static void GetNumberOfNodes( size_type& N, const Node* node ) + { + if ( node != nullptr ) + { + ++N; + GetNumberOfNodes( N, node->nw ); + GetNumberOfNodes( N, node->ne ); + GetNumberOfNodes( N, node->sw ); + GetNumberOfNodes( N, node->se ); + } + } + + static void GetNumberOfLeafNodes( size_type& N, const Node* node ) + { + if ( node != nullptr ) + { + if ( node->IsLeaf() ) + ++N; + GetNumberOfLeafNodes( N, node->nw ); + GetNumberOfLeafNodes( N, node->ne ); + GetNumberOfLeafNodes( N, node->sw ); + GetNumberOfLeafNodes( N, node->se ); + } + } + + static int TreeHeight( const Node* node, int h ) + { + if ( node == nullptr ) + return h; + return h + 1 + Max( Max( Max( TreeHeight( node->nw, h ), + TreeHeight( node->ne, h ) ), + TreeHeight( node->sw, h ) ), + TreeHeight( node->se, h ) ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_QuadTree_h + +// ---------------------------------------------------------------------------- +// EOF pcl/QuadTree.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/RGBColorSystem.h b/3rdparty/include/pcl/RGBColorSystem.h new file mode 100644 index 0000000..23ce26b --- /dev/null +++ b/3rdparty/include/pcl/RGBColorSystem.h @@ -0,0 +1,1587 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/RGBColorSystem.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_RGBColorSystem_h +#define __PCL_RGBColorSystem_h + +/// \file pcl/RGBColorSystem.h + +#include + +#include +#include +#include + +#define _1_3 3.333333333333333e-01 // 1/3 +#define _1_6 1.666666666666667e-01 // 1/6 +#define _2_3 6.666666666666667e-01 // 2/3 +#define _16_116 1.379310344827586e-01 // 16/116 +#define CIEEpsilon 8.856451679035631e-03 // 216/24389 +#define CIEKappa 9.032962962962963e+02 // 24389/27 +#define CIEKappa116 7.787037037037037e+00 // CIEKappa/116 +#define sRGBEpsilon 0.04045 +#define sRGBEpsilonInv 0.0031308 +#define sRGBGamma 2.4 +#define sRGBGammaInv 4.166666666666667e-01 //1/sRGBGamma + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class RGBColorSystem + * \brief A colorimetrically defined RGB working color space. + * + * %RGBColorSystem is a rigorous and efficient implementation of a RGB working + * space (RGBWS). This class provides all conversions between the supported + * color spaces: RGB, CIE XYZ, CIE L*a*b*, CIE L*c*h* and grayscale, plus the + * HSV and HSI color ordering systems, which are also supported for + * convenience, although obviously not linked to any particular RGBWS. + * + * Color components and channel values are represented as reals by means of + * \c double floating point variables. Normalization of components and channel + * values to the standard real range [0,1] is ensured for all supported color + * spaces and color ordering systems. + * + * Chrominance coordinates and luminance coefficients are always considered + * relative to the D50 reference white, in conformance to the ICC standard. + * + * Finally, our implementation maximizes dynamic range usage (coding + * efficiency) by ensuring that all components and channel values make use of + * the entire [0,1] normalized real range to the maximum possible extent. + * + * \sa ImageColor, AbstractImage, GenericImage, ImageVariant + */ +class PCL_CLASS RGBColorSystem +{ +public: + + /*! + * The type used to represent components and channel values for all + * supported color spaces and color ordering systems. + */ + typedef double sample; + + /*! + * Constructs a %RGBColorSystem object as a new instance of the default RGB + * working space. The default RGBWS is sRGB in current versions of the + * PixInsight platform. + * + * This constructor increments the reference counter of the source RGB + * working space data. + */ + RGBColorSystem() + : m_data( RGBColorSystem::sRGB.m_data ) + { + if ( m_data != nullptr ) + m_data->Attach(); + else + m_data = new Data( 2.2F/*gamma*/, true/*issRGB*/, sRGB_x, sRGB_y, sRGB_Y ); + } + + /*! + * Constructs a %RGBColorSystem object as a copy of an existing instance. + * + * This constructor increments the reference counter of the source RGB + * working space data. + */ + RGBColorSystem( const RGBColorSystem& s ) + : m_data( s.m_data ) + { + m_data->Attach(); + } + + /*! + * Constructs a new %RGBColorSystem instance by its RGB working space + * parameters. + * + * \param gamma Gamma value of the RGB working space. + * + * \param issRGB If true, this space uses the sRGB gamma function. If this + * parameter is false, the space uses a standard raise gamma + * function. + * + * \param x,y Vectors of chromaticity coordinates of the RGB working + * space, relative to the D50 reference white. + * + * \param Y Vector of luminance coefficients of the RGB working space, + * with respect to the D50 reference white. + * + * This constructor creates a new RGB working space data object with a + * reference count value of one. + */ + RGBColorSystem( float gamma, bool issRGB, const FVector& x, const FVector& y, const FVector& Y ) + { + m_data = new Data( gamma, issRGB, x, y, Y ); + } + + /*! + * Constructs a new %RGBColorSystem instance by its RGB working space + * parameters. + * + * \param gamma Gamma value of the RGB working space. + * + * \param issRGB If true, this space uses the sRGB gamma function. If this + * parameter is false, the space uses a standard raise gamma + * function. + * + * \param x,y Arrays of chromaticity coordinates of the RGB working + * space, relative to the D50 reference white. + * + * \param Y Arrays of luminance coefficients of the RGB working space, + * with respect to the D50 reference white. + * + * This constructor creates a new RGB working space data object with a + * reference count value of one. + */ + RGBColorSystem( float gamma, bool issRGB, const float* x, const float* y, const float* Y ) + { + m_data = new Data( gamma, issRGB, FVector( x, 3 ), FVector( y, 3 ), FVector( Y, 3 ) ); + } + + /*! + * Destroys a %RGBColorSystem instance. + * + * Decrements the reference count of the RGB working space data object. If + * the data object becomes \e garbage, i.e. if its reference count becomes + * zero, it is destroyed and its allocated space is disposed. + */ + virtual ~RGBColorSystem() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + /*! + * Returns true iff this %RGBColorSystem object uniquely references its RGB + * working space data. + */ + bool IsUnique() const + { + return m_data->IsUnique(); + } + + /*! + * Returns true iff this %RGBColorSystem object is an alias of another + * %RGBColorSystem instance \a s. + * + * Two instances of %RGBColorSystem are aliases if both share the same RGB + * working space data. + */ + bool IsAliasOf( const RGBColorSystem& s ) const + { + return m_data == s.m_data; + } + + /*! + * Ensures that this %RGBColorSystem object uniquely references its RGB + * working space data. + * + * If necessary, this member function generates a duplicate of the RGB + * working space data, references it, and then decrements the reference + * counter of the original data. + */ + void EnsureUnique() + { + if ( !IsUnique() ) + { + Data* newData = new Data( *m_data ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the gamma value of this RGB working space. + * + * \note If this space uses a sRGB gamma function, the returned value is + * 2.2, but the space doesn't use that value as the exponent of a standard + * raise gamma function. + */ + float Gamma() const + { + return m_data->gamma; + } + + /*! + * Returns true iff this space uses a sRGB gamma function. + */ + bool IsSRGB() const + { + return m_data->issRGB; + } + + /*! + * Returns true iff this space uses a linear gamma function. + * + * A linear RGB space has gamma=1 and doesn't use a sRGB gamma function. + */ + bool IsLinear() const + { + return m_data->isLinear; + } + + /*! + * Returns a reference to a vector with the elements of the immutable 3x3 + * RGB to CIE XYZ conversion matrix used in this RGB working space. + * + * The RGB->XYZ conversion matrix is a function of the luminance + * coefficients and chromaticity coordinates that define this RGB color + * space. + * + * The nine matrix elements are stored contiguously in row order in the + * returned vector: M[0][0], M[0][1], ..., M[2][2]. + */ + const Vector& RGBToXYZMatrix() const + { + return m_data->M; + } + + /*! + * Returns a reference to a vector with the elements of the immutable 3x3 + * CIE XYZ to RGB inverse conversion matrix used in this RGB working space. + * + * The XYZ->RGB inverse conversion matrix is a function of the luminance + * coefficients and chromaticity coordinates that define this RGB color + * space. + * + * The nine inverse matrix elements are stored contiguously in row order in + * the returned vector: M_[0][0], M_[0][1], ..., M_[2][2]. + */ + const Vector& XYZToRGBMatrix() const + { + return m_data->M_; + } + + /*! + * Returns a reference to the immutable vector of X chromaticity coordinates + * in this RGB working space. + * + * In PCL, chromaticity coordinates are relative to the D50 reference white. + */ + const FVector& ChromaticityXCoordinates() const + { + return m_data->x; + } + + /*! + * Returns a reference to the immutable vector of Y chromaticity coordinates + * in this RGB working space. + * + * In PCL, chromaticity coordinates are relative to the D50 reference white. + */ + const FVector& ChromaticityYCoordinates() const + { + return m_data->y; + } + + /*! + * Returns a reference to the immutable vector of luminance coefficients in + * this RGB working space. + * + * In PCL, luminance coefficients are relative to the D50 reference white. + */ + const FVector& LuminanceCoefficients() const + { + return m_data->Y; + } + + /*! + * Returns true iff two %RGBColorSystem instances define the same RGB working + * space. This happens when either both instances are aliases, or if they + * define exactly the same RGB space parameters. + */ + friend bool operator ==( const RGBColorSystem& S1, const RGBColorSystem& S2 ) + { + return S1.IsAliasOf( S2 ) || *S1.m_data == *S2.m_data; + } + + /*! + * Causes this %RGBColorSystem instance to reference the same RGB working + * space as another instance. + * + * The reference count of the previously referenced space is decremented, + * and the previous space is deleted if it becomes unreferenced. The + * reference count of the new space is then incremented. + */ + void Assign( const RGBColorSystem& s ) + { + s.m_data->Attach(); + DetachFromData(); + m_data = s.m_data; + } + + /*! + * Assignment iterator. Returns a reference to this object. + * + * This operator calls Assign() with the specified source space \a s. + */ + RGBColorSystem& operator =( const RGBColorSystem& s ) + { + Assign( s ); + return *this; + } + + /*! + * Returns the lightness component in the CIE L*a*b* space corresponding to + * a set of specified RGB components. + * + * \param R,G,B RGB components from which lightness will be calculated. + * + * \note A synonym for this function is CIEL(). + */ + sample Lightness( sample R, sample G, sample B ) const + { + XYZLab( R = m_data->CIEY( R, G, B ) ); + return sample( (1.16 * R) - 0.16 ); + } + + // ### Deprecated - retained for compatibility -> suppress in PCL 2.x + sample Luminance( sample R, sample G, sample B ) const + { + return Lightness( R, G, B ); + } + + /*! + * A synonym for Lightness(). + */ + sample CIEL( sample R, sample G, sample B ) const + { + return Lightness( R, G, B ); + } + + /*! + * Calculates the lightness component in the CIE L*a*b* space corresponding + * to a set of RGB components, and copies it to a specified variable \a K. + * + * \param[out] K Reference to an output variable for the calculated + * lightness component. + * + * \param R,G,B Input RGB components. + */ + void RGBToGray( sample& K, sample R, sample G, sample B ) const + { + K = Lightness( R, G, B ); + } + + /*! + * Returns the Value channel value in the HSV color ordering system, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * \note This is an utility function provided for convenience; HSV is not a + * color space, but a color ordering system not based on a RGBWS. + */ + sample Value( sample R, sample G, sample B ) const + { + return pcl::Max( pcl::Max( R, G ), B ); + } + + /*! + * Returns the Intensity channel value in the HSI color ordering system, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * \note HSI is more often known as HSL; however we reserve the L channel + * identifier exclusively for the CIE L* component (lightness) in PCL. + * + * \note This is an utility function provided for convenience; HSI is not a + * color space, but a color ordering system not based on a RGBWS. + */ + sample Intensity( sample R, sample G, sample B ) const + { + return sample( 0.5*( pcl::Min( pcl::Min( R, G ), B ) + + pcl::Max( pcl::Max( R, G ), B ) ) ); + } + + /*! + * Returns the Hue channel value in the HSV and HSI color ordering systems, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * The returned value is a normalized hue, which is the hue angle + * rescaled to the normalized [0,1[ range. A normalized hue value of 1 + * corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * \note This is an utility function, provided for convenience. HSV and HSI + * are not color spaces, but color ordering systems not based on any RGBWS. + */ + sample Hue( sample R, sample G, sample B ) const + { + sample max = pcl::Max( pcl::Max( R, G ), B ); + sample delta = max - pcl::Min( pcl::Min( R, G ), B ); + if ( delta != 0 ) + { + sample H; + if ( R == max ) + H = (G - B)/delta; // between yellow & magenta + else if ( G == max ) + H = 2 + (B - R)/delta; // between cyan & yellow + else + H = 4 + (R - G)/delta; // between magenta & cyan + + H /= 6; + if ( H < 0 ) + H += 1; + return H; + } + + // Achromatic case: R = G = B + // Hue is undefined (H is set to 0 conventionally) + return 0; + } + + /*! + * Returns the Saturation channel value in the HSV color ordering system, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * \note This is an utility function provided for convenience; HSV is not a + * color space, but a color ordering system not based on a RGBWS. + */ + sample HSVSaturation( sample R, sample G, sample B ) const + { + sample max = pcl::Max( pcl::Max( R, G ), B ); + sample delta = max - pcl::Min( pcl::Min( R, G ), B ); + return sample( (1.0 + max != 1.0) ? delta/max : 0.0 ); + } + + /*! + * Returns the Saturation channel value in the HSI color ordering system, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * \note HSI is more often known as HSL; however we reserve the L channel + * identifier exclusively for the CIE L* component (lightness) in PCL. + * + * \note This is an utility function provided for convenience; HSI is not a + * color space, but a color ordering system not based on a RGBWS. + */ + sample HSISaturation( sample R, sample G, sample B ) const + { + sample min = pcl::Min( pcl::Min( R, G ), B ); + sample max = pcl::Max( pcl::Max( R, G ), B ); + sample delta = max - min; + if ( delta != 0 ) + { + sample sum = min + max; + return delta/((sum <= 1) ? sum : 2-sum); + } + return sample( 0 ); + } + + /*! + * Returns the Saturation channel value in the HSV color ordering system, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * This function is a synonym for HSVSaturation(). + */ + sample Saturation( sample R, sample G, sample B ) const + { + return HSVSaturation( R, G, B ); + } + + /*! + * Converts a set of RGB components to the corresponding channel values in + * the HSV (Hue, Saturation, Value) color ordering system. + * + * \param[out] H,S,V References to the variables where output HSV channel + * values will be copied. + * + * \param R,G,B Input RGB components. + * + * The output \a H value is a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * \note This is a static function provided for convenience; HSV is not a + * color space, but a color ordering system not based on a RGBWS. + */ + static void RGBToHSV( sample& H, sample& S, sample& V, sample R, sample G, sample B ) + { + V = pcl::Max( pcl::Max( R, G ), B ); // V = Value( R, G, B ); + + sample delta = V - pcl::Min( pcl::Min( R, G ), B ); + if ( delta != 0 ) + { + S = delta/V; + + if ( R == V ) + H = (G - B)/delta; // between yellow & magenta + else if ( G == V ) + H = 2 + (B - R)/delta; // between cyan & yellow + else + H = 4 + (R - G)/delta; // between magenta & cyan + + H /= 6; + if ( H < 0 ) + H += 1; + } + else + { + // Achromatic case: R = G = B + // S = 0, and H is undefined (H is set to 0 conventionally) + S = H = 0; + } + } + + /*! + * Converts a set of RGB components to the corresponding channel values in + * the HSI (Hue, Saturation, Intensity) color ordering system. + * + * \param[out] H,S,I References to the variables where output HSI channel + * values will be copied. + * + * \param R,G,B Input RGB components. + * + * The output \a H value is a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * \note HSI is more often known as HSL; however we reserve the L channel + * identifier exclusively for the CIE L* component (lightness) in PCL. + * + * \note This is a static function provided for convenience; HSV is not a + * color space, but a color ordering system not based on a RGBWS. + */ + static void RGBToHSI( sample& H, sample& S, sample& I, sample R, sample G, sample B ) + { + sample min = pcl::Min( pcl::Min( R, G ), B ); + sample max = pcl::Max( pcl::Max( R, G ), B ); + sample delta = max - min; + sample sum = min + max; + + I = 0.5*sum; + + if ( delta != 0 ) + { + S = delta/((sum <= 1) ? sum : 2-sum); + + if ( R == max ) + H = (G - B)/delta; // between yellow & magenta + else if ( G == max ) + H = 2 + (B - R)/delta; // between cyan & yellow + else + H = 4 + (R - G)/delta; // between magenta & cyan + + H /= 6; + if ( H < 0 ) + H += 1; + } + else + { + // Achromatic case: R = G = B + // S = 0, and H is undefined (H is set to 0 conventionally) + S = H = 0; + } + } + + /*! + * Converts a set of RGB components to the corresponding channel values in + * the HSV (Hue, Saturation, Value) color ordering system, plus the + * L* component (lightness) in the CIE L*a*b* space. + * + * \param[out] H,S,V References to the variables where output HSV channel + * values will be copied. + * + * \param[out] L Reference to a variable where the output CIE L* + * component will be copied. + * + * \param R,G,B Input RGB components. + * + * The output \a H value is a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + */ + void RGBToHSVL( sample& H, sample& S, sample& V, sample& L, sample R, sample G, sample B ) const + { + RGBToHSV( H, S, V, R, G, B ); + L = Lightness( R, G, B ); + } + + /*! + * Converts a set of RGB components to the corresponding channel values in + * the HSI (Hue, Saturation, Intensity) color ordering system, plus the + * L* component (lightness) in the CIE L*a*b* space. + * + * \param[out] H,S,I References to the variables where output HSI channel + * values will be copied. + * + * \param[out] L Reference to a variable where the output CIE L* + * component will be copied. + * + * \param R,G,B Input RGB components. + * + * The output \a H value is a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * \note HSI is more often known as HSL; however we reserve the L channel + * identifier exclusively for the CIE L* component (lightness) in PCL. + */ + void RGBToHSIL( sample& H, sample& S, sample& I, sample& L, sample R, sample G, sample B ) const + { + RGBToHSI( H, S, I, R, G, B ); + L = Lightness( R, G, B ); + } + + /*! + * Conversion from the RGB color space to the CIE XYZ color space. + * + * \param[out] X,Y,Z References to the variables where output CIE XYZ + * components will be copied. + * + * \param R,G,B Input RGB components. + */ + void RGBToCIEXYZ( sample& X, sample& Y, sample& Z, sample R, sample G, sample B ) const + { + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + } + + /*! + * Calculates the chrominance components in the CIE XYZ color space + * corresponding to a specified set of RGB components. + * + * \param[out] X,Z References to the variables where output CIE X and Z + * components will be copied. + * + * \param R,G,B Input RGB components. + * + * This function avoids the calculation of the CIE Y component, which saves + * computing time when only the chrominance components are required. + */ + void RGBToCIEXZ( sample& X, sample& Z, sample R, sample G, sample B ) const + { + m_data->RGBToCIEXZ( X, Z, R, G, B ); + } + + /*! + * CIE X component from RGB components. + * + * \param R,G,B Input RGB components. + */ + sample CIEX( sample R, sample G, sample B ) const + { + return m_data->CIEX( R, G, B ); + } + + /*! + * CIE Y component from RGB components. + * + * \param R,G,B Input RGB components. + */ + sample CIEY( sample R, sample G, sample B ) const + { + return m_data->CIEY( R, G, B ); + } + + /*! + * CIE Z component from RGB components. + * + * \param R,G,B Input RGB components. + */ + sample CIEZ( sample R, sample G, sample B ) const + { + return m_data->CIEZ( R, G, B ); + } + + /*! + * CIE L* component from CIE Y. + * + * \param Y Source CIE Y component. + */ + sample CIEYToCIEL( sample Y ) const + { + XYZLab( Y ); return 1.16*Y - 0.16; + } + + /*! + * CIE Y component from CIE L*. + * + * \param L Source CIE L* component. + */ + sample CIELToCIEY( sample L ) const + { + LabXYZ( L = (L + 0.16)/1.16 ); return L; + } + + /*! + * Conversion from the RGB color space to the CIE L*a*b* color space. + * + * \param[out] L,a,b References to the variables where output CIE L*a*b* + * components will be copied. + * + * \param R,G,B Input RGB components. + */ + void RGBToCIELab( sample& L, sample& a, sample& b, sample R, sample G, sample B ) const + { + sample X, Y, Z; + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + CIEXYZToCIELab( L, a, b, X, Y, Z ); + } + + /*! + * Calculates the chrominance components in the CIE L*a*b* color space + * corresponding to a specified set of RGB components. + * + * \param[out] a,b References to the variables where output CIE a* and b* + * components will be copied. + * + * \param R,G,B Input RGB components. + * + * This function avoids the calculation of the CIE L* component, which saves + * computing time when only the chrominance components are required. + */ + void RGBToCIEab( sample& a, sample& b, sample R, sample G, sample B ) const + { + sample X, Y, Z; + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + XYZLab( X ); XYZLab( Y ); XYZLab( Z ); + a = (5*(X - Y) + m_data->abOffset)/m_data->abDelta; + b = (2*(Y - Z) + m_data->abOffset)/m_data->abDelta; + } + + /*! + * Returns the a* chrominance component in the CIE L*a*b* color space, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * This function avoids calculation of the L* and b* components, which + * saves computing time when only the a* component is required. + */ + sample CIEa( sample R, sample G, sample B ) const + { + sample X, Y; + m_data->RGBToCIEXY( X, Y, R, G, B ); + XYZLab( X ); XYZLab( Y ); + return (5*(X - Y) + m_data->abOffset)/m_data->abDelta; + } + + /*! + * Returns the b* chrominance component in the CIE L*a*b* color space, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * This function avoids the calculation of the L* and a* channels, which + * saves computing time when only the b* chrominance component is required. + */ + sample CIEb( sample R, sample G, sample B ) const + { + sample Y, Z; + m_data->RGBToCIEYZ( Y, Z, R, G, B ); + XYZLab( Y ); XYZLab( Z ); + return (2*(Y - Z) + m_data->abOffset)/m_data->abDelta; + } + + /*! + * Returns the c* chrominance component in the CIE L*c*h* color space, + * corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * This function avoids the calculation of the L* and h* channels, which + * saves computing time when only the c* chrominance component is required. + */ + sample CIEc( sample R, sample G, sample B ) const + { + sample X, Y, Z; + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + XYZLab( X ); XYZLab( Y ); XYZLab( Z ); + sample a = 5*(X - Y); + sample b = 2*(Y - Z); + return pcl::Sqrt( a*a + b*b )/m_data->cDelta; + } + + /*! + * Returns the normalized h* chrominance component in the CIE L*c*h* color + * space, corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * This function avoids the calculation of the L* and c* channels, which + * saves computing time when only the h* chrominance component is required. + * + * The returned value is the hue angle normalized to the range [0,1[, where + * 0 corresponds to a hue angle of zero degrees, and 1 to an angle of 360 + * degrees (2*pi radians). + */ + sample CIEh( sample R, sample G, sample B ) const + { + return CIEhr( R, G, B )/Const::_2pi(); + } + + /*! + * Returns the h* chrominance component in the CIE L*c*h* color space, + * expressed in radians, corresponding to a specified set of RGB components. + * + * \param R,G,B Input RGB components. + * + * This function avoids the calculation of the L* and c* channels, which + * saves computing time when only the h* chrominance component is required. + * + * The returned value is the hue angle in radians, in the range [0,2pi[. + */ + sample CIEhr( sample R, sample G, sample B ) const + { + sample X, Y, Z; + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + XYZLab( X ); XYZLab( Y ); XYZLab( Z ); + sample h = ArcTan( 2*(Y - Z), 5*(X - Y) ); + if ( h < 0 ) + h += Const::_2pi(); + return h; + } + + /*! + * Conversion from the RGB color space to the CIE L*c*h* color space. + * + * \param[out] L,c,h References to the variables where output CIE L*c*h* + * components will be copied. + * + * \param R,G,B Input RGB components. + */ + void RGBToCIELch( sample& L, sample& c, sample& h, sample R, sample G, sample B ) const + { + sample X, Y, Z; + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + XYZLab( X ); XYZLab( Y ); XYZLab( Z ); + L = sample( (1.16 * Y) - 0.16 ); + sample a = 5*(X - Y); + sample b = 2*(Y - Z); + c = pcl::Sqrt( a*a + b*b )/m_data->cDelta; + h = ArcTan( b, a ); + if ( h < 0 ) + h += Const::_2pi(); + h /= Const::_2pi(); + } + + /*! + * Conversion from the RGB color space to the CIE L*a*b* color space, with + * optimized, on-the-fly calculation of the CIE c* component. + * + * \param[out] L,a,b References to the variables where output CIE L*a*b* + * components will be copied. + * + * \param[out] c Reference to a variable where the output CIE c* + * component will be copied. + * + * \param R,G,B Input RGB components. + * + * If only the CIE c* component is required besides CIE L*a*b* components, + * this function is much faster than performing two separate conversions to + * the CIE L*a*b* and L*c*h* color spaces. + */ + void RGBToCIELabc( sample& L, sample& a, sample& b, sample& c, sample R, sample G, sample B ) const + { + sample X, Y, Z; + m_data->RGBToCIEXYZ( X, Y, Z, R, G, B ); + XYZLab( X ); XYZLab( Y ); XYZLab( Z ); + L = sample( (1.16 * Y) - 0.16 ); + a = ((X = 5*(X - Y)) + m_data->abOffset)/m_data->abDelta; + b = ((Z = 2*(Y - Z)) + m_data->abOffset)/m_data->abDelta; + c = pcl::Sqrt( X*X + Z*Z )/m_data->cDelta; + } + + /*! + * Conversion from the HSV color ordering system to the RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param H,S,V Input HSV channel values. + * + * The input \a H value must be a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * \note This is a static function provided for convenience; HSV is not a + * color space, but a color ordering system not based on a RGBWS. + */ + static void HSVToRGB( sample& R, sample& G, sample& B, sample H, sample S, sample V ) + { + if ( S != 0 ) + { + H *= 6; // degrees -> quadrant index + + int i = TruncInt( Floor( H ) ); // i = sector 0 to 5 + sample f = H - i; // f = fractional part of H + sample p = V*(1 - S); + sample q = V*(1 - S*f); + sample t = V*(1 - S*(1 - f)); + + switch( i ) + { + case 0: R = V; G = t; B = p; break; + case 1: R = q; G = V; B = p; break; + case 2: R = p; G = V; B = t; break; + case 3: R = p; G = q; B = V; break; + case 4: R = t; G = p; B = V; break; + case 5: R = V; G = p; B = q; break; + default: R = G = B = V; break; // out-of-range H argument + } + } + else + R = G = B = V; // achromatic + } + + /*! + * Transformation from separate HSV chrominance and CIE L* components to the + * RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param H,S,V Input HSV channel values for chrominance. + * + * \param L Input CIE L* (lightness) component. + * + * The lightness implicitly defined by the input HSV values is discarded + * and replaced with the specified CIE L* component. + * + * Strictly speaking, the resulting chrominance is not colorimetrically + * defined, since it derives from HSV channel values. However, the + * chrominance is supposed to be expressed in the RGB working space + * referenced by this %RGBColorSystem instance. + * + * The input \a H value must be a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * The primary usefulness of this function is implementing accurate + * hue/saturation image transformations in the HSV system with full + * preservation of the CIE lightness component. + */ + void HSVLToRGB( sample& R, sample& G, sample& B, sample H, sample S, sample V, sample L ) const + { + HSVToRGB( R, G, B, H, S, V ); +#define a H +#define b S + RGBToCIEab( a, b, R, G, B ); + CIELabToRGB( R, G, B, L, a, b ); +#undef a +#undef b + } + + /*! + * Conversion from the HSI color ordering system to the RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param H,S,I Input HSI channel values. + * + * The input \a H value must be a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * \note HSI is more often known as HSL; however we reserve the L channel + * identifier exclusively for the CIE L* component (lightness) in PCL. + * + * \note This is a static function provided for convenience; HSI is not a + * color space, but a color ordering system not based on a RGBWS. + */ + static void HSIToRGB( sample& R, sample& G, sample& B, sample H, sample S, sample I ) + { + if ( S != 0 ) + { + sample v2 = (I < 0.5) ? I*(1 + S) : I + S - S*I; + sample v1 = I+I - v2; + R = HSIH2RGB( v1, v2, H+_1_3 ); + G = HSIH2RGB( v1, v2, H ); + B = HSIH2RGB( v1, v2, H-_1_3 ); + } + else + R = G = B = I; // achromatic + } + + /*! + * Transformation from separate HSI chrominance and CIE L* components to the + * RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param H,S,I Input HSI channel values for chrominance. + * + * \param L Input CIE L* component (lightness). + * + * The lightness implicitly defined by the input HSI values is discarded + * and replaced with the specified CIE L* component. + * + * Strictly speaking, the resulting chrominance is not colorimetrically + * defined, since it derives from HSI channel values. However, the + * chrominance is supposed to be expressed in the RGB working space + * referenced by this %RGBColorSystem instance. + * + * The input \a H value must be a normalized hue, which is the hue + * angle rescaled to the normalized [0,1] range. A normalized hue value of + * one corresponds to a hue angle of 2*pi radians, or 360 degrees. + * + * The primary usefulness of this function is implementing accurate + * hue/saturation image transformations in the HSI system with full + * preservation of the CIE lightness component. + * + * \note HSI is more often known as HSL; however we reserve the L channel + * identifier exclusively for the CIE L* component (lightness) in PCL. + */ + void HSILToRGB( sample& R, sample& G, sample& B, sample H, sample S, sample I, sample L ) const + { + HSIToRGB( R, G, B, H, S, I ); +#define a H +#define b S + RGBToCIEab( a, b, R, G, B ); + CIELabToRGB( R, G, B, L, a, b ); +#undef a +#undef b + } + + /*! + * Conversion from the CIE XYZ color space to the RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param X,Y,Z Input CIE XYZ components. + */ + void CIEXYZToRGB( sample& R, sample& G, sample& B, sample X, sample Y, sample Z ) const + { + m_data->CIEXYZToRGB( R, G, B, X, Y, Z ); + } + + /*! + * Conversion from the CIE XYZ color space to the CIE L*a*b* color space. + * + * \param[out] L,a,b References to the variables where output CIE L*a*b* + * components will be copied. + * + * \param X,Y,Z Input CIE XYZ components. + */ + void CIEXYZToCIELab( sample& L, sample& a, sample& b, sample X, sample Y, sample Z ) const + { + XYZLab( X ); XYZLab( Y ); XYZLab( Z ); + L = sample( (1.16 * Y) - 0.16 ); + a = (5*(X - Y) + m_data->abOffset)/m_data->abDelta; + b = (2*(Y - Z) + m_data->abOffset)/m_data->abDelta; + } + + /*! + * Conversion from the CIE L*a*b* color space to the RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param L,a,b Input CIE L*a*b* components. + */ + void CIELabToRGB( sample& R, sample& G, sample& B, sample L, sample a, sample b ) const + { + sample X, Y, Z; + CIELabToCIEXYZ( X, Y, Z, L, a, b ); + m_data->CIEXYZToRGB( R, G, B, X, Y, Z ); + } + + /*! + * Conversion from the CIE L*a*b* color space to the CIE XYZ color space. + * + * \param[out] X,Y,Z References to the variables where output CIE XYZ + * components will be copied. + * + * \param L,a,b Input CIE L*a*b* components. + */ + void CIELabToCIEXYZ( sample& X, sample& Y, sample& Z, sample L, sample a, sample b ) const + { + Y = sample( (L + 0.16)/1.16 ); + X = (m_data->abDelta*a - m_data->abOffset)/5 + Y; + Z = Y - (m_data->abDelta*b - m_data->abOffset)/2; + LabXYZ( X ); LabXYZ( Y ); LabXYZ( Z ); + } + + /*! + * Conversion from the CIE L*a*b* color space to the CIE L*c*h* color space. + * + * \param[out] L,c,h References to the variables where output CIE L*c*h* + * components will be copied. + * + * \param L0,a,b Input CIE L*a*b* components. + * + * \note The output L component is always identical to the input L0 + * component; the L parameter of this function has been included for the + * sake of coherence in function signatures. + */ + void CIELabToCIELch( sample& L, sample& c, sample& h, sample L0, sample a, sample b ) const + { + L = L0; + a = m_data->abDelta*a - m_data->abOffset; + b = m_data->abDelta*b - m_data->abOffset; + c = Sqrt( a*a + b*b )/m_data->cDelta; + h = ArcTan( b, a )/Const::pi(); + if ( h < 0 ) + h += 1; + } + + /*! + * Conversion from the CIE L*c*h* color space to the RGB color space. + * + * \param[out] R,G,B References to the variables where output RGB + * components will be copied. + * + * \param L,c,h Input CIE L*c*h* components. + */ + void CIELchToRGB( sample& R, sample& G, sample& B, sample L, sample c, sample h ) const + { + sample a, b; + SinCos( h*Const::_2pi(), b, a ); + c *= m_data->cDelta; + a *= c; + b *= c; + sample Y = sample( (L + 0.16)/1.16 ); + sample X = a/5 + Y; + sample Z = Y - b/2; + LabXYZ( X ); LabXYZ( Y ); LabXYZ( Z ); + m_data->CIEXYZToRGB( R, G, B, X, Y, Z ); + } + + /*! + * Conversion from the CIE L*c*h* color space to the CIE L*a*b* color space. + * + * \param[out] L,a,b References to the variables where output CIE L*a*b* + * components will be copied. + * + * \param L0,c,h Input CIE L*c*h* components. + * + * \note The output L component is always identical to the input L0 + * component; the L parameter of this function has been included for the + * sake of coherence in function signatures. + */ + void CIELchToCIELab( sample& L, sample& a, sample& b, sample L0, sample c, sample h ) const + { + L = L0; + SinCos( h*Const::_2pi(), b, a ); + c *= m_data->cDelta; + a = (c*a + m_data->abOffset)/m_data->abDelta; + b = (c*b + m_data->abOffset)/m_data->abDelta; + } + +protected: + + struct Data : public ReferenceCounter + { + float gamma, gammaInv; // gamma, 1/gamma + bool issRGB; // true if sRGB gamma function is being used + bool isLinear; // true if gamma=1.0 and is not sRGB, for optimization + + /* + * Chromaticity coordinates w.r.t. the D50 reference white + */ + FVector x, y; + + /* + * Luminance coefficients w.r.t. the D50 reference white + */ + FVector Y; + + /* + * RGB <-> CIE XYZ transformation matrices + */ + Vector M; // RGB -> CIE XYZ + Vector M_; // CIE XYZ -> RGB + + /* + * Normalization coefficients for X and Z coordinates + */ + sample mX, mZ; + + /* + * Normalization of CIE a*, b* and c* components + */ + sample abOffset; + sample abDelta; + sample cDelta; + + Data( float, bool, const FVector&, const FVector&, const FVector& ); + Data( float, bool, const float*, const float*, const float* ); + Data( const Data& ) = default; + + void Initialize(); + + bool operator ==( const RGBColorSystem::Data& data ) const + { + return gamma == data.gamma && + issRGB == data.issRGB && + Y == data.Y && + x == data.x && y == data.y; + } + + /* + * Primary gamma functions + */ + + void LinearRGB( sample& x ) const + { + x = issRGB ? + ((x > sRGBEpsilon) ? + Pow( sample( (x + 0.055)/1.055 ), sample( sRGBGamma ) ) : sample( x/12.92 )) : + Pow( x, sample( gamma ) ); + } + + void GammaRGB( sample& x ) const + { + x = issRGB ? + ((x > sRGBEpsilonInv) ? + sample( 1.055*Pow( x, sample( sRGBGammaInv ) ) - 0.055 ) : sample( 12.92*x )) : + Pow( x, sample( gammaInv ) ); + } + + /* + * Primary linear transformations + */ + + void RGBToCIEXYZ( sample& X, sample& Y, sample& Z, sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + X = Range( (R*M[0] + G*M[1] + B*M[2])/mX ); + Y = Range( R*M[3] + G*M[4] + B*M[5] ); + Z = Range( (R*M[6] + G*M[7] + B*M[8])/mZ ); + } + + void CIEXYZToRGB( sample& R, sample& G, sample& B, sample X, sample Y, sample Z ) const + { + X *= mX; + Z *= mZ; + R = Range( X*M_[0] + Y*M_[1] + Z*M_[2] ); + G = Range( X*M_[3] + Y*M_[4] + Z*M_[5] ); + B = Range( X*M_[6] + Y*M_[7] + Z*M_[8] ); + + if ( !isLinear ) + { + GammaRGB( R ); + GammaRGB( G ); + GammaRGB( B ); + } + } + + /* + * Utility functions for fast partial luminance/chrominance calculations + */ + + sample CIEX( sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + return Range( (R*M[0] + G*M[1] + B*M[2])/mX ); + } + + sample CIEY( sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + return Range( R*M[3] + G*M[4] + B*M[5] ); + } + + sample CIEZ( sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + return Range( (R*M[6] + G*M[7] + B*M[8])/mZ ); + } + + void RGBToCIEXY( sample& X, sample& Y, sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + X = Range( (R*M[0] + G*M[1] + B*M[2])/mX ); + Y = Range( R*M[3] + G*M[4] + B*M[5] ); + } + + void RGBToCIEYZ( sample& Y, sample& Z, sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + Y = Range( R*M[3] + G*M[4] + B*M[5] ); + Z = Range( (R*M[6] + G*M[7] + B*M[8])/mZ ); + } + + void RGBToCIEXZ( sample& X, sample& Z, sample R, sample G, sample B ) const + { + if ( !isLinear ) + { + LinearRGB( R ); + LinearRGB( G ); + LinearRGB( B ); + } + + X = Range( (R*M[0] + G*M[1] + B*M[2])/mX ); + Z = Range( (R*M[6] + G*M[7] + B*M[8])/mZ ); + } + + static bool ValidateParameters( const FVector& x, const FVector& y, const FVector& Y ); + + static sample Range( const sample& x ) // Ensure nominal [0,1] range + { + return pcl::Range( x, sample( 0 ), sample( 1 ) ); + } + }; + + Data* m_data = nullptr; + + void DetachFromData() + { + if ( !m_data->Detach() ) + delete m_data; + } + + static void XYZLab( sample& x ) + { + x = (x > CIEEpsilon) ? Pow( x, sample( _1_3 ) ) : sample( CIEKappa116*x + _16_116 ); + } + + static void LabXYZ( sample& x ) + { + sample x3 = x*x*x; + x = (x3 > CIEEpsilon) ? x3 : sample( (x - _16_116)/CIEKappa116 ); + } + + static sample HSIH2RGB( sample v1, sample v2, sample H ) + { + if ( H < 0 ) + H += 1; + else if ( H > 1 ) + H -= 1; + + if ( H < _1_6 ) + return v1 + 6*H*(v2 - v1); + + if ( H < 0.5 ) + return v2; + + if ( H < _2_3 ) + return v1 + 6*(_2_3 - H)*(v2 - v1); + + return v1; + } + + friend struct Data; + +public: + + /*! + * sRGB x chromaticity coordinates (D50). + */ + static const float sRGB_x[ 3 ]; + + /*! + * sRGB y chromaticity coordinates (D50). + */ + static const float sRGB_y[ 3 ]; + + /*! + * sRGB luminance coefficients (D50). + */ + static const float sRGB_Y[ 3 ]; + + /*! + * The sRGB (D50) working space. + */ + static const RGBColorSystem sRGB; + +#ifdef __PCL_WITH_STANDARD_RGB_WORKING_SPACES + + /* + * Adobe RGB 1998 + */ + static const float AdobeRGB1998_x[ 3 ]; + static const float AdobeRGB1998_y[ 3 ]; + static const float AdobeRGB1998_Y[ 3 ]; + + /* + * Apple RGB + */ + static const float AppleRGB_x[ 3 ]; + static const float AppleRGB_y[ 3 ]; + static const float AppleRGB_Y[ 3 ]; + + /* + * Best RGB + */ + static const float BestRGB_x[ 3 ]; + static const float BestRGB_y[ 3 ]; + static const float BestRGB_Y[ 3 ]; + + /* + * Beta RGB (by Bruce Lindbloom) + */ + static const float BetaRGB_x[ 3 ]; + static const float BetaRGB_y[ 3 ]; + static const float BetaRGB_Y[ 3 ]; + + /* + * Bruce RGB + */ + static const float BruceRGB_x[ 3 ]; + static const float BruceRGB_y[ 3 ]; + static const float BruceRGB_Y[ 3 ]; + + /* + * CIE RGB + */ + static const float CIERGB_x[ 3 ]; + static const float CIERGB_y[ 3 ]; + static const float CIERGB_Y[ 3 ]; + + /* + * Color Match RGB + */ + static const float ColorMatchRGB_x[ 3 ]; + static const float ColorMatchRGB_y[ 3 ]; + static const float ColorMatchRGB_Y[ 3 ]; + + /* + * NTSC RGB + */ + static const float NTSCRGB_x[ 3 ]; + static const float NTSCRGB_y[ 3 ]; + static const float NTSCRGB_Y[ 3 ]; + + /* + * PAL/SECAM RGB + */ + static const float PALSECAMRGB_x[ 3 ]; + static const float PALSECAMRGB_y[ 3 ]; + static const float PALSECAMRGB_Y[ 3 ]; + + /* + * ProPhoto RGB + */ + static const float ProPhotoRGB_x[ 3 ]; + static const float ProPhotoRGB_y[ 3 ]; + static const float ProPhotoRGB_Y[ 3 ]; + + /* + * SMPTE-C RGB + */ + static const float SMPTECRGB_x[ 3 ]; + static const float SMPTECRGB_y[ 3 ]; + static const float SMPTECRGB_Y[ 3 ]; + + /* + * Wide Gamut RGB + */ + static const float WideGamutRGB_x[ 3 ]; + static const float WideGamutRGB_y[ 3 ]; + static const float WideGamutRGB_Y[ 3 ]; + +#endif // __PCL_WITH_STANDARD_RGB_WORKING_SPACES + +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#undef _1_3 +#undef _1_6 +#undef _2_3 +#undef _16_116 +#undef CIEEpsilon +#undef CIEKappa +#undef CIEKappa116 +#undef sRGBEpsilon +#undef sRGBEpsilonInv +#undef sRGBGamma +#undef sRGBGammaInv + +#endif // __PCL_RGBColorSystem_h + +// ---------------------------------------------------------------------------- +// EOF pcl/RGBColorSystem.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/RadioButton.h b/3rdparty/include/pcl/RadioButton.h new file mode 100644 index 0000000..2ae2728 --- /dev/null +++ b/3rdparty/include/pcl/RadioButton.h @@ -0,0 +1,117 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/RadioButton.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_RadioButton_h +#define __PCL_RadioButton_h + +/// \file pcl/RadioButton.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class RadioButton + * \brief Client-side interface to a PixInsight %RadioButton control. + * + * ### TODO: Write a detailed description for %RadioButton + */ +class PCL_CLASS RadioButton : public Button +{ +public: + + /*! + * Constructs a %RadioButton with the specified \a text, as a child control + * of \a parent. + */ + RadioButton( const String& text = String(), Control& parent = Control::Null() ); + + /*! + * Destroys a %RadioButton control. + */ + virtual ~RadioButton() + { + } + + /*! + * Returns false, since radio buttons are not pushable buttons. + */ + bool IsPushable() const override + { + return false; + } + + /*! + * Returns true, since radio buttons are checkable buttons. + */ + bool IsCheckable() const override + { + return true; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_RadioButton_h + +// ---------------------------------------------------------------------------- +// EOF pcl/RadioButton.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Random.h b/3rdparty/include/pcl/Random.h new file mode 100644 index 0000000..3d49988 --- /dev/null +++ b/3rdparty/include/pcl/Random.h @@ -0,0 +1,921 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Random.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_Random_h +#define __PCL_Random_h + +/// \file pcl/Random.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup random_numbers Random Number Generation + */ + +/*! + * Returns a 64-bit random generator seed. + * + * On UNIX/Linux platforms, this function reads the /dev/urandom system device + * to acquire a high-quality random seed. On Windows, the rand_s() CRT function + * is invoked with the same purpose. + * + * In the extremely rare cases where a system random seed cannot be obtained, + * the time() function is used to get a unique initialization value. + * + * Subsequent calls to this function are guaranteed to return unique values. + * + * This function is thread-safe. It can be safely called from multiple + * execution threads running concurrently. + * + * \ingroup random_numbers + */ +extern uint64 RandomSeed64(); + +/*! + * Returns a 32-bit random generator seed. + * + * This function simply calls RandomSeed64() and returns the XOR combination of + * the 32-bit words in the 64-bit random seed. + * + * As RandomSeed64(), this function is thread-safe and is guaranteed to return + * a unique value on each call. + * + * \ingroup random_numbers + */ +inline uint32 RandomSeed32() +{ + union { uint64 u64; uint32 u32[ 2 ]; } seed; + seed.u64 = RandomSeed64(); + return seed.u32[0] ^ seed.u32[1]; +} + +// ---------------------------------------------------------------------------- + +class FastMersenneTwister; + +// ---------------------------------------------------------------------------- + +/*! + * \class RandomNumberGenerator + * \brief Mersenne Twister (MT19937) pseudo-random number generator. + * + * \deprecated This class has been deprecated. Use the XoShiRo256ss and + * XoRoShiRo1024ss classes for all newly produced code. + * + * Generation of pseudo-random numbers with user-selectable range and + * probability distributions. + * + * This generator supports the uniform, normal (Gaussian) and Poisson + * distributions. In addition, the upper range of generated uniform deviates + * can be arbitrarily defined. + * + * %RandomNumberGenerator is a functional class. The function call operator()() + * returns pseudo-random numbers in the range [0,ymax], where ymax is the + * user-defined arbitrary upper range. + * + * Example of use: + * + * \code + * RandomNumberGenerator R, R1( 10 ); // R's ymax = 1, R1's ymax = 10 + * // ... + * double y = R(); // y = random uniform deviate in the range [0,1] + * double z = R1(); // z = random uniform deviate in the range [0,10] + * \endcode + * + * References + * + * Based on an adaptation of SIMD-oriented Fast Mersenne Twister (SFMT) by + * Mutsuo Saito and Makoto Matsumoto (Hiroshima University). + * + * Currently PCL implements a SFMT generator with a period of 2^19937-1. + * + * SFMT Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima + * University. All rights reserved. + * + * \ingroup random_numbers + */ +class PCL_CLASS RandomNumberGenerator +{ +public: + + /*! + * Constructs a %RandomNumberGenerator object. + * + * \param ymax Upper bound of uniform deviates. The function call + * operator double operator()() and the Uniform() member + * function (which are synonyms) will return uniform + * pseudo-random deviates in the range [0,ymax]. The default + * value is 1.0. + * + * \param seed 32-bit initialization seed. If this parameter is zero, a + * unique random seed will be generated automatically. The + * default value is zero. + */ + RandomNumberGenerator( double ymax = 1.0, uint32 seed = 0 ); + + /*! + * Destroys a %RandomNumberGenerator object. + */ + virtual ~RandomNumberGenerator(); + + /*! + * Generates a floating point uniform deviate in the range [0,UpperBound()] + */ + double operator ()() + { + return m_rmax*Rand32(); + } + + /*! + * Generates a 32-bit unsigned integer uniform deviate. + */ + uint32 Rand32(); + + /*! + * Generates a floating point uniform deviate in the range [0,1] (i.e., + * ignoring UpperBound()). + */ + double Rand1() + { + return double( Rand32() )/uint32_max; + } + + /*! + * Generates a floating point uniform deviate in the range [0,UpperBound()] + * + * This is a convenience alias for operator()(). + */ + double Uniform() + { + return operator()(); + } + + /*! + * Generates a floating point normal deviate with the specified \a mean and + * standard deviation \a sigma. + */ + double Normal( double mean = 0, double sigma = 1 ); + + /*! + * Generates a floating point normal deviate with the specified \a mean and + * standard deviation \a sigma. + * + * This is a convenience alias for Normal( mean, sigma ). + */ + double Gaussian( double mean = 0, double sigma = 1 ) + { + return Normal( mean, sigma ); + } + + /*! + * Generates a discrete random deviate from a Poisson distribution with the + * specified expected value \a lambda. + */ + int Poisson( double lambda ); + + /*! + * Returns the current upper bound of this random number generator. + */ + double UpperBound() const + { + return m_ymax; + } + + /*! + * Sets the upper bound \a ymax > 0 for this random number generator. + */ + void SetUpperBound( double ymax ) + { + PCL_PRECONDITION( ymax > 0 ) + PCL_PRECONDITION( 1 + ymax != 1 ) + m_rmax = (m_ymax = ymax)/double( uint32_max ); + m_normal = false; + } + +private: + + AutoPointer m_generator; + double m_ymax; + double m_rmax; + bool m_normal; + double m_vs; // second result from Box–Muller transform + DVector m_lambda; // precalculated for current Poisson lambda +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XorShift1024 + * \brief Implementation of the XorShift1024* pseudo-random number generator. + * + * \deprecated This class has been deprecated. Use the XoShiRo256ss and + * XoRoShiRo1024ss classes for all newly produced code. + * + * Generation of pseudo-random uniform deviates using the xorshift1024* + * generator developed in 2014 by Sebastiano Vigna. This is a fast, top-quality + * generator with a period of 2^1024-1, passing strong statistical test suites. + * + * Examples of use: + * + * \code + * XorShift1024 X; // initialized automatically + * // ... + * double x = X(); // x = random uniform deviate in the range [0,1) + * uint64 y = X.UI64(); // y = 64-bit unsigned integer random uniform deviate + * uint32 z = X.UI32(); // z = 32-bit unsigned integer random uniform deviate + * uint32 t = X.UIN( 100 ); // t = integer uniform deviate in the range [0,99] + * \endcode + * + * References + * + * Sebastiano Vigna (2014), An experimental exploration of Marsaglia's + * xorshift generators, scrambled, arXiv:1402.6246 + * + * Sebastiano Vigna (2014), Further scramblings of Marsaglia's xorshift + * generators, arXiv:1404.0390 + * + * See also: http://xorshift.di.unimi.it/ + * + * \ingroup random_numbers + */ +class PCL_CLASS XorShift1024 +{ +public: + + /*! + * Constructs a %XorShift1024 pseudo-random number generator. + * + * \param seed 64-bit initialization seed. If this parameter is zero, a + * unique random seed will be generated automatically. The + * default value is zero. + */ + XorShift1024( uint64 seed = 0 ) noexcept( false ) + { + Initialize( seed ); + } + + /*! + * Returns a double precision uniform random deviate in the [0,1) range. + */ + double operator ()() noexcept + { + return 5.4210108624275221703311e-20 * UI64(); // 1.0/(2^64 -1) + } + + /*! + * Returns a 64-bit unsigned integer uniform random deviate. + */ + uint64 UI64() noexcept + { + uint64 s0 = m_s[m_p]; + uint64 s1 = m_s[m_p = (m_p + 1) & 15]; + s1 ^= s1 << 31; // a + s1 ^= s1 >> 11; // b + s0 ^= s0 >> 30; // c + return (m_s[m_p] = s0 ^ s1) * 1181783497276652981ull; + } + + /*! + * Returns a 32-bit unsigned integer uniform random deviate. + */ + uint32 UI32() noexcept + { + return uint32( UI64() ); + } + + /*! + * Returns a 64-bit unsigned integer uniform random deviate in the range + * [0,n-1]. + */ + uint64 UI64N( uint64 n ) noexcept + { + return UI64() % n; + } + + /*! + * Returns an unsigned integer uniform random deviate in the range [0,n-1]. + */ + uint32 UIN( uint32 n ) noexcept + { + return UI64() % n; + } + + /*! + * A synonym for UIN(). + */ + uint32 UI32N( uint32 n ) noexcept + { + return UIN( n ); + } + + /*! + * Reinitializes this generator with a new \a seed. + * + * If the specified \a seed is zero, a unique, high-quality random seed will + * be generated automatically by calling RandomSeed64(). + */ + void Initialize( uint64 x ) + { + if ( x == 0 ) + x = RandomSeed64(); + // Use a xorshift64* generator to initialize the state space. + for ( int i = 0; i < 16; ++i ) + { + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + m_s[i] = x * 2685821657736338717ull; + } + m_p = 0; + } + +private: + + uint64 m_s[ 16 ]; // state space + int m_p; // current index +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XoRoShiRo1024ss + * \brief Base class of xoshiro and xoroshiro pseudo-random number generators. + */ +class PCL_CLASS XoShiRoBase +{ +public: + + /*! + * Default constructor. + */ + XoShiRoBase() = default; + +protected: + + /*! + * \internal + * The left rotation function used by the generator. + */ + static uint64 RotL( const uint64 x, int k ) noexcept + { + return (x << k) | (x >> (64 - k)); + } + + /*! + * \internal + * The SplitMix64 generator used for state space initialization, as + * recommended by Blackman/Vigna. + */ + static uint64 SplitMix64( uint64& x ) noexcept + { + uint64 z = (x += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); + } + + /*! + * \internal + * Conversion of a 64-bit unsigned inteter to 64-bit floating point with + * uniform probability over the entire 53-bit significant digits. + * See: http://prng.di.unimi.it/#remarks + */ + static double UI64ToDouble( uint64 x ) noexcept + { + return (x >> 11) * 0x1.0p-53; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XoShiRo256ss + * \brief Implementation of the xoshiro256** pseudo-random number generator. + * + * Generation of pseudo-random uniform deviates using the xoroshiro1024** + * generator developed in 2019 by David Blackman and Sebastiano Vigna. This is + * a fast, top-quality generator with a period of 2^256-1, passing strong + * statistical test suites—actually, it passes all tests we are aware of. + * + * Examples of use: + * + * \code + * XoShiRo256ss X; // initialized automatically + * // ... + * double x = X(); // x = random uniform deviate in the range [0,1) + * uint64 y = X.UI64(); // y = 64-bit unsigned integer random uniform deviate + * uint32 z = X.UI32(); // z = 32-bit unsigned integer random uniform deviate + * uint32 t = X.UIN( 100 ); // t = integer uniform deviate in the range [0,99] + * \endcode + * + * References + * + * David Blackman and Sebastiano Vigna (2019), Scrambled linear + * pseudorandom number generators (preprint). + * + * See also: http://prng.di.unimi.it/ + * + * \ingroup random_numbers + */ +class PCL_CLASS XoShiRo256ss : public XoShiRoBase +{ +public: + + /*! + * Constructs a %XoShiRo256ss pseudo-random number generator. + * + * \param seed 64-bit initialization seed. If this parameter is zero, a + * unique random seed will be generated automatically. The + * default value is zero. + */ + XoShiRo256ss( uint64 seed = 0 ) noexcept( false ) + { + Initialize( seed ); + } + + /*! + * Returns a double precision uniform random deviate in the [0,1) range. + */ + double operator ()() noexcept + { + return UI64ToDouble( UI64() ); + } + + /*! + * Returns a 64-bit unsigned integer uniform random deviate. + */ + uint64 UI64() noexcept + { + const uint64 result = RotL( m_s[1]*5, 7 ) * 9; + const uint64 t = m_s[1] << 17; + m_s[2] ^= m_s[0]; + m_s[3] ^= m_s[1]; + m_s[1] ^= m_s[2]; + m_s[0] ^= m_s[3]; + m_s[2] ^= t; + m_s[3] = RotL( m_s[3], 45 ); + return result; + } + + /*! + * Returns a 32-bit unsigned integer uniform random deviate. + */ + uint32 UI32() noexcept + { + return uint32( UI64() ); + } + + /*! + * Returns a 64-bit unsigned integer uniform random deviate in the range + * [0,n-1]. + */ + uint64 UI64N( uint64 n ) noexcept + { + return UI64() % n; + } + + /*! + * Returns an unsigned integer uniform random deviate in the range [0,n-1]. + */ + uint32 UIN( uint32 n ) noexcept + { + return UI64() % n; + } + + /*! + * A synonym for UIN(). + */ + uint32 UI32N( uint32 n ) noexcept + { + return UIN( n ); + } + + /*! + * Reinitializes this generator with a new \a seed. + * + * If the specified \a seed is zero, a unique, high-quality random seed will + * be generated automatically by calling RandomSeed64(). + */ + void Initialize( uint64 x ) + { + if ( x == 0 ) + x = RandomSeed64(); + // Use a SplitMix64 generator to initialize the state space. + for ( int i = 0; i < 4; ++i ) + m_s[i] = SplitMix64( x ); + } + +private: + + uint64 m_s[ 4 ]; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XoRoShiRo1024ss + * \brief Implementation of the xoroshiro1024** pseudo-random number generator. + * + * Generation of pseudo-random uniform deviates using the xoroshiro1024** + * generator developed in 2019 by David Blackman and Sebastiano Vigna. This is + * a fast, top-quality generator with a period of 2^1024-1, passing strong + * statistical test suites—actually, it passes all tests we are aware of. + * + * Examples of use: + * + * \code + * XoRoShiRo1024ss X; // initialized automatically + * // ... + * double x = X(); // x = random uniform deviate in the range [0,1) + * uint64 y = X.UI64(); // y = 64-bit unsigned integer random uniform deviate + * uint32 z = X.UI32(); // z = 32-bit unsigned integer random uniform deviate + * uint32 t = X.UIN( 100 ); // t = integer uniform deviate in the range [0,99] + * \endcode + * + * References + * + * David Blackman and Sebastiano Vigna (2019), Scrambled linear + * pseudorandom number generators (preprint). + * + * See also: http://prng.di.unimi.it/ + * + * \ingroup random_numbers + */ +class PCL_CLASS XoRoShiRo1024ss : public XoShiRoBase +{ +public: + + /*! + * Constructs a %XoRoShiRo1024ss pseudo-random number generator. + * + * \param seed 64-bit initialization seed. If this parameter is zero, a + * unique random seed will be generated automatically. The + * default value is zero. + */ + XoRoShiRo1024ss( uint64 seed = 0 ) noexcept( false ) + { + Initialize( seed ); + } + + /*! + * Returns a double precision uniform random deviate in the [0,1) range. + */ + double operator ()() noexcept + { + return UI64ToDouble( UI64() ); + } + + /*! + * Returns a 64-bit unsigned integer uniform random deviate. + */ + uint64 UI64() noexcept + { + const int q = m_p; + const uint64 s0 = m_s[m_p = (m_p + 1) & 15]; + uint64 s15 = m_s[q]; + const uint64 result = RotL( s0*5, 7 ) * 9; + s15 ^= s0; + m_s[q] = RotL( s0, 25 ) ^ s15 ^ (s15 << 27); + m_s[m_p] = RotL( s15, 36 ); + return result; + } + + /*! + * Returns a 32-bit unsigned integer uniform random deviate. + */ + uint32 UI32() noexcept + { + return uint32( UI64() ); + } + + /*! + * Returns a 64-bit unsigned integer uniform random deviate in the range + * [0,n-1]. + */ + uint64 UI64N( uint64 n ) noexcept + { + return UI64() % n; + } + + /*! + * Returns an unsigned integer uniform random deviate in the range [0,n-1]. + */ + uint32 UIN( uint32 n ) noexcept + { + return UI64() % n; + } + + /*! + * A synonym for UIN(). + */ + uint32 UI32N( uint32 n ) noexcept + { + return UIN( n ); + } + + /*! + * Reinitializes this generator with a new \a seed. + * + * If the specified \a seed is zero, a unique, high-quality random seed will + * be generated automatically by calling RandomSeed64(). + */ + void Initialize( uint64 x ) + { + if ( x == 0 ) + x = RandomSeed64(); + // Use a SplitMix64 generator to initialize the state space. + for ( int i = 0; i < 16; ++i ) + m_s[i] = SplitMix64( x ); + m_p = 0; + } + +private: + + uint64 m_s[ 16 ]; + int m_p; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class NormalRandomDeviates + * \brief Generation of random normal (Gaussian) deviates. + * \ingroup random_numbers + */ +template +class PCL_CLASS NormalRandomDeviates +{ +public: + + /*! + * Constructs a %NormalRandomDeviates objects using the specified + * pseudo-random number generator \a R. + */ + NormalRandomDeviates( RNG& R ) noexcept( false ) + : m_R( R ) + { + } + + /*! + * Returns a random deviate from a Gaussian distribution with zero mean and + * unit standard deviation. + */ + double operator ()() noexcept + { + /* + * Marsaglia polar method. + */ + double x; + if ( m_first ) + { + do + { + double u1 = m_R(); + double u2 = m_R(); + m_v1 = 2*u1 - 1; + m_v2 = 2*u2 - 1; + m_s = m_v1*m_v1 + m_v2*m_v2; + } + while ( m_s >= 1 || m_s <= std::numeric_limits::epsilon() ); + + x = m_v1 * Sqrt( -2*Ln( m_s )/m_s ); + } + else + x = m_v2 * Sqrt( -2*Ln( m_s )/m_s ); + + m_first = !m_first; + return x; + } + +private: + + RNG& m_R; + double m_v1 = 0; + double m_v2 = 0; + double m_s = 0; + bool m_first = true; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PoissonRandomDeviates + * \brief Generation of random Poisson deviates. + * \ingroup random_numbers + */ +template +class PCL_CLASS PoissonRandomDeviates +{ +public: + + /*! + * Constructs a %PoissonRandomDeviates objects using the specified + * pseudo-random number generator \a R. + */ + PoissonRandomDeviates( RNG& R ) noexcept( false ) + : m_R( R ) + { + } + + /*! + * Returns a random Poisson deviate for the specified \a value. + */ + int operator ()( double value ) noexcept + { + if ( value < 30 ) + { + /* + * Implementation of the algorithm by Donald E. Knuth, 1969. + * + * This algorithm is slow (unusable) for large values. + */ + double p = 1, L = Exp( -value ); + int k = 0; + do + { + ++k; + p *= m_R(); + } + while ( p > L ); + return k-1; + } + + /* + * Code adapted from 'Random number generation in C++', by John D. Cook: + * + * https://www.johndcook.com/blog/cpp_random_number_generation/ + * + * The algorithm is from "The Computer Generation of Poisson Random + * Variables" by A. C. Atkinson, Journal of the Royal Statistical + * Society Series C (Applied Statistics) Vol. 28, No. 1. (1979) + * + * This algorithm is slow (unusable) for small values. + */ + double c = 0.767 - 3.36/value; + double beta = Const::pi()/Sqrt( 3*value ); + double alpha = beta*value; + double k = Ln( c ) - value - Ln( beta ); + for ( ;; ) + { + double u = m_R(); + double x = (alpha - Ln( (1 - u)/u ))/beta; + int n = int( Floor( x + 0.5 ) ); + if ( n < 0 ) + continue; + double v = m_R(); + double y = alpha - beta*x; + double temp = 1 + Exp( y ); + double lhs = y + Ln( v/temp/temp ); + double rhs = k + n*Ln( value ) - LnFactorial( n ); + if ( lhs <= rhs ) + return n; + } + } + +private: + + RNG& m_R; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GammaRandomDeviates + * \brief Generation of random gamma deviates. + * \ingroup random_numbers + */ +template +class PCL_CLASS GammaRandomDeviates +{ +public: + + /*! + * Constructs a %GammaRandomDeviates objects using the specified + * pseudo-random number generator \a R. + */ + GammaRandomDeviates( RNG& R, double shape = 1, double scale = 1 ) noexcept( false ) + : m_R( R ) + , m_shape( shape ) + , m_scale( scale ) + , m_normal( R ) + { + if ( m_shape <= 0 ) + throw Error( "GammaRandomDeviates(): The function shape parameter must be > 0." ); + if ( m_scale <= 0 ) + throw Error( "GammaRandomDeviates(): The scale parameter must be > 0." ); + + m_d = ((m_shape >= 1) ? m_shape : m_shape + 1) - 1.0/3.0; + m_c = 1/Sqrt( 9*m_d ); + } + + /*! + * Returns a random deviate from a Gaussian distribution with zero mean and + * unit standard deviation. + */ + double operator ()() noexcept + { + /* + * Code adapted from 'Random number generation in C++', by John D. Cook: + * https://www.johndcook.com/blog/cpp_random_number_generation/ + * + * Implementation based on "A Simple Method for Generating Gamma + * Variables" by George Marsaglia and Wai Wan Tsang. ACM Transactions on + * Mathematical Software Vol 26, No 3, September 2000, pages 363-372. + */ + for ( ;; ) + { + double x, v; + do + { + x = m_normal(); + v = 1 + m_c*x; + } + while ( v <= 0 ); + v = v*v*v; + double u = m_R(); + double xsquared = x*x; + if ( u < 1 - 0.0331*xsquared*xsquared || Ln( u ) < 0.5*xsquared + m_d*(1 - v + Ln( v )) ) + { + double g = m_scale*m_d*v; + if ( m_shape < 1 ) + g *= Pow( m_R(), 1/m_shape ); + return g; + } + } + } + +private: + + RNG& m_R; + double m_shape; + double m_scale; + double m_d; + double m_c; + NormalRandomDeviates m_normal; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Random_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Random.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ReadWriteMutex.h b/3rdparty/include/pcl/ReadWriteMutex.h new file mode 100644 index 0000000..56fa9c9 --- /dev/null +++ b/3rdparty/include/pcl/ReadWriteMutex.h @@ -0,0 +1,194 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ReadWriteMutex.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_ReadWriteMutex_h +#define __PCL_ReadWriteMutex_h + +/// \file pcl/ReadWriteMutex.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ReadWriteMutex + * \brief Client-side interface to a PixInsight read/write mutex object + * + * %ReadWriteMutex provides separate thread synchronization for read and write + * operations. This can be more efficient than plain Mutex synchronization + * because multiple threads can access a data item for read-only operations + * simultaneously, which in turn improves concurrency if write accesses are + * relatively infrequent. + * + * \sa Mutex + */ +class PCL_CLASS ReadWriteMutex : public UIObject +{ +public: + + /*! + * Constructs a ReadWriteMutex object. + */ + ReadWriteMutex(); + + /*! + * Destroys a ReadWriteMutex object. + * + * \warning Destroying a locked %ReadWriteMutex object may result in + * undefined (mostly catastrophic) behavior. Always ensure that a read/write + * mutex has been unlocked before destroying it. + */ + virtual ~ReadWriteMutex() + { + } + + /*! + * Copy constructor. This constructor is disabled because %ReadWriteMutex + * represents unique server-side objects. + */ + ReadWriteMutex( const ReadWriteMutex& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %ReadWriteMutex + * represents unique server-side objects. + */ + ReadWriteMutex& operator =( const ReadWriteMutex& ) = delete; + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since mutexes are unique objects by definition, calling this member + * function has no effect. + */ + void EnsureUnique() override + { + // ReadWriteMutex instances are unique objects + } + + /*! + * Returns a reference to a null %ReadWriteMutex instance. A null + * %ReadWriteMutex does not correspond to an existing read/write mutex in + * the PixInsight core application. + */ + static ReadWriteMutex& Null(); + + /*! + * Locks this read/write mutex object for reading. + * + * The calling thread will block its execution if other thread has locked + * this read/write mutex for writing. + */ + void LockForRead(); + + /*! + * Locks this read/write mutex object for writing. + * + * The calling thread will block its execution if other thread has locked + * this read/write mutex for reading or writing. + */ + void LockForWrite(); + + /*! + * Attempts locking this read/write mutex object for reading. Returns true + * if this mutex has been successfully locked by the calling thread, false + * otherwise. + * + * Locking for reading will only fail if other thread has locked this object + * for writing. If other threads have locked this object for reading only, + * the calling thread will also lock it and this function will return true. + * + * Unlike LockForRead(), this function does not block execution of the + * calling thread if this %ReadWriteMutex cannot be locked for reading. + */ + bool TryLockForRead(); + + /*! + * Attempts locking this read/write mutex object for writing. Returns true if + * this mutex has been successfully locked by the calling thread, false + * otherwise. + * + * Locking for writing will fail if other thread has locked this object for + * reading or writing. + * + * Unlike LockForWrite(), this function does not block execution of the + * calling thread if this %ReadWriteMutex cannot be locked for writing. + */ + bool TryLockForWrite(); + + /*! + * Unlocks this %ReadWriteMutex object. + */ + void Unlock(); + +private: + + ReadWriteMutex( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ReadWriteMutex_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ReadWriteMutex.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ReadoutOptions.h b/3rdparty/include/pcl/ReadoutOptions.h new file mode 100644 index 0000000..fed809e --- /dev/null +++ b/3rdparty/include/pcl/ReadoutOptions.h @@ -0,0 +1,724 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ReadoutOptions.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_ReadoutOptions_h +#define __PCL_ReadoutOptions_h + +/// \file pcl/ReadoutOptions.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ReadoutData + * \brief Pixel readout data modes. + * + * + * + * + * + * + * + * + * + * + *
ReadoutData::RGBK RGB components or grayscale
ReadoutData::RGBL RGB components + CIE L* (lightness)
ReadoutData::RGBY RGB components + CIE Y (luminance)
ReadoutData::CIEXYZ CIE XYZ unit vectors
ReadoutData::CIELab CIE L*a*b* normalized components
ReadoutData::CIELch CIE L*c*h* normalized components
ReadoutData::HSV HSV components
ReadoutData::HSI HSI components
+ */ +namespace ReadoutData +{ + enum value_type + { + RGBK, // RGB components or grayscale + RGBL, // RGB components + CIE L* + RGBY, // RGB components + CIE Y + CIEXYZ, // CIE XYZ unit vectors + CIELab, // CIE L*a*b* normalized components + CIELch, // CIE L*c*h* normalized components + HSV, // HSV components + HSI, // HSI components + NumberOfModes + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ReadoutMode + * \brief Pixel readout calculation modes. + * + * + * + * + * + * + *
ReadoutMode::Mean Average of readout probe pixel values
ReadoutMode::Median Median of readout probe pixel values
ReadoutMode::Minimum The maximum pixel value in the readout probe area
ReadoutMode::Maximum The minimum pixel value in the readout probe area
+ */ +namespace ReadoutMode +{ + enum value_type + { + Mean, // Average of probe pixel values + Median, // Median of probe pixel values + Minimum, // The maximum pixel value in the probe area + Maximum, // The minimum pixel value in the probe area + NumberOfModes + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class ReadoutOptions + * \brief A structure to hold global pixel readout options. + * + * %ReadoutOptions holds a set of parameters that define how PixInsight + * calculates and presents numerical pixel data obtained directly from images. + * + * Readouts are generated dynamically when the user moves a pointing device + * cursor over an image in PixInsight. Generated readout data are shown on the + * %Readout toolbar, normally located at the bottom of the core application's + * main window, and are also shown on popup windows when the user clicks on the + * image. Furthermore, when the user presses the mouse over an image, readout + * values are sent to interface windows that request them (see + * \ref readout_notifications). When those interfaces receive readout values, + * they usually provide some visual feedback, or use them to modify their + * behavior, as appropriate. + * + * With %ReadoutOptions you can specify two sets of parameters: a first set + * that defines how readout values are calcualted, and a second set that + * indicates how the numerical readout values are presented to the user. + * + * The first parameter set includes the color space in which data is generated + * (e.g. RGB, HSV, CIE Lab, etc), the calculation mode used (average, median, + * minimum or maximum), and the size of the square box used to calculate + * readouts. + * + * The second set of parameters lets you choose between real and integer + * readouts. Real readouts are normalized to the [0,1] interval, where 0=black + * and 1=white. For real readouts you may also specify a resolution degree in + * terms of the amount of decimal digits shown (from 0 to 15). Integer readouts + * are given in the range from zero to an arbitrary maximum value that you can + * specify from 1 to 2^32-1. + * + * \sa ProcessInterface + */ +class PCL_CLASS ReadoutOptions +{ +public: + + /*! + * Represents a pixel readout data mode. + */ + typedef ReadoutData::value_type readout_data; + + /*! + * Represents a pixel readout calculation mode. + */ + typedef ReadoutMode::value_type readout_mode; + + /*! + * Maximum allowed size of a square readout probe. + */ + enum { MaxProbeSize = 15 }; + + /*! + * Maximum allowed number of decimal digits for real readout display. + */ + enum { MaxPrecision = 15 }; + + /*! + * Minimum and maximum allowed sizes of a square readout preview. + */ + enum { MinPreviewSize = 15, MaxPreviewSize = 127 }; + + /*! + * Maximum allowed zoom factor for readout previews. + */ + enum { MaxPreviewZoomFactor = 16 }; + + /*! + * Constructs a default %ReadoutOptions object. + */ + ReadoutOptions() = default; + + /*! + * Copy constructor. + */ + ReadoutOptions( const ReadoutOptions& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ReadoutOptions& operator =( const ReadoutOptions& ) = default; + + /*! + * Returns the current readout options retrieved from the PixInsight core + * application. + */ + static ReadoutOptions GetCurrentOptions(); + + /*! + * Sets new readout options in the PixInsight core application. + */ + static void SetCurrentOptions( const ReadoutOptions& ); + + /*! + * Returns the readout data mode in this %ReadoutOptions object. + */ + readout_data Data() const + { + return data; + } + + /*! + * Sets the readout data mode in this %ReadoutOptions object. + */ + void SetData( readout_data d ) + { + data = d; + } + + /*! + * Returns the readout calculation mode in this %ReadoutOptions object. + */ + readout_mode Mode() const + { + return mode; + } + + /*! + * Sets the readout calculation mode in this %ReadoutOptions object. + */ + void SetMode( readout_mode m ) + { + mode = m; + } + + /*! + * Returns true iff this %ReadoutOptions object enables presentation of alpha + * channel pixel readouts. + */ + bool ShowAlphaChannel() const + { + return showAlpha; + } + + /*! + * Enables inclusion of alpha channel values on pixel readouts. + */ + void EnableAlphaChannel( bool enable = true ) + { + showAlpha = enable; + } + + /*! + * Disables inclusion of alpha channel values on pixel readouts. + * + * This is a convenience function, equivalent to: + * EnableAlphaChannel( !disable ) + */ + void DisableAlphaChannel( bool disable = true ) + { + EnableAlphaChannel( !disable ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables presentation of mask + * channel pixel readouts. + */ + bool ShowMaskChannel() const + { + return showMask; + } + + /*! + * Enables inclusion of mask channel values on pixel readouts. + */ + void EnableMaskChannel( bool enable = true ) + { + showMask = enable; + } + + /*! + * Disables inclusion of mask channel values on pixel readouts. + * + * This is a convenience function, equivalent to: + * EnableMaskChannel( !disable ) + */ + void DisableMaskChannel( bool disable = true ) + { + EnableMaskChannel( !disable ); + } + + /*! + * Returns the readout probe size in pixels. + */ + int ProbeSize() const + { + return probeSize; + } + + /*! + * Sets the readout probe size in pixels. If a value of one is specified, + * readouts will be calculated for a single pixel. The specified size \a sz + * must be an odd integer in the range [1,15]. + */ + void SetProbeSize( int sz ) + { + probeSize = pcl::Range( sz, 1, int( MaxProbeSize ) ) | 1; + } + + /*! + * Returns the size in pixels of the real-time readout preview. + */ + int PreviewSize() const + { + return previewSize; + } + + /*! + * Sets the size in pixels of the real-time readout preview. The specified + * size \a sz must be an odd integer in the range [15,127]. + */ + void SetPreviewSize( int sz ) + { + previewSize = pcl::Range( sz, int( MinPreviewSize ), int( MaxPreviewSize ) ) | 1; + } + + /*! + * Returns the zoom factor applied to real-time readout previews. The + * returned value has the same meaning as for ImageWindow::ZoomFactor() and + * ImageWindow::SetViewport(). + */ + int PreviewZoomFactor() const + { + return previewZoom; + } + + /*! + * Sets the zoom factor to apply for generation of real-time readout + * previews. The specified \a zoom factor must be in the range [1,16], and + * has the same meaning as zoom factors for ImageWindow::SetViewport(). + */ + void SetPreviewZoomFactor( int zoom ) + { + previewZoom = pcl::Range( zoom, 1, int( MaxPreviewZoomFactor ) ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables generation of + * real-time readout previews. + */ + bool ShowPreview() const + { + return showPreview; + } + + /*! + * Enables generation of real-time readout previews. + */ + void EnablePreview( bool enable = true ) + { + showPreview = enable; + } + + /*! + * Disables generation of real-time readout previews. + */ + void DisablePreview( bool disable = true ) + { + EnablePreview( !disable ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables crosshair center + * lines on real-time readout previews. + */ + bool ShowPreviewCenter() const + { + return previewCenter; + } + + /*! + * Enables or disables crosshair center lines on real-time readout previews. + */ + void EnablePreviewCenter( bool enable = true ) + { + previewCenter = enable; + } + + /*! + * Disables or enables crosshair center lines on real-time readout previews. + */ + void DisablePreviewCenter( bool disable = true ) + { + EnablePreviewCenter( !disable ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables equatorial + * coordinates, which can be shown when the image has a valid astrometric + * solution. + */ + bool ShowEquatorialCoordinates() const + { + return showEquatorial; + } + + /*! + * Enables equatorial coordinates, which can be shown when the image has a + * valid astrometric solution. + */ + void EnableEquatorialCoordinates( bool enable = true ) + { + showEquatorial = enable; + } + + /*! + * Disables equatorial coordinates, which can be shown when the image has a + * valid astrometric solution. + */ + void DisableEquatorialCoordinates( bool disable = true ) + { + EnableEquatorialCoordinates( !disable ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables ecliptic + * coordinates, which can be shown when the image has a valid astrometric + * solution. + */ + bool ShowEclipticCoordinates() const + { + return showEcliptic; + } + + /*! + * Enables ecliptic coordinates, which can be shown when the image has a + * valid astrometric solution. + */ + void EnableEclipticCoordinates( bool enable = true ) + { + showEcliptic = enable; + } + + /*! + * Disables ecliptic coordinates, which can be shown when the image has a + * valid astrometric solution. + */ + void DisableEclipticCoordinates( bool disable = true ) + { + EnableEclipticCoordinates( !disable ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables galactic + * coordinates, which can be shown when the image has a valid astrometric + * solution. + */ + bool ShowGalacticCoordinates() const + { + return showGalactic; + } + + /*! + * Enables galactic coordinates, which can be shown when the image has a + * valid astrometric solution. + */ + void EnableGalacticCoordinates( bool enable = true ) + { + showGalactic = enable; + } + + /*! + * Disables galactic coordinates, which can be shown when the image has a + * valid astrometric solution. + */ + void DisableGalacticCoordinates( bool disable = true ) + { + EnableGalacticCoordinates( !disable ); + } + + /*! + * Returns the number of items used in sexagesimal representations of + * celestial spherical coordinates. The returned value can be one of: + * + * \li 1 - degrees/hours only. + * \li 2 - degrees/hours and minutes. + * \li 3 - degrees/hours, minutes and secons. + */ + int CoordinateItems() const + { + return coordinateItems; + } + + /*! + * Sets the number of items used in sexagesimal representations of celestial + * spherical coordinates. The specified value \a n must be one of: + * + * \li 1 - degrees/hours only. + * \li 2 - degrees/hours and minutes. + * \li 3 - degrees/hours, minutes and secons. + */ + void SetCoordinateItems( int n ) + { + coordinateItems = Range( n, 1, 3 ); + } + + /*! + * Returns the number of decimal digits represented for the last item in + * sexagesimal representations of celestial spherical coordinates. The + * returned value is an integer in the range [0,8]. + */ + int CoordinatePrecision() const + { + return coordinatePrecision; + } + + /*! + * Returns the actual number of decimal digits that should be used to + * represent spherical coordinates, as a function of the number of + * represented sexagesimal items. Returns a maximum of 3, 5 and 7 digits, + * respectively for 3, 2 and 1 represented items. These constraints allow + * for the representation of coordinates with milliarcsecond precision. + */ + int RealCoordinatePrecision() const + { + return Range( coordinatePrecision, 0, 3 + 2*(3 - coordinateItems) ); + } + + /*! + * Sets the number of decimal digits represented for the last item in + * sexagesimal representations of celestial spherical coordinates. The + * specified value \a n must be in the range [0,8]. + */ + void SetCoordinatePrecision( int n ) + { + coordinatePrecision = Range( n, 0, 8 ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables broadcasting of + * readout notifications. + * \sa \ref readout_notifications "readout notifications" + */ + bool IsBroadcastEnabled() const + { + return broadcast; + } + + /*! + * Enables or disables broadcasting of readout notifications. + * \sa \ref readout_notifications "readout notifications" + */ + void EnableBroadcast( bool enable = true ) + { + broadcast = enable; + } + + /*! + * Disables or enables broadcasting of readout notifications. + * \sa \ref readout_notifications "readout notifications" + */ + void DisableBroadcast( bool disable = true ) + { + EnableBroadcast( !disable ); + } + + /*! + * Returns true iff this %ReadoutOptions object enables floating point real + * pixel readouts. + */ + bool IsReal() const + { + return real; + } + + /*! + * Enables or disables floating point real pixel readouts. + */ + void SetReal( bool b = true ) + { + real = b; + } + + /*! + * Returns true iff this %ReadoutOptions object disables floating point real + * pixel readouts. + * + * This is a convenience function, equivalent to: + * !IsReal(). + */ + bool IsInteger() const + { + return !IsReal(); + } + + /*! + * Enables or disables integer pixel readouts. + * + * This is a convenience function, equivalent to: + * SetReal( !b ) + */ + void SetInteger( bool b = true ) + { + SetReal( !b ); + } + + /*! + * Returns the precision for floating point real pixel readouts. The + * returned value is the number of decimal digits employed to represent real + * pixel readouts. + */ + int Precision() const + { + return precision; + } + + /*! + * Sets the precision for floating point real pixel readouts. The specified + * value is the number \a n of decimal digits employed to represent real + * pixel readouts. + */ + void SetPrecision( int n ) + { + precision = pcl::Range( n, 0, int( MaxPrecision ) ); + } + + /*! + * Returns the maximum value of integer pixel readouts. + */ + unsigned IntegerRange() const + { + return range; + } + + /*! + * Sets the maximum value of integer pixel readouts. + */ + void SetIntegerRange( unsigned n ) + { + range = pcl::Range( uint32( n ), uint32( 1 ), ~uint32( 0 ) ); + } + + /*! + * Selects the 8-bit integer readout range. + * + * This is a convenience function, equivalent to: + * SetIntegerRange( uint8_max ) + */ + void Set8BitRange() + { + SetIntegerRange( uint8_max ); + } + + /*! + * Selects the 16-bit integer readout range. + * + * This is a convenience function, equivalent to: + * SetIntegerRange( uint16_max ) + */ + void Set16BitRange() + { + SetIntegerRange( uint16_max ); + } + + /*! + * Selects the 32-bit integer readout range. + * + * This is a convenience function, equivalent to: + * SetIntegerRange( uint32_max ) + */ + void Set32BitRange() + { + SetIntegerRange( uint32_max ); + } + +#ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION +protected: +#else +private: +#endif + + readout_data data = ReadoutData::RGBK; + readout_mode mode = ReadoutMode::Mean; + int probeSize = 1; // size of the square probe - must be an odd number + int previewSize = 25; // size of the square preview - must be an odd number + int previewZoom = 8; // readout preview zoom factor >= 1 + int precision = 4; // number of decimal digits if real==true + unsigned range = uint16_max; // maximum discrete value if real==false + bool showAlpha = true; // show alpha channel readouts? + bool showMask = true; // show mask channel readouts? + bool showPreview = true; // show real-time readout previews? + bool previewCenter = true; // draw center crosshairs on readout previews? + bool showEquatorial = true; // show equatorial coordinates + bool showEcliptic = false; // show ecliptic coordinates + bool showGalactic = false; // show galactic coordinates + int coordinateItems = 3; // 1=degrees/hours 2=minutes 3=seconds + int coordinatePrecision = 2; // decimal digits of last represented item + bool broadcast = true; // broadcast readouts? + bool real = true; // true=real, false=integer +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ReadoutOptions_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ReadoutOptions.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/RealTimePreview.h b/3rdparty/include/pcl/RealTimePreview.h new file mode 100644 index 0000000..4d75853 --- /dev/null +++ b/3rdparty/include/pcl/RealTimePreview.h @@ -0,0 +1,241 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/RealTimePreview.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_RealTimePreview_h +#define __PCL_RealTimePreview_h + +/// \file pcl/RealTimePreview.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class ProcessInterface; + +/*! + * \class RealTimePreview + * \brief Client-side interface to the Real-Time Preview system. + * + * %RealTimePreview is a high-level, client-side interface to the Real-Time + * Preview system available in the PixInsight core application. + * + * \note The Real-Time Preview system is undergoing extensive development in + * PixInsight. Be aware that this class will be updated and enhanced + * considerably in future PCL releases. + */ +class PCL_CLASS RealTimePreview +{ +public: + + /*! + * Default constructor. This constructor is disabled because + * %RealTimePreview is not an instantiable class. + */ + RealTimePreview() = delete; + + /*! + * Copy constructor. This constructor is disabled because %RealTimePreview + * is not an instantiable class. + */ + RealTimePreview( const RealTimePreview& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %RealTimePreview is + * not an instantiable class. + */ + RealTimePreview& operator =( const RealTimePreview& ) = delete; + + /*! + * Destructor. This destructor is disabled because %RealTimePreview is not + * an instantiable class. + */ + ~RealTimePreview() = delete; + + /*! + * Sets the owner of the Real-Time Preview interface. + * + * \param owner Reference to a process interface that will own the + * Real-Time Preview interface in the PixInsight core + * application. + * + * The owner of the Real-Time Preview is the interface currently providing + * data for generation of real-time image renditions. Only one interface can + * own the Real-Time Preview at a given time. + * + * Calling this function causes the immediate regeneration of the real-time + * image rendition, in the terms described for the Update() member function. + */ + static bool SetOwner( ProcessInterface& owner ); + + /*! + * Generates a new Real-Time Preview image rendition. + * + * A new real-time preview image can always be generated if there is a view + * currently selected on the Real-Time Preview window, if the selected view + * is not read-locked, and if the Real-Time Preview is not already busy. + * When all of that conditions are met, calling this function causes the + * immediate regeneration of the real-time preview image. + */ + static void Update(); + + /*! + * Returns true iff the Real-Time Preview is currently busy, i.e. if there is + * an active real-time rendition process. + */ + static bool IsUpdating(); + + /*! + * Requests a modal progress dialog associated with the Real-Time Preview + * interface during a real-time preview generation process. + * + * \param title The title of the modal progress dialog. + * + * \param text The informative text shown on the progress dialog. Keep in + * mind that this string will be shown on a single text line, + * so a reasonable maximum length should be about 50-60 + * characters. + * + * \param total Total number of progress steps. The progress bar + * on the dialog can be incremented by successive calls to + * SetProgressCount() up to this value. If this parameter is + * zero, the progress dialog will be \e unbounded and will + * only show a busy state (typically, a progress bar + * bouncing horizontally at regular intervals). + * + * This function allows you to show a modal dialog with a horizontal + * progress bar, a single-line text label and a standard Cancel button + * during long real-time generation procedures. These dialogs are useful to + * provide feedback to the user and to allow her or him to abort the ongoing + * real-time rendition task. + * + * This member function can only be called during a real-time preview + * generation process, that is, when a reimplemented + * ProcessInterface::GenerateRealTimePreview() function is running. Calling + * this function when no real-time rendition is taking place has no effect. + * + * Unlike most PCL routines involving dynamic changes to graphical interface + * elements, this function is thread-safe. You can safely call it from a + * running thread, which is a typical use because real-time generation tasks + * are normally (and \e should normally be) implemented as parallel threads + * to keep the GUI responsive. However, for the progress dialog to work it + * is necessary that the application's main event queue be active with + * sufficient granularity. In general, if you follow good UI programming + * techniques and use PCL example modules as a starting point to write your + * code, there should be no practical problems. + * + * \note Be aware that the progress dialog shown by this function is + * application-modal. This means that the only user interaction allowed + * while the dialog is visible is closing it, either by clicking its Cancel + * button, by pressing the Esc key, or by clicking its Close title bar icon. + * An important consequence of this is that you \e must ensure that your + * real-time generation process will end immediately and unconditionally + * when the dialog is closed. If your code is coherent with the GUI states + * of your process interface, the default PCL implementation should work. In + * some complex scenarios you may need to reimplement the + * ProcessInterface::CancelRealTimePreview() member function. + */ + static void ShowProgressDialog( const String& title, const String& text, size_type total ); + + /*! + * Requests closing a progress dialog previously shown by a call to + * ShowProgressDialog(). + */ + static void CloseProgressDialog(); + + /*! + * Returns true iff a modal progress dialog is currently visible after a call + * to ShowProgressDialog(). + */ + static bool IsProgressDialogVisible(); + + /*! + * Sets the current value of the modal progress dialog associated with the + * Real-Time Preview interface to the specified \a count. + * + * If the progress dialog is bounded, i.e. if you specified a nonzero total + * count when you called ShowProgressDialog(), then the \a count value set + * by this function should never be greater than the dialog's total count. + * If the dialog is unbounded, then you just have to increment the count to + * animate the dialog's busy state. + * + * If a progress dialog is not visible after a successful call to + * ShowProgressDialog(), this function is simply ignored. + */ + static void SetProgressCount( size_type count ); + + /*! + * Sets the current single-line label's \a text shown on the modal progress + * dialog associated with the Real-Time Preview interface. + * + * If a progress dialog is not visible after a successful call to + * ShowProgressDialog(), this function is simply ignored. + */ + static void SetProgressText( const String& text ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_RealTimePreview_h + +// ---------------------------------------------------------------------------- +// EOF pcl/RealTimePreview.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/RealTimeProgressStatus.h b/3rdparty/include/pcl/RealTimeProgressStatus.h new file mode 100644 index 0000000..e183788 --- /dev/null +++ b/3rdparty/include/pcl/RealTimeProgressStatus.h @@ -0,0 +1,188 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/RealTimeProgressStatus.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_RealTimeProgressStatus_h +#define __PCL_RealTimeProgressStatus_h + +/// \file pcl/RealTimeProgressStatus.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class RealTimeProgressStatus + * \brief A status monitoring callback to provide progress feedback during long + * real-time preview generation procedures. + * + * %RealTimeProgressStatus allows you to drive the Real-Time Preview progress + * dialog during long real-time preview generation tasks. Using this class is + * recommended for real-time renditions consistently taking more than a couple + * of seconds to complete on contemporary hardware. + * + * For detailed information on the Real-Time Preview system and its associated + * modal progress dialog functionality, please refer to the RealTimePreview + * class and the RealTimePreview::ShowProgressDialog() static member function. + * + * \sa RealTimePreview, StatusCallback, StatusMonitor, MuteStatus + */ +class PCL_CLASS RealTimeProgressStatus : public MuteStatus +{ +public: + + /*! + * Constructs a %RealTimeProgressStatus instance. + * + * \param title The text that will be shown as the tile of the Real-Time + * Preview progress dialog window. Typically this text will + * be shown centered on the dialog's title bar. + */ + RealTimeProgressStatus( const String& title ) + : m_title( title ) + { + } + + /*! + * Copy constructor. + */ + RealTimeProgressStatus( const RealTimeProgressStatus& x ) + : MuteStatus( x ) + , m_title( x.m_title ) + { + } + + /*! + * This function is called by a status \a monitor object when a new + * monitored process is about to start. + * + * As reimplemented in %RealTimeProgressStatus, this function opens the + * Real-Time Preview progress dialog window and initializes it with the + * monitor's total count and information text. + */ + int Initialized( const StatusMonitor& monitor ) const override + { + if ( MuteStatus::Initialized( monitor ) == 0 ) + { + RealTimePreview::ShowProgressDialog( m_title, monitor.Info(), monitor.Total() ); + return 0; + } + return 1; + } + + /*! + * Function called by a status \a monitor object to signal an update of the + * progress count for the current process. + * + * As reimplemented in %RealTimeProgressStatus, this function updates the + * Real-Time Preview progress dialog with the current monitor's count. + */ + int Updated( const StatusMonitor& monitor ) const override + { + if ( MuteStatus::Updated( monitor ) == 0 ) + { + RealTimePreview::SetProgressCount( monitor.Count() ); + return 0; + } + return 1; + } + + /*! + * Function called by a status \a monitor object to signal that the current + * process has finished. + * + * As reimplemented in %RealTimeProgressStatus, this function closes the + * Real-Time Preview progress dialog window. + */ + int Completed( const StatusMonitor& monitor ) const override + { + if ( MuteStatus::Completed( monitor ) == 0 ) + { + RealTimePreview::CloseProgressDialog(); + return 0; + } + return 1; + } + + /*! + * Function called by a status \a monitor object when the progress + * information for the current process has been changed. + * + * As reimplemented in %RealTimeProgressStatus, this function updates the + * single-line label text on the Real-Time Preview progress dialog. + */ + void InfoUpdated( const StatusMonitor& monitor ) const override + { + RealTimePreview::SetProgressText( monitor.Info() ); + } + +private: + + String m_title; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_RealTimeProgressStatus_h + +// ---------------------------------------------------------------------------- +// EOF pcl/RealTimeProgressStatus.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Rectangle.h b/3rdparty/include/pcl/Rectangle.h new file mode 100644 index 0000000..1662402 --- /dev/null +++ b/3rdparty/include/pcl/Rectangle.h @@ -0,0 +1,3024 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Rectangle.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_Rectangle_h +#define __PCL_Rectangle_h + +/// \file pcl/Rectangle.h + +#include + +#include +#include +#include +#include + +#ifdef __PCL_QT_INTERFACE +# include +# ifndef __PCL_QT_NO_RECT_DRAWING_HELPERS +# include +# include +# endif +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::Clip + * \brief %Clip codes used by the Sutherland-Cohen line clipping algorithm. + * + * Sutherland-Cohen clip codes: + * + * + * + * + * + * + *
Clip::Left Clipping occurs at the left side of the clipping rectangle
Clip::Top Clipping occurs at the top side of the clipping rectangle
Clip::Right Clipping occurs at the right side of the clipping rectangle
Clip::Bottom Clipping occurs at the bottom side of the clipping rectangle
+ */ +namespace Clip +{ + enum mask_type + { + Left = 0x01, // Clipped at the left side + Top = 0x02, // Clipped at the top side + Right = 0x04, // Clipped at the right side + Bottom = 0x08 // Clipped at the bottom side + }; +} + +/*! + * A collection of Sutherland-Cohen clip code flags. + */ +typedef Flags ClipFlags; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup rect_classification_2d Rectangle Classification Functions + */ + +/*! + * Returns true iff a set of rectangle coordinates correspond to a point. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * The specified coordinates define a point if and only if + * \a x0 = \a x1 and \a y0 = \a y1. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsPoint( T x0, T y0, T x1, T y1 ) noexcept +{ + return x0 == x1 && y0 == y1; +} + +/*! + * Returns true iff a set of rectangle coordinates define a line. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * The specified coordinates define a line if any of two conditions hold: + * \a x0 = \a x1 or \a y0 = \a y1, but not both conditions, that is, if + * the coordinates don't define a point. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsLine( T x0, T y0, T x1, T y1 ) noexcept +{ + return ((x0 == x1) ^ (y0 == y1)) != 0; +} + +/*! + * Returns true iff a set of rectangle coordinates define a horizontal line. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * The specified coordinates define a horizontal line if and only if + * \a y0 = \a y1 and \a x0 != \a x1. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsHorizontalLine( T x0, T y0, T x1, T y1 ) noexcept +{ + return y0 == y1 && x0 != x1; +} + +/*! + * Returns true iff a set of rectangle coordinates define a vertical line. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * The specified coordinates define a vertical line if and only if + * \a x0 = \a x1 and \a y0 != \a y1. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsVerticalLine( T x0, T y0, T x1, T y1 ) noexcept +{ + return x0 == x1 && y0 != y1; +} + +/*! + * Returns true iff a set of rectangle coordinates define a point or a line. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * The specified coordinates define a point or line if either + * \a x0 = \a x1 or \a y0 = \a y1. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsPointOrLine( T x0, T y0, T x1, T y1 ) noexcept +{ + return x0 == x1 || y0 == y1; +} + +/*! + * Returns true iff a set of rectangle coordinates define a rectangle. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * The specified coordinates define a rectangle if and only if + * \a x0 != \a x1 and \a y0 != \a y1. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsRect( T x0, T y0, T x1, T y1 ) noexcept +{ + return x0 != x1 && y0 != y1; +} + +/*! + * Returns true iff a set of rectangle coordinates define a normal rectangle. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * A normal rectangle requires that \a x0 < \a x1 and \a y0 < \a y1. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsNormalRect( T x0, T y0, T x1, T y1 ) noexcept +{ + return x0 < x1 && y0 < y1; +} + +/*! + * Returns true iff a set of rectangle coordinates define an ordered rectangle. + * + * \param x0,y0 Upper left corner coordinates. + * \param x1,y1 Lower right corner coordinates. + * + * An ordered rectangle requires that \a x0 <= \a x1 and \a y0 <= \a y1, that + * is, it can be a normal rectangle, a line, or a point. + * + * \ingroup rect_classification_2d + */ +template inline +bool IsOrderedRect( T x0, T y0, T x1, T y1 ) noexcept +{ + return x0 <= x1 && y0 <= y1; +} + +/*! + * Orders a set of rectangle coordinates to define an ordered rectangle. + * + * \param[out] x0,y0 References to the upper left corner coordinates. + * \param[out] x1,y1 References to the lower right corner coordinates. + * + * This function ensures that \a x0 <= \a x1 and \a y0 <= \a y1, by exchanging + * coordinates if necessary. + * + * \ingroup rect_classification_2d + */ +template inline +void OrderRect( T& x0, T& y0, T& x1, T& y1 ) noexcept +{ + if ( x1 < x0 ) + pcl::Swap( x0, x1 ); + if ( y1 < y0 ) + pcl::Swap( y0, y1 ); +} + +// ---------------------------------------------------------------------------- + +/* + * ### NB: Template class GenericRectangle cannot have virtual member + * functions. This is because internal PCL and core routines rely on + * GenericRectangle, GenericRectangle and + * GenericRectangle to be directly castable to int*, float* and + * double*, respectively. See also the PCL_ASSERT_RECT_SIZE() macro. + */ + +#define PCL_ASSERT_RECT_SIZE() \ + static_assert( sizeof( *this ) == 4*sizeof( T ), "Invalid sizeof( GenericRectangle<> )" ) + +/*! + * \class GenericRectangle + * \brief A generic rectangle in the two-dimensional space. + * + * %GenericRectangle implements a rectangle in the plane, specified by the \a x + * and \a y coordinates of two of its corners. The type T represents scalar + * rectangle coordinates and can be any real or integer numerical type. + * + * The coordinates of %GenericRectangle are directly accessed by its x0, y0, x1 + * and y1 data members. If the rectangle is \e ordered, x0 and y0 are the + * coordinates of its upper left corner, and x1, y1 are the coordinates of its + * lower right corner. Given a %GenericRectangle instance \a r, you can use + * \a r.x0, \a r.y0, \a r.x1 and \a r.y1 directly to get or set coordinate + * values. + * + * \b Important - In PCL, the right and bottom coordinates of a rectangle (that + * is, the values of its x1 and y1 members) are \e excluded from the + * corresponding rectangular area. The following holds for any rectangle \a r + * in PCL: + * + * \a r.Width() = \a r.x1 - \a r.x0 \n + * \a r.Height() = \a r.y1 - \a r.y0 + * + * This is particularly relevant with template instantiations for integer + * types, as GenericRectangle\. + * + * \sa \ref rect_types_2d "2-D Rectangle Types", + * \ref rect_functions_2d "2-D Rectangle Operators and Functions", + * \ref rect_classification_2d "2-D Rectangle Classification Functions", + * GenericPoint + */ +template +class PCL_CLASS GenericRectangle +{ +public: + + /*! + * Represents the type of a point or rectangle component. + */ + typedef T component; + + /*! + * Represents a point on the plane. + */ + typedef GenericPoint point; + + /* + * Rectangle coordinates: x0=left, y0=top, x1=right, y1=bottom. + * The x1 (right) and y1 (bottom) coordinates are excluded from the + * rectangular area, so we always have: width=x1-x0 and height=y1-y0. + */ + component x0; //!< Horizontal coordinate of the upper left corner. + component y0; //!< Vertical coordinate of the upper left corner. + component x1; //!< Horizontal coordinate of the lower right corner. + component y1; //!< Vertical coordinate of the lower right corner. + + /*! + * Constructs a default %GenericRectangle instance. Rectangle coordinates + * are not initialized, so they'll have unpredictable garbage values. + */ + constexpr GenericRectangle() + { + PCL_ASSERT_RECT_SIZE(); + } + + /*! + * Constructs a %GenericRectangle instance given by its coordinates in the + * plane. + * + * \param left,top Coordinates of the upper left corner. + * \param right,bottom Coordinates of the lower right corner. + * + * The type T1 can be any suitable real or integer numerical type, or a + * type with numeric conversion semantics. + */ + template + constexpr GenericRectangle( T1 left, T1 top, T1 right, T1 bottom ) + : x0( component( left ) ) + , y0( component( top ) ) + , x1( component( right ) ) + , y1( component( bottom ) ) + { + PCL_ASSERT_RECT_SIZE(); + } + + /*! + * Constructs a %GenericRectangle instance from coordinates taken from the + * specified initializer list \a l. + * + * This constructor will copy 4, 3, 2, 1 or zero rectangle coordinates, + * depending on the number of values in the initializer list. Coordinates + * that cannot be initialized from list values will be set to zero. For + * example, the following code: + * + * \code + * Rect r1 = {}; + * Rect r2 = { 1, 2 }; + * Rect r3 = { 1, 2, 3 }; + * Rect r4 = { 1, 2, 3, 4 }; + * \endcode + * + * is functionally equivalent to: + * + * \code + * Rect r1( 0, 0, 0, 0 ); + * Rect r2( 1, 2, 0, 0 ); + * Rect r3( 1, 2, 3, 0 }; + * Rect r4( 1, 2, 3, 4 }; + * \endcode + */ + template + GenericRectangle( std::initializer_list l ) + { + PCL_ASSERT_RECT_SIZE(); + switch ( l.size() ) + { + default: + case 4: y1 = component( l.begin()[3] ); + case 3: x1 = component( l.begin()[2] ); + case 2: y0 = component( l.begin()[1] ); + case 1: x0 = component( l.begin()[0] ); + case 0: break; + } + switch ( l.size() ) + { + case 0: x0 = component( 0 ); + case 1: y0 = component( 0 ); + case 2: x1 = component( 0 ); + case 3: y1 = component( 0 ); + default: + case 4: break; + } + } + + /*! + * Constructs a %GenericRectangle instance given two points in the plane. + * + * \param leftTop Position of the upper left corner. + * \param rightBottom Position of the lower right corner. + * + * The type T1 can be any suitable real or integer numerical type, or a + * type with numeric conversion semantics. + */ + template + GenericRectangle( const pcl::GenericPoint& leftTop, const pcl::GenericPoint& rightBottom ) + : GenericRectangle( component( leftTop.x ), component( leftTop.y ), + component( rightBottom.x ), component( rightBottom.y ) ) + { + PCL_ASSERT_RECT_SIZE(); + } + + /*! + * Constructs a %GenericRectangle instance given its \a width and \a height. + * The coordinates of the constructed rectangle will be as follows: + * + * x0 = y0 = 0 \n + * x1 = width \n + * y1 = height + */ + constexpr GenericRectangle( component width, component height ) + : GenericRectangle( component( 0 ), component( 0 ), width, height ) + { + PCL_ASSERT_RECT_SIZE(); + } + + /*! + * Constructs a %GenericRectangle instance corresponding to a point located + * at the coordinates specified by a scalar \a d. + * + * The constructed rectangle will have all of its coordinates equal to the + * scalar \a d. + */ + constexpr GenericRectangle( component d ) + : GenericRectangle( d, d, d, d ) + { + PCL_ASSERT_RECT_SIZE(); + } + + /*! + * Nontrivial copy constructor. Constructs a %GenericRectangle instance as a + * copy of the specified rectangle \a r. + */ + template + GenericRectangle( const GenericRectangle& r ) + : GenericRectangle( component( r.x0 ), component( r.y0 ), + component( r.x1 ), component( r.y1 ) ) + { + PCL_ASSERT_RECT_SIZE(); + } + +#ifdef __PCL_QT_INTERFACE + GenericRectangle( const QRect& r ) + : GenericRectangle( component( r.left() ), component( r.top() ), + component( r.right()+1 ), component( r.bottom()+1 ) ) + { + PCL_ASSERT_RECT_SIZE(); + } + + GenericRectangle( const QPoint& p0, const QPoint& p1 ) + : GenericRectangle( component( p0.x() ), component( p0.y() ), + component( p1.x() ), component( p1.y() ) ) + { + PCL_ASSERT_RECT_SIZE(); + } +#endif + + /*! + * Returns the left coordinate of this rectangle. This function returns the + * value of the x0 data member. + */ + component Left() const noexcept + { + return x0; + } + + /*! + * Returns the top coordinate of this rectangle. This function returns the + * value of the y0 data member. + */ + component Top() const noexcept + { + return y0; + } + + /*! + * Returns the right coordinate of this rectangle. This function returns the + * value of the x1 data member. + */ + component Right() const noexcept + { + return x1; + } + + /*! + * Returns the bottom coordinate of this rectangle. This function returns + * the value of the y1 data member. + */ + component Bottom() const noexcept + { + return y1; + } + + /*! + * Returns a point with the coordinates of the upper left (left-top) corner + * of this rectangle. + */ + point LeftTop() const noexcept + { + return point( pcl::Min( x0, x1 ), pcl::Min( y0, y1 ) ); + } + + /*! + * A synonym for LeftTop(). + */ + point TopLeft() const noexcept + { + return LeftTop(); + } + + /*! + * Returns a point with the coordinates of the upper right (right-top) + * corner of this rectangle. + */ + point RightTop() const noexcept + { + return point( pcl::Max( x0, x1 ), pcl::Min( y0, y1 ) ); + } + + /*! + * A synonym for RightTop(). + */ + point TopRight() const noexcept + { + return RightTop(); + } + + /*! + * Returns a point with the coordinates of the lower left (left-bottom) + * corner of this rectangle. + */ + point LeftBottom() const noexcept + { + return point( pcl::Min( x0, x1 ), pcl::Max( y0, y1 ) ); + } + + /*! + * A synonym for LeftBottom(). + */ + point BottomLeft() const noexcept + { + return LeftBottom(); + } + + /*! + * Returns a point with the coordinates of the lower right (right-bottom) + * corner of this rectangle. + */ + point RightBottom() const noexcept + { + return point( pcl::Max( x0, x1 ), pcl::Max( y0, y1 ) ); + } + + /*! + * A synonym for RightBottom(). + */ + point BottomRight() const noexcept + { + return RightBottom(); + } + + /*! + * Returns a point with the coordinates of the center of this rectangle. + */ + point Center() const noexcept + { + return point( (x0 + x1)/2, (y0 + y1)/2 ); + } + + /*! + * Returns the upper middle (center-top) point of this rectangle. + */ + point CenterTop() const noexcept + { + return point( (x0 + x1)/2, pcl::Min( y0, y1 ) ); + } + + /*! + * Returns the lower middle (center-bottom) point of this rectangle. + */ + point CenterBottom() const noexcept + { + return point( (x0 + x1)/2, pcl::Min( y0, y1 ) ); + } + + /*! + * Returns the left middle (center-left) point of this rectangle. + */ + point CenterLeft() const noexcept + { + return point( pcl::Min( x0, x1 ), (y0 + y1)/2 ); + } + + /*! + * Returns the right middle (center-right) point of this rectangle. + */ + point CenterRight() const noexcept + { + return point( pcl::Min( x0, x1 ), (y0 + y1)/2 ); + } + + /*! + * Returns the width of this rectangle. The returned value is the absolute + * difference between the x1 and x0 data members. + */ + component Width() const noexcept + { + return pcl::Abs( x1 - x0 ); + } + + /*! + * Returns the height of this rectangle. The returned value is the absolute + * difference between the y1 and y0 data members. + */ + component Height() const noexcept + { + return pcl::Abs( y1 - y0 ); + } + + /*! + * Returns the perimeter of this rectangle. The returned value is equal to + * twice the width plus twice the height. + */ + component Perimeter() const noexcept + { + component w = Width(), h = Height(); + return w+w+h+h; + } + + /*! + * Returns the Manhattan distance between two opposite corners of this + * rectangle. + * + * The returned value is equal to the width plus the height. + */ + component ManhattanDistance() const noexcept + { + return Width() + Height(); + } + + /*! + * Returns the area of this rectangle. The returned value is equal to the + * width multiplied by the height. + */ + component Area() const noexcept + { + return pcl::Abs( (x1 - x0)*(y1 - y0) ); + } + + /*! + * Returns the x coordinate of the central point of this rectangle. The + * returned value is a \c double real value equal to 0.5*(x0 + x1). + */ + double CenterX() const noexcept + { + return 0.5*(x0 + x1); + } + + /*! + * Returns the y coordinate of the central point of this rectangle. The + * returned value is a \c double real value equal to 0.5*(y0 + y1). + */ + double CenterY() const noexcept + { + return 0.5*(y0 + y1); + } + + /*! + * Returns the square of the diagonal of this rectangle. This is also the + * square of the hypotenuse of the half-triangle defined by this rectangle. + * The returned value is equal to the square of the width multiplied by the + * square of the height. + */ + double Hypot() const noexcept + { + double w = x1 - x0, h = y1 - y0; + return w*w + h*h; + } + + /*! + * Returns the length of the diagonal of this rectangle, equal to the square + * root of the Hypot() function. + */ + double Diagonal() const noexcept + { + return pcl::Sqrt( Hypot() ); + } + + /*! + * Returns true iff this rectangle defines a point in the plane. + */ + bool IsPoint() const noexcept + { + return pcl::IsPoint( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this rectangle defines a line. + */ + bool IsLine() const noexcept + { + return pcl::IsLine( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this rectangle defines a horizontal line. + */ + bool IsHorizontalLine() const noexcept + { + return pcl::IsHorizontalLine( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this rectangle defines a vertical line. + */ + bool IsVerticalLine() const noexcept + { + return pcl::IsVerticalLine( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this rectangle defines a point or a line. + */ + bool IsPointOrLine() const noexcept + { + return pcl::IsPointOrLine( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff the coordinates of this object define a rectangle, + * instead of a point or a line. + */ + bool IsRect() const noexcept + { + return pcl::IsRect( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this is a normal rectangle. + */ + bool IsNormal() const noexcept + { + return pcl::IsNormalRect( x0, y0, x1, y1 ); + } + + /*! + * Returns true iff this is an ordered rectangle. + */ + bool IsOrdered() const noexcept + { + return pcl::IsOrderedRect( x0, y0, x1, y1 ); + } + + /*! + * Orders the coordinates of this rectangle. + */ + void Order() noexcept + { + pcl::OrderRect( x0, y0, x1, y1 ); + } + + /*! + * Returns an ordered rectangle equivalent to this. + */ + GenericRectangle Ordered() const noexcept + { + GenericRectangle r = *this; + r.Order(); + return r; + } + + /*! + * Given the coordinates \a x and \a y of a point in the plane, this + * function returns a clip code for the Sutherland-Cohen line clipping + * algorithm. + * + * The returned value is a combination of flags defined in the Clip + * namespace. + */ + template + ClipFlags ClipCode( T1 x, T1 y ) const noexcept + { + ClipFlags clip; // defaults to zero + + if ( x0 <= x1 ) + { + if ( x < x0 ) clip |= Clip::Left; + if ( x > x1 ) clip |= Clip::Right; + } + else + { + if ( x < x1 ) clip |= Clip::Left; + if ( x > x0 ) clip |= Clip::Right; + } + + if ( y0 <= y1 ) + { + if ( y < y0 ) clip |= Clip::Top; + if ( y > y1 ) clip |= Clip::Bottom; + } + else + { + if ( y < y1 ) clip |= Clip::Top; + if ( y > y0 ) clip |= Clip::Bottom; + } + + return clip; + } + + /*! + * Given a point \a p in the plane, this function returns a clip code for + * the Sutherland-Cohen line clipping algorithm. + * + * The returned value is a combination of flags defined in the Clip + * namespace. + */ + template + ClipFlags ClipCode( const pcl::GenericPoint& p ) const noexcept + { + return ClipCode( p.x, p.y ); + } + + /*! + * Returns true iff this rectangle includes a point specified by its + * separate \a x and \a y coordinates. + */ + template + bool Includes( T1 x, T1 y ) const noexcept + { + return ((x0 < x1) ? (x >= x0 && x <= x1) : (x >= x1 && x <= x0)) && + ((y0 < y1) ? (y >= y0 && y <= y1) : (y >= y1 && y <= y0)); + } + + /*! + * Returns true iff this rectangle includes a point \a p. + */ + template + bool Includes( const pcl::GenericPoint& p ) const noexcept + { + return Includes( p.x, p.y ); + } + + /*! + * Returns true iff this rectangle completely includes a rectangle \a r. + */ + template + bool Includes( const GenericRectangle& r ) const noexcept + { + return Includes( r.x0, r.y0 ) && Includes( r.x1, r.y1 ); + } + +#ifdef __PCL_QT_INTERFACE + bool Includes( const QPoint& p ) const noexcept + { + return Includes( p.x(), p.y() ); + } + + bool Includes( const QRect& r ) const noexcept + { + return Includes( r.left(), r.top() ) && Includes( r.right()+1, r.bottom()+1 ); + } +#endif + + /*! + * Returns true iff this rectangle includes a point specified by its + * separate \a x and \a y coordinates. + * + * This function assumes an ordered rectangle, that is, it requires that the + * conditions x0 ≤ x1 and y0 ≤ y1 hold. Otherwise this function will + * return a wrong result. + */ + template + bool IncludesFast( T1 x, T1 y ) const noexcept + { + return x >= x0 && y >= y0 && x <= x1 && y <= y1; + } + + /*! + * Returns true iff this rectangle includes a point \a p. + * + * This function assumes an ordered rectangle, that is, it requires that the + * conditions x0 ≤ x1 and y0 ≤ y1 hold. Otherwise this function will + * return a wrong result. + */ + template + bool IncludesFast( const pcl::GenericPoint& p ) const noexcept + { + return IncludesFast( p.x, p.y ); + } + + /*! + * Returns true iff this rectangle intersects a rectangle specified by its + * individual coordinates. + * + * \param left,top Upper left corner coordinates of a rectangle to test + * for intersection. + * + * \param right,bottom Lower right corner coordinates of a rectangle to test + * for intersection. + */ + template + bool Intersects( T1 left, T1 top, T1 right, T1 bottom ) const noexcept + { + OrderRect( left, top, right, bottom ); + return ((x0 < x1) ? (right >= x0 && left <= x1) : (right >= x1 && left <= x0)) && + ((y0 < y1) ? (bottom >= y0 && top <= y1) : (bottom >= y1 && top <= y0)); + } + + /*! + * Returns true iff this rectangle intersects a rectangle \a r. + */ + template + bool Intersects( const pcl::GenericRectangle& r ) const noexcept + { + return Intersects( r.x0, r.y0, r.x1, r.y1 ); + } + +#ifdef __PCL_QT_INTERFACE + bool Intersects( const QRect& r ) const noexcept + { + return Intersects( r.left(), r.top(), r.right()+1, r.bottom()+1 ); + } +#endif + + /*! + * Returns true iff this rectangle intersects a rectangle specified by its + * individual coordinates. + * + * \param left,top Upper left corner coordinates of a rectangle to test + * for intersection. + * + * \param right,bottom Lower right corner coordinates of a rectangle to test + * for intersection. + * + * For a valid result, this function assumes the following conditions: + * + * \li The specified set \a left, \a top, \a right and \a bottom must define + * an ordered rectangle, that is, the conditions \a left ≤ \a right and + * \a top ≤ \a bottom must hold. + * + * \li This rectangle must be ordered, that is, the conditions x0 ≤ x1 + * and y0 ≤ y1 must hold. + */ + template + bool IntersectsFast( T1 left, T1 top, T1 right, T1 bottom ) const noexcept + { + return right >= x0 && left <= x1 && bottom >= y0 && top <= y1; + } + + /*! + * Returns true iff this rectangle intersects a rectangle \a r. + * + * To give a valid result, this function assumes that both this and the + * specified object \a r are ordered rectangles. + */ + template + bool IntersectsFast( const pcl::GenericRectangle& r ) const noexcept + { + return IntersectsFast( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Causes this rectangle to include a given rectangle \a r, by adjusting its + * coordinates as necessary. + */ + template + void Unite( const GenericRectangle& r ) noexcept + { + Unite( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Causes this rectangle to include a rectangle specified by its individual + * coordinates. + * + * \param left,top Upper left corner coordinates of a rectangle that + * will be included by this rectangle. + * + * \param right,bottom Lower right corner coordinates of a rectangle that + * will be included by this rectangle. + */ + template + void Unite( T1 left, T1 top, T1 right, T1 bottom ) noexcept + { + if ( right < left ) + Swap( left, right ); + if ( bottom < top ) + Swap( top, bottom ); + + if ( x0 <= x1 ) + { + x0 = pcl::Min( x0, component( left ) ); + x1 = pcl::Max( x1, component( right ) ); + } + else + { + x0 = pcl::Max( x0, component( right ) ); + x1 = pcl::Min( x1, component( left ) ); + } + + if ( y0 <= y1 ) + { + y0 = pcl::Min( y0, component( top ) ); + y1 = pcl::Max( y1, component( bottom ) ); + } + else + { + y0 = pcl::Max( y0, component( bottom ) ); + y1 = pcl::Min( y1, component( top ) ); + } + } + + /*! + * Causes this rectangle to include a given rectangle \a r, by adjusting its + * coordinates as necessary. + * + * To produce a valid result, this function assumes that both this and the + * specified object \a r are ordered rectangles. + */ + template + void UniteFast( const GenericRectangle& r ) noexcept + { + UniteFast( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Causes this rectangle to include a rectangle specified by its individual + * coordinates. + * + * \param left,top Upper left corner coordinates of a rectangle that + * will be included by this rectangle. + * + * \param right,bottom Lower right corner coordinates of a rectangle that + * will be included by this rectangle. + * + * For a valid result, this function assumes the following conditions: + * + * \li The specified set \a left, \a top, \a right and \a bottom must define + * an ordered rectangle, that is, the conditions \a left ≤ \a right and + * \a top ≤ \a bottom must hold. + * + * \li This rectangle must be ordered, that is, the conditions x0 ≤ x1 + * and y0 ≤ y1 must hold. + */ + template + void UniteFast( T1 left, T1 top, T1 right, T1 bottom ) noexcept + { + x0 = pcl::Min( x0, component( left ) ); + y0 = pcl::Min( y0, component( top ) ); + x1 = pcl::Max( x1, component( right ) ); + y1 = pcl::Max( y1, component( bottom ) ); + } + + /*! + * Returns a rectangle that includes this one and another rectangle \a r. + */ + template + GenericRectangle Union( const GenericRectangle& r ) const noexcept + { + GenericRectangle r1 = *this; + r1.Unite( r ); + return r1; + } + + /*! + * Returns a rectangle that includes this one and another rectangle \a r. + * + * To give a valid result, this function assumes that both this and the + * specified object \a r are ordered rectangles. + */ + template + GenericRectangle UnionFast( const GenericRectangle& r ) const noexcept + { + GenericRectangle r1 = *this; + r1.UniteFast( r ); + return r1; + } + + /*! + * Causes this rectangle to include a given rectangle \a r, by adjusting + * coordinates as necessary. Returns a reference to this rectangle. + */ + template + GenericRectangle& operator |=( const GenericRectangle& r ) noexcept + { + Unite( r ); + return *this; + } + +#ifdef __PCL_QT_INTERFACE + void Unite( const QRect& r ) + { + Unite( r.left(), r.top(), r.right()+1, r.bottom()+1 ); + } + + GenericRectangle Union( const QRect& r ) const noexcept + { + GenericRectangle r1 = *this; + r1.Unite( r ); + return r1; + } + + GenericRectangle& operator |=( const QRect& r ) noexcept + { + Unite( r ); + return *this; + } +#endif + + /*! + * Causes this rectangle to be equal to its intersection with a given + * rectangle \a r. + * + * Returns true iff the resulting intersection is a nonempty rectangle, i.e. + * iff this->x0 != this->x1 and this->y0 != this->y1 after calling this + * function. + */ + template + bool Intersect( const GenericRectangle& r ) noexcept + { + return Intersect( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Causes this rectangle to be equal to its intersection with a rectangle + * specified by its individual coordinates. + * + * \param left,top Upper left corner coordinates of a rectangle that + * will intersect this rectangle. + * + * \param right,bottom Lower right corner coordinates of a rectangle that will + * intersect this rectangle. + * + * Returns true iff the resulting intersection is a nonempty rectangle, i.e. + * iff this->x0 != this->x1 and this->y0 != this->y1 after calling this + * function. + */ + template + bool Intersect( T1 left, T1 top, T1 right, T1 bottom ) noexcept + { + if ( right < left ) + Swap( left, right ); + if ( bottom < top ) + Swap( top, bottom ); + + if ( x0 <= x1 ) + { + x0 = pcl::Max( x0, component( left ) ); + x1 = pcl::Min( x1, component( right ) ); + } + else + { + x0 = pcl::Min( x0, component( right ) ); + x1 = pcl::Max( x1, component( left ) ); + } + + if ( y0 <= y1 ) + { + y0 = pcl::Max( y0, component( top ) ); + y1 = pcl::Min( y1, component( bottom ) ); + } + else + { + y0 = pcl::Min( y0, component( bottom ) ); + y1 = pcl::Max( y1, component( top ) ); + } + + return IsRect(); + } + + /*! + * Causes this rectangle to be equal to its intersection with a given + * rectangle \a r. + * + * Returns true iff the resulting intersection is a nonempty rectangle, i.e. + * iff this->x0 != this->x1 and this->y0 != this->y1 after calling this + * function. + * + * To produce a valid result, this function assumes that both this and the + * specified object \a r are ordered rectangles. + */ + template + bool IntersectFast( const GenericRectangle& r ) noexcept + { + return IntersectFast( r.x0, r.y0, r.x1, r.y1 ); + } + + /*! + * Causes this rectangle to be equal to its intersection with a rectangle + * specified by its individual coordinates. + * + * \param left,top Upper left corner coordinates of a rectangle that + * will intersect this rectangle. + * + * \param right,bottom Lower right corner coordinates of a rectangle that will + * intersect this rectangle. + * + * Returns true iff the resulting intersection is a nonempty rectangle, i.e. + * iff this->x0 != this->x1 and this->y0 != this->y1 after calling this + * function. + * + * For a valid result, this function assumes the following conditions: + * + * \li The specified set \a left, \a top, \a right and \a bottom must define + * an ordered rectangle, that is, the conditions \a left ≤ \a right and + * \a top ≤ \a bottom must hold. + * + * \li This rectangle must be ordered, that is, the conditions x0 ≤ x1 + * and y0 ≤ y1 must hold. + */ + template + bool IntersectFast( T1 left, T1 top, T1 right, T1 bottom ) noexcept + { + x0 = pcl::Max( x0, component( left ) ); + y0 = pcl::Max( y0, component( top ) ); + x1 = pcl::Min( x1, component( right ) ); + y1 = pcl::Min( y1, component( bottom ) ); + return IsRect(); + } + + /*! + * Returns a rectangle equal to the intersection of this rectangle and + * another rectangle \a r. + */ + template + GenericRectangle Intersection( const GenericRectangle& r ) const noexcept + { + GenericRectangle r1 = *this; + (void)r1.Intersect( r ); + return r1; + } + + /*! + * Returns a rectangle equal to the intersection of this rectangle and + * another rectangle \a r. + * + * To give a valid result, this function assumes that both this and the + * specified object \a r are ordered rectangles. + */ + template + GenericRectangle IntersectionFast( const GenericRectangle& r ) const noexcept + { + GenericRectangle r1 = *this; + (void)r1.IntersectFast( r ); + return r1; + } + + /*! + * Causes this rectangle to be equal to its intersection with another + * rectangle \a r. Returns a reference to this rectangle. + */ + template + GenericRectangle& operator &=( const GenericRectangle& r ) noexcept + { + Intersect( r ); + return *this; + } + +#ifdef __PCL_QT_INTERFACE + bool Intersect( const QRect& r ) noexcept + { + return Intersect( r.left(), r.top(), r.right()+1, r.bottom()+1 ); + } + + GenericRectangle Intersection( const QRect& r ) const noexcept + { + GenericRectangle r1 = *this; + (void)r1.Intersect( r ); + return r1; + } + + GenericRectangle& operator &=( const QRect& r ) noexcept + { + Intersect( r ); + return *this; + } +#endif + + /*! + * Sets the four coordinates of this rectangle to the specified values. + * + * \param left,top New upper left corner coordinates. + * \param right,bottom New lower right corner coordinates. + */ + template + void Set( T1 left, T1 top, T1 right, T1 bottom ) noexcept + { + x0 = component( left ); + y0 = component( top ); + x1 = component( right ); + y1 = component( bottom ); + } + + /*! + * Moves this rectangle to the specified location, by setting its upper left + * corner coordinates to those of a given point \a p. + * + * The coordinates of the lower right corner of this rectangle are + * readjusted to keep its width and height unmodified. + */ + template + void MoveTo( const pcl::GenericPoint& p ) noexcept + { + MoveTo( p.x, p.y ); + } + + /*! + * Moves this rectangle to the specified location, by setting its upper left + * corner coordinates equal to the given \a x and \a y coordinates. + * + * The coordinates of the lower right corner of this rectangle are + * readjusted to keep its width and height unmodified. + */ + template + void MoveTo( T1 x, T1 y ) noexcept + { + component dx = x1 - x0, dy = y1 - y0; + x0 = component( x ); + y0 = component( y ); + x1 = x0 + dx; + y1 = y0 + dy; + } + +#ifdef __PCL_QT_INTERFACE + void MoveTo( const QPoint& p ) noexcept + { + MoveTo( p.x(), p.y() ); + } +#endif + + /*! + * Returns a rectangle \a r equal to this rectangle moved to the specified + * location: + * + * \code GenericRectangle r( *this ); r.MoveTo( p ); \endcode + */ + template + GenericRectangle MovedTo( const pcl::GenericPoint& p ) const noexcept + { + GenericRectangle r( *this ); + r.MoveTo( p ); + return r; + } + + /*! + * Returns a rectangle \a r equal to this rectangle moved to the specified + * location: + * + * \code GenericRectangle r( *this ); r.MoveTo( x, y ); \endcode + */ + template + GenericRectangle MovedTo( T1 x, T1 y ) const noexcept + { + GenericRectangle r( *this ); + r.MoveTo( x, y ); + return r; + } + + /*! + * Moves this rectangle relative to its current position, by applying the + * coordinates of a point \a d as increments in the X and Y directions. + */ + template + void MoveBy( const pcl::GenericPoint& d ) noexcept + { + MoveBy( d.x, d.y ); + } + + /*! + * Moves this rectangle relative to its current position, by applying the + * specified \a dx and \a dy increments to its coordinates in the X and Y + * directions, respectively. + */ + template + void MoveBy( T1 dx, T1 dy ) noexcept + { + x0 += component( dx ); + y0 += component( dy ); + x1 += component( dx ); + y1 += component( dy ); + } + + /*! + * Moves this rectangle relative to its current position, by applying the + * specified \a dxy increment to its four coordinates in the X and Y + * directions. + * + * This function is functionally equivalent to: + * + * \code MoveBy( dxy, dxy ); \endcode + */ + template + void MoveBy( T1 dxy ) noexcept + { + x0 += component( dxy ); + y0 += component( dxy ); + x1 += component( dxy ); + y1 += component( dxy ); + } + +#ifdef __PCL_QT_INTERFACE + void MoveBy( const QPoint& p ) noexcept + { + MoveBy( p.x(), p.y() ); + } +#endif + + /*! + * Returns a rectangle \a r equal to this rectangle moved relative to its + * current position: + * + * \code GenericRectangle r( *this ); r.MoveBy( d ); \endcode + */ + template + GenericRectangle MovedBy( const pcl::GenericPoint& d ) const noexcept + { + GenericRectangle r( *this ); + r.MoveBy( d ); + return r; + } + + /*! + * Returns a rectangle \a r equal to this rectangle moved relative to its + * current position: + * + * \code GenericRectangle r( *this ); r.MoveBy( dx, dy ); \endcode + */ + template + GenericRectangle MovedBy( T1 dx, T1 dy ) const noexcept + { + GenericRectangle r( *this ); + r.MoveBy( dx, dy ); + return r; + } + + /*! + * Changes the size of this rectangle to the specified width \a w and height + * \a h, respectively. + * + * This function does not vary the current order of rectangle coordinates. + * If a coordinate of the upper left corner is less than or equal to its + * bottom right counterpart, the bottom right coordinate is modified. + * Inversely, if the bottom right coordinate is less than the upper left + * one, the upper left coordinate is modified. + */ + template + void ResizeTo( T1 w, T1 h ) noexcept + { + if ( x0 <= x1 ) + x1 = x0 + component( w ); + else + x0 = x1 + component( w ); + + if ( y0 <= y1 ) + y1 = y0 + component( h ); + else + y0 = y1 + component( h ); + } + + /*! + * Returns a rectangle \a r equal to this rectangle resized to the specified + * dimensions: + * + * \code GenericRectangle r( *this ); r.ResizeTo( w, h ); \endcode + */ + template + GenericRectangle ResizedTo( T1 w, T1 h ) const noexcept + { + GenericRectangle r( *this ); + r.ResizeTo( w, h ); + return r; + } + + /*! + * Changes the size of this rectangle relative to its current dimensions, by + * applying the specified \a dw and \a dh increments to its width and + * height, respectively. + * + * This function does not vary the current order of rectangle coordinates. + * If a coordinate of the upper left corner is less than or equal to its + * bottom right counterpart, the bottom right coordinate is modified. + * Inversely, if the bottom right coordinate is less than the upper left + * one, the upper left coordinate is modified. + */ + template + void ResizeBy( T1 dw, T1 dh ) noexcept + { + if ( x0 <= x1 ) + x1 += component( dw ); + else + x0 += component( dw ); + + if ( y0 <= y1 ) + y1 += component( dh ); + else + y0 += component( dh ); + } + + /*! + * Returns a rectangle \a r equal to this rectangle resized relative to its + * current dimensions: + * + * \code GenericRectangle r( *this ); r.ResizeBy( dw, dh ); \endcode + */ + template + GenericRectangle ResizedBy( T1 dw, T1 dh ) const noexcept + { + GenericRectangle r( *this ); + r.ResizeBy( dw, dh ); + return r; + } + + /*! + * Sets the width of this rectangle to the specified value \a w. + * + * This function does not vary the current order of horizontal rectangle + * coordinates. If the x0 rectangle coordinate is less than or equal to x1, + * the x1 coordinate is modified. Inversely, if the x1 coordinate is less + * than x0, then x0 is modified. + */ + template + void SetWidth( T1 w ) noexcept + { + if ( x0 <= x1 ) + x1 = x0 + component( w ); + else + x0 = x1 + component( w ); + } + + /*! + * Sets the height of this rectangle to the specified value \a h. + * + * This function does not vary the current order of vertical rectangle + * coordinates. If the y0 rectangle coordinate is less than or equal to y1, + * the y1 coordinate is modified. Inversely, if the y1 coordinate is less + * than y0, then y0 is modified. + */ + template + void SetHeight( T1 h ) noexcept + { + if ( y0 <= y1 ) + y1 = y0 + component( h ); + else + y0 = y1 + component( h ); + } + + /*! + * Inflates this rectangle by the specified \a dx and \a dy increments on + * the X and Y axes respectively. Subtracts \a dx and \a dy to the upper + * left corner, and adds them to the bottom right corner. + */ + template + void InflateBy( T1 dx, T1 dy ) noexcept + { + if ( x1 < x0 ) + dx = -dx; + if ( y1 < y0 ) + dy = -dy; + x0 -= dx; + y0 -= dy; + x1 += dx; + y1 += dy; + } + + /*! + * Inflates this rectangle by the specified \a d increment on both axes. + * Subtracts \a d to the upper left corner, and adds it to the bottom right + * corner. + */ + template + void InflateBy( T1 d ) noexcept + { + if ( x0 <= x1 ) + x0 -= d, x1 += d; + else + x0 += d, x1 -= d; + + if ( y0 <= y1 ) + y0 -= d, y1 += d; + else + y0 += d, y1 -= d; + } + + /*! + * Returns a rectangle equivalent to this rectangle inflated by the + * specified \a dx and \a dy increments. + */ + template + GenericRectangle InflatedBy( T1 dx, T1 dy ) const noexcept + { + GenericRectangle r( *this ); + r.InflateBy( dx, dy ); + return r; + } + + /*! + * Returns a rectangle equivalent to this rectangle inflated by the + * specified \a d increments on both axes. + */ + template + GenericRectangle InflatedBy( T1 d ) const noexcept + { + GenericRectangle r( *this ); + r.InflateBy( d ); + return r; + } + + /*! + * Shrinks this rectangle by the specified \a dx and \a dy increments on the + * X and Y axes respectively. Adds \a dx and \a dy to the upper left corner, + * and subtracts them to the bottom right corner. + */ + template + void DeflateBy( T1 dx, T1 dy ) noexcept + { + if ( x1 < x0 ) + dx = -dx; + if ( y1 < y0 ) + dy = -dy; + x0 += dx; + y0 += dy; + x1 -= dx; + y1 -= dy; + } + + /*! + * Shrinks this rectangle by the specified \a d increment on both axes. Adds + * \a d to the upper left corner, and subtracts it to the bottom right + * corner. + */ + template + void DeflateBy( T1 d ) noexcept + { + if ( x0 <= x1 ) + x0 += d, x1 -= d; + else + x0 -= d, x1 += d; + + if ( y0 <= y1 ) + y0 += d, y1 -= d; + else + y0 -= d, y1 += d; + } + + /*! + * Returns a rectangle equivalent to this rectangle shrunk by the specified + * \a dx and \a dy increments. + */ + template + GenericRectangle DeflatedBy( T1 dx, T1 dy ) const noexcept + { + GenericRectangle r( *this ); + r.DeflateBy( dx, dy ); + return r; + } + + /*! + * Returns a rectangle equivalent to this rectangle shrunk by the specified + * \a d increment on both axes. + */ + template + GenericRectangle DeflatedBy( T1 d ) const noexcept + { + GenericRectangle r( *this ); + r.DeflateBy( d ); + return r; + } + + /*! + * Returns a rectangle \a r equal to this rectangle resized horizontally to + * the specified width \a w: + * + * \code GenericRectangle r( *this ); r.SetWidth( w ); \endcode + */ + template + GenericRectangle WidthSetTo( T1 w ) const noexcept + { + GenericRectangle r( *this ); + r.SetWidth( w ); + return r; + } + + /*! + * Returns a rectangle \a r equal to this rectangle resized vertically to + * the specified height \a h: + * + * \code GenericRectangle r( *this ); r.SetHeight( h ); \endcode + */ + template + GenericRectangle HeightSetTo( T1 h ) const noexcept + { + GenericRectangle r( *this ); + r.SetHeight( h ); + return r; + } + + /*! + * Rotates this rectangle in the plane by the specified \a angle in radians, + * with respect to a center of rotation given by its coordinates \a xc and + * \a yc. + */ + template + void Rotate( T1 angle, T2 xc, T2 yc ) noexcept + { + T1 sa, ca; pcl::SinCos( angle, sa, ca ); + pcl::Rotate( x0, y0, sa, ca, xc, yc ); + pcl::Rotate( x1, y1, sa, ca, xc, yc ); + } + + /*! + * Rotates this rectangle in the plane by the specified \a angle in radians, + * with respect to the specified \a center of rotation. + */ + template + void Rotate( T1 angle, const GenericPoint& center ) noexcept + { + Rotate( angle, center.x, center.y ); + } + + /*! + * Rotates this rectangle in the plane by the specified angle, given by its + * sine and cosine, \a sa and \a ca respectively, with respect to a center + * of rotation given by its coordinates \a xc and \a yc. + */ + template + void Rotate( T1 sa, T1 ca, T2 xc, T2 yc ) noexcept + { + pcl::Rotate( x0, y0, sa, ca, xc, yc ); + pcl::Rotate( x1, y1, sa, ca, xc, yc ); + } + + /*! + * Rotates this rectangle in the plane by the specified angle, given by its + * sine and cosine, \a sa and \a ca respectively, with respect to the + * specified \a center of rotation. + */ + template + void Rotate( T1 sa, T1 ca, const GenericPoint& center ) noexcept + { + Rotate( sa, ca, center.x, center.y ); + } + + /*! + * Returns a rectangle whose coordinates are the coordinates of this object + * rotated in the plane by the specified \a angle in radians, with respect + * to a center of rotation given by its coordinates \a xc and \a yc. + */ + template + GenericRectangle Rotated( T1 angle, T2 xc, T2 yc ) const noexcept + { + GenericRectangle r( *this ); + r.Rotate( angle, xc, yc ); + return r; + } + + /*! + * Returns a rectangle whose coordinates are the coordinates of this object + * rotated in the plane by the specified \a angle in radians, with respect + * to the specified \a center of rotation. + */ + template + GenericRectangle Rotated( T1 angle, const GenericPoint& center ) const noexcept + { + GenericRectangle r( *this ); + r.Rotate( angle, center ); + return r; + } + + /*! + * Returns a rectangle whose coordinates are the coordinates of this object + * rotated in the plane by the specified angle given by its sine and cosine, + * \a sa and \a ca respectively, with respect to a center of rotation given + * by its coordinates \a xc and \a yc. + */ + template + GenericRectangle Rotated( T1 sa, T1 ca, T2 xc, T2 yc ) const noexcept + { + GenericRectangle r( *this ); + r.Rotate( sa, ca, xc, yc ); + return r; + } + + /*! + * Returns a rectangle whose coordinates are the coordinates of this object + * rotated in the plane by the specified angle given by its sine and cosine, + * \a sa and \a ca respectively, with respect to the specified \a center of + * rotation. + */ + template + GenericRectangle Rotated( T1 sa, T1 ca, const GenericPoint& center ) const noexcept + { + GenericRectangle r( *this ); + r.Rotate( sa, ca, center ); + return r; + } + + /*! + * Rounds the coordinates of this rectangle to their corresponding nearest + * integer coordinates. + */ + void Round() noexcept + { + x0 = component( pcl::Round( double( x0 ) ) ); + y0 = component( pcl::Round( double( y0 ) ) ); + x1 = component( pcl::Round( double( x1 ) ) ); + y1 = component( pcl::Round( double( y1 ) ) ); + } + + /*! + * Rounds the coordinates of this rectangle to \a n fractional digits + * (\a n >= 0). + */ + void Round( int n ) noexcept + { + PCL_PRECONDITION( n >= 0 ) + if ( n < 0 ) + n = 0; + x0 = component( pcl::Round( double( x0 ), n ) ); + y0 = component( pcl::Round( double( y0 ), n ) ); + x1 = component( pcl::Round( double( x1 ), n ) ); + y1 = component( pcl::Round( double( y1 ), n ) ); + } + + /*! + * Returns a rectangle whose coordinates are the coordinates of this object + * rounded to their nearest integers. + */ + GenericRectangle Rounded() const noexcept + { + return GenericRectangle( component( pcl::Round( double( x0 ) ) ), component( pcl::Round( double( y0 ) ) ), + component( pcl::Round( double( x1 ) ) ), component( pcl::Round( double( y1 ) ) ) ); + } + + /*! + * Returns a rectangle whose coordinates are the coordinates of this object + * rounded to \a n fractional digits (\a n >= 0). + */ + GenericRectangle Rounded( int n ) const noexcept + { + PCL_PRECONDITION( n >= 0 ) + return GenericRectangle( component( pcl::Round( double( x0 ), n ) ), component( pcl::Round( double( y0 ), n ) ), + component( pcl::Round( double( x1 ), n ) ), component( pcl::Round( double( y1 ), n ) ) ); + } + + /*! + * Returns a rectangle of integer template type whose coordinates are the + * coordinates of this object rounded to their nearest integers. + */ + GenericRectangle RoundedToInt() const noexcept + { + return GenericRectangle( pcl::RoundInt( double( x0 ) ), pcl::RoundInt( double( y0 ) ), + pcl::RoundInt( double( x1 ) ), pcl::RoundInt( double( y1 ) ) ); + } + + /*! + * Integer truncation of coordinates. Sets the coordinates x0, y0, x1, y1 of + * this rectangle to the nearest integer coordinates a, b, c, d such that + * a <= x0, b <= y0, c <= x1, d <= y1. + */ + void Truncate() noexcept + { + x0 = component( pcl::Trunc( double( x0 ) ) ); + y0 = component( pcl::Trunc( double( y0 ) ) ); + x1 = component( pcl::Trunc( double( x1 ) ) ); + y1 = component( pcl::Trunc( double( y1 ) ) ); + } + + /*! + * Integer truncation of coordinates. Returns a rectangle whose coordinates + * are the coordinates x0, y0, x1, y1 of this rectangle, truncated to their + * nearest integer coordinates a, b, c, d such that a <= x0, b <= y0, + * c <= x1, d <= y1. + */ + GenericRectangle Truncated() const noexcept + { + return GenericRectangle( component( pcl::Trunc( double( x0 ) ) ), component( pcl::Trunc( double( y0 ) ) ), + component( pcl::Trunc( double( x1 ) ) ), component( pcl::Trunc( double( y1 ) ) ) ); + } + + /*! + * Integer truncation of coordinates. Returns a rectangle of integer + * template type whose coordinates are the coordinates x0, y0, x1, y1 of + * this rectangle truncated to the nearest integer coordinates a, b, c, d + * such that a <= x0, b <= y0, c <= x1, d <= y1. + */ + GenericRectangle TruncatedToInt() const noexcept + { + return GenericRectangle( pcl::TruncInt( double( x0 ) ), pcl::TruncInt( double( y0 ) ), + pcl::TruncInt( double( x1 ) ), pcl::TruncInt( double( y1 ) ) ); + } + + /*! + * Assigns a rectangle \a r to this rectangle. Returns a reference to this + * rectangle. + */ + template + GenericRectangle& operator =( const GenericRectangle& r ) noexcept + { + x0 = component( r.x0 ); + y0 = component( r.y0 ); + x1 = component( r.x1 ); + y1 = component( r.y1 ); + return *this; + } + + /*! + * Assigns a point \a p to this rectangle. Returns a reference to this + * rectangle. + * + * The \a p.x and \a p.y coordinates are assigned, respectively, to the + * horizontal and vertical coordinates of this rectangle. + */ + template + GenericRectangle& operator =( const pcl::GenericPoint& p ) noexcept + { + x0 = x1 = component( p.x ); + y0 = y1 = component( p.y ); + return *this; + } + + /*! + * Assigns a scalar \a d to this rectangle. Returns a reference to this + * rectangle. + * + * The scalar \a d is assigned to the four coordinates of this rectangle. + */ + GenericRectangle& operator =( component d ) noexcept + { + x0 = y0 = x1 = y1 = d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericRectangle& operator =( const QRect& r ) noexcept + { + x0 = component( r.left() ); + y0 = component( r.top() ); + x1 = component( r.right()+1 ); + y1 = component( r.bottom()+1 ); + return *this; + } +#endif + + /*! + * Adds a rectangle \a r to this rectangle. Returns a reference to this + * rectangle. + * + * This function adds homonym coordinates. Given two rectangles \a r1 and + * \a r2, the sum rectangle \a s = \a r1 + \a r2 is given by: + * + * \a s.x0 = \a r1.x0 + \a r2.x0 \n + * \a s.y0 = \a r1.y0 + \a r2.y0 \n + * \a s.x1 = \a r1.x1 + \a r2.x1 \n + * \a s.y1 = \a r1.y1 + \a r2.y1 + */ + template + GenericRectangle& operator +=( const GenericRectangle& r ) noexcept + { + x0 += component( r.x0 ); + y0 += component( r.y0 ); + x1 += component( r.x1 ); + y1 += component( r.y1 ); + return *this; + } + + /*! + * Adds a point \a p to this rectangle. Returns a reference to this + * rectangle. + * + * This function is equivalent to a translation relative to the current + * position. Given a rectangle \a r and a point \a p, the sum rectangle + * \a s = \a r + \a p is given by: + * + * \a s.x0 = \a r.x0 + \a p.x \n + * \a s.y0 = \a r.y0 + \a p.y \n + * \a s.x1 = \a r.x1 + \a p.x \n + * \a s.y1 = \a r.y1 + \a p.y + */ + template + GenericRectangle& operator +=( const pcl::GenericPoint& p ) noexcept + { + x0 += component( p.x ); + y0 += component( p.y ); + x1 += component( p.x ); + y1 += component( p.y ); + return *this; + } + + /*! + * Adds a scalar \a d to this rectangle. Returns a reference to this + * rectangle. + * + * This function adds the specified scalar to the four rectangle + * coordinates. This is equivalent to a translation relative to the current + * position. Given a rectangle \a r and a scalar \a d, the sum rectangle + * \a s = \a r + \a d is given by: + * + * \a s.x0 = \a r.x0 + \a d \n + * \a s.y0 = \a r.y0 + \a d \n + * \a s.x1 = \a r.x1 + \a d \n + * \a s.y1 = \a r.y1 + \a d + */ + GenericRectangle& operator +=( component d ) noexcept + { + x0 += d; + y0 += d; + x1 += d; + y1 += d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericRectangle& operator +=( const QPoint& p ) noexcept + { + component dx = component( p.x() ), dy = component( p.y() ); + x0 += dx; + y0 += dy; + x1 += dx; + y1 += dy; + return *this; + } +#endif + + /*! + * Subtracts a rectangle \a r from this rectangle. Returns a reference to + * this rectangle. + * + * This function subtracts homonym coordinates. Given two rectangles \a r1 + * and \a r2, the difference rectangle \a s = \a r1 - \a r2 is given by: + * + * \a s.x0 = \a r1.x0 - \a r2.x0 \n + * \a s.y0 = \a r1.y0 - \a r2.y0 \n + * \a s.x1 = \a r1.x1 - \a r2.x1 \n + * \a s.y1 = \a r1.y1 - \a r2.y1 + */ + template + GenericRectangle& operator -=( const GenericRectangle& r ) noexcept + { + x0 -= component( r.x0 ); + y0 -= component( r.y0 ); + x1 -= component( r.x1 ); + y1 -= component( r.y1 ); + return *this; + } + + /*! + * Subtracts a point \a p from this rectangle. Returns a reference to this + * rectangle. + * + * This function is equivalent to a translation relative to the current + * position. Given a rectangle \a r and a point \a p, the difference + * rectangle \a s = \a r - \a p is given by: + * + * \a s.x0 = \a r.x0 - \a p.x \n + * \a s.y0 = \a r.y0 - \a p.y \n + * \a s.x1 = \a r.x1 - \a p.x \n + * \a s.y1 = \a r.y1 - \a p.y + */ + template + GenericRectangle& operator -=( const pcl::GenericPoint& p ) noexcept + { + x0 -= component( p.x ); + y0 -= component( p.y ); + x1 -= component( p.x ); + y1 -= component( p.y ); + return *this; + } + + /*! + * Subtracts a scalar \a d from this rectangle. Returns a reference to this + * rectangle. + * + * This function subtracts the specified scalar from the four rectangle + * coordinates. This is equivalent to a translation relative to the current + * position. Given a rectangle \a r and a scalar \a d, the difference + * rectangle \a s = \a r - \a d is given by: + * + * \a s.x0 = \a r.x0 - \a d \n + * \a s.y0 = \a r.y0 - \a d \n + * \a s.x1 = \a r.x1 - \a d \n + * \a s.y1 = \a r.y1 - \a d + */ + GenericRectangle& operator -=( component d ) noexcept + { + x0 -= d; + y0 -= d; + x1 -= d; + y1 -= d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericRectangle& operator -=( const QPoint& p ) noexcept + { + component dx = component( p.x() ), dy = component( p.y() ); + x0 -= dx; + y0 -= dy; + x1 -= dx; + y1 -= dy; + return *this; + } +#endif + + /*! + * Multiplies this rectangle by a rectangle \a r. Returns a reference to + * this rectangle. + * + * This function multiplies homonym coordinates. Given two rectangles \a r1 + * and \a r2, the product rectangle \a P = \a r1 * \a r2 is given by: + * + * \a P.x0 = \a r1.x0 * \a r2.x0 \n + * \a P.y0 = \a r1.y0 * \a r2.y0 \n + * \a P.x1 = \a r1.x1 * \a r2.x1 \n + * \a P.y1 = \a r1.y1 * \a r2.y1 + */ + template + GenericRectangle& operator *=( const GenericRectangle& r ) noexcept + { + x0 *= component( r.x0 ); + y0 *= component( r.y0 ); + x1 *= component( r.x1 ); + y1 *= component( r.y1 ); + return *this; + } + + /*! + * Multiplies this rectangle by a point \a p. Returns a reference to this + * rectangle. + * + * This function is equivalent to a translation relative to the current + * position, plus a scaling factor applied to both sides of the rectangle. + * Given a rectangle \a r and a point \a p, the product rectangle + * \a P = \a r * \a p is given by: + * + * \a P.x0 = \a r.x0 * \a p.x \n + * \a P.y0 = \a r.y0 * \a p.y \n + * \a P.x1 = \a r.x1 * \a p.x \n + * \a P.y1 = \a r.y1 * \a p.y + */ + template + GenericRectangle& operator *=( const pcl::GenericPoint& p ) noexcept + { + x0 *= component( p.x ); + y0 *= component( p.y ); + x1 *= component( p.x ); + y1 *= component( p.y ); + return *this; + } + + /*! + * Multiplies this rectangle by a scalar \a d. Returns a reference to this + * rectangle. + * + * This function is equivalent to a translation relative to the current + * position, plus a scaling factor applied to both sides of the rectangle. + * Given a rectangle \a r and a scalar \a d, the product rectangle + * \a P = \a r * \a d is given by: + * + * \a P.x0 = \a r.x0 * \a d \n + * \a P.y0 = \a r.y0 * \a d \n + * \a P.x1 = \a r.x1 * \a d \n + * \a P.y1 = \a r.y1 * \a d + */ + GenericRectangle& operator *=( component d ) noexcept + { + x0 *= d; + y0 *= d; + x1 *= d; + y1 *= d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericRectangle& operator *=( const QPoint& p ) noexcept + { + component dx = component( p.x() ), dy = component( p.y() ); + x0 *= dx; y0 *= dy; x1 *= dx; y1 *= dy; + return *this; + } +#endif + + /*! + * Divides this rectangle by a rectangle \a r. Returns a reference to this + * rectangle. + * + * This function divides homonym coordinates. Given two rectangles \a r1 + * and \a r2, the quotient rectangle \a Q = \a r1 / \a r2 is given by: + * + * \a Q.x0 = \a r1.x0 / \a r2.x0 \n + * \a Q.y0 = \a r1.y0 / \a r2.y0 \n + * \a Q.x1 = \a r1.x1 / \a r2.x1 \n + * \a Q.y1 = \a r1.y1 / \a r2.y1 + */ + template + GenericRectangle& operator /=( const GenericRectangle& r ) noexcept + { + PCL_PRECONDITION( component( r.x0 ) != component( 0 ) && component( r.y0 ) != component( 0 ) && + component( r.x1 ) != component( 0 ) && component( r.y1 ) != component( 0 ) ) + x0 /= component( r.x0 ); + y0 /= component( r.y0 ); + x1 /= component( r.x1 ); + y1 /= component( r.y1 ); + return *this; + } + + /*! + * Divides this rectangle by a point \a p. Returns a reference to this + * rectangle. + * + * This function is equivalent to a translation relative to the current + * position, plus a scaling factor applied to both sides of the rectangle. + * Given a rectangle \a r and a point \a p, the quotient rectangle + * \a Q = \a r / \a p is given by: + * + * \a Q.x0 = \a r.x0 / \a p.x \n + * \a Q.y0 = \a r.y0 / \a p.y \n + * \a Q.x1 = \a r.x1 / \a p.x \n + * \a Q.y1 = \a r.y1 / \a p.y + */ + template + GenericRectangle& operator /=( const pcl::GenericPoint& p ) noexcept + { + PCL_PRECONDITION( component( p.x ) != component( 0 ) && component( p.y ) != component( 0 ) ) + x0 /= component( p.x ); + y0 /= component( p.y ); + x1 /= component( p.x ); + y1 /= component( p.y ); + return *this; + } + + /*! + * Divides this rectangle by a scalar \a d. Returns a reference to this + * rectangle. + * + * This function is equivalent to a translation relative to the current + * position, plus a scaling factor applied to both sides of the rectangle. + * Given a rectangle \a r and a scalar \a d, the quotient rectangle + * \a Q = \a r / \a d is given by: + * + * \a Q.x0 = \a r.x0 / \a d \n + * \a Q.y0 = \a r.y0 / \a d \n + * \a Q.x1 = \a r.x1 / \a d \n + * \a Q.y1 = \a r.y1 / \a d + */ + GenericRectangle& operator /=( component d ) noexcept + { + PCL_PRECONDITION( d != component( 0 ) ) + x0 /= d; y0 /= d; x1 /= d; y1 /= d; + return *this; + } + +#ifdef __PCL_QT_INTERFACE + GenericRectangle& operator /=( const QPoint& p ) noexcept + { + PCL_PRECONDITION( component( p.x() ) != component( 0 ) && component( p.y() ) != component( 0 ) ) + component dx = component( p.x() ), dy = component( p.y() ); + x0 /= dx; + y0 /= dy; + x1 /= dx; + y1 /= dy; + return *this; + } +#endif + + /*! + * Returns a copy of this rectangle. + */ + GenericRectangle operator +() const noexcept + { + return *this; + } + + /*! + * Returns a rectangle whose coordinates have the same magnitudes as the + * coordinates of this rectangle, but opposite signs. The returned rectangle + * so defined is symmetric to this rectangle with respect to the origin of + * coordinates. + */ + GenericRectangle operator -() const noexcept + { + return GenericRectangle( -x0, -y0, -x1, -y1 ); + } + +#ifdef __PCL_QT_INTERFACE + operator QRect() const noexcept + { + return QRect( int( x0 ), int( y0 ), int( x1-x0 ), int( y1-y0 ) ); + } +#endif + +#ifdef __PCL_QT_INTERFACE +# ifndef __PCL_QT_NO_RECT_DRAWING_HELPERS + + void Draw( QPainter& p, const QBrush* b ) const + { + int rx0, ry0, rx1, ry1; + + if ( x0 <= x1 ) + rx0 = x0, rx1 = x1; + else + rx0 = x1, rx1 = x0; + + if ( y0 <= y1 ) + ry0 = y0, ry1 = y1; + else + ry0 = y1, ry1 = y0; + + if ( rx1 - rx0 <= 1 ) + { + if ( ry1 - ry0 <= 1 ) + p.drawPoint( rx0, ry0 ); + else + p.drawLine( rx0, ry0, rx0, ry1-1 ); + } + else if ( ry1 - ry0 <= 1 ) + { + p.drawLine( rx0, ry0, rx1-1, ry0 ); + } + else + { +# if ( QT_VERSION >= 0x040000 ) + int w = rx1-rx0-1, h = ry1-ry0-1; +# else + int w = rx1-rx0, h = ry1-ry0; +# endif + if ( b != 0 ) + p.fillRect( rx0, ry0, w, h, *b ); + p.drawRect( rx0, ry0, w, h ); + } + } + + void Draw( QPainter& p ) const + { + Draw( p, 0 ); + } + + void Draw( QPainter& p, const QColor& c ) const + { + QBrush b( c ); + Draw( p, &b ); + } + +# endif // !__PCL_QT_NO_RECT_DRAWING_HELPERS +#endif // __PCL_QT_INTERFACE + +}; // GenericRectangle + +#undef PCL_ASSERT_RECT_SIZE + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup rect_functions_2d Rectangle Operators and Functions + */ + +/*! + * Returns true iff two rectangles \a r1 and \a r2 are equal. Two rectangles + * are equal if their homonym coordinates are equal. + * \ingroup rect_functions_2d + */ +template inline +bool operator ==( const GenericRectangle& r1, const GenericRectangle& r2 ) noexcept +{ + return r1.x0 == r2.x0 && r1.y0 == r2.y0 && r1.x1 == r2.x1 && r1.y1 == r2.y1; +} + +/*! + * Returns true iff a rectangle \a r1 is equal to a scalar \a d2. A rectangle + * is equal to a scalar \a d if the four coordinates of \a r are equal to \a d. + * \ingroup rect_functions_2d + */ +template inline +bool operator ==( const GenericRectangle& r1, T d2 ) noexcept +{ + return r1.x0 == d2 && r1.y0 == d2 && r1.x1 == d2 && r1.y1 == d2; +} + +/*! + * Returns true iff a scalar \a d1 is equal to a rectangle \a r2. A scalar \a d + * is equal to a rectangle \a r if the four coordinates of \a r are equal to + * \a d. + * \ingroup rect_functions_2d + */ +template inline +bool operator ==( T d1, const GenericRectangle& r2 ) noexcept +{ + return d1 == r2.x0 && d1 == r2.y0 && d1 == r2.x1 && d1 == r2.y1; +} + +/*! + * Returns true iff a rectangle \a r1 is less than another rectangle \a r2. + * For rectangle comparisons, vertical coordinates have precedence over + * horizontal coordinates. + * \ingroup rect_functions_2d + */ +template inline +bool operator <( const GenericRectangle& r1, const GenericRectangle& r2 ) noexcept +{ + T1 x01 = Min( r1.x0, r1.x1 ); T1 y01 = Min( r1.y0, r1.y1 ); + T1 x11 = Max( r1.x0, r1.x1 ); T1 y11 = Max( r1.y0, r1.y1 ); + T2 x02 = Min( r2.x0, r2.x1 ); T2 y02 = Min( r2.y0, r2.y1 ); + T2 x12 = Max( r2.x0, r2.x1 ); T2 y12 = Max( r2.y0, r2.y1 ); + if ( y01 != y02 ) + return y01 < y02; + if ( x01 != x02 ) + return x01 < x02; + if ( y11 != y12 ) + return y11 < y12; + return x11 < x12; +} + +/*! + * Adds two rectangles \a r1 and \a r2, and returns the resulting sum + * rectangle. + * + * Rectangle addition consists in adding homonym coordinates. Given two + * rectangles \a r1 and \a r2, the sum rectangle \a s = \a r1 + \a r2 is + * given by: + * + * \a s.x0 = \a r1.x0 + \a r2.x0 \n + * \a s.y0 = \a r1.y0 + \a r2.y0 \n + * \a s.x1 = \a r1.x1 + \a r2.x1 \n + * \a s.y1 = \a r1.y1 + \a r2.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator +( const GenericRectangle& r1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( T1( r1.x0 + r2.x0 ), T1( r1.y0 + r2.y0 ), + T1( r1.x1 + r2.x1 ), T1( r1.y1 + r2.y1 ) ); +} + +/*! + * Adds a rectangle \a r1 and a point \a p2, and returns the resulting sum + * rectangle. + * + * Given a rectangle \a r and a point \a p, the sum rectangle + * \a s = \a r + \a p is given by: + * + * \a s.x0 = \a r.x0 + \a p.x \n + * \a s.y0 = \a r.y0 + \a p.y \n + * \a s.x1 = \a r.x1 + \a p.x \n + * \a s.y1 = \a r.y1 + \a p.y + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator +( const GenericRectangle& r1, const GenericPoint& p2 ) noexcept +{ + return GenericRectangle( T1( r1.x0 + p2.x ), T1( r1.y0 + p2.y ), + T1( r1.x1 + p2.x ), T1( r1.y1 + p2.y ) ); +} + +/*! + * Adds a point \a p1 and a rectangle \a r2, and returns the resulting sum + * rectangle. + * + * Rectangle addition is a commutative operation, thus see + * pcl::operator +( const GenericRectangle&, const GenericPoint& ). + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator +( const GenericPoint& p1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( T2( p1.x + r2.x0 ), T2( p1.y + r2.y0 ), + T2( p1.x + r2.x1 ), T2( p1.y + r2.y1 ) ); +} + +/*! + * Adds a rectangle \a r1 and a scalar \a d2, and returns the resulting sum + * rectangle. + * + * Given a rectangle \a r and a scalar \a d, the sum rectangle + * \a s = \a r + \a d is given by: + * + * \a s.x0 = \a r.x0 + \a d \n + * \a s.y0 = \a r.y0 + \a d \n + * \a s.x1 = \a r.x1 + \a d \n + * \a s.y1 = \a r.y1 + \a d + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator +( const GenericRectangle& r1, T d2 ) noexcept +{ + return GenericRectangle( r1.x0+d2, r1.y0+d2, r1.x1+d2, r1.y1+d2 ); +} + +/*! + * Adds a scalar \a d1 and a rectangle \a r2, and returns the resulting sum + * rectangle. + * + * Rectangle addition is a commutative operation, thus see + * pcl::operator +( const GenericRectangle&, T ). + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator +( T d1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( d1+r2.x0, d1+r2.y0, d1+r2.x1, d1+r2.y1 ); +} + +/*! + * Subtracts two rectangles \a r1 and \a r2, and returns the resulting + * difference rectangle. + * + * Rectangle subtraction consists in subtracting homonym coordinates. Given + * two rectangles \a r1 and \a r2, the difference rectangle + * \a s = \a r1 - \a r2 is given by: + * + * \a s.x0 = \a r1.x0 - \a r2.x0 \n + * \a s.y0 = \a r1.y0 - \a r2.y0 \n + * \a s.x1 = \a r1.x1 - \a r2.x1 \n + * \a s.y1 = \a r1.y1 - \a r2.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator -( const GenericRectangle& r1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( T1( r1.x0 - r2.x0 ), T1( r1.y0 - r2.y0 ), + T1( r1.x1 - r2.x1 ), T1( r1.y1 - r2.y1 ) ); +} + +/*! + * Subtracts a point \a p2 from a rectangle \a r1, and returns the resulting + * difference rectangle. + * + * Given a rectangle \a r and a point \a p, the difference rectangle + * \a s = \a r - \a p is given by: + * + * \a s.x0 = \a r.x0 - \a p.x \n + * \a s.y0 = \a r.y0 - \a p.y \n + * \a s.x1 = \a r.x1 - \a p.x \n + * \a s.y1 = \a r.y1 - \a p.y + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator -( const GenericRectangle& r1, const GenericPoint& p2 ) noexcept +{ + return GenericRectangle( T1( r1.x0 - p2.x ), T1( r1.y0 - p2.y ), + T1( r1.x1 - p2.x ), T1( r1.y1 - p2.y ) ); +} + +/*! + * Subtracts a rectangle \a r2 from a point \a p1, and returns the resulting + * difference rectangle. + * + * Given a rectangle \a r and a point \a p, the difference rectangle + * \a s = \a p - \a r is given by: + * + * \a s.x0 = \a p.x - \a r.x0 \n + * \a s.y0 = \a p.y - \a r.y0 \n + * \a s.x1 = \a p.x - \a r.x1 \n + * \a s.y1 = \a p.y - \a r.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator -( const GenericPoint& p1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( T2( p1.x - r2.x0 ), T2( p1.y - r2.y0 ), + T2( p1.x - r2.x1 ), T2( p1.y - r2.y1 ) ); +} + +/*! + * Subtracts a scalar \a d2 from a rectangle \a r1, and returns the resulting + * difference rectangle. + * + * Given a rectangle \a r and a scalar \a d, the difference rectangle + * \a s = \a r - \a d is given by: + * + * \a s.x0 = \a r.x0 - \a d \n + * \a s.y0 = \a r.y0 - \a d \n + * \a s.x1 = \a r.x1 - \a d \n + * \a s.y1 = \a r.y1 - \a d + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator -( const GenericRectangle& r1, T d2 ) noexcept +{ + return GenericRectangle( r1.x0-d2, r1.y0-d2, r1.x1-d2, r1.y1-d2 ); +} + +/*! + * Subtracts a rectangle \a r2 from a scalar \a d1, and returns the resulting + * difference rectangle. + * + * Given a rectangle \a r and a scalar \a d, the difference rectangle + * \a s = \a d - \a r is given by: + * + * \a s.x0 = \a d - \a r.x0 \n + * \a s.y0 = \a d - \a r.y0 \n + * \a s.x1 = \a d - \a r.x1 \n + * \a s.y1 = \a d - \a r.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator -( T d1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( d1-r2.x0, d1-r2.y0, d1-r2.x1, d1-r2.y1 ); +} + +/*! + * Multiplies two rectangles \a r1 and \a r2, and returns the resulting + * product rectangle. + * + * Rectangle multiplication consists in multiplying homonym coordinates. Given + * two rectangles \a r1 and \a r2, the product rectangle \a P = \a r1 * \a r2 + * is given by: + * + * \a P.x0 = \a r1.x0 * \a r2.x0 \n + * \a P.y0 = \a r1.y0 * \a r2.y0 \n + * \a P.x1 = \a r1.x1 * \a r2.x1 \n + * \a P.y1 = \a r1.y1 * \a r2.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator *( const GenericRectangle& r1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( T1( r1.x0 * r2.x0 ), T1( r1.y0 * r2.y0 ), + T1( r1.x1 * r2.x1 ), T1( r1.y1 * r2.y1 ) ); +} + +/*! + * Multiplies a rectangle \a r1 by a point \a p2, and returns the resulting + * product rectangle. + * + * Given a rectangle \a r and a point \a p, the product rectangle + * \a P = \a r * \a p is given by: + * + * \a P.x0 = \a r1.x0 * \a p.x \n + * \a P.y0 = \a r1.y0 * \a p.y \n + * \a P.x1 = \a r1.x1 * \a p.x \n + * \a P.y1 = \a r1.y1 * \a p.y + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator *( const GenericRectangle& r1, const GenericPoint& p2 ) noexcept +{ + return GenericRectangle( T1( r1.x0 * p2.x ), T1( r1.y0 * p2.y ), + T1( r1.x1 * p2.x ), T1( r1.y1 * p2.y ) ); +} + +/*! + * Multiplies a point \a p1 by a rectangle \a r2, and returns the resulting + * product rectangle. + * + * Rectangle multiplication is a commutative operation, thus see + * pcl::operator *( const GenericRectangle&, const GenericPoint& ). + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator *( const GenericPoint& p1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( T2( p1.x * r2.x0 ), T2( p1.y * r2.y0 ), + T2( p1.x * r2.x1 ), T2( p1.y * r2.y1 ) ); +} + +/*! + * Multiplies a rectangle \a r1 by a scalar \a d2, and returns the resulting + * product rectangle. + * + * Given a rectangle \a r and a scalar \a d, the product rectangle + * \a P = \a r * \a d is given by: + * + * \a P.x0 = \a r1.x0 * \a d \n + * \a P.y0 = \a r1.y0 * \a d \n + * \a P.x1 = \a r1.x1 * \a d \n + * \a P.y1 = \a r1.y1 * \a d + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator *( const GenericRectangle& r1, T d2 ) noexcept +{ + return GenericRectangle( r1.x0*d2, r1.y0*d2, r1.x1*d2, r1.y1*d2 ); +} + +/*! + * Multiplies a scalar \a d1 by a rectangle \a r2, and returns the resulting + * product rectangle. + * + * Rectangle multiplication is a commutative operation, thus see + * pcl::operator *( const GenericRectangle&, T ). + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator *( T d1, const GenericRectangle& r2 ) noexcept +{ + return GenericRectangle( d1*r2.x0, d1*r2.y0, d1*r2.x1, d1*r2.y1 ); +} + +/*! + * Divides two rectangles \a r1 and \a r2, and returns the resulting quotient + * rectangle. + * + * Rectangle division consists in dividing homonym coordinates. Given two + * rectangles \a r1 and \a r2, the quotient rectangle + * \a Q = \a r1 / \a r2 is given by: + * + * \a Q.x0 = \a r1.x0 / \a r2.x0 \n + * \a Q.y0 = \a r1.y0 / \a r2.y0 \n + * \a Q.x1 = \a r1.x1 / \a r2.x1 \n + * \a Q.y1 = \a r1.y1 / \a r2.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator /( const GenericRectangle& r1, const GenericRectangle& r2 ) noexcept +{ + PCL_PRECONDITION( r2.x0 != T2( 0 ) && r2.y0 != T2( 0 ) && + r2.x1 != T2( 0 ) && r2.y1 != T2( 0 ) ) + return GenericRectangle( T1( r1.x0 / r2.x0 ), T1( r1.y0 / r2.y0 ), + T1( r1.x1 / r2.x1 ), T1( r1.y1 / r2.y1 ) ); +} + +/*! + * Divides a rectangle \a r1 by a point \a p2, and returns the resulting + * quotient rectangle. + * + * Given a rectangle \a r and a point \a p, the quotient rectangle + * \a Q = \a r / \a p is given by: + * + * \a Q.x0 = \a r.x0 / \a p.x \n + * \a Q.y0 = \a r.y0 / \a p.y \n + * \a Q.x1 = \a r.x1 / \a p.x \n + * \a Q.y1 = \a r.y1 / \a p.y + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator /( const GenericRectangle& r1, const GenericPoint& p2 ) noexcept +{ + PCL_PRECONDITION( p2.x != T2( 0 ) && p2.y != T2( 0 ) ) + return GenericRectangle( T1( r1.x0 / p2.x ), T1( r1.y0 / p2.y ), + T1( r1.x1 / p2.x ), T1( r1.y1 / p2.y ) ); +} + +/*! + * Divides a point \a p1 by a rectangle \a r2, and returns the resulting + * quotient rectangle. + * + * Given a rectangle \a r and a point \a p, the quotient rectangle + * \a Q = \a p / \a r is given by: + * + * \a Q.x0 = \a p.x / \a r.x0 \n + * \a Q.y0 = \a p.y / \a r.y0 \n + * \a Q.x1 = \a p.x / \a r.x1 \n + * \a Q.y1 = \a p.y / \a r.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator /( const GenericPoint& p1, const GenericRectangle& r2 ) noexcept +{ + PCL_PRECONDITION( r2.x0 != T2( 0 ) && r2.y0 != T2( 0 ) && + r2.x1 != T2( 0 ) && r2.y1 != T2( 0 ) ) + return GenericRectangle( T2( p1.x / r2.x0 ), T2( p1.y / r2.y0 ), + T2( p1.x / r2.x1 ), T2( p1.y / r2.y1 ) ); +} + +/*! + * Divides a rectangle \a r1 by a scalar \a d2, and returns the resulting + * quotient rectangle. + * + * Given a rectangle \a r and a scalar \a d, the quotient rectangle + * \a Q = \a r / \a d is given by: + * + * \a Q.x0 = \a r.x0 / \a d \n + * \a Q.y0 = \a r.y0 / \a d \n + * \a Q.x1 = \a r.x1 / \a d \n + * \a Q.y1 = \a r.y1 / \a d + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator /( const GenericRectangle& r1, T d2 ) noexcept +{ + PCL_PRECONDITION( d2 != T( 0 ) ) + return GenericRectangle( r1.x0/d2, r1.y0/d2, r1.x1/d2, r1.y1/d2 ); +} + +/*! + * Divides a scalar \a d1 by a rectangle \a r2, and returns the resulting + * quotient rectangle. + * + * Given a rectangle \a r and a scalar \a d, the quotient rectangle + * \a Q = \a d / \a r is given by: + * + * \a Q.x0 = \a d / \a r.x0 \n + * \a Q.y0 = \a d / \a r.y0 \n + * \a Q.x1 = \a d / \a r.x1 \n + * \a Q.y1 = \a d / \a r.y1 + * + * \ingroup rect_functions_2d + */ +template inline +GenericRectangle operator /( T d1, const GenericRectangle& r2 ) noexcept +{ + PCL_PRECONDITION( r2.x0 != T( 0 ) && r2.y0 != T( 0 ) && + r2.x1 != T( 0 ) && r2.y1 != T( 0 ) ) + return GenericRectangle( d1/r2.x0, d1/r2.y0, d1/r2.x1, d1/r2.y1 ); +} + +/*! + * Rotates a rectangle in the plane, given a rotation angle and the + * coordinates of a center of rotation. + * + * \param r Reference to a rectangle that will be rotated. + * \param a Rotation angle in radians. Positive angles are measured + * counter-clockwise. + * \param xc Abscissa (x coordinate) of the center of rotation. + * \param yc Ordinate (y coordinate) of the center of rotation. + * + * The coordinates \a r.x0, \a r.y0, \a r.x1 and \a r.y1 are replaced by their + * corresponding rotated values. + * + * \ingroup rect_functions_2d + */ +template inline +void Rotate( GenericRectangle& r, T1 a, T2 xc, T2 yc ) noexcept +{ + T1 sa, ca; pcl::SinCos( a, sa, ca ); + pcl::Rotate( r.x0, r.y0, sa, ca, xc, yc ); + pcl::Rotate( r.x1, r.y1, sa, ca, xc, yc ); +} + +/*! + * Rotates a rectangle in the plane, given a rotation angle and a rotation + * center point. + * + * \param r Reference to a rectangle that will be rotated. + * \param a Rotation angle in radians. Positive angles are measured + * counter-clockwise. + * \param c Reference to a point that will be taken as the center of + * rotation. + * + * The coordinates \a r.x0, \a r.y0, \a r.x1 and \a r.y1 are replaced by their + * corresponding rotated values. + * + * \ingroup rect_functions_2d + */ +template inline +void Rotate( GenericRectangle& r, T1 a, const GenericPoint& c ) noexcept +{ + pcl::Rotate( r, a, c.x, c.y ); +} + +/*! + * Rotates a rectangle in the plane, given a rotation angle by its sine and + * cosine, and the coordinates of a center of rotation. + * + * \param r Reference to a rectangle that will be rotated. + * \param sa Sine of the rotation angle. + * \param ca Cosine of the rotation angle. + * \param xc Abscissa (x coordinate) of the center of rotation. + * \param yc Ordinate (y coordinate) of the center of rotation. + * + * The coordinates \a r.x0, \a r.y0, \a r.x1 and \a r.y1 are replaced by their + * corresponding rotated values. + * + * \ingroup rect_functions_2d + */ +template inline +void Rotate( GenericRectangle& r, T1 sa, T1 ca, T2 xc, T2 yc ) noexcept +{ + pcl::Rotate( r.x0, r.y0, sa, ca, xc, yc ); + pcl::Rotate( r.x1, r.y1, sa, ca, xc, yc ); +} + +/*! + * Rotates a rectangle in the plane, given a rotation angle by its sine and + * cosine, and a rotation center point. + * + * \param r Reference to a rectangle that will be rotated. + * \param sa Sine of the rotation angle. + * \param ca Cosine of the rotation angle. + * \param c Reference to a point that will be taken as the center of + * rotation. + * + * The coordinates \a r.x0, \a r.y0, \a r.x1 and \a r.y1 are replaced by their + * corresponding rotated values. + * + * \ingroup rect_functions_2d + */ +template inline +void Rotate( GenericRectangle& r, T1 sa, T1 ca, const GenericPoint& c ) noexcept +{ + pcl::Rotate( r, sa, ca, c.x, c.y ); +} + +/*! + * Exchanges two rectangles \a r1 and \a r2. Calling this function is + * equivalent to: + * + * \code + * pcl::Swap( r1.x0, r2.x0 ); pcl::Swap( r1.y0, r2.y0 ); + * pcl::Swap( r1.x1, r2.x1 ); pcl::Swap( r1.y1, r2.y1 ); + * \endcode + * + * \ingroup rect_functions_2d + */ +template inline +void Swap( GenericRectangle& r1, GenericRectangle& r2 ) noexcept +{ + pcl::Swap( r1.x0, r2.x0 ); pcl::Swap( r1.y0, r2.y0 ); + pcl::Swap( r1.x1, r2.x1 ); pcl::Swap( r1.y1, r2.y1 ); +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_RECT_INSTANTIATE + +/*! + * \defgroup rect_types_2d Rectangle Types + */ + +/*! + * \class pcl::I32Rect + * \ingroup rect_types_2d + * \brief 32-bit integer rectangle on the plane. + * + * %I32Rect is a template instantiation of GenericRectangle for \c int32. + */ +typedef GenericRectangle I32Rect; + +/*! + * \class pcl::Rect + * \ingroup rect_types_2d + * \brief 32-bit integer rectangle on the plane. + * + * %Rect is an alias for I32Rect. It is a template instantiation of + * GenericRectangle for \c int32. + */ +typedef I32Rect Rect; + +/*! + * \class pcl::F32Rect + * \ingroup rect_types_2d + * \brief 32-bit floating-point rectangle in the R^2 space. + * + * %F32Rect is a template instantiation of GenericRectangle for \c float. + */ +typedef GenericRectangle F32Rect; + +/*! + * \class pcl::FRect + * \ingroup rect_types_2d + * \brief 32-bit floating-point rectangle in the R^2 space. + * + * %FRect is an alias for F32Rect. It is a template instantiation of + * GenericRectangle for \c float. + */ +typedef F32Rect FRect; + +/*! + * \class pcl::F64Rect + * \ingroup rect_types_2d + * \brief 64-bit floating-point rectangle in the R^2 space. + * + * %F64Rect is a template instantiation of GenericRectangle for \c double. + */ +typedef GenericRectangle F64Rect; + +/*! + * \class pcl::DRect + * \ingroup rect_types_2d + * \brief 64-bit floating-point rectangle in the R^2 space. + * + * %DRect is an alias for F64Rect. It is a template instantiation of + * GenericRectangle for \c double. + */ +typedef F64Rect DRect; + +#endif + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Rectangle_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Rectangle.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/RedundantMultiscaleTransform.h b/3rdparty/include/pcl/RedundantMultiscaleTransform.h new file mode 100644 index 0000000..93c8814 --- /dev/null +++ b/3rdparty/include/pcl/RedundantMultiscaleTransform.h @@ -0,0 +1,576 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/RedundantMultiscaleTransform.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_RedundantMultiscaleTransform_h +#define __PCL_RedundantMultiscaleTransform_h + +/// \file pcl/RedundantMultiscaleTransform.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup multiscale_transforms Multiscale Transforms + */ + +/*! + * \class RedundantMultiscaleTransform + * \brief Base class of all redundant multiscale transforms. + * + * A redundant multiscale transform produces a set {w1,w2,...,wN,cN}, where + * each wj is a set of coefficients at scale j, which we call detail + * layer, and cN is a large-scale smoothed residual, which we call + * residual layer. Each layer has the same dimensions as the input + * image, so the generated multiscale transform is called \e redundant. Two + * well-known examples of redundant multiscale transform algorithms are the + * à trous (with holes) wavelet transform, also known as starlet + * transform, and the multiscale median transform. + * + * In all cases the reconstruction algorithm consists of the sum of all wj + * multiscale layers for 1 <= j <= N, plus the residual layer cN. + * + * In our implementation, each layer in a redundant multiscale transform is a + * floating-point image with the same dimensions as the transformed image. + * Layers are indexed from 0 to N. Layers at indexes from 0 to N-1 are + * detail layers, whose elements are actually difference coefficients. Pixel + * samples in a detail layer can be negative, zero or positive real values. + * + * The last layer, at index N, is the large-scale residual layer. Pixel samples + * in the residual layer image can only be positive or zero real values. + * + * \ingroup multiscale_transforms + * \sa ATrousWaveletTransform, StarletTransform, MultiscaleMedianTransform, + * MultiscaleLinearTransform + */ +class PCL_CLASS RedundantMultiscaleTransform : public BidirectionalImageTransformation, + public ParallelProcess +{ +public: + + /*! + * Represents a multiscale layer. + */ + typedef Image layer; + + /*! + * Represents a set of multiscale layers, or multiscale transform. + */ + typedef Array transform; + + /*! + * Represents a set of layer enabled/disabled states. + */ + typedef GenericVector layer_state_set; + + /*! + * Constructs a redundant multiscale transform. + * + * \param n Number of detail layers. The transform will consist of \a n + * detail layers plus a residual layer, that is n+1 total + * layers. The default value is 4. + * + * \param d Scaling sequence. If \a d ≤ 0, the transform will use the + * dyadic sequence: 1, 2, 4, ... 2^i. If \a d > 0, its value is + * the distance in pixels between two successive scales. + * + * The default values for \a n and \a d are 4 and 0, respectively (four + * layers and the dyadic scaling sequence). + * + * Successive layers are computed by applying linear or nonlinear operations + * with kernels of size 2*s + 1. The scaling sequence parameter \a d is + * interpreted as follows: + * + * - If the specified sequence parameter \a d is zero 0, then the transform + * uses the dyadic sequence: s = 1, 2, 4, ..., 2^j for 0 ≤ j < n. + * + * - If \a d > 0, then \a d is the constant increment in pixels between two + * successive scales (linear scaling sequence): s = d*j for 1 ≤ j < n. + */ + RedundantMultiscaleTransform( int n = 4, int d = 0 ) + : m_delta( Max( 0, d ) ) + , m_numberOfLayers( Max( 1, n ) ) + { + PCL_PRECONDITION( n >= 1 ) + PCL_PRECONDITION( d >= 0 ) + InitializeLayersAndStates(); + } + + /*! + * Copy constructor. + */ + RedundantMultiscaleTransform( const RedundantMultiscaleTransform& x ) + : BidirectionalImageTransformation( x ) + , ParallelProcess( x ) + , m_delta( x.m_delta ) + , m_numberOfLayers( x.m_numberOfLayers ) + , m_transform( x.m_transform ) + , m_layerEnabled( x.m_layerEnabled ) + { + m_transform.EnsureUnique(); + } + + /*! + * Move constructor. + */ + RedundantMultiscaleTransform( RedundantMultiscaleTransform&& ) = default; + + /*! + * Destroys this %RedundantMultiscaleTransform object. All existing layers + * are destroyed and deallocated. + */ + virtual ~RedundantMultiscaleTransform() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + RedundantMultiscaleTransform& operator =( const RedundantMultiscaleTransform& x ) + { + (void)BidirectionalImageTransformation::operator =( x ); + (void)ParallelProcess::operator =( x ); + m_delta = x.m_delta; + m_numberOfLayers = x.m_numberOfLayers; + m_transform = x.m_transform; + m_transform.EnsureUnique(); + m_layerEnabled = x.m_layerEnabled; + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + RedundantMultiscaleTransform& operator =( RedundantMultiscaleTransform&& ) = default; + + /*! + * Returns the scaling sequence used by this multiscale transform. + * + * Successive layers are computed by applying linear on nonlinear operations + * with kernels of size 2*s + 1. + * + * If the value returned by this function is zero 0, then the transform uses + * the dyadic sequence: s = 1, 2, 4, ..., 2^j for 0 <= j < n. + * + * If the returned value is > 0, it is the constant increment in pixels + * between two successive scales (linear scaling sequence): s = d*j for + * 1 <= j < n. + */ + int ScalingSequence() const + { + return m_delta; + } + + /*! + * Sets the scaling sequence \a d used by this multiscale transform. + * + * For the meaning of the \a d scaling sequence parameter, see the + * documentation for the ScalingSequence() member function. + * + * \note As a consequence of calling this member function, all existing + * layers in this transform are destroyed. + */ + void SetScalingSequence( int d ) + { + PCL_PRECONDITION( d >= 0 ) + DestroyLayers(); + m_delta = Max( 0, d ); + } + + /*! + * Selects the dyadic scaling sequence for this multiscale transform. + * + * This is a convenience function, equivalent to: + * SetScalingSequence( 0 ); + * + * \note As a consequence of calling this member function, all existing + * layers in this transform are destroyed. + */ + void SetDyadicScalingSequence() + { + SetScalingSequence( 0 ); + } + + /*! + * Selects a linear scaling sequence with distance \a d in pixels. + * + * This is a convenience function, equivalent to: + * SetScalingSequence( d ); + * + * \note As a consequence of calling this member function, all existing + * layers in this transform are destroyed. + */ + void SetLinearScalingSequence( int d = 1 ) + { + PCL_PRECONDITION( d >= 1 ) + SetScalingSequence( Max( 1, d ) ); + } + + /*! + * Returns the filter size for the specified layer \a j. Returns an odd + * integer larger than or equal to three. For the dyadic scaling sequence, + * the returned value is equal to 1 + 2*2^j (3, 5, 9, 17, 33, ...). For a + * linear scaling sequence with distance d, returns 1 + 2*d*(1 + j). + */ + int FilterSize( int j ) const + { + return 1 + (((m_delta < 1) ? 1 << j : (1 + j)*m_delta) << 1); + } + + /*! + * Returns the number of detail layers that will be (or have been) generated + * by this transform. + * + * The number returned does not include the residual layer. In + * other words, the total number of layers generated is always equal to one + * plus the value returned by this member function, since the large-scale + * residual layer is always generated by all multiscale transforms. + */ + int NumberOfLayers() const + { + return m_numberOfLayers; + } + + /*! + * Sets the number of detail layers that will be generated by this + * transform. + * + * \param n Number of detail layers, not including the last, + * large-scale residual layer. Must be \a n >= 1. + * + * \note Calling this function implicitly performs a complete reset of this + * object, including the deletion of all existing layers. + */ + void SetNumberOfLayers( int n ) + { + PCL_PRECONDITION( n >= 1 ) + m_numberOfLayers = Max( 1, n ); + InitializeLayersAndStates(); + } + + /*! + * Returns a reference to the immutable layer at scale index \a i, + * 0 <= \a i <= \a n, where \a n is the number of generated detail layers. + * If \a i == \a n, this member function returns a reference to the + * large-scale residual layer. + * + * \note Before trying to access layers, the multiscale transform must be + * performed on an image. In addition, the specified layer must exist (must + * not have been deleted). Otherwise this function (as well as others that + * provide access to layer images) throws an Error exception. + */ + const layer& Layer( int i ) const + { + ValidateLayerAccess( i ); + return m_transform[i]; + } + + /*! + * Returns a reference to the (mutable) layer at scale index \a i. This is + * an overloaded member function, provided for convenience. + * + * See Layer( int ) const for more information. + */ + layer& Layer( int i ) + { + ValidateLayerAccess( i ); + return m_transform[i]; + } + + /*! + * Returns a reference to the (immutable) layer at scale index \a i. This is + * a convenience operator, equivalent to: + * + * \code Layer( i ) const; \endcode + * + * The array subscript operators can produce more elegant code than the + * %Layer functions. + */ + const layer& operator []( int i ) const + { + return Layer( i ); + } + + /*! + * Returns a reference to the (mutable) layer at scale index \a i. This is a + * convenience operator, equivalent to: + * + * \code Layer( i ); \endcode + * + * The array subscript operators can produce more elegant code than the + * %Layer functions. + */ + layer& operator []( int i ) + { + return Layer( i ); + } + + /*! + * Deletes the layer at layer index \a i, 0 <= \a i <= \a n, where \a n is + * the number of generated layers. If \a i == \a n this member function + * deletes the large-scale residual layer. + * + * Deleted layers are excluded from image reconstructions performed by + * subsequent inverse multiscale transforms. + * + * For example, if you delete the first two layers of a transform, a + * subsequent inverse transform will remove all small-scale image structures + * smaller than four pixels, assuming a dyadic scaling sequence. + */ + void DeleteLayer( int i ) + { + ValidateLayerAccess( i ); + m_transform[i].FreeData(); + } + + /*! + * Returns true iff the layer at layer index \a i exists (0 <= \a i <= \a n, + * where \a n is the number of generated layers), that is, if the multiscale + * transform has been generated and the specified layer has been calculated + * (because it was not disabled) and has not been deleted. + */ + bool IsLayer( int i ) const + { + ValidateLayerIndex( i ); + return !m_transform[i].IsEmpty(); + } + + /*! + * Enables or disables the layer at index \a i, 0 <= \a i <= \a n, where + * \a n is the number of generated layers. If \a i == \a n, this member + * function enables or disables the large-scale residual layer. + * + * Disabled layers are not generated during multiscale transforms, so they + * are obviously excluded from image reconstructions (inverse transforms). + * This has the advantage that a lot of memory can be saved if one or more + * layers aren't required or have to be excluded from the inverse transform. + * + * For the reason explained, disabling layers is more efficient, in terms of + * memory consumption, if done \e before the multiscale transform. When the + * transform has already been performed, disabling one or more layers + * excludes them from reconstructions, but does not delete them, so the + * after-transformation layer disable operation, unlike layer deletion, is + * reversible. + */ + void EnableLayer( int i, bool enable = true ) + { + ValidateLayerIndex( i ); + m_layerEnabled[i] = enable; + } + + /*! + * Disables or enables the layer at index \a i, 0 <= \a i <= \a n, where + * \a n is the number of generated layers. If \a i == \a n, this member + * function disables or enables the large-scale residual layer. + * + * This is a convenience function, equivalent to: + * EnableLayer( i, !disable ); + */ + void DisableLayer( int i, bool disable = true ) + { + EnableLayer( i, !disable ); + } + + /*! + * Returns true iff the layer at index \a i is enabled, false if it is + * disabled. See the documentation for EnableLayer( int, bool ) for detailed + * information about disabled layers. + */ + bool IsLayerEnabled( int i ) const + { + ValidateLayerIndex( i ); + return m_layerEnabled[i]; + } + + /*! + * Biases a multiscale transform layer. + * + * \param i Layer index, 0 <= \a i <= \a n, where \a n is the number of + * generated multiscale layers. If \a i == \a n, the residual + * layer is biased. + * + * \param k Bias factor. Positive biases increase the relative weight of + * biased layers in image reconstructions (inverse transforms). + * Negative biases decrease relative layer weights. A zero bias + * factor does not change a layer. + * + * This member function can be used to enhance or attenuate image structures + * at selected scales. Consider this code: + * + * \code + * Image img; + * // ... + * RedundantMultiscaleTransform* M; + * // ... + * *M << img; // decomposition (transform) + * M->BiasLayer( 1, +2.5 ); + * M->BiasLayer( 3, -1 ); + * *M >> img; // reconstruction (inverse transform) + * \endcode + * + * In the example above, the second and fourth layers of a multiscale + * transform have been biased. The layer at index 1 (the second layer) has + * been enhanced because a positive layer bias has been applied (2.5). The + * layer at index 3 (fourth layer) has been attenuated because a negative + * bias (-1) has been applied. + * + * \note Layer biasing is an \e irreversible operation because it works by + * multiplying all coefficients in the specified layer by a constant derived + * from the specified bias factor. + */ + void BiasLayer( int i, float k ) + { + ValidateLayerAccess( i ); + if ( k != 0 ) + m_transform[i] *= (k > 0) ? (1 + k) : 1/(1 - k); + } + + /*! + * Returns the set of layers in this transform, after clearing the transform + * without destroying its layers, whose ownership is then transferred to the + * caller. + * + * If no multiscale transform has been performed, this function returns an + * empty set. + * + * The caller is responsible for deallocation of the returned layers. After + * calling this function, this object will be empty, just as if no transform + * had been performed. + */ + virtual transform ReleaseTransform() + { + transform r = m_transform; + DestroyLayers(); + return r; + } + + /*! + * Destroys and deallocates all existing layers and resets all layer states + * so that all layers are enabled. + */ + virtual void Reset() + { + InitializeLayersAndStates(); + } + +protected: + + /* + * delta >= 1 : + * Linear scaling sequence. delta is the constant scale difference + * between two consecutive layers. + * + * delta < 1 : + * Dyadic scaling sequence (1, 2, 4, 8, 16, ...). + */ + int m_delta = 0; + + /* + * Number of detail layers, *not including* the residual smoothed layer, + * which is always generated in a multiscale transform. + */ + int m_numberOfLayers = 4; + + /* + * Array of transform layers, including the residual layer, so the length + * of this array is numberOfLayers+1. + */ + transform m_transform; + + /* + * Vector of layer enable/disable states. + */ + layer_state_set m_layerEnabled; + + /* + * Inverse transform (reconstruction) + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::ComplexImage& ) const override; + void Apply( pcl::DComplexImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; + + void InitializeLayersAndStates() + { + DestroyLayers(); + m_layerEnabled = layer_state_set( true, m_numberOfLayers+1 ); + } + + void DestroyLayers() + { + m_transform = transform( size_type( m_numberOfLayers+1 ) ); + } + + void ValidateLayerIndex( int j ) const; + void ValidateLayerAccess( int j ) const; + + friend class MTReconstruction; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_RedundantMultiscaleTransform_h + +// ---------------------------------------------------------------------------- +// EOF pcl/RedundantMultiscaleTransform.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ReferenceArray.h b/3rdparty/include/pcl/ReferenceArray.h new file mode 100644 index 0000000..0089bcb --- /dev/null +++ b/3rdparty/include/pcl/ReferenceArray.h @@ -0,0 +1,2253 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ReferenceArray.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_ReferenceArray_h +#define __PCL_ReferenceArray_h + +/// \file pcl/ReferenceArray.h + +#include + +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ReferenceArray + * \brief Dynamic array of pointers to objects providing direct iteration and + * element access by reference. + * + * %ReferenceArray is a generic, finite ordered sequence of pointers to + * objects, implemented as a reference-counted, dynamic array of pointers to T + * instances. The type A provides dynamic allocation for contiguous sequences + * of void* (StandardAllocator is used by default). + * + * Unlike IndirectArray, %ReferenceArray provides direct access to the objects + * pointed to by its contained pointers, including direct iteration through + * references instead of pointers. This makes %ReferenceArray a perfect + * replacement for Array in cases where storing copies of objects is inviable + * or impractical; for example, when the objects to be stored are unique by + * nature, when the cost of a copy operation is excessive, or as the underlying + * implementation of an heterogeneous container. As a prerequisite for this + * functionality, %ReferenceArray, unlike IndirectArray, cannot contain null + * pointers. + * + * \sa ReferenceSortedArray, IndirectArray, IndirectSortedArray, Array, + * SortedArray, ReferenceCounter + * \ingroup dynamic_arrays + */ +template +class PCL_CLASS ReferenceArray : public DirectContainer +{ +public: + + /*! # + */ + typedef IndirectArray array_implementation; + + /*! # + */ + typedef typename array_implementation::block_allocator + block_allocator; + + /*! # + */ + typedef typename array_implementation::allocator + allocator; + + /*! # + */ + typedef typename array_implementation::iterator + indirect_iterator; + + /*! # + */ + typedef typename array_implementation::const_iterator + const_indirect_iterator; + + /*! + * \class pcl::ReferenceArray::iterator + * \brief Mutable %ReferenceArray iterator + */ + class iterator : public Iterator + { + public: + + typedef Iterator iterator_base; + + typedef typename iterator_base::iterator_class + iterator_class; + + typedef typename iterator_base::item_type item_type; + + /*! + * Default constructor. Constructs an uninitialized iterator object. + */ + iterator() = default; + + /*! + * Copy constructor. + */ + iterator( const iterator& ) = default; + + /*! + * Constructs a null iterator. + */ + iterator( std::nullptr_t ) : it( nullptr ) + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + iterator& operator =( const iterator& ) = default; + + /*! + * Pointer-to-object conversion operator. Returns a pointer to the object + * pointed to by this iterator. + */ + operator T*() const + { + return *it; + } + + /*! + * Indirection operator. Returns a reference to the object pointed to by + * this iterator. + */ + T& operator *() const + { + return **it; + } + + /*! + * Structure selection operator. Returns a pointer to the object pointed + * to by this iterator. + */ + T* operator ->() const + { + return *it; + } + + /*! + * Preincrement operator. Increments this iterator so that it points to + * the next object in the iterated container, then returns a reference to + * this iterator. + */ + iterator& operator ++() + { + ++it; + return *this; + } + + /*! + * Postincrement operator. Increments this iterator so that it points to + * the next object in the iterated container. Returns a copy of the + * iterator as it was before incrementing it. + */ + iterator operator ++( int ) + { + indirect_iterator it0 = it; + ++it; + return it0; + } + + /*! + * Predecrement operator. Decrements this iterator so that it points to + * the previous object in the iterated container, then returns a + * reference to this iterator. + */ + iterator& operator --() + { + --it; + return *this; + } + + /*! + * Postdecrement operator. Decrements this iterator so that it points to + * the previous object in the iterated container. Returns a copy of the + * iterator as it was before decrementing it. + */ + iterator operator --( int ) + { + indirect_iterator it0 = it; + --it; + return it0; + } + + /*! + * Assignment/addition operator. Increments this iterator by a distance + * \a d from its current position. Positive increments cause this + * iterator to move forward by \a d elements. Negative increments move + * this iterator backward by \a d elements. Returns a reference to this + * iterator. + */ + iterator& operator +=( distance_type d ) + { + it += d; + return *this; + } + + /*! + * Assignment/subtraction operator. Decrements this iterator by a + * distance \a d from its current position. Positive increments cause + * this iterator to move backward by \a d elements. Negative increments + * move this iterator forward by \a d elements. Returns a reference to + * this iterator. + */ + iterator& operator -=( distance_type d ) + { + it -= d; + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to this iterator incremented by a distance \a d. + */ + iterator operator +( distance_type d ) const + { + return iterator( it + d ); + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * this iterator decremented by a distance \a d. + */ + iterator operator -( distance_type d ) const + { + return iterator( it - d ); + } + + /*! + * Iterator subtraction operator. Returns the distance (in container + * elements) between this iterator and another iterator \a i. + */ + distance_type operator -( const iterator& i ) const + { + return it - i.it; + } + + /*! + * Equality operator. Returns true if this iterator points to the same + * object as another iterator \a i. + */ + bool operator ==( const iterator& i ) const + { + return it == i.it; + } + + /*! + * Less than operator. Returns true if this iterator points to a + * container element that precedes another iterator \a i. + */ + bool operator <( const iterator& i ) const + { + return it < i.it; + } + + private: + + indirect_iterator it = nullptr; + + /*! + * Constructor from an IndirectArray iterator (a pointer to a pointer to + * an object in the iterated container). + */ + explicit + iterator( indirect_iterator i ) : it( i ) + { + } + + friend class ReferenceArray; + friend class ReferenceArray::const_iterator; + }; + + /*! + * \class pcl::ReferenceArray::const_iterator + * \brief Immutable %ReferenceArray iterator + */ + class const_iterator : public Iterator + { + public: + + typedef Iterator iterator_base; + + typedef typename iterator_base::iterator_class + iterator_class; + + typedef typename iterator_base::item_type item_type; + + /*! + * Default constructor. Constructs an uninitialized iterator object. + */ + const_iterator() = default; + + /*! + * Constructor from non-const iterator. + */ + const_iterator( const iterator& i ) : it( i.it ) + { + } + + /*! + * Constructs a null iterator. + */ + const_iterator( std::nullptr_t ) : it( nullptr ) + { + } + + /*! + * Copy constructor. + */ + const_iterator( const const_iterator& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this immutable + * iterator. + */ + const_iterator& operator =( const const_iterator& ) = default; + + /*! + * Mutable iterator assignment operator. Returns a reference to this + * immutable iterator object. + */ + const_iterator& operator =( const iterator& i ) + { + it = i.it; + return *this; + } + + /*! + * Pointer-to-const-object conversion operator. Returns a pointer to the + * immutable object pointed to by this iterator. + */ + operator const T*() const + { + return *it; + } + + /*! + * Indirection operator. Returns a reference to the object pointed to by + * this iterator. + */ + const T& operator *() const + { + return **it; + } + + /*! + * Structure selection operator. Returns a pointer to the object pointed + * to by this iterator. + */ + const T* operator ->() const + { + return *it; + } + + /*! + * Preincrement operator. Increments this iterator so that it points to + * the next object in the iterated container, then returns a reference to + * this iterator. + */ + const_iterator& operator ++() + { + ++it; + return *this; + } + + /*! + * Postincrement operator. Increments this iterator so that it points to + * the next object in the iterated container. Returns a copy of the + * iterator as it was before incrementing it. + */ + const_iterator operator ++( int ) + { + const_indirect_iterator it0 = it; + ++it; + return it0; + } + + /*! + * Predecrement operator. Decrements this iterator so that it points to + * the previous object in the iterated container, then returns a + * reference to this iterator. + */ + const_iterator& operator --() + { + --it; + return *this; + } + + /*! + * Postdecrement operator. Decrements this iterator so that it points to + * the previous object in the iterated container. Returns a copy of the + * iterator as it was before decrementing it. + */ + const_iterator operator --( int ) + { + const_indirect_iterator it0 = it; + --it; + return it0; + } + + /*! + * Assignment/addition operator. Increments this iterator by a distance + * \a d from its current position. Positive increments cause this + * iterator to move forward by \a d elements. Negative increments move + * this iterator backward by \a d elements. Returns a reference to this + * iterator. + */ + const_iterator& operator +=( distance_type d ) + { + it += d; + return *this; + } + + /*! + * Assignment/subtraction operator. Decrements this iterator by a + * distance \a d from its current position. Positive increments cause + * this iterator to move backward by \a d elements. Negative increments + * move this iterator forward by \a d elements. Returns a reference to + * this iterator. + */ + const_iterator& operator -=( distance_type d ) + { + it -= d; + return *this; + } + + /*! + * Scalar-to-iterator addition operator. Returns an iterator equivalent + * to this iterator incremented by a distance \a d. + */ + const_iterator operator +( distance_type d ) const + { + return const_iterator( it + d ); + } + + /*! + * Scalar-to-iterator subtraction operator. Returns an iterator equal to + * this iterator decremented by a distance \a d. + */ + const_iterator operator -( distance_type d ) const + { + return const_iterator( it - d ); + } + + /*! + * Iterator subtraction operator. Returns the distance (in container + * elements) between this iterator and another iterator \a i. + */ + distance_type operator -( const const_iterator& i ) const + { + return it - i.it; + } + + /*! + * Iterator subtraction operator. Returns the distance (in container + * elements) between this iterator and a mutable iterator \a i. + */ + distance_type operator -( const iterator& i ) const + { + return it - i.it; + } + + /*! + * Equality operator. Returns true if this iterator points to the same + * object as another iterator \a i. + */ + bool operator ==( const const_iterator& i ) const + { + return it == i.it; + } + + /*! + * Equality operator. Returns true if this iterator points to the same + * object as a mutable iterator \a i. + */ + bool operator ==( const iterator& i ) const + { + return it == i.it; + } + + /*! + * Less than operator. Returns true if this iterator precedes another + * iterator \a i. + */ + bool operator <( const const_iterator& i ) const + { + return it < i.it; + } + + /*! + * Less than operator. Returns true if this iterator points to a + * container element that precedes a mutable iterator \a i. + */ + bool operator <( const iterator& i ) const + { + return it < i.it; + } + + private: + + const_indirect_iterator it = nullptr; + + /*! + * Constructor from an IndirectArray iterator (a pointer to a pointer to + * an object in the iterated container). + */ + explicit + const_iterator( const_indirect_iterator i ) : it( i ) + { + } + + friend class ReferenceArray; + }; + + /*! + * \class pcl::ReferenceArray::reverse_iterator + * \brief Mutable %ReferenceArray reverse iterator. + */ + typedef ReverseRandomAccessIterator + reverse_iterator; + + /*! + * \class pcl::ReferenceArray::const_reverse_iterator + * \brief Immutable %ReferenceArray reverse iterator. + */ + typedef ReverseRandomAccessIterator + const_reverse_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty reference array. + */ + ReferenceArray() = default; + + /*! + * Constructs a reference array that stores \a n copies of a non-null + * pointer \a p. + * + * If \a p is \c nullptr, this function constructs an empty reference array. + */ + ReferenceArray( size_type n, const T* p ) + { + PCL_PRECONDITION( p != nullptr ) + if ( p != nullptr ) + m_array = array_implementation( n, p ); + } + + /*! + * Constructs a reference array as a copy of the sequence of non-null + * pointers defined by the range [i,j) of forward iterators. + * + * If the range [i,j) contains null pointers, these are ignored and hence + * not included in the constructed reference array. + */ + template + ReferenceArray( FI i, FI j ) + { + for ( ; i != j; ++i ) + if ( *i != nullptr ) + m_array.Append( *i ); + } + + /*! + * Copy constructor. + */ + ReferenceArray( const ReferenceArray& ) = default; + + /*! + * Move constructor. + */ + ReferenceArray( ReferenceArray&& ) = default; + + /*! + * Destroys a %ReferenceArray object. + * + * Deallocates the internal array of pointers to objects, but does not + * destroy the pointed objects. To destroy them, you have to call Destroy() + * or Delete() explicitly. + */ + ~ReferenceArray() + { + } + + /*! + * Returns true iff this reference array uniquely references its contained + * array of pointers to objects. + */ + bool IsUnique() const + { + return m_array.IsUnique(); + } + + /*! + * Returns true iff this reference array is an alias of the array \a x. + * + * Two objects are aliases if both share the same data. Two reference + * containers are aliases if they share a unique set of object pointers. + */ + bool IsAliasOf( const ReferenceArray& x ) const + { + return m_array.IsAliasOf( x.m_array ); + } + + /*! + * Ensures that this reference array uniquely references its contained + * object pointers. + * + * If necessary, this member function generates a duplicate of the array + * of pointers, references it, and then decrements the reference counter of + * the original pointer array. + */ + void EnsureUnique() + { + m_array.EnsureUnique(); + } + + /*! + * Returns the total number of bytes required to store the array of object + * pointers contained by this reference array. + */ + size_type Size() const + { + return m_array.Size(); + } + + /*! + * Returns the length of this reference array. + */ + size_type Length() const + { + return m_array.Length(); + } + + /*! + * Returns the capacity of this reference array. The capacity is the maximum + * number of pointers to objects that this reference array can contain + * without requiring a reallocation. + */ + size_type Capacity() const + { + return m_array.Capacity(); + } + + /*! + * Returns the length of the space available in this reference array, or + * zero if this reference array cannot contain more pointers. The available + * space is the number of pointers to objects that can be added to this + * reference array without requiring a reallocation. It is equal to + * Capacity() - Length() by definition. + */ + size_type Available() const + { + return m_array.Available(); + } + + /*! + * Returns true only if this reference array is valid. A reference array is + * valid if it references an internal structure with an array of pointers, + * even if it is an empty array. + * + * In general, all %ReferenceArray objects are valid with only two + * exceptions: + * + * \li Objects that have been move-copied or move-assigned to other arrays. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid array object cannot be used and should be destroyed + * immediately. Invalid arrays are always destroyed automatically during + * move construction and move assignment operations. + */ + bool IsValid() const + { + return m_array.IsValid(); + } + + /*! + * Returns true iff this reference array is empty. + */ + bool IsEmpty() const + { + return m_array.IsEmpty(); + } + + /*! + * Returns the minimum legal index in this array (always zero). For empty + * arrays, this function returns a meaningless value. + */ + size_type LowerBound() const + { + return m_array.LowerBound(); + } + + /*! + * Returns the maximum legal index in this array. It is equal to Length()-1. + * For empty arrays, this function returns a meaningless value. + */ + size_type UpperBound() const + { + return m_array.UpperBound(); + } + + /*! + * Returns a reference to the allocator object used by this reference array. + */ + const allocator& Allocator() const + { + return m_array.Allocator(); + } + + /*! + * Sets a new allocator object for this reference array. + */ + void SetAllocator( const allocator& a ) + { + m_array.SetAllocator( a ); + } + + /*! + * Returns a mutable reference array iterator located at the specified array + * index \a i. + */ + iterator At( size_type i ) + { + return iterator( m_array.At( i ) ); + } + + /*! + * Returns an immutable reference array iterator located at the specified + * array index \a i. + */ + const_iterator At( size_type i ) const + { + return const_iterator( m_array.At( i ) ); + } + + /*! + * Returns a mutable iterator pointing to the same array element as the + * specified immutable iterator \a i. + * + * \warning As a side-effect of calling this function, the specified + * immutable iterator \a i may become invalid. This happens when this + * function is called for a shared array, since in this case getting a + * mutable iterator involves a deep copy of the array through an implicit + * call to EnsureUnique(). + */ + iterator MutableIterator( const_iterator i ) + { + return iterator( m_array.MutableIterator( i.it ) ); + } + + /*! + * Returns a reference to the object at the specified array index + * \a i. No bounds checking is performed. + */ + T& operator []( size_type i ) + { + return *m_array[i]; + } + + /*! + * Returns a reference to the immutable object at the specified array + * index \a i. No bounds checking is performed. + */ + const T& operator []( size_type i ) const + { + return *m_array[i]; + } + + /*! + * Returns a reference to the first object in this reference array. + */ + T& operator *() + { + return **m_array.Begin(); + } + + /*! + * Returns a reference to the unmodifiable first object in this reference + * array. + */ + const T& operator *() const + { + return **m_array.Begin(); + } + + /*! + * Returns a mutable iterator located at the beginning of this array. + */ + iterator Begin() + { + return iterator( m_array.Begin() ); + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator Begin() const + { + return const_iterator( m_array.Begin() ); + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator ConstBegin() const + { + return const_iterator( m_array.ConstBegin() ); + } + + /*! + * Returns a mutable iterator located at the end of this array. + */ + iterator End() + { + return iterator( m_array.End() ); + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator End() const + { + return const_iterator( m_array.End() ); + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator ConstEnd() const + { + return const_iterator( m_array.ConstEnd() ); + } + + /*! + * Returns a mutable reverse iterator located at the reverse + * beginning of this reference array. + * + * The reverse beginning corresponds to the last object in the array. + */ + reverse_iterator ReverseBegin() + { + return iterator( m_array.End()-1 ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this reference array. + * + * The reverse beginning corresponds to the last object in the array. + */ + const_reverse_iterator ReverseBegin() const + { + return const_iterator( m_array.End()-1 ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this indirect array. + * + * The reverse beginning corresponds to the last pointer in the array. + */ + const_reverse_iterator ConstReverseBegin() const + { + PCL_PRECONDITION( !IsEmpty() ) + return const_iterator( m_array.End()-1 ); + } + + /*! + * Returns a mutable reverse iterator located at the reverse end of + * this reference array. + * + * The reverse end corresponds to a (nonexistent) object immediately before + * the first object in the array. + */ + reverse_iterator ReverseEnd() + { + PCL_PRECONDITION( !IsEmpty() ) + return iterator( m_array.Begin()-1 ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this reference array. + * + * The reverse end corresponds to a (nonexistent) object immediately before + * the first object in the array. + */ + const_reverse_iterator ReverseEnd() const + { + PCL_PRECONDITION( !IsEmpty() ) + return const_iterator( m_array.Begin()-1 ); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this reference array. + * + * The reverse end corresponds to a (nonexistent) object immediately before + * the first object in the array. + */ + const_reverse_iterator ConstReverseEnd() const + { + PCL_PRECONDITION( !IsEmpty() ) + return const_iterator( m_array.Begin()-1 ); + } + + /*! + * Returns a reference to the first object in this reference array. This + * function should never be called for an empty array. + */ + T& First() + { + return **m_array.Begin(); + } + + /*! + * Returns a reference to the first unmodifiable object in this reference + * array. This function should never be called for an empty array. + */ + const T& First() const + { + return **m_array.Begin(); + } + + /*! + * Returns a reference to the last object in this reference array. This + * function should never be called for an empty array. + */ + T& Last() + { + return **m_array.ReverseBegin(); + } + + /*! + * Returns a reference to the last unmodifiable object in this reference + * array. This function should never be called for an empty array. + */ + const T& Last() const + { + return **m_array.ReverseBegin(); + } + + /*! + * Ensures that the specified iterator represents a pointer stored in a + * uniquely referenced indirect array. If necessary, this function builds a + * new, uniquely referenced copy of the underlying indirect array by calling + * EnsureUnique(). + * + * If the iterator \a i is changed, it is guaranteed to point to the object + * at the same array index it was pointing to before calling this function. + */ + void UniquifyIterator( iterator& i ) + { + m_array.UniquifyIterator( i.it ); + } + + /*! + * Ensures that the specified iterators represents a pointer stored in a + * uniquely referenced indirect array. If necessary, this function builds a + * new, uniquely referenced copy of the underlying indirect array by calling + * EnsureUnique(). + * + * If the iterators \a i and \a j are changed, they are guaranteed to point + * to the objects at the same array indices they were pointing to before + * calling this function. + */ + void UniquifyIterators( iterator& i, iterator& j ) + { + m_array.UniquifyIterators( i.it, j.it ); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + iterator end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Copy assignment operator. + * + * Causes this reference array to reference the same set of objects as + * another array \a x. Returns a reference to this object. + */ + ReferenceArray& operator =( const ReferenceArray& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns a reference array \a x to this reference array. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Increments the reference counter of the source array's data and + * references it in this array. + */ + void Assign( const ReferenceArray& x ) + { + m_array.Assign( x.m_array ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ReferenceArray& operator =( ReferenceArray&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from another reference array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( ReferenceArray& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! + * Transfers data from another reference array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( ReferenceArray&& x ) + { + m_array.Transfer( std::move( x.m_array ) ); + } + + /*! + * Replaces the contents of this reference array with a sequence of \a n + * pointers equal to \a p. + * + * if \a p is \c nullptr, this function yields an empty array. + */ + void Assign( const T* p, size_type n = 1 ) + { + if ( p != nullptr ) + m_array.Assign( p, n ); + else + m_array.Clear(); + } + + /*! + * Replaces the contents of this reference array with a copy of the sequence + * of pointers defined by the range [i,j) of forward iterators. + * + * If the range [i,j) contains null pointers, these are ignored and hence + * not included in this reference array. + * + * \note \a i and \a j must not be iterators into this array. + */ + template + void Assign( FI i, FI j ) + { + m_array.Clear(); + for ( ; i != j; ++i ) + if ( *i != nullptr ) + m_array.Append( *i ); + } + + /*! + * Replaces the contents of this reference array with a set of pointers to + * newly created copies of the objects stored in the specified container + * \a x. This function works for both direct and indirect containers. + * + * Keep in mind that after calling this function (with a reference to a + * nonempty container) this array will store newly allocated objects. You + * should call Destroy() to deallocate these objects before destructing this + * reference array in order to avoid a memory leak. + */ + template + void CloneAssign( const C& x ) + { + PCL_ASSERT_CONTAINER( C, T ); + CloneObjects( x, (C*)nullptr ); + } + + /*! + * Causes this reference array to store the sequence of pointers defined by + * the range [i,j) of iterators. The previously referenced data structure is + * dereferenced and deallocated if it becomes unreferenced. + */ + void Import( iterator i, iterator j ) + { + m_array.Import( i.it, j.it ); + } + + /*! + * Releases the set of pointers contained by this reference array. + * + * This member function returns a pointer to the internal block of pointers + * stored in this object, after ensuring that it is uniquely referenced. + * If the array is empty, this function may return the null pointer. + * + * Before returning, this member function empties this array without + * deallocating its contained data. The caller is then responsible for + * deallocating the returned block when it is no longer required. + */ + indirect_iterator Release() + { + return m_array.Release(); + } + + /*! + * Inserts a copy of the sequence of pointers contained by the reference + * array \a x at the specified location \a i in this reference array. + * + * The insertion point \a i is constrained to stay in the range + * [Begin(),End()) of existing array elements. The source array \a x can + * safely be a reference to this array. + * + * Returns an iterator pointing to the first newly created array element, or + * \a i if \a x is empty. + */ + iterator Insert( const_iterator i, const ReferenceArray& x ) + { + return iterator( m_array.Insert( i.it, x.m_array ) ); + } + + /*! + * Inserts a contiguous sequence of \a n non-null pointers equal to \a p at + * the specified location \a i. + * + * If \a p is \c nullptr, this function has no effect. The insertion point + * \a i is constrained to stay in the range [Begin(),End()) of existing + * array elements. + * + * Returns an iterator pointing to the first inserted array element, or \a i + * if \a n is zero or \a p is \c nullptr. + */ + iterator Insert( const_iterator i, const T* p, size_type n = 1 ) + { + return (p != nullptr) ? iterator( m_array.Insert( i.it, p, n ) ) : + iterator( const_cast( i.it ) ); + } + + /*! + * Inserts a copy of the sequence of pointers defined by the range [p,q) + * of forward iterators at the specified location \a i in this reference + * array. + * + * If the range [p,q) contains null pointers, these are ignored and not + * inserted in this array. The insertion point \a i is constrained to stay + * in the range [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first inserted array element, or \a i + * if \a q <= \a p or no element in [p,q) is a non-null pointer. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + iterator Insert( const_iterator i, FI p, FI q ) + { + const_indirect_iterator it = i.it; + for ( ; p != q; ++p ) + if ( *p != nullptr ) + it = m_array.Insert( it, *p ); + return iterator( const_cast( it ) ); + } + + /*! + * Appends a copy of the sequence of pointers contained by the reference + * array \a x to this array. + */ + void Append( const ReferenceArray& x ) + { + m_array.Append( x.m_array ); + } + + /*! + * Appends a contiguous sequence of \a n pointers equal to \a p to this + * reference array. + * + * If \a p is \c nullptr, this function has no effect. + */ + void Append( const T* p, size_type n = 1 ) + { + if ( p != nullptr ) + m_array.Append( p, n ); + } + + /*! + * Appends a copy of the sequence of pointers defined by the range [p,q) + * of forward iterators to this reference array. + * + * If the range [p,q) contains null pointers, these are ignored and not + * inserted in this array. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + void Append( FI p, FI q ) + { + for ( ; p != q; ++p ) + if ( *p != nullptr ) + m_array.Append( *p ); + } + + /*! + * Inserts a copy of the sequence of pointers contained by the reference + * array \a x at the beginning of this reference array. + */ + void Prepend( const ReferenceArray& x ) + { + m_array.Prepend( x.m_array ); + } + + /*! + * Inserts a contiguous sequence of \a n pointers equal to \a p at the + * beginning of this indirect array. + * + * If \a p is \c nullptr, this function has no effect. + */ + void Prepend( const T* p, size_type n = 1 ) + { + if ( p != nullptr ) + m_array.Prepend( p, n ); + } + + /*! + * Inserts a copy of the sequence of pointers defined by the range [p,q) of + * forward iterators at the beginning of this indirect array. + * + * If the range [p,q) contains null pointers, these are ignored and not + * inserted in this array. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + void Prepend( FI p, FI q ) + { + for ( ; p != q; ++p ) + if ( *p != nullptr ) + m_array.Prepend( *p ); + } + + /*! + * A synonym for Append( const ReferenceArray<>& ) + */ + void Add( const ReferenceArray& x ) + { + Append( x ); + } + + /*! + * A synonym for Append( const T*, size_type ) + */ + void Add( const T* p, size_type n = 1 ) + { + Append( p, n ); + } + + /*! + * A synonym for Append( FI, FI ) + */ + template + void Add( FI i, FI j ) + { + Append( i, j ); + } + + /*! + * Removes a sequence of \a n contiguous pointers starting at the specified + * location \a i in this reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const_iterator i, size_type n = 1 ) + { + m_array.Remove( i.it, n ); + } + + /*! + * Removes a sequence of contiguous pointers in the range [i,j) of this + * reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const_iterator i, const_iterator j ) + { + m_array.Remove( i.it, j.it ); + } + + /*! + * Removes a trailing sequence of contiguous pointers from the specified + * iterator of this reference array. This operation is equivalent to: + * + * \code Remove( i, End() ) \endcode + * + * If the specified iterator is located at or after the end of this array, + * this function does nothing. Otherwise the iterator is constrained to stay + * in the range [Begin(),End()) of existing array elements. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Truncate( const_iterator i ) + { + m_array.Truncate( i.it ); + } + + /*! + * Removes a contiguous trailing sequence of \a n existing pointers from + * this reference array. This operation is equivalent to: + * + * \code Truncate( End() - n ) \endcode + * + * If the specified count \a n is greater than or equal to the length of + * this array, this function calls Clear() to yield an empty array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Shrink( size_type n = 1 ) + { + m_array.Shrink( n ); + } + + /*! + * Removes all existing pointers whose pointed objects are equal to the + * specified value \a v in this reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const T& v ) + { + m_array.Remove( v ); + } + + /*! + * Removes every pointer x in this reference array such that the binary + * predicate p( *x, \a v ) is true. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + template + void Remove( const T& v, BP p ) + { + m_array.Remove( v, p ); + } + + /*! + * Removes all contained pointers equal to \a p in this reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void RemovePointer( const T* p ) + { + m_array.Remove( p ); + } + + /*! + * Removes all pointers contained by this object, yielding an empty + * reference array. + * + * If this array is empty, then calling this member function has no effect. + * + * If this array uniquely references its internal array data structure, all + * pointers contained are deallocated; otherwise its reference counter is + * decremented. Then a new, empty array data structure is created and + * uniquely referenced. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Clear() + { + m_array.Clear(); + } + + /*! + * Destroys and removes a sequence of \a n contiguous objects, starting at + * the specified location \a i in this reference array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( iterator i, size_type n = 1 ) + { + m_array.Destroy( i.it, n ); + } + + /*! + * Destroys and removes the objects in a range [i,j) of iterators in this + * reference array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning This function is potentially dangerous. If the array contains + * duplicate pointers in the specified range of iterators, this function + * will lead to a crash as a result of multiple deletions. To minimize the + * risk of multiple deletions, this function ignores the normal data sharing + * mechanism so that all objects sharing the same array data structure will + * correctly have the destroyed objects removed. However, be aware of + * potential problems if other reference or indirect containers store + * pointers to deleted objects in different data structures, which will be + * invalid after calling this function. + */ + void Destroy( iterator i, iterator j ) + { + m_array.Destroy( i.it, j.it ); + } + + /*! + * Destroys and removes all objects equal to \a v in this reference array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( const T& v ) + { + m_array.Destroy( v ); + } + + /*! + * Destroys and removes every object x in this reference array such that the + * binary predicate p( x, \a v ) is true. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + template + void Destroy( const T& v, BP p ) + { + m_array.Destroy( v, p ); + } + + /*! + * Destroys and removes all objects in this reference array, yielding an + * empty array. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy() + { + m_array.Destroy(); + } + + /*! + * Replaces a sequence of contiguous pointers defined by the range [i,j) of + * iterators in this array by the pointers stored in a reference array \a x. + * + * If the starting iterator \a i is located at or after the end of this + * array, or if \a j precedes \a i, this function does nothing. Otherwise + * the range [i,j) is constrained to stay in the range [Begin(),End()) of + * existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or a null iterator if the resulting array is + * empty. + */ + iterator Replace( const_iterator i, const_iterator j, const ReferenceArray& x ) + { + return iterator( m_array.Replace( i.it, j.it, x.m_array ) ); + } + + /*! + * Replaces a sequence of contiguous pointers defined by the range [i,j) in + * this reference array by \a n copies of the specified non-null pointer + * \a p. + * + * If \a p is \c nullptr, this function removes the subset [i,j) from this + * array, as if \a n = 0 had been specified. + */ + iterator Replace( const_iterator i, const_iterator j, const T* p, size_type n = 1 ) + { + return iterator( m_array.Replace( i.it, j.it, p, (p != nullptr) ? n : size_type( 0 ) ) ); + } + + /*! + * Replaces a sequence of contiguous pointers defined by the range [i,j) in + * this reference array by the sequence of pointers in the range [p,q) of + * forward iterators. + * + * If the range [p,q) contains null pointers, these are ignored and not + * inserted in this array. If the starting iterator \a i is located at or + * after the end of this array, or if \a j precedes \a i, this function does + * nothing. Otherwise the range [i,j) is constrained to stay in the range + * [Begin(),End()) of existing array elements. + * + * Returns an iterator pointing to the first replaced array element, \a i + * if no elements are replaced, or a null iterator if the resulting array is + * empty. + * + * \note \a p and \a q must not be iterators into this array. + */ + template + iterator Replace( const_iterator i, const_iterator j, FI p, FI q ) + { + array_implementation m; + for ( ; p != q; ++p ) + if ( *p != nullptr ) + m.Append( *p ); + return iterator( m_array.Replace( i.it, j.it, m ) ); + } + + /*! + * Ensures that this reference array has enough capacity to store \a n + * pointers. + * + * After calling this member function with \a n > 0, this object is + * guaranteed to uniquely reference its array data. + */ + void Reserve( size_type n ) + { + m_array.Reserve( n ); + } + + /*! + * Causes this reference array to allocate the exact required memory space + * to store its contained pointers. + * + * If the array has excess capacity, a new copy of its contained pointers is + * generated and stored in a newly allocated memory block that fits them + * exactly, then the previous memory block is deallocated. + * + * If the array is empty, calling this function is equivalent to Clear(). + * Note that in this case a previously allocated memory block (by a call to + * Reserve()) may also be deallocated. + */ + void Squeeze() + { + m_array.Squeeze(); + } + + /*! + * Sets all objects contained by this array equal to \a v. + */ + void Fill( const T& v ) + { + pcl::Fill( Begin(), End(), v ); + } + + /*! + * Calls f( T& x ) for every object x in this reference array, successively + * from the first contained object to the last. + */ + template + void Apply( F f ) + { + pcl::Apply( Begin(), End(), f ); + } + + /*! + * Calls f( const T& x ) for every unmodifiable object x in this reference + * array, successively from the first contained object to the last. + */ + template + void Apply( F f ) const + { + pcl::Apply( Begin(), End(), f ); + } + + /*! + * Returns an iterator pointing to the first object x in this reference + * array such that f( const T& x ) is true. Returns End() if such pointer + * does not exist. + */ + template + iterator FirstThat( F f ) const + { + return iterator( const_cast( pcl::FirstThat( Begin(), End(), f ).it ) ); + } + + /*! + * Returns an iterator pointing to the last object x in this reference array + * such that f( const T& x ) is true. Returns End() if such pointer does not + * exist. + */ + template + iterator LastThat( F f ) const + { + return iterator( const_cast( pcl::LastThat( Begin(), End(), f ).it ) ); + } + + /*! + * Returns the number of objects equal to \a v in this reference array. + */ + size_type Count( const T& v ) const + { + return pcl::Count( Begin(), End(), v ); + } + + /*! + * Returns the number of pointers equal to \a p stored in this reference + * array. + * + * If \a p is \c nullptr, this function \e should return zero --- or you are + * in serious trouble! + */ + size_type Count( const T* p ) const + { + return m_array.Count( p ); + } + + /*! + * Returns the number of objects in this reference array such that for each + * counted object x the binary predicate p( x, v ) returns true. + */ + template + size_type Count( const T& v, BP p ) const + { + return pcl::Count( Begin(), End(), v, p ); + } + + /*! + * Returns the number of objects in this reference array such that for each + * counted object x the unary predicate p( x ) returns true. + */ + template + size_type CountIf( UP p ) const + { + return pcl::CountIf( Begin(), End(), p ); + } + + /*! # + */ + iterator MinItem() const + { + return iterator( const_cast( pcl::MinItem( Begin(), End() ).it ) ); + } + + /*! # + */ + template + iterator MinItem( BP p ) const + { + return iterator( const_cast( pcl::MinItem( Begin(), End(), p ).it ) ); + } + + /*! # + */ + iterator MaxItem() const + { + return iterator( const_cast( pcl::MaxItem( Begin(), End() ).it ) ); + } + + /*! # + */ + template + iterator MaxItem( BP p ) const + { + return iterator( const_cast( pcl::MaxItem( Begin(), End(), p ).it ) ); + } + + /*! # + */ + void Reverse() + { + m_array.Reverse(); + } + + /*! # + */ + void Rotate( distance_type n ) + { + m_array.Rotate( n ); + } + + /*! # + */ + void ShiftLeft( const T* p, size_type n = 1 ) + { + m_array.ShiftLeft( p, n ); + } + + /*! # + */ + void ShiftRight( const T* p, size_type n = 1 ) + { + m_array.ShiftRight( p, n ); + } + + /*! # + */ + iterator Search( const T& v ) const + { + return iterator( const_cast( pcl::LinearSearch( Begin(), End(), v ).it ) ); + } + + /*! # + */ + iterator Search( const T* p ) const + { + return iterator( m_array.Search( p ) ); + } + + /*! # + */ + template + iterator Search( const T& v, BP p ) const + { + return iterator( const_cast( pcl::LinearSearch( Begin(), End(), v, p ).it ) ); + } + + /*! # + */ + iterator SearchLast( const T& v ) const + { + return iterator( const_cast( pcl::LinearSearchLast( Begin(), End(), v ).it ) ); + } + + /*! # + */ + iterator SearchLast( const T* p ) const + { + return iterator( m_array.SearchLast( p ) ); + } + + /*! # + */ + template + iterator SearchLast( const T& v, BP p ) const + { + return iterator( const_cast( pcl::LinearSearchLast( Begin(), End(), v, p ).it ) ); + } + + /*! # + */ + template + iterator SearchSubset( FI i, FI j ) const + { + return iterator( const_cast( pcl::Search( Begin(), End(), i, j ).it ) ); + } + + /*! # + */ + template + iterator SearchSubset( FI i, FI j, BP p ) const + { + return iterator( const_cast( pcl::Search( Begin(), End(), i, j, p ).it ) ); + } + + /*! # + */ + template + iterator SearchSubset( const C& c ) const + { + return iterator( const_cast( pcl::Search( Begin(), End(), c.Begin(), c.End() ).it ) ); + } + + /*! # + */ + template + iterator SearchSubset( const C& c, BP p ) const + { + return iterator( const_cast( pcl::Search( Begin(), End(), c.Begin(), c.End(), p ).it ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( BI i, BI j ) const + { + return iterator( const_cast( pcl::SearchLast( Begin(), End(), i, j ).it ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( BI i, BI j, BP p ) const + { + return iterator( const_cast( pcl::SearchLast( Begin(), End(), i, j, p ).it ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( const C& c ) const + { + return iterator( const_cast( pcl::SearchLast( Begin(), End(), c.Begin(), c.End() ).it ) ); + } + + /*! # + */ + template + iterator SearchLastSubset( const C& c, BP p ) const + { + return iterator( const_cast( pcl::SearchLast( Begin(), End(), c.Begin(), c.End(), p ).it ) ); + } + + /*! # + */ + bool Contains( const T& v ) const + { + return Search( v ) != End(); + } + + /*! # + */ + bool Contains( const T* p ) const + { + return m_array.Contains( p ); + } + + /*! # + */ + template + bool Contains( const T& v, BP p ) const + { + return Search( v, p ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( FI i, FI j ) const + { + return SearchSubset( i, j ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( FI i, FI j, BP p ) const + { + return SearchSubset( i, j, p ) != End(); + } + + /*! # + */ + template + iterator ContainsSubset( const C& c ) const + { + return m_array.ContainsSubset( c ); + } + + /*! # + */ + template + iterator ContainsSubset( const C& c, BP p ) const + { + return SearchSubset( c ) != End(); + } + + /*! # + */ + void Sort() + { + pcl::QuickSort( m_array.Begin(), m_array.End(), + []( const T* a, const T* b ){ return *a < *b; } ); + } + + /*! # + */ + template + void Sort( BP p ) + { + pcl::QuickSort( m_array.Begin(), m_array.End(), + [p]( const T* a, const T* b ){ return p( *a, *b ); } ); + } + + /*! + * Exchanges two reference arrays \a x1 and \a x2. + */ + friend void Swap( ReferenceArray& x1, ReferenceArray& x2 ) + { + pcl::Swap( x1.m_array, x2.m_array ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each element in this array, this function appends a string + * representation (known as a \e token) to the target string \a s. If the + * array contains more than one element, successive tokens are separated + * with the specified \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform an array element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + const_iterator i = Begin(); + if ( i < End() ) + { + s.Append( S( *i ) ); + if ( ++i < End() ) + do + { + s.Append( separator ); + s.Append( S( *i ) ); + } + while ( ++i < End() ); + } + return s; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each element x in this array, this function appends a string + * representation (known as a \e token) to the target string \a s by + * calling the \a append function: + * + *\code append( s, S( x ) ); \endcode + * + * If the array contains more than one element, successive tokens are + * separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform an + * array element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably easier to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + const_iterator i = Begin(); + if ( i < End() ) + { + append( s, S( *i ) ); + if ( ++i < End() ) + { + S p( separator ); + do + { + append( s, p ); + append( s, S( *i ) ); + } + while ( ++i < End() ); + } + } + return s; + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return ToSeparated( s, ',' ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return ToSeparated( s, ' ' ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return ToSeparated( s, '\t' ); + } + + /*! + * Generates a newline-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\n' ); \endcode + */ + template + S& ToNewLineSeparated( S& s ) const + { + return ToSeparated( s, '\n' ); + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this reference + * array. + * + * This function calls pcl::Hash64() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const + { + return m_array.Hash64( seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this reference + * array. + * + * This function calls pcl::Hash32() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const + { + return m_array.Hash32( seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this reference array. + * This function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const + { + return Hash64( seed ); + } + +private: + + array_implementation m_array; + + template + void CloneObjects( const C& x, DirectContainer* ) + { + m_array.CloneAssign( x ); + } + + template + void CloneObjects( const C& x, IndirectContainer* ) + { + m_array.Clear(); + m_array.Reserve( x.Length() ); + allocator a; + for ( typename C::const_iterator p = x.Begin(); p != x.End(); ++p ) + if ( *p != nullptr ) + { + T* o = a.Allocate( 1 ); + pcl::Construct( o, **p, a ); + m_array.Append( o ); + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff two reference arrays \a x1 and \a x2 are equal. This + * operator compares the objects pointed to by the pointers stored in the + * reference arrays. + * \ingroup array_relational_operators + */ +template inline +bool operator ==( const ReferenceArray& x1, const ReferenceArray& x2 ) +{ + return x1.Length() == x2.Length() && pcl::Equal( x1.Begin(), x2.Begin(), x2.End() ); +} + +/*! + * Returns true iff a reference array \a x1 precedes another reference array + * \a x2. This operator compares the objects pointed to by the pointers stored + * in the reference arrays. + * \ingroup array_relational_operators + */ +template inline +bool operator <( const ReferenceArray& x1, const ReferenceArray& x2 ) +{ + return pcl::Compare( x1.Begin(), x1.End(), x2.Begin(), x2.End() ) < 0; +} + +/*! + * Appends a non-null pointer \a p to a reference array \a x. Returns a + * reference to the left-hand reference array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +ReferenceArray& operator <<( ReferenceArray& x, const V* p ) +{ + x.Append( static_cast( p ) ); + return x; +} + +/*! + * Appends a non-null pointer \a p to a temporary reference array \a x. Returns + * a reference to the left-hand reference array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +ReferenceArray& operator <<( ReferenceArray&& x, const V* p ) +{ + x.Append( static_cast( p ) ); + return x; +} + +/*! + * Appends a reference array \a x2 to a reference array \a x1. Returns a + * reference to the left-hand reference array. + * \ingroup array_insertion_operators + */ +template inline +ReferenceArray& operator <<( ReferenceArray& x1, const ReferenceArray& x2 ) +{ + x1.Append( x2 ); + return x1; +} + +/*! + * Appends a reference array \a x2 to a temporary reference array \a x1. + * Returns a reference to the left-hand reference array. + * \ingroup array_insertion_operators + */ +template inline +ReferenceArray& operator <<( ReferenceArray&& x1, const ReferenceArray& x2 ) +{ + x1.Append( x2 ); + return x1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ReferenceArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ReferenceArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ReferenceCounter.h b/3rdparty/include/pcl/ReferenceCounter.h new file mode 100644 index 0000000..ffceb85 --- /dev/null +++ b/3rdparty/include/pcl/ReferenceCounter.h @@ -0,0 +1,231 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ReferenceCounter.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_ReferenceCounter_h +#define __PCL_ReferenceCounter_h + +/// \file pcl/ReferenceCounter.h + +#include + +#include + +#ifdef __PCL_REFCOUNT_CHECK_DETACHMENT +# include +#else +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ReferenceCounter + * \brief Thread-safe reference counter for copy-on-write data structures. + * + * %ReferenceCounter is used internally by most PCL container and image classes + * to implement reference-counted, copy-on-write shared data. + * + * %ReferenceCounter is a thread-safe reference counter because it implements + * its internal counter as an instance of the AtomicInt class. This means that + * counter increment and decrement are implemented as atomic operations. + * + * Copy-on-write is a fundamental technique for optimization of resources and + * execution speed by preventing unnecessary duplication of data, especially + * when objects are copied and aliased frequently but seldom modified. + * Basically, a set of objects can share the same data with the condition that + * the data remains unmodified. In this case, the set of objects is said to be + * \e referencing a single data item, and all objects in the set are considered + * as \e aliases of the data. When an alias object tries to modify its + * referenced data, a new copy is generated on-demand and the object uniquely + * references the newly generated data, which can then be freely modified. This + * mechanism works in a completely automatic and transparent way, and + * %ReferenceCounter just provides a thread-safe counter to keep track of the + * number of aliased objects that reference the same data structure at a given + * time, plus a number of useful related functions. + * + * \sa AtomicInt + */ +class PCL_CLASS ReferenceCounter +{ +public: + + /*! + * Constructs a new %ReferenceCounter object. The reference counter is + * initialized to one, which means that only one object (the caller) is + * referencing the data associated with this object. + */ + ReferenceCounter() = default; + + /*! + * Destroys a %ReferenceCounter object. + */ + ~ReferenceCounter() + { + } + + /*! + * Copy constructor. This constructor is equivalent to the default + * constructor because reference counters are unique objects. In other + * words, the reference counter is always initialized to one for newly + * constructed %ReferenceCounter objects. + * + * This constructor exists and is not disabled to allow reference-counted + * data structures to have copy constructors. + */ + ReferenceCounter( const ReferenceCounter& ) + : ReferenceCounter() + { + } + + /*! + * Copy assignment. This operator is disabled because reference counters are + * unique objects. + */ + ReferenceCounter& operator =( const ReferenceCounter& ) = delete; + + /*! + * Increments the reference counter by one unit. This happens when a new + * object references the data being controlled with this counter. + * + * \note This attachment operation is thread-safe: the internal increment + * operation is atomic. + * + * \sa Detach() + */ + void Attach() + { + m_count.Increment(); + } + + /*! + * Decrements the reference counter by one unit. This happens when an object + * ceases to reference the data being controlled with this counter. + * + * Returns true if the reference counter is greater than zero after the + * decrement; false if the reference counter becomes zero. When the + * reference counter is zero, the data being controlled with this counter is + * no longer referenced by any object and thus can be safely destroyed. + * + * \note This detachment operation is thread-safe: the internal dereference + * operation is atomic. + * + * \sa Attach() + */ + bool Detach() + { + PCL_CHECK( m_count.Load() > 0 ) + return m_count.Dereference(); + } + + /*! + * Returns the current value of this reference counter. + * + * \sa RefCountAtomic(), IsUnique() + */ + int RefCount() const + { + return m_count; + } + + /*! + * Returns the current value of this reference counter. + * + * \note This operation is thread-safe: the integer load has been + * implemented as an atomic operation. + * + * \sa RefCount(), IsUniqueAtomic() + */ + int RefCountAtomic() const + { + return m_count.Load(); + } + + /*! + * Returns true iff the data being controlled with this counter is not being + * referenced by more than one object. + * + * \sa IsUniqueAtomic(), Attach(), Detach() + */ + bool IsUnique() const + { + return RefCount() < 2; + } + + /*! + * Returns true iff the data being controlled with this counter is not being + * referenced by more than one object. + * + * \note This operation is thread-safe: the integer comparison has been + * implemented as an atomic operation. + * + * \sa IsUnique(), Attach(), Detach() + */ + bool IsUniqueAtomic() const + { + return RefCountAtomic() < 2; + } + +private: + + mutable AtomicInt m_count = 1; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ReferenceCounter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ReferenceCounter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ReferenceSortedArray.h b/3rdparty/include/pcl/ReferenceSortedArray.h new file mode 100644 index 0000000..60b87c3 --- /dev/null +++ b/3rdparty/include/pcl/ReferenceSortedArray.h @@ -0,0 +1,1552 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ReferenceSortedArray.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_ReferenceSortedArray_h +#define __PCL_ReferenceSortedArray_h + +/// \file pcl/ReferenceSortedArray.h + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ReferenceSortedArray + * \brief Dynamic sorted array of pointers to objects providing direct + * iteration and element access by reference. + * + * %ReferenceSortedArray is a generic, finite sorted sequence of pointers to + * objects, implemented as a reference-counted, dynamic array of pointers to T + * instances with automatic sorting of inserted array elements. The type A + * provides dynamic allocation for contiguous sequences of void* + * (StandardAllocator is used by default). + * + * Ordering of array elements is implemented by indirection, that is, the + * pointed-to objects are compared for sorting, not the contained pointers. + * + * Unlike IndirectArray and IndirectSortedArray, %ReferenceSortedArray provides + * direct access to the objects pointed to by its contained pointers, including + * direct iteration through references instead of pointers. This makes + * %ReferenceSortedArray a perfect replacement for SortedArray in cases where + * storing copies of objects is impractical or inviable; for example, when the + * objects to be stored are unique by nature. As a prerequisite for this + * functionality, %ReferenceSortedArray, unlike IndirectSortedArray and + * IndirectArray, and like ReferenceArray, cannot contain null pointers. + * + * \sa ReferenceArray, IndirectArray, IndirectSortedArray, Array, SortedArray, + * ReferenceCounter + * \ingroup dynamic_arrays + */ +template +class PCL_CLASS ReferenceSortedArray : public DirectContainer +{ +public: + + /*! # + */ + typedef ReferenceArray array_implementation; + + /*! # + */ + typedef typename array_implementation::block_allocator + block_allocator; + + /*! # + */ + typedef typename array_implementation::allocator + allocator; + + /*! # + */ + typedef typename array_implementation::iterator + iterator; + + /*! # + */ + typedef typename array_implementation::const_iterator + const_iterator; + + /*! # + */ + typedef typename array_implementation::reverse_iterator + reverse_iterator; + + /*! # + */ + typedef typename array_implementation::const_reverse_iterator + const_reverse_iterator; + + /*! # + */ + typedef typename array_implementation::indirect_iterator + indirect_iterator; + + /*! # + */ + typedef typename array_implementation::const_indirect_iterator + const_indirect_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty reference sorted array. + */ + ReferenceSortedArray() = default; + + /*! + * Constructs a reference sorted array that stores \a n copies of a non-null + * pointer \a p. + * + * If \a p is \c nullptr, this function constructs an empty reference array. + */ + ReferenceSortedArray( size_type n, const T* p ) + { + PCL_PRECONDITION( p != nullptr ) + if ( p != nullptr ) + m_array = array_implementation( n, p ); + } + + /*! + * Constructs a reference array as a copy of the sequence of non-null + * pointers defined by the range [i,j) of forward iterators. The stored + * sequence of pointers is sorted in ascending order by comparing the + * pointed objects. + * + * If the range [i,j) contains null pointers, these are ignored and hence + * not included in the constructed reference array. + */ + template + ReferenceSortedArray( FI i, FI j ) + : m_array( i, j ) + { + Sort(); + } + + /*! + * Copy constructor. + */ + ReferenceSortedArray( const ReferenceSortedArray& ) = default; + + /*! + * Move constructor. + */ + ReferenceSortedArray( ReferenceSortedArray&& ) = default; + + /*! + * Destroys a %ReferenceSortedArray object. + * + * Deallocates the internal array of pointers to objects, but does not + * destroy the pointed objects. To destroy them, you have to call Destroy() + * or Delete() explicitly. + */ + ~ReferenceSortedArray() + { + } + + /*! + * Returns true iff this reference array uniquely references its contained + * array of pointers to objects. + */ + bool IsUnique() const + { + return m_array.IsUnique(); + } + + /*! + * Returns true iff this reference array is an alias of the array \a x. + * + * Two objects are aliases if both share the same data. Two reference + * containers are aliases if they share a unique set of object pointers. + */ + bool IsAliasOf( const ReferenceSortedArray& x ) const + { + return m_array.IsAliasOf( x.m_array ); + } + + /*! + * Ensures that this reference array uniquely references its contained + * object pointers. + * + * If necessary, this member function generates a duplicate of the array + * of pointers, references it, and then decrements the reference counter of + * the original pointer array. + */ + void EnsureUnique() + { + m_array.EnsureUnique(); + } + + /*! + * Returns the total number of bytes required to store the array of object + * pointers contained by this reference array. + */ + size_type Size() const + { + return m_array.Size(); + } + + /*! + * Returns the length of this reference array. + */ + size_type Length() const + { + return m_array.Length(); + } + + /*! + * Returns the capacity of this reference array. The capacity is the maximum + * number of pointers to objects that this reference array can contain + * without requiring a reallocation. + */ + size_type Capacity() const + { + return m_array.Capacity(); + } + + /*! + * Returns the length of the space available in this reference array, or + * zero if this reference array cannot contain more pointers. The available + * space is the number of pointers to objects that can be added to this + * reference array without requiring a reallocation. It is equal to + * Capacity() - Length() by definition. + */ + size_type Available() const + { + return m_array.Available(); + } + + /*! + * Returns true only if this reference array is valid. A reference array is + * valid if it references an internal structure with an array of pointers, + * even if it is an empty array. + * + * In general, all %ReferenceSortedArray objects are valid with only two + * exceptions: + * + * \li Objects that have been move-copied or move-assigned to other arrays. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid array object cannot be used and should be destroyed + * immediately. Invalid arrays are always destroyed automatically during + * move construction and move assignment operations. + */ + bool IsValid() const + { + return m_array.IsValid(); + } + + /*! + * Returns true iff this reference array is empty. + */ + bool IsEmpty() const + { + return m_array.IsEmpty(); + } + + /*! + * Returns the minimum legal index in this array (always zero). For empty + * arrays, this function returns a meaningless value. + */ + size_type LowerBound() const + { + return m_array.LowerBound(); + } + + /*! + * Returns the maximum legal index in this array. It is equal to Length()-1. + * For empty arrays, this function returns a meaningless value. + */ + size_type UpperBound() const + { + return m_array.UpperBound(); + } + + /*! + * Returns a reference to the allocator object used by this reference array. + */ + const allocator& Allocator() const + { + return m_array.Allocator(); + } + + /*! + * Sets a new allocator object for this reference array. + */ + void SetAllocator( const allocator& a ) + { + m_array.SetAllocator( a ); + } + + /*! + * Returns an immutable reference array iterator located at the specified + * array index \a i. + */ + const_iterator At( size_type i ) const + { + return m_array.At( i ); + } + + /*! + * Returns a mutable reference array iterator located at the specified + * array index \a i. + */ + iterator MutableAt( size_type i ) + { + return m_array.At( i ); + } + + /*! + * Returns a mutable iterator pointing to the same array element as the + * specified immutable iterator \a i. + * + * \warning As a side-effect of calling this function, the specified + * immutable iterator \a i may become invalid. This happens when this + * function is called for a shared array, since in this case getting a + * mutable iterator involves a deep copy of the array through an implicit + * call to EnsureUnique(). + */ + iterator MutableIterator( const_iterator i ) + { + return m_array.MutableIterator( i ); + } + + /*! + * Returns a reference to the immutable object at the specified array + * index \a i. No bounds checking is performed. + */ + const T& operator []( size_type i ) const + { + return m_array[i]; + } + + /*! + * Returns a reference to the unmodifiable first object in this reference + * array. + */ + const T& operator *() const + { + return *m_array; + } + + /*! + * Returns an immutable iterator located at the beginning of this array. + */ + const_iterator Begin() const + { + return m_array.ConstBegin(); + } + + /*! + * Returns a mutable iterator located at the beginning of this array. + */ + iterator MutableBegin() + { + return m_array.Begin(); + } + + /*! + * Returns an immutable iterator located at the end of this array. + */ + const_iterator End() const + { + return m_array.ConstEnd(); + } + + /*! + * Returns a mutable iterator located at the end of this array. + */ + iterator MutableEnd() + { + return m_array.End(); + } + + /*! + * Returns an immutable reverse iterator located at the reverse + * beginning of this reference array. + * + * The reverse beginning corresponds to the last object in the array. + */ + const_reverse_iterator ReverseBegin() const + { + return m_array.ConstReverseBegin(); + } + + /*! + * Returns a mutable reverse iterator located at the reverse + * beginning of this reference array. + * + * The reverse beginning corresponds to the last object in the array. + */ + reverse_iterator MutableReverseBegin() + { + return m_array.ReverseBegin(); + } + + /*! + * Returns an immutable reverse iterator located at the reverse end + * of this reference array. + * + * The reverse end corresponds to a (nonexistent) object immediately before + * the first object in the array. + */ + const_reverse_iterator ReverseEnd() const + { + return m_array.ConstReverseEnd(); + } + + /*! + * Returns a mutable reverse iterator located at the reverse end of + * this reference array. + * + * The reverse end corresponds to a (nonexistent) object immediately before + * the first object in the array. + */ + reverse_iterator MutableReverseEnd() + { + return m_array.ReverseEnd(); + } + + /*! + * Returns a reference to the first unmodifiable object in this reference + * array. This function should never be called for an empty array. + */ + const T& First() const + { + return m_array.First(); + } + + /*! + * Returns a reference to the first object in this reference array. This + * function should never be called for an empty array. + */ + T& MutableFirst() + { + return m_array.First(); + } + + /*! + * Returns a reference to the last unmodifiable object in this reference + * array. This function should never be called for an empty array. + */ + const T& Last() const + { + return m_array.Last(); + } + + /*! + * Returns a reference to the last object in this reference array. This + * function should never be called for an empty array. + */ + T& MutableLast() + { + return m_array.Last(); + } + + /*! + * Ensures that the specified iterator represents a pointer stored in a + * uniquely referenced indirect array. If necessary, this function builds a + * new, uniquely referenced copy of the underlying indirect array by calling + * EnsureUnique(). + * + * If the iterator \a i is changed, it is guaranteed to point to the object + * at the same array index it was pointing to before calling this function. + */ + void UniquifyIterator( iterator& i ) + { + m_array.UniquifyIterator( i ); + } + + /*! + * Ensures that the specified iterators represents a pointer stored in a + * uniquely referenced indirect array. If necessary, this function builds a + * new, uniquely referenced copy of the underlying indirect array by calling + * EnsureUnique(). + * + * If the iterators \a i and \a j are changed, they are guaranteed to point + * to the objects at the same array indices they were pointing to before + * calling this function. + */ + void UniquifyIterators( iterator& i, iterator& j ) + { + m_array.UniquifyIterators( i, j ); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Copy assignment operator. + * + * Causes this reference sorted array to reference the same set of objects + * as another reference sorted array \a x. Returns a reference to this + * object. + */ + ReferenceSortedArray& operator =( const ReferenceSortedArray& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns a reference sorted array \a x to this reference sorted array. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Increments the reference counter of the source array's data and + * references it in this array. + */ + void Assign( const ReferenceSortedArray& x ) + { + m_array.Assign( x.m_array ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ReferenceSortedArray& operator =( ReferenceSortedArray&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from another reference sorted array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( ReferenceSortedArray& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! + * Transfers data from another reference sorted array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. + */ + void Transfer( ReferenceSortedArray&& x ) + { + m_array.Transfer( std::move( x.m_array ) ); + } + + /*! + * Assigns a reference array \a x to this reference sorted array. + * + * Causes this reference sorted array to store a sorted copy of the pointers + * in the source array \a x. Sorting is performed by comparing the pointed + * objects, not the pointers. Returns a reference to this object. + */ + ReferenceSortedArray& operator =( const array_implementation& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns a reference array \a x to this reference sorted array. + * + * Causes this reference sorted array to store a sorted copy of the pointers + * in the source array \a x. Sorting is performed by comparing the pointed + * objects, not the pointers. + */ + void Assign( const array_implementation& x ) + { + m_array.Assign( x ); + Sort(); + } + + /*! + * Move assignment of a reference array. + * + * The transferred array is sorted after the assignment. Returns a reference + * to this object. + */ + ReferenceSortedArray& operator =( array_implementation&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from a reference array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. The transferred array is sorted after the assignment. + */ + void Transfer( array_implementation& x ) + { + m_array.Transfer( x ); + Sort(); + } + + /*! + * Transfers data from a reference array \a x to this object. + * + * Decrements the reference counter of the current array data, and destroys + * it if it becomes unreferenced. + * + * Transfers source array data to this object, leaving empty and invalid the + * source object \a x. The transferred array is sorted after the assignment. + */ + void Transfer( array_implementation&& x ) + { + m_array.Transfer( std::move( x ) ); + Sort(); + } + + /*! + * Replaces the contents of this reference sorted array with a sequence of + * \a n pointers equal to \a p. + * + * if \a p is \c nullptr, this function yields an empty array. + */ + void Assign( const T* p, size_type n = 1 ) + { + m_array.Assign( p, n ); + } + + /*! + * Replaces the contents of this reference sorted array with a sorted copy + * of the sequence of pointers defined by the range [i,j) of forward + * iterators. + * + * If the range [i,j) contains null pointers, these are ignored and hence + * not included in this reference array. Sorting is performed by comparing + * the pointed objects, not the pointers. + * + * \note \a i and \a j must not be iterators into this array. + */ + template + void Assign( FI i, FI j ) + { + m_array.Assign( i, j ); + Sort(); + } + + /*! + * Replaces the contents of this reference sorted array with a sorted list + * of pointers to newly created copies of the objects stored in the + * specified container \a x. This function works for both direct and + * indirect containers. + * + * Keep in mind that after calling this function (with a reference to a + * nonempty container) this array will store newly allocated objects. You + * should call Destroy() to deallocate these objects before destructing this + * reference array in order to avoid a memory leak. + */ + template + void CloneAssign( const C& x ) + { + m_array.CloneAssign( x ); + Sort(); + } + + /*! # + */ + void CloneAssign( ReferenceSortedArray& x ) + { + m_array.CloneAssign( x.m_array ); + } + + /*! # + */ + void CloneAssign( SortedArray& x ) + { + m_array.CloneAssign( x ); + } + + /*! # + */ + void CloneAssign( IndirectSortedArray& x ) + { + m_array.CloneAssign( x ); + } + + /*! + * Causes this reference sorted array to store the sequence of pointers + * defined by the range [i,j) of iterators. The previously referenced data + * structure is dereferenced and deallocated if it becomes unreferenced. The + * sequence [i,j) is sorted in ascending order by comparing the pointed + * objects. + */ + void Import( iterator i, iterator j ) + { + m_array.Import( i, j ); + Sort(); + } + + /*! + * Releases the set of pointers contained by this reference sorted array. + * + * This member function returns a pointer to the internal block of pointers + * stored in this object, after ensuring that it is uniquely referenced. + * If the array is empty, this function may return the null pointer. + * + * Before returning, this member function empties this array without + * deallocating its contained data. The caller is then responsible for + * deallocating the returned block when it is no longer required. + */ + indirect_iterator Release() + { + return m_array.Release(); + } + + /*! # + */ + void Add( const ReferenceSortedArray& x ) + { + const_iterator p = x.Begin(), q = x.End(); + for ( iterator i = Begin(); i < End() && p < q; ++i ) + if ( *p < *i ) + i = m_array.Insert( i, (T*)p++ ); + if ( p < q ) + m_array.Append( p, q ); + } + + /*! # + */ + void Add( const array_implementation& x ) + { + Add( x.Begin(), x.End() ); + } + + /*! # + */ + const_iterator Add( const T* p, size_type n = 1 ) + { + if ( p != nullptr ) + return m_array.Insert( pcl::InsertionPoint( Begin(), End(), *p ), p, n ); + return const_iterator( nullptr ); + } + + /*! # + */ + template + void Add( FI i, FI j ) + { + if ( i != j ) + { + EnsureUnique(); + for ( const_iterator l = Begin(), r = End(); ; ) + { + FI h = i; + const_iterator m = m_array.Insert( pcl::InsertionPoint( l, r, **i ), *i ); + + if ( ++i == j ) + break; + + if ( **i < **h ) + { + l = m_array.Begin(); + r = m; + } + else + { + l = m + 1; + r = m_array.End(); + } + } + } + } + + /*! + * Removes a sequence of \a n contiguous pointers starting at the specified + * location \a i in this reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const_iterator i, size_type n = 1 ) + { + m_array.Remove( i, n ); + } + + /*! + * Removes a sequence of contiguous pointers in the range [i,j) of this + * reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const_iterator i, const_iterator j ) + { + m_array.Remove( i, j ); + } + + /*! + * Removes a trailing sequence of contiguous pointers from the specified + * iterator of this reference array. This operation is equivalent to: + * + * \code Remove( i, End() ) \endcode + * + * If the specified iterator is located at or after the end of this array, + * this function does nothing. Otherwise the iterator is constrained to stay + * in the range [Begin(),End()) of existing array elements. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Truncate( const_iterator i ) + { + m_array.Truncate( i ); + } + + /*! + * Removes a contiguous trailing sequence of \a n existing pointers from + * this reference array. This operation is equivalent to: + * + * \code Truncate( End() - n ) \endcode + * + * If the specified count \a n is greater than or equal to the length of + * this array, this function calls Clear() to yield an empty array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Shrink( size_type n = 1 ) + { + m_array.Shrink( n ); + } + + /*! + * Removes all existing pointers whose pointed objects are equal to the + * specified value \a v in this reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Remove( const T& v ) + { + m_array.Remove( v ); + } + + /*! + * Removes every pointer x in this reference array such that the binary + * predicate p( *x, \a v ) is true. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + template + void Remove( const T& v, BP p ) + { + m_array.Remove( v, p ); + } + + /*! + * Removes all contained pointers equal to \a p in this reference array. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void RemovePointer( const T* p ) + { + m_array.RemovePointer( p ); + } + + /*! + * Removes all pointers contained by this object, yielding an empty + * reference sorted array. + * + * If this array is empty, then calling this member function has no effect. + * + * If this array uniquely references its internal array data structure, all + * pointers contained are deallocated; otherwise its reference counter is + * decremented. Then a new, empty array data structure is created and + * uniquely referenced. + * + * Only pointers are removed by this function; the pointed objects are not + * affected in any way. + */ + void Clear() + { + m_array.Clear(); + } + + /*! + * Destroys and removes a sequence of \a n contiguous objects, starting at + * the specified location \a i in this reference sorted array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( iterator i, size_type n = 1 ) + { + m_array.Destroy( i, n ); + } + + /*! + * Destroys and removes the objects in a range [i,j) of iterators in this + * reference sorted array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning This function is potentially dangerous. If the array contains + * duplicate pointers in the specified range of iterators, this function + * will lead to a crash as a result of multiple deletions. To minimize the + * risk of multiple deletions, this function ignores the normal data sharing + * mechanism so that all objects sharing the same array data structure will + * correctly have the destroyed objects removed. However, be aware of + * potential problems if other reference or indirect containers store + * pointers to deleted objects in different data structures, which will be + * invalid after calling this function. + */ + void Destroy( iterator i, iterator j ) + { + m_array.Destroy( i, j ); + } + + /*! + * Destroys and removes all objects equal to \a v in this reference sorted + * array. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy( const T& v ) + { + m_array.Destroy( v ); + } + + /*! + * Destroys and removes every object x in this reference sorted array such + * that the binary predicate p( x, \a v ) is true. + * + * This function destroys and deallocates the pointed objects, then removes + * the corresponding pointers in this array. The array length is decreased + * by the number of destroyed objects. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + template + void Destroy( const T& v, BP p ) + { + m_array.Destroy( v, p ); + } + + /*! + * Destroys and removes all objects in this reference sorted array, yielding + * an empty array. + * + * \warning See Destroy( iterator, iterator ) for critical information on + * this member function. + */ + void Destroy() + { + m_array.Destroy(); + } + + /*! + * Ensures that this reference array has enough capacity to store \a n + * pointers. + * + * After calling this member function with \a n > 0, this object is + * guaranteed to uniquely reference its array data. + */ + void Reserve( size_type n ) + { + m_array.Reserve( n ); + } + + /*! + * Causes this reference array to allocate the exact required memory space + * to store its contained pointers. + * + * If the array has excess capacity, a new copy of its contained pointers is + * generated and stored in a newly allocated memory block that fits them + * exactly, then the previous memory block is deallocated. + * + * If the array is empty, calling this function is equivalent to Clear(). + * Note that in this case a previously allocated memory block (by a call to + * Reserve()) may also be deallocated. + */ + void Squeeze() + { + m_array.Squeeze(); + } + + /*! + * Sets all objects contained by this array equal to \a v. + */ + void Fill( const T& v ) + { + m_array.Fill( v ); + } + + /*! + * Calls f( const T& x ) for every unmodifiable object x in this reference + * array, successively from the first contained object to the last. + */ + template + void Apply( F f ) const + { + pcl::Apply( Begin(), End(), f ); + } + + /*! + * Returns an immutable iterator pointing to the first object x in this + * reference sorted array such that f( const T& x ) is true. Returns End() + * if such pointer does not exist. + */ + template + const_iterator FirstThat( F f ) const + { + return pcl::FirstThat( Begin(), End(), f ); + } + + /*! + * Returns an immutable iterator pointing to the last object x in this + * reference sorted array such that f( const T& x ) is true. Returns End() + * if such pointer does not exist. + */ + template + const_iterator LastThat( F f ) const + { + return pcl::LastThat( Begin(), End(), f ); + } + + /*! + * Returns the number of objects equal to \a v in this reference array. + */ + size_type Count( const T& v ) const + { + const_iterator i = pcl::BinarySearch( Begin(), End(), v ); + return (i != End()) ? pcl::InsertionPoint( i+1, End(), v ) - i : 0; + } + + /*! + * Returns the number of pointers equal to \a p stored in this reference + * array. + * + * If \a p is \c nullptr, this function \e should return zero --- or you are + * in serious trouble! + */ + size_type Count( const T* p ) const + { + return m_array.Count( p ); + } + + /*! + * Returns the number of objects in this reference array such that for each + * counted object x the binary predicate p( x, v ) returns true. + */ + template + size_type Count( const T& v, BP p ) const + { + return m_array.Count( v, p ); + } + + /*! + * Returns the number of objects in this reference array such that for each + * counted object x the unary predicate p( x ) returns true. + */ + template + size_type CountIf( UP p ) const + { + return m_array.CountIf( p ); + } + + /*! # + */ + const_iterator MinItem() const + { + return Begin(); + } + + /*! # + */ + template + const_iterator MinItem( BP p ) const + { + return pcl::MinItem( Begin(), End(), p ); + } + + /*! # + */ + const_iterator MaxItem() const + { + return IsEmpty() ? End() : End()-1; + } + + /*! # + */ + template + const_iterator MaxItem( BP p ) const + { + return pcl::MaxItem( Begin(), End(), p ); + } + + /*! # + */ + const_iterator Search( const T& v ) const + { + return pcl::BinarySearch( Begin(), End(), v ); + } + + /*! # + */ + const_iterator Search( const T* p ) const + { + return m_array.Search( p ); + } + + /*! # + */ + template + const_iterator Search( const T& v, BP p ) const + { + return pcl::LinearSearch( Begin(), End(), v, p ); + } + + /*! # + */ + const_iterator SearchLast( const T& v ) const + { + return pcl::BinarySearchLast( Begin(), End(), v ); + } + + /*! # + */ + const_iterator SearchLast( const T* p ) const + { + return m_array.SearchLast( p ); + } + + /*! # + */ + template + const_iterator SearchLast( const T& v, BP p ) const + { + return pcl::LinearSearchLast( Begin(), End(), v, p ); + } + + /*! # + */ + bool Contains( const T& v ) const + { + return Search( v ) != End(); + } + + /*! # + */ + bool Contains( const T* p ) const + { + return m_array.Contains( p ); + } + + /*! # + */ + template + bool Contains( const T& v, BP p ) const + { + return Search( v, p ) != End(); + } + + /*! # + */ + void Sort() + { + m_array.Sort(); + } + + /*! + * Exchanges two reference sorted arrays \a x1 and \a x2. + */ + friend void Swap( ReferenceSortedArray& x1, ReferenceSortedArray& x2 ) + { + pcl::Swap( x1.m_array, x2.m_array ); + } + + /*! + * Returns true only if two reference sorted arrays \a x1 and \a x2 are + * equal. + * \ingroup array_relational_operators + */ + friend bool operator ==( const ReferenceSortedArray& x1, const ReferenceSortedArray& x2 ) + { + return x1.m_array == x2.m_array; + } + + /*! + * Returns true only if a reference sorted array \a x1 is equal to a + * reference array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator ==( const ReferenceSortedArray& x1, const array_implementation& x2 ) + { + return x1.m_array == x2; + } + + /*! + * Returns true only if a reference array \a x1 is equal to a reference + * sorted array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator ==( const array_implementation& x1, const ReferenceSortedArray& x2 ) + { + return x1 == x2.m_array; + } + + /*! + * Returns true only if a reference sorted array \a x1 precedes another + * reference sorted array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const ReferenceSortedArray& x1, const ReferenceSortedArray& x2 ) + { + return x1.m_array < x2.m_array; + } + + /*! + * Returns true only if a reference sorted array \a x1 precedes a reference + * array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const ReferenceSortedArray& x1, const array_implementation& x2 ) + { + return x1.m_array < x2; + } + + /*! + * Returns true only if a reference array \a x1 precedes a reference sorted + * array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const array_implementation& x1, const ReferenceSortedArray& x2 ) + { + return x1 < x2.m_array; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each element in this array, this function appends a string + * representation (known as a \e token) to the target string \a s. If the + * array contains more than one element, successive tokens are separated + * with the specified \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform an array element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + return m_array.ToSeparated( s, separator ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each element x in this array, this function appends a string + * representation (known as a \e token) to the target string \a s by + * calling the \a append function: + * + *\code append( s, S( x ) ); \endcode + * + * If the array contains more than one element, successive tokens are + * separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform an + * array element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably easier to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + return m_array.ToSeparated( s, separator, append ); + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return m_array.ToCommaSeparated( s ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return m_array.ToSpaceSeparated( s ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return m_array.ToTabSeparated( s ); + } + + /*! + * Generates a newline-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\n' ); \endcode + */ + template + S& ToNewLineSeparated( S& s ) const + { + return m_array.ToNewLineSeparated( s ); + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this reference + * array. + * + * This function calls pcl::Hash64() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const + { + return m_array.Hash64( seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this reference + * array. + * + * This function calls pcl::Hash32() for the internal array of pointers, + * \e not for the pointed objects. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const + { + return m_array.Hash32( seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this reference array. + * This function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const + { + return Hash64( seed ); + } + +private: + + array_implementation m_array; +}; + +// ---------------------------------------------------------------------------- + +/*! + * Adds a non-null pointer \a p to a reference sorted array \a x. Returns a + * reference to the left-hand reference sorted array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +ReferenceSortedArray& operator <<( ReferenceSortedArray& x, const V* p ) +{ + x.Add( static_cast( p ) ); + return x; +} + +/*! + * Adds a non-null pointer \a p to a temporary reference sorted array \a x. + * Returns a reference to the left-hand reference sorted array. + * + * A pointer to the template argument type V must be statically castable to T*. + * \ingroup array_insertion_operators + */ +template inline +ReferenceSortedArray& operator <<( ReferenceSortedArray&& x, const V* p ) +{ + x.Add( static_cast( p ) ); + return x; +} + +/*! + * Adds a reference sorted array \a x2 to a reference sorted array \a x1. + * Returns a reference to the left-hand reference sorted array. + * \ingroup array_insertion_operators + */ +template inline +ReferenceSortedArray& operator <<( ReferenceSortedArray& x1, const ReferenceSortedArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds a reference sorted array \a x2 to a temporary reference sorted array + * \a x1. Returns a reference to the left-hand reference sorted array. + * \ingroup array_insertion_operators + */ +template inline +ReferenceSortedArray& operator <<( ReferenceSortedArray&& x1, const ReferenceSortedArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds a reference array \a x2 to a reference sorted array \a x1. Returns a + * reference to the left-hand reference sorted array. + * \ingroup array_insertion_operators + */ +template inline +ReferenceSortedArray& operator <<( ReferenceSortedArray& x1, const ReferenceArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds a reference array \a x2 to a temporary reference sorted array \a x1. + * Returns a reference to the left-hand reference sorted array. + * \ingroup array_insertion_operators + */ +template inline +ReferenceSortedArray& operator <<( ReferenceSortedArray&& x1, const ReferenceArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ReferenceSortedArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ReferenceSortedArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Relational.h b/3rdparty/include/pcl/Relational.h new file mode 100644 index 0000000..6a4b30a --- /dev/null +++ b/3rdparty/include/pcl/Relational.h @@ -0,0 +1,129 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Relational.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_Relational_h +#define __PCL_Relational_h + +/// \file pcl/Relational.h + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup generic_relational_operators Generic Relational Operators + * + * This section defines the template operator functions not equal to, + * less than or equal, greater than, and greater than or + * equal. + * + * For applicability of these generic operators, the following conditions are + * assumed for the template argument type T: + * + * \li For the != operator, there must be a meaningful == operator for the + * type T. + * + * \li For the <=, > and >= operators, there must be a meaningful < operator + * for the type T. + */ + +/*! + * Returns true iff two objects \a a and \a b are not equal. + * \ingroup generic_relational_operators + */ +template inline +bool operator !=( const T1& a, const T2& b ) +{ + return !(a == b); +} + +/*! + * Returns true iff an object \a a is less than or equal to another object \a b. + * \ingroup generic_relational_operators + */ +template inline +bool operator <=( const T1& a, const T2& b ) +{ + return !(b < a); +} + +/*! + * Returns true iff an object \a a is greater than another object \a b. + * \ingroup generic_relational_operators + */ +template inline +bool operator >( const T1& a, const T2& b ) +{ + return b < a; +} + +/*! + * Returns true iff an object \a a is greater than or equal to another object + * \a b. + * \ingroup generic_relational_operators + */ +template inline +bool operator >=( const T1& a, const T2& b ) +{ + return !(a < b); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Relational_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Relational.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Resample.h b/3rdparty/include/pcl/Resample.h new file mode 100644 index 0000000..a527038 --- /dev/null +++ b/3rdparty/include/pcl/Resample.h @@ -0,0 +1,406 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Resample.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_Resample_h +#define __PCL_Resample_h + +/// \file pcl/Resample.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + \namespace pcl::ResizeMode + \brief Resizing modes for the Resample process. + + + + + + + + +
ResizeMode::RelativeDimensions Resize relative to current image dimensions
ResizeMode::AbsolutePixels Resize to absolute dimensions in pixels
ResizeMode::AbsoluteCentimeters Resize to absolute dimensions in centimeters
ResizeMode::AbsoluteInches Resize to absolute dimensions in inches
ResizeMode::ForceArea Force the total number of pixels and keep existing aspect ratio
ResizeMode::Default Default resizing mode, equal to ResizeMode::RelativeDimensions
+*/ +namespace ResizeMode +{ + enum value_type + { + RelativeDimensions, // Resize relative to current image dimensions + AbsolutePixels, // ... to absolute dimensions in pixels + AbsoluteCentimeters, // ... to absolute dimensions in centimeters + AbsoluteInches, // ... to absolute dimensions in inches + ForceArea, // Force number of pixels, keep aspect ratio + NumberOfResizeModes, + Default = RelativeDimensions + }; +} + +// ---------------------------------------------------------------------------- + +/*! + \namespace pcl::AbsoluteResizeMode + \brief Absolute resizing modes for the Resample process. + + Absolute resize modes are applicable only when the main resize mode is + ResizeMode::AbsolutePixels, ResizeMode::AbsoluteCentimeters or + ResizeMode::AbsoluteInches. + + + + preserve existing aspect ratio + preserve existing aspect ratio + equal to AbsoluteResizeMode::ForceWidthAndHeight +
AbsoluteResizeMode::ForceWidthAndHeight Force both image dimensions
AbsoluteResizeMode::ForceWidth Force width
AbsoluteResizeMode::ForceHeight Force height
AbsoluteResizeMode::Default Default absolute resizing mode
+*/ +namespace AbsoluteResizeMode +{ + enum value_type + { + ForceWidthAndHeight, // Force both dimensions + ForceWidth, // Force width, preserve aspect ratio + ForceHeight, // Force height, preserve aspect ratio + NumberOfAbsoluteResizeModes, + Default = ForceWidthAndHeight + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Resample + * \brief %Image resampling algorithm. + * + * ### TODO: Write a detailed description for %Resample + */ +class PCL_CLASS Resample : public InterpolatingGeometricTransformation, + public ImageResolution, + public ParallelProcess +{ +public: + + /*! + * Represents a resizing mode. + */ + typedef ResizeMode::value_type resize_mode; + + /*! + * Represents an absolute resizing mode. + */ + typedef AbsoluteResizeMode::value_type abs_resize_mode; + + /*! + * Constructs a default %Resample object using the specified pixel + * interpolation \a p and a single scaling ratio for both axes. + * + * The specified pixel interpolation object \a p must remain valid while + * this object exists. + * + * The resizing mode is set relative to current image dimensions. + */ + Resample( PixelInterpolation& p, double scale = 1.0 ) + : InterpolatingGeometricTransformation( p ) + , m_xSize( scale ) + , m_ySize( scale ) + { + } + + /*! + * Constructs a default %Resample object using the specified pixel + * interpolation \a p and separate scaling ratios for the X and Y axes, + * \a scaleX and \a scaleY respectively. + * + * The specified pixel interpolation object \a p must remain valid while + * this object exists. + * + * The resizing mode is set relative to current image dimensions. + */ + Resample( PixelInterpolation& p, double scaleX, double scaleY ) + : InterpolatingGeometricTransformation( p ) + , m_xSize( scaleX ) + , m_ySize( scaleY ) + { + } + + /*! + * Copy constructor. + */ + Resample( const Resample& ) = default; + + /*! + * Gets the resampled image \a width and \a height. + * + * Use GetSizes(), XSize() and YSize() semantics to define a %Resample + * instance that resizes images to fixed dimensions. + */ + void GetSizes( double& width, double& height ) const + { + width = m_xSize; height = m_ySize; + } + + /*! + * Returns the resampled image width. + * + * Use GetSizes(), XSize() and YSize() semantics to define a %Resample + * instance that resizes images to fixed dimensions. + */ + double XSize() const + { + return m_xSize; + } + + /*! + * Returns the resampled image height. + * + * Use GetSizes(), XSize() and YSize() semantics to define a %Resample + * instance that resizes images to fixed dimensions. + */ + double YSize() const + { + return m_ySize; + } + + /*! + * Sets the resampled image \a width and \a height. + * + * Use SetSizes(), SetXSize() and SetYSize() semantics to define a %Resample + * instance that resizes images to fixed dimensions. + */ + void SetSizes( double width, double height ) + { + m_xSize = width; m_ySize = height; + } + + /*! + * Sets the resampled image \a width. + * + * Use SetSizes(), SetXSize() and SetYSize() semantics to define a %Resample + * instance that resizes images to fixed dimensions. + */ + void SetXSize( double width ) + { + m_xSize = width; + } + + /*! + * Sets the resampled image \a height. + * + * Use SetSizes(), SetXSize() and SetYSize() semantics to define a %Resample + * instance that resizes images to fixed dimensions. + */ + void SetYSize( double height ) + { + m_ySize = height; + } + + /*! + * Gets the scaling factors \a sx and \a sy for the X and Y axes, + * respectively. + * + * Use GetScalingFactors(), XScale() and YScale() semantics to define a + * %Resample instance that resizes images relative to their current + * dimensions. + */ + void GetScalingFactors( double& sx, double& sy ) const + { + GetSizes( sx, sy ); + } + + /*! + * Returns the horizontal scaling factor. + * + * Use GetScalingFactors(), XScale() and YScale() semantics to define a + * %Resample instance that resizes images relative to their current + * dimensions. + */ + double XScale() const + { + return XSize(); + } + + /*! + * Returns the vertical scaling factor. + * + * Use GetScalingFactors(), XScale() and YScale() semantics to define a + * %Resample instance that resizes images relative to their current + * dimensions. + */ + double YScale() const + { + return YSize(); + } + + /*! + * Sets the scaling factors \a sx and \a sy for the X and Y axes, + * respectively. + * + * Use SetScalingFactors(), SetXScale() and SetYScale() semantics to define + * a %Resample instance that resizes images relative to their current + * dimensions. + */ + void SetScalingFactors( double sx, double sy ) + { + SetSizes( sx, sy ); + } + + /*! + * Sets the horizontal scaling factor. + * + * Use SetScalingFactors(), SetXScale() and SetYScale() semantics to define + * a %Resample instance that resizes images relative to their current + * dimensions. + */ + void SetXScale( double sx ) + { + SetXSize( sx ); + } + + /*! + * Sets the vertical scaling factor. + * + * Use SetScalingFactors(), SetXScale() and SetYScale() semantics to define + * a %Resample instance that resizes images relative to their current + * dimensions. + */ + void SetYScale( double sy ) + { + SetYSize( sy ); + } + + /*! + * Returns the current resize mode. + */ + resize_mode Mode() const + { + return m_mode; + } + + /*! + * Returns true iff this %Resample object resizes images relative to their + * current dimensions, i.e. when Mode() is equal to + * ResizeMode::RelativeDimensions. + */ + bool IsRelative() const + { + return m_mode == ResizeMode::RelativeDimensions; + } + + /*! + * Returns true iff this %Resample object resizes images to fixed dimensions, + * i.e. when Mode() is not equal to ResizeMode::RelativeDimensions. + */ + bool IsAbsolute() const + { + return !IsRelative(); + } + + /*! + * Sets the current resize mode. + */ + void SetMode( resize_mode mode ) + { + m_mode = mode; + } + + /*! + * Returns the current absolute resizing mode. The absolute resizing mode is + * only applied when Mode() is not equal to ResizeMode::RelativeDimensions. + */ + abs_resize_mode AbsMode() const + { + return m_absMode; + } + + /*! + * Sets the absolute resizing mode. The absolute resizing mode is only + * applied when Mode() is not equal to ResizeMode::RelativeDimensions. + */ + void SetAbsMode( abs_resize_mode absMode ) + { + m_absMode = absMode; + } + + /*! + */ + void GetNewSizes( int& width, int& height ) const override; + +protected: + + double m_xSize = 1.0; + double m_ySize = 1.0; + resize_mode m_mode = ResizeMode::Default; + abs_resize_mode m_absMode = AbsoluteResizeMode::Default; + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Resample_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Resample.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/RobustChauvenetRejection.h b/3rdparty/include/pcl/RobustChauvenetRejection.h new file mode 100644 index 0000000..b28a7f6 --- /dev/null +++ b/3rdparty/include/pcl/RobustChauvenetRejection.h @@ -0,0 +1,369 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/RobustChauvenetRejection.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_RobustChauvenetRejection_h +#define __PCL_RobustChauvenetRejection_h + +/// \file pcl/RobustChauvenetRejection.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class RobustChauvenetRejection + * \brief Robust Chauvenet outlier rejection algorithm + * + * This class implements a robust iterative sigma clipping outlier rejection + * algorithm with Chauvenet rejection criterion. The design and implementation + * are based on: + * + * Maples, M. P., Reichart, D. E. et al., Robust Chauvenet Outlier + * Rejection, Astrophysical Journal Supplement Series, 2018, ApJS, 238, + * A2, 1-49. + */ +class PCL_CLASS RobustChauvenetRejection +{ +public: + + /*! + * Default constructor. + */ + RobustChauvenetRejection() = default; + + /*! + * Copy constructor. + */ + RobustChauvenetRejection( const RobustChauvenetRejection& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~RobustChauvenetRejection() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + RobustChauvenetRejection& operator =( const RobustChauvenetRejection& ) = default; + + /*! + * Returns the limit for the altered Chauvenet rejection criterion. + * + * The larger the value of this parameter, the more pixels will be rejected + * by the Robust Chauvenet Rejection algorithm. The original Chauvenet + * rejection criterion is N*P(x > |z|) < 0.5, where N is the number of + * measurements and P() represents the probability of x being more than z + * standard deviations from the mean. This parameter alters the rejection + * criterion by replacing 0.5 with an arbitrary limit in the [0,1] range, in + * order to make the algorithm controllable. + * + * The default rejection limit is 0.5, that is, the original Chauvenet + * rejection criterion is applied by default. + */ + float RejectionLimit() const + { + return m_rejectionLimit; + } + + /*! + * Sets the limit for the altered Chauvenet rejection criterion. See + * RejectionLimit() for a description of this parameter. + */ + void SetRejectionLimit( float r ) + { + PCL_PRECONDITION( r > 0 && r < 1 ) + m_rejectionLimit = Range( r, 0.0F, 1.0F ); + } + + /*! + * Returns the minimum length to enable bulk rejection. + * + * For data sets smaller than the value of this parameter the robust + * Chauvenet rejection routine rejects a single value at each iteration. + * This improves stability and accuracy of the rejection process. + * + * For larger data sets, a bulk rejection procedure is enabled for + * performance reasons. The larger the length of the input array with + * respect to this parameter, the more values will be rejected at each + * iteration, which accelerates the process and allows this implementation + * to handle even very large data sets of hundreds of thousands of items. + * + * The default large sample size is 20,000. + */ + int LargeSampleSize() const + { + return m_largeSampleSize; + } + + /*! + * Sets the minimum length to enable bulk rejection. See LargeSampleSize() + * for a description of this parameter. + */ + void SetLargeSampleSize( int n ) + { + m_largeSampleSize = Max( 1, n ); + } + + /*! + * Performs a Robust Chauvenet Rejection procedure for the specified data. + * + * \param[out] i Reference to a variable where the function will + * store the zero-based index of the first non-rejected + * element in the sorted \a data array. + * + * \param[out] j Reference to a variable where the function will + * store the zero-based index of the end of the + * non-rejected sequence in the sorted \a data array. + * + * \param[out] mean Reference to a variable where the function will + * store the mean of the subset of non-rejected + * elements in the \a data array. + * + * \param[out] sigma Reference to a variable where the function will + * store the standard deviation of the subset of + * non-rejected elements in the \a data array. + * + * \param[in,out] data Random-access container of objects to be analyzed + * and rejected. On output, the elements in this + * container will be sorted in ascending order. + * + * On output, the subset of non-rejected array elements is defined by the + * range [i,j) of zero-based array indices relative to the beginning of the + * \a data container. The elements in the \a data container will be sorted + * in ascending order. + * + * This function will perform a three-stage iterative rejection procedure, + * applying a Chauvenet rejection criterion to reject one or more array + * elements at each iteration (depending on the length of the input + * array and the value of the LargeSampleSize() parameter), in succesive + * stages of decreasing robustness/increasing precision. On output, the + * robust location and scale parameters of the non-rejected subset will be + * returned in the specified \a mean and \a sigma variables, respectively. + * + * The template parameter C represents a vector or array-like container with + * indexed random access. If T is the type of an element in a container of + * type C, the following operators must be implicitly or explicitly defined: + * + * \code + * T::operator double() const; + * bool T::operator <( const T& ) const; + * \endcode + * + * The type represented by the I template parameter should correspond to an + * integral scalar type such as int, unsigned, etc. + * + * \note This function is thread-safe. + */ + template + void PerformRejection( I& i, I& j, double& mean, double& sigma, C& data ) const + { + data.Sort(); + i = I( 0 ); + j = I( data.Length() ); + + for ( int phase = 0; phase < 3; ++phase ) + for ( ;; ) + { + switch ( phase ) + { + case 0: // + robustness / - precision + mean = Median( data.At( i ), data.At( j ) ); + sigma = LineFitDeviation( data, i, j, mean ); + break; + case 1: // = robustness / = precision + mean = Median( data.At( i ), data.At( j ) ); + sigma = SampleDeviation( data, i, j, mean ); + break; + case 2: // - robustness / + precision + mean = Mean( data.At( i ), data.At( j ) ); + sigma = StdDev( data.At( i ), data.At( j ), mean ); + break; + } + + if ( 1 + sigma == 1 ) + return; + + I n = j - i; + if ( n < I( 3 ) ) + return; + + if ( n <= I( m_largeSampleSize ) + I( m_largeSampleSize >> 1 ) ) + { + /* + * Optimal single-pixel rejection iteration for 'small' samples. + */ + double d0 = n*QF( (mean - data[i])/sigma ); + double d1 = n*QF( (data[j-1] - mean)/sigma ); + if ( d0 >= m_rejectionLimit ) + if ( d1 >= m_rejectionLimit ) + break; + if ( d1 < d0 ) + --j; + else + ++i; + } + else + { + /* + * Accelerated bulk rejection for large samples. + */ + int nc = RoundInt( double( n )/m_largeSampleSize ); + int c = 0; + for ( int it = 0; it < nc && n*QF( (mean - data[i])/sigma ) < m_rejectionLimit; ++i, ++c, ++it ) {} + for ( int it = 0; it < nc && n*QF( (data[j-1] - mean)/sigma ) < m_rejectionLimit; --j, ++c, ++it ) {} + if ( c == 0 ) + break; + } + } + } + + /*! + * Performs a Robust Chauvenet Rejection procedure. + * + * This operator is equivalent to the PerformRejection() const member + * function. + * + * \note This function is thread-safe. + */ + template + void operator()( I& i, I& j, double& mean, double& sigma, C& data ) const + { + return PerformRejection( i, j, mean, sigma, data ); + } + +private: + + float m_rejectionLimit = 0.5; // 0.5 = Chauvenet rejection criterion + int m_largeSampleSize = 20000; + + /* + * The Q-function: the probability for a value from a normal distribution of + * being more than x standard deviations from the mean. + */ + static double QF( double x ) + { + return 0.5*(1 - Erf( x/Const::sqrt2() )); + } + + /* + * Correction factor for 68.3-percentile deviations to avoid overaggressive + * rejection for small samples. + */ + template + static double FN( I N ) + { + return 1/(1 - 2.9442*Pow( double( N ), -1.073 )); + } + + /* + * The 68.3-percentile value from the distribution of absolute deviations. + */ + template + static double SampleDeviation( const C& R, I i, I j, double m ) + { + int N = int( j - i ); + Vector D( N ); + for ( int k = 0; i < j; ++i, ++k ) + D[k] = Abs( double( R[i] ) - m ); + return FN( N ) * *pcl::Select( D.Begin(), D.End(), TruncInt( 0.683*D.Length() ) ); + } + + /* + * 68.3-percentile deviation by fitting a zero-intercept line to the vector + * of absolute differences. + */ + template + static double LineFitDeviation( const C& R, I i, I j, double m ) + { + int N = int( j - i ); + int n = int( 0.683*N + 0.317 ); + if ( n < 8 ) + return SampleDeviation( R, i, j, m ); + + Vector y( N ); + int k = 0; + for ( I ii = i; ii < j; ++ii, ++k ) + y[k] = Abs( double( R[ii] ) - m ); + y.Sort(); + y = Vector( y.Begin(), n ); + + Vector x( n ); + for ( int i = 0; i < n; ++i ) + x[i] = Const::sqrt2() * ErfInv( (i + 1 - 0.317)/N ); + + double s; + LinearFit f( x, y ); + if ( f.IsValid() ) + s = FN( N ) * f( 1.0 ); + else + s = SampleDeviation( R, i, j, m ); + + return s; + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_RobustChauvenetRejection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/RobustChauvenetRejection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Rotate.h b/3rdparty/include/pcl/Rotate.h new file mode 100644 index 0000000..d79837f --- /dev/null +++ b/3rdparty/include/pcl/Rotate.h @@ -0,0 +1,247 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Rotate.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_Rotate_h +#define __PCL_Rotate_h + +#include + +#include +#include + +// Template formal parameters: +// +// FI Forward iterator +// BI Bidirectional iterator +// RI Random access iterator +// UP Unary predicate +// BP Binary predicate +// T Item type +// F Function + +// ### TODO: Document this file. + +namespace pcl +{ + +// ---------------------------------------------------------------------------- +// void Reverse( BI, BI ) +// ---------------------------------------------------------------------------- + +template inline +void Reverse( BI i, BI j ) +{ + __reverse__( i, j, IteratorClass( i ) ); +} + +template inline +void __reverse__( BI i, BI j, BidirectionalIterator ) +{ + for ( ; i != j && i != --j; ++i ) + Swap( *i, *j ); +} + +template inline +void __reverse__( RI i, RI j, RandomAccessIterator ) +{ + if ( i < j ) + for ( ; i < --j; ++i ) + Swap( *i, *j ); +} + +// ---------------------------------------------------------------------------- +// void Rotate( FI, FI, FI ) +// ---------------------------------------------------------------------------- + +template inline +void Rotate( FI i, FI m, FI j ) +{ + if ( m != i && m != j ) + __rotate__( i, m, j, IteratorClass( i ) ); +} + +template inline +void __rotate__( FI i, FI m, FI j, ForwardIterator ) +{ + for ( FI k = m; ; ) + { + Swap( *i, *k ); + if ( ++i == m ) + if ( ++k == j ) + break; + else + m = k; + else if ( ++k == j ) + k = m; + } +} + +template inline +void __rotate__( BI i, BI m, BI j, BidirectionalIterator ) +{ + Reverse( i, m ); + Reverse( m, j ); + Reverse( i, j ); +} + +template inline +void __rotate__( RI i, RI m, RI j, RandomAccessIterator ) +{ + __rotate_ri__( i, m, j, ItemType( i ) ); +} + +template inline +void __rotate_ri__( RI i, RI m, RI j, const T* ) +{ + distance_type d = m-i; + distance_type n = j-i; + + for ( distance_type a = d; a != 0; ) + { + distance_type b = n % a; + n = a; + a = b; + } + + if ( n < j-i ) + for ( ; 0 < n; --n ) + { + RI x = i+n; + RI y = x; + RI z = y+d; + if ( z == j ) + z = i; + + T v = *x; + + while ( z != x ) + { + *y = *z; + y = z; + z = (d < j-z) ? z+d : i+(d-(j-z)); + } + + *y = v; + } +} + +// ---------------------------------------------------------------------------- +// void Shift( FI, FI, FI, T ) +// void ShiftLeft( FI, FI, FI, T ) +// ---------------------------------------------------------------------------- + +template inline +void Shift( FI i, FI m, FI j, const T& v ) +{ + if ( m != i ) + { + for ( ; m != j; ++m, ++i ) + *i = *m; + for ( ; i != j; ++i ) + *i = v; + } +} + +template inline +void ShiftLeft( FI i, FI m, FI j, const T& v ) +{ + Shift( i, m, j, v ); +} + +// ---------------------------------------------------------------------------- +// void ShiftRight( FI, FI, FI, T ) +// ---------------------------------------------------------------------------- + +template inline +void ShiftRight( FI i, FI m, FI j, const T& v ) +{ + if ( i != j && m != j ) + __shift_right__( i, m, j, v, IteratorClass( i ) ); +} + +template inline +void __shift_right__( FI i, FI m, FI j, const T& v, ForwardIterator ) +{ + do + { + if ( m != i ) + { + FI k = i; + do + Swap( *++k, *i ); + while ( k != m ); + *m = *i; + } + + *i = v; + ++i; + } + while ( ++m != j ); +} + +template inline +void __shift_right__( BI i, BI m, BI j, const T& v, BidirectionalIterator ) +{ + while ( m != i ) + *--j = *--m; + do + *m = v; + while ( ++m != j ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Rotate_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Rotate.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Rotation.h b/3rdparty/include/pcl/Rotation.h new file mode 100644 index 0000000..e91fa7d --- /dev/null +++ b/3rdparty/include/pcl/Rotation.h @@ -0,0 +1,272 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Rotation.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_Rotation_h +#define __PCL_Rotation_h + +/// \file pcl/Rotation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Rotation + * \brief %Image rotation algorithm. + * + * ### TODO: Write a detailed description for %Rotation + */ +class PCL_CLASS Rotation : public InterpolatingGeometricTransformation, + public ParallelProcess +{ +public: + + /*! + * Constructs a new %Rotation object. + * + * \param p Reference to a pixel interpolation, which must remain + * valid while this object exists. + * + * \param angle Rotation angle in radians + * + * \param cx Horizontal coordinate of the center of rotation, measured + * in pixels in the image coordinate system. + * + * \param cy Vertical coordinate of the center of rotation, measured + * in pixels in the image coordinate system. + */ + Rotation( PixelInterpolation& p, double angle = 0, double cx = 0, double cy = 0 ) + : InterpolatingGeometricTransformation( p ) + , m_angle( angle ) + , m_center( cx, cy ) + { + } + + /*! + * Constructs a new %Rotation object. + * + * \param p Reference to a pixel interpolation, which must remain + * valid while this object exists. + * + * \param angle Rotation angle in radians + * + * \param center Coordinates of the center of rotation, measured in pixels + * in the image coordinate system. + */ + Rotation( PixelInterpolation& p, double angle, const DPoint& center ) + : InterpolatingGeometricTransformation( p ) + , m_angle( angle ) + , m_center( center ) + { + } + + /*! + * Copy constructor. + */ + Rotation( const Rotation& ) = default; + + /*! + * Returns the rotation angle in radians. + */ + double Angle() const + { + return m_angle; + } + + /*! + * Sets the rotation angle in radians. + */ + void SetAngle( double rads ) + { + m_angle = rads; + } + + /*! + * Returns the center of rotation. The returned point coordinates are + * measured in pixels in the image coordinate system. + */ + DPoint Center() const + { + return m_center; + } + + /*! + * Returns the horizontal coordinate of the center of rotation, measured in + * pixels in the image coordinate system. + */ + double CenterX() const + { + return m_center.x; + } + + /*! + * Returns the vertical coordinate of the center of rotation, measured in + * pixels in the image coordinate system. + */ + double CenterY() const + { + return m_center.y; + } + + /*! + * Sets the center of rotation. The specified \a center point coordinates + * must be expressed in pixels in the image coordinate system. + */ + void SetCenter( const DPoint& center ) + { + m_center = center; + } + + /*! + * Sets the center of rotation to the specified coordinates \a xc and \a yc, + * which must be expressed in pixels in the image coordinate system. + */ + void SetCenter( double xc, double yc ) + { + m_center.x = xc; m_center.y = yc; + } + + /*! + * Returns true iff this transformation will preserve the entire target + * image without clipping any pixels after rotating it. + * + * An unclipped rotation ignores the specified rotation center coordinates + * (see CenterX() and CenterY(), as well as the class constructor) and + * rotates images with respect to their geometric centers. To accommodate + * all rotated pixels in the result, the unclipped rotated image will always + * be bigger than the original, except for the trivial cases of rotations by + * 0 and 180 degrees. + */ + bool IsUnclipped() const + { + return m_unclipped; + } + + /*! + * Enables unclipped rotations for this object. See IsUnclipped() for + * information on unclipped rotations. + */ + void EnableUnclippedRotation( bool enable = true ) + { + m_unclipped = enable; + } + + /*! + * Disables unclipped rotations for this object. See IsUnclipped() for + * information on unclipped rotations. + */ + void DisableUnclippedRotation( bool disable = true ) + { + EnableUnclippedRotation( !disable ); + } + + /*! + * Returns the current vector of per-channel filling values for uncovered + * image regions. + * + * See the documentation for SetFillValues() for more information. + */ + const DVector& FillValues() const + { + return m_fillValues; + } + + /*! + * Sets a vector of per-channel filling values for uncovered image regions. + * + * Uncovered regions result when an image is rotated by non-orthogonal + * angles. + * + * By default, there are no filling values defined (and hence the returned + * vector is empty by default). When the %Rotation instance is executed and + * a filling value is not defined for a channel of the target image, + * uncovered regions are filled with the minimum sample value in the native + * range of the image (usually zero). + */ + void SetFillValues( const DVector& fillValues ) + { + m_fillValues = fillValues; + } + + /*! + */ + void GetNewSizes( int& width, int& height ) const override; + +protected: + + double m_angle = 0; // radians + bool m_unclipped = false; + DPoint m_center = DPoint( 0 ); + DVector m_fillValues; + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Rotation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Rotation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SVG.h b/3rdparty/include/pcl/SVG.h new file mode 100644 index 0000000..ac3b501 --- /dev/null +++ b/3rdparty/include/pcl/SVG.h @@ -0,0 +1,259 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SVG.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_SVG_h +#define __PCL_SVG_h + +/// \file pcl/SVG.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SVG + * \brief Scalable %Vector %Graphics generation. + * + * The %SVG class performs generation of Scalable %Vector %Graphics output. + * Generated %SVG data can be sent to either a disk file or to a memory buffer. + * The Bitmap class can be used to render %SVG objects as images. + * + * \sa Graphics, Bitmap + */ +class PCL_CLASS SVG : public UIObject +{ +public: + + /*! + * Constructs an %SVG object that will send graphics output to a file at the + * specified \a filePath. + * + * The optional \a width and \a height values, if nonzero, will be written + * as the corresponding attributes of the root <svg> XML element. + */ + SVG( const String& filePath, int width = 0, int height = 0 ); + + /*! + * Constructs an %SVG object that will send graphics output to a memory + * buffer. + * + * The optional \a width and \a height values, if nonzero, will be written + * as the corresponding attributes of the <svg> XML element. + */ + SVG( int width = 0, int height = 0 ); + + /*! + * Destroys an %SVG object. + */ + virtual ~SVG() + { + } + + /*! + * Returns a reference to a null %SVG instance. A null %SVG does not + * correspond to an existing SVG object in the PixInsight core application. + */ + static SVG& Null(); + + /*! + * Obtains the dimensions (width, height) of this %SVG object in pixels. + */ + void GetDimensions( int& width, int& height ) const; + + /*! + * Sets the dimensions of this %SVG object, width and height in pixels. + */ + void SetDimensions( int width, int height ) const; + + /*! + * Returns the width of this %SVG object. + */ + int Width() const + { + int w, dum; GetDimensions( w, dum ); return w; + } + + /*! + * Returns the height of this %SVG object. + */ + int Height() const + { + int dum, h; GetDimensions( dum, h ); return h; + } + + /*! + * Returns the bounding rectangle of this %SVG object. The returned + * rectangle is equal to %Rect( 0, 0, Width(), Height() ). + */ + Rect Bounds() const + { + int w, h; GetDimensions( w, h ); return Rect( w, h ); + } + + /*! + * Returns the viewBox attribute of this %SVG object. The viewBox defines a + * clipping rectangle for graphics output. It can be useful when an %SVG + * drawing will be used as an element of a larger drawing. + */ + DRect ViewBox() const; + + /*! + * Sets the viewBox attribute of this %SVG object. + * + * \param x0 Left coordinate of the viewBox rectangle. + * \param y0 Upper coordinate of the viewBox rectangle. + * \param x1 Right coordinate of the viewBox rectangle. + * \param y1 Bottom coordinate of the viewBox rectangle. + * + * The viewBox defines a clipping rectangle for graphics output. It can be + * useful when an %SVG drawing will be used as an element of a larger drawing. + */ + void SetViewBox( double x0, double y0, double x1, double y1 ); + + /*! + * Sets the viewBox attribute of this %SVG object to the specified + * rectangle \a r. + */ + template + void SetViewBox( const GenericRectangle& r ) + { + SetViewBox( double( r.x0 ), double( r.y0 ), double( r.x1 ), double( r.y1 ) ); + } + + /*! + * Returns the resolution attribute of this %SVG object in dots per inch. + */ + int Resolution() const; + + /*! + * Sets the resolution attribute of this %SVG object in dots per inch. + */ + void SetResolution( int r ); + + /*! + * Returns the output file path of this %SVG object. If this object sends + * its graphics output to a memory buffer, this function returns an empty + * string. + */ + String FilePath() const; + + /*! + * Returns a copy of the output data buffer generated by this %SVG object + * as a dynamic array of bytes. If this object sends graphics output to a + * file buffer, or if a Graphics object is still painting it, this function + * returns an empty array. + */ + ByteArray Data() const; + + /*! + * Returns the title attribute of this %SVG object. + */ + String Title() const; + + /*! + * Sets the title attribute of this %SVG object. + * + * If no specific value is set by a call to this function, a default title + * attribute is set to "PixInsight SVG Document" by the PixInsight core + * application. + */ + void SetTitle( const String& title ); + + /*! + * Returns the description attribute of this %SVG object. + */ + String Description() const; + + /*! + * Sets the description attribute of this %SVG object. + * + * If no specific value is set by a call to this function, a default + * description attribute is set to "Generated with " plus a string + * representing the version of the PixInsight core application. + */ + void SetDescription( const String& desc ); + + /*! + * Returns true iff this %SVG instance is being actively painted by a + * Graphics object. + */ + bool IsPainting() const; + +protected: + + SVG( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class GraphicsContextBase; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_SVG_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SVG.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ScrollBox.h b/3rdparty/include/pcl/ScrollBox.h new file mode 100644 index 0000000..efc07a9 --- /dev/null +++ b/3rdparty/include/pcl/ScrollBox.h @@ -0,0 +1,664 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ScrollBox.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_ScrollBox_h +#define __PCL_ScrollBox_h + +/// \file pcl/ScrollBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ScrollBox + * \brief Client-side interface to a PixInsight %ScrollBox control. + * + * ### TODO: Write a detailed description for %ScrollBox. + */ +class PCL_CLASS ScrollBox : public Frame +{ +public: + + /*! + * Constructs a %ScrollBox as a child control of \a parent. + */ + ScrollBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %ScrollBox control. + */ + virtual ~ScrollBox() + { + } + + /*! + * Returns true iff the horizontal scroll bar is currently visible on this + * scroll box. + */ + bool IsHorizontalScrollBarVisible() const; + + /*! + * Returns true iff the vertical scroll bar is currently visible on this + * scroll box. + */ + bool IsVerticalScrollBarVisible() const; + + /*! + * Forces visibility of scroll bars. + * + * \param showHorz Visibility of the horizontal scroll bar. + * \param showVert Visibility of the vertical scroll bar. + */ + void ShowScrollBars( bool showHorz = true, bool showVert = true ); + + /*! + * Forces visibility of scroll bars. + * + * This is a convenience member function, equivalent to + * ShowScrollBars( !hideHorz, !hideVert ) + */ + void HideScrollBars( bool hideHorz = true, bool hideVert = true ) + { + ShowScrollBars( !hideHorz, !hideVert ); + } + + /*! + * Forces visibility of the horizontal scroll bar. + * + * This is a convenience member function, equivalent to + * ShowScrollBars( show, IsVerticalScrollBarVisible() ) + */ + void ShowHorizontalScrollBar( bool show = true ) + { + ShowScrollBars( show, IsVerticalScrollBarVisible() ); + } + + /*! + * Forces visibility of the horizontal scroll bar. + * + * This is a convenience member function, equivalent to + * ShowHorizontalScrollBar( !hide ) + */ + void HideHorizontalScrollBar( bool hide = true ) + { + ShowHorizontalScrollBar( !hide ); + } + + /*! + * Forces visibility of the vertical scroll bar. + * + * This is a convenience member function, equivalent to + * ShowScrollBars( IsHorizontalScrollBarVisible(), show ) + */ + void ShowVerticalScrollBar( bool show = true ) + { + ShowScrollBars( IsHorizontalScrollBarVisible(), show ); + } + + /*! + * Forces visibility of the vertical scroll bar. + * + * This is a convenience member function, equivalent to + * ShowVerticalScrollBar( !hide ) + */ + void HideVerticalScrollBar( bool hide = true ) + { + ShowVerticalScrollBar( !hide ); + } + + /*! + * Returns true iff the automatic scroll mode is enabled for the + * horizontal scroll bar. + * + * In automatic scroll mode, scroll bars are automatically shown or hidden + * as necessary. A scroll bar is shown only if the corresponding scrolling + * range is larger than the visible length of the scrolling area. + */ + bool IsHorizontalAutoScrollEnabled() const; + + /*! + * Returns true iff the automatic scroll mode is enabled for the + * vertical scroll bar. + * + * In automatic scroll mode, scroll bars are automatically shown or hidden + * as necessary. A scroll bar is shown only if the corresponding scrolling + * range is larger than the visible length of the scrolling area. + */ + bool IsVerticalAutoScrollEnabled() const; + + /*! + * Enables the automatic scroll mode. + * + * \param enableHorz New enabled state for the horizontal scroll bar. + * \param enableVert New enabled state for the vertical scroll bar. + * + * In automatic scroll mode, scroll bars are automatically shown or hidden + * as necessary. A scroll bar is shown only if the corresponding scrolling + * range is larger than the visible length of the scrolling area. + */ + void EnableAutoScroll( bool enableHorz = true, bool enableVert = true ); + + /*! + * Disables the automatic scroll mode. + * + * This is a convenience member function, equivalent to + * EnableAutoScroll( !disableHorz, !disableVert ) + */ + void DisableAutoScroll( bool disableHorz = true, bool disableVert = true ) + { + EnableAutoScroll( !disableHorz, !disableVert ); + } + + /*! + * Gets the current horizontal scroll range. + * + * \param[out] minPos Minimum horizontal scrolling position + * \param[out] maxPos Maximum horizontal scrolling position + * + * The virtual document width is equal to + * maxPos - minPos + PageWidth() in scrolling units. + */ + void GetHorizontalScrollRange( int& minPos, int& maxPos ) const; + + /*! + * Gets the current vertical scroll range. + * + * \param[out] minPos Minimum vertical scrolling position + * \param[out] maxPos Maximum vertical scrolling position + * + * The virtual document height is equal to + * maxPos - minPos + PageHeight() in scrolling units. + */ + void GetVerticalScrollRange( int& minPos, int& maxPos ) const; + + /*! + * Returns the minimum horizontal scrolling position. + */ + int MinHorizontalScrollPosition() const + { + int minPos, dum; GetHorizontalScrollRange( minPos, dum ); return minPos; + } + + /*! + * Returns the maximum horizontal scrolling position. + */ + int MaxHorizontalScrollPosition() const + { + int dum, maxPos; GetHorizontalScrollRange( dum, maxPos ); return maxPos; + } + + /*! + * Returns the minimum vertical scrolling position. + */ + int MinVerticalScrollPosition() const + { + int minPos, dum; GetVerticalScrollRange( minPos, dum ); return minPos; + } + + /*! + * Returns the maximum horizontal scrolling position. + */ + int MaxVerticalScrollPosition() const + { + int dum, maxPos; GetVerticalScrollRange( dum, maxPos ); return maxPos; + } + + /*! + * Sets the horizontal scroll range. + * + * \param minPos Minimum horizontal scrolling position + * \param maxPos Maximum horizontal scrolling position + * + * The virtual document width will be equal to + * maxPos - minPos + PageWidth() in scrolling units. + */ + void SetHorizontalScrollRange( int minPos, int maxPos ); + + /*! + * Sets the vertical scroll range. + * + * \param minPos Minimum vertical scrolling position + * \param maxPos Maximum vertical scrolling position + * + * The virtual document height will be equal to + * maxPos - minPos + PageHeight() in scrolling units. + */ + void SetVerticalScrollRange( int minPos, int maxPos ); + + /*! + * Returns the current page width of this scroll box in scrolling + * units. + * + * The page width is the length of the horizontal scroll bar's slider. + */ + int PageWidth() const; + + /*! + * Returns the current page height of this scroll box in scrolling + * units. + * + * The page height is the length of the vertical scroll bar's slider, or + * the amount scrolled when the user presses the PgUp or PgDn keys. + */ + int PageHeight() const; + + /*! + * Sets the page size of this scroll box. + * + * \param width New page width in scrolling units. + * \param height New page height in scrolling units. + */ + void SetPageSize( int width, int height ); + + /*! + * Sets the page width of this scroll box in scrolling units. + */ + void SetPageWidth( int width ) + { + SetPageSize( width, PageHeight() ); + } + + /*! + * Sets the page height of this scroll box in scrolling units. + */ + void SetPageHeight( int height ) + { + SetPageSize( PageWidth(), height ); + } + + /*! + * Returns the current line width of this scroll box control. + * + * The line width is the number of scrolling units scrolled when the user + * clicks on an arrow icon of the horizontal scroll bar. + */ + int LineWidth() const; + + /*! + * Returns the current line height of this scroll box control. + * + * The line height is the number of scrolling units scrolled when the user + * clicks on an arrow icon of the vertical scroll bar. + */ + int LineHeight() const; + + /*! + * Sets the line sizes of this scroll box. + * + * \param width New line width in scrolling units. + * \param height New line height in scrolling units. + */ + void SetLineSize( int width, int height ); + + /*! + * Sets the line width of this scroll box in scrolling units. + */ + void SetLineWidth( int width ) + { + SetLineSize( width, LineHeight() ); + } + + /*! + * Sets the line height of this scroll box in scrolling units. + */ + void SetLineHeight( int height ) + { + SetLineSize( LineWidth(), height ); + } + + /*! + * Returns the current scroll position. Returned oordinates are expressed in + * scrolling units. + */ + pcl::Point ScrollPosition() const; + + /*! + * Returns the current horizontal scroll position in scrolling units. + */ + int HorizontalScrollPosition() const + { + pcl::Point pos = ScrollPosition(); return pos.x; + } + + /*! + * Returns the current vertical scroll position in scrolling units. + */ + int VerticalScrollPosition() const + { + pcl::Point pos = ScrollPosition(); return pos.y; + } + + /*! + * Sets the scroll position \a pos of this scroll box control. + */ + void SetScrollPosition( const pcl::Point& pos ) + { + SetScrollPosition( pos.x, pos.y ); + } + + /*! + * Sets the scroll coordinates \a horzPos and \a vertPos of this scroll box + * control. + */ + void SetScrollPosition( int horzPos, int vertPos ); + + /*! + * Sets the horizontal scroll position. + */ + void SetHorizontalScrollPosition( int horzPos ) + { + SetScrollPosition( horzPos, VerticalScrollPosition() ); + } + + /*! + * Sets the vertical scroll position. + */ + void SetVerticalScrollPosition( int vertPos ) + { + SetScrollPosition( HorizontalScrollPosition(), vertPos ); + } + + /*! + * Returns true iff the automatic tracking mode is enabled for the + * horizontal scroll bar of this scroll box control. + */ + bool IsHorizontalTrackingEnabled() const; + + /*! + * Returns true iff the automatic tracking mode is enabled for the + * vertical scroll bar of this scroll box control. + */ + bool IsVerticalTrackingEnabled() const; + + /*! + * Enables or disables the automatic tracking mode for this scroll + * box control. + * + * \param enableHorz New state of automatic tracking mode for the + * horizontal scroll bar. + * + * \param enableVert New state of automatic tracking mode for the + * vertical scroll bar. + * + * When automatic tracking is enabled, the viewport receives continuous + * update requests while the user is moving an scroll bar with the mouse. + * When automatic tracking is disabled, the viewport is updated only when + * the mouse is released. + */ + void EnableTracking( bool enableHorz = true, bool enableVert = true ); + + /*! + * Enables or disables the automatic tracking mode for the + * horizontal scroll bar of this box control control. + * + * This is a convenience member function, equivalent to + * EnableTracking( enableHorz, IsVerticalTrackingEnabled() ) + */ + void EnableHorizontalTracking( bool enableHorz = true ) + { + EnableTracking( enableHorz, IsVerticalTrackingEnabled() ); + } + + /*! + * Enables or disables the automatic tracking mode for the + * vertical scroll bar of this box control control. + * + * This is a convenience member function, equivalent to + * EnableTracking( IsHorizontalTrackingEnabled(), enableVert ) + */ + void EnableVerticalTracking( bool enableVert = true ) + { + EnableTracking( IsHorizontalTrackingEnabled(), enableVert ); + } + + /*! + * Disables or enables the automatic tracking mode for this scroll + * box control. + * + * This is a convenience member function, equivalent to + * EnableTracking( !disableHorz, !disableVert ) + */ + void DisableTracking( bool disableHorz = true, bool disableVert = true ) + { + EnableTracking( !disableHorz, !disableVert ); + } + + /*! + * Disables or enables the automatic tracking mode for the + * horizontal scroll bar of this box control control. + * + * This is a convenience member function, equivalent to + * EnableTracking( !disableHorz, IsVerticalTrackingEnabled() ) + */ + void DisableHorizontalTracking( bool disableHorz = true ) + { + EnableTracking( !disableHorz, IsVerticalTrackingEnabled() ); + } + + /*! + * Disables or enables the automatic tracking mode for the + * vertical scroll bar of this box control control. + * + * This is a convenience member function, equivalent to + * EnableTracking( IsHorizontalTrackingEnabled(), !disableVert ) + */ + void DisableVerticalTracking( bool disableVert = true ) + { + EnableTracking( IsHorizontalTrackingEnabled(), !disableVert ); + } + + /*! + * Returns a constant reference to the viewport control of this + * scroll box. + * + * The viewport control represents the contents, or "virtual document" of + * the scroll box. + */ + const Control& Viewport() const + { + return m_viewport; + } + + /*! + * Returns a reference to the viewport control of this scroll box. + * + * The viewport control represents the contents, or "virtual document" of + * the scroll box. + */ + Control& Viewport() + { + return m_viewport; + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnHorizontalScrollPosUpdated( ScrollBox& sender, int horzPos ); + // void OnVerticalScrollPosUpdated( ScrollBox& sender, int vertPos ); + // void OnHorizontalScrollRangeUpdated( ScrollBox& sender, int minHorzPos, int maxHorzPos ); + // void OnVerticalScrollRangeUpdated( ScrollBox& sender, int minVertPos, int maxVertPos ); + + /*! + * \defgroup scroll_box_event_handlers ScrollBox Event Handlers + */ + + /*! + * Defines the prototype of a scroll position event handler. + * + * A scroll position event is generated after the scroll position has been + * changed by the user, either by clicking a scroll bar with the mouse or by + * pressing a direction key when a scroll bar has the keyboard focus. + * + * \param sender The control that sends a scroll position event. + * \param pos New scroll position in scrolling units. + * + * \ingroup scroll_box_event_handlers + */ + typedef void (Control::*pos_event_handler)( ScrollBox& sender, int pos ); + + /*! + * Defines the prototype of a scroll range event handler. + * + * A scroll range event is generated after a scrolling range has been + * changed for the horizontal or vertical scroll bars. + * + * \param sender The control that sends a scroll range event. + * \param minValue New minimum scroll position. + * \param maxValue New maximum scroll position. + * + * \ingroup scroll_box_event_handlers + */ + typedef void (Control::*range_event_handler)( ScrollBox& sender, int minValue, int maxValue ); + + /*! + * Sets the scroll position event handler for the horizontal scroll bar. + * + * \param handler The scroll position event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive horizontal scroll + * position events from this scroll box. + * + * \ingroup scroll_box_event_handlers + */ + void OnHorizontalScrollPosUpdated( pos_event_handler handler, Control& receiver ); + + /*! + * Sets the scroll position event handler for the vertical scroll bar. + * + * \param handler The scroll position event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive vertical scroll + * position events from this scroll box. + * + * \ingroup scroll_box_event_handlers + */ + void OnVerticalScrollPosUpdated( pos_event_handler handler, Control& receiver ); + + /*! + * Sets the scroll range event handler for the horizontal scroll bar. + * + * \param handler The scroll range event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive horizontal scroll + * range events from this scroll box. + * + * \ingroup scroll_box_event_handlers + */ + void OnHorizontalScrollRangeUpdated( range_event_handler handler, Control& receiver ); + + /*! + * Sets the scroll range event handler for the vertical scroll bar. + * + * \param handler The scroll range event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive vertical scroll + * range events from this scroll box. + * + * \ingroup scroll_box_event_handlers + */ + void OnVerticalScrollRangeUpdated( range_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + pos_event_handler onHorizontalScrollPosUpdated = nullptr; + pos_event_handler onVerticalScrollPosUpdated = nullptr; + range_event_handler onHorizontalScrollRangeUpdated = nullptr; + range_event_handler onVerticalScrollRangeUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + +protected: + + Control m_viewport; + + /*! + * \internal + */ + ScrollBox( void* ); + + /*! + * \internal + */ + ScrollBox( void*, void* ); + + friend class ScrollBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ScrollBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ScrollBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Search.h b/3rdparty/include/pcl/Search.h new file mode 100644 index 0000000..5c489ec --- /dev/null +++ b/3rdparty/include/pcl/Search.h @@ -0,0 +1,510 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Search.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_Search_h +#define __PCL_Search_h + +/// \file pcl/Search.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup search_algorithms Search Algorithms + * + * Template formal parameters: + * + * FI Forward iterator \n + * BI Bidirectional iterator \n + * RI Random access iterator \n + * UP Unary predicate \n + * BP Binary predicate \n + * T Item type \n + * F Function + */ + +// ---------------------------------------------------------------------------- + +/*! + * Generic linear search algorithm. + * + * Returns the first iterator k in the range [i,j) such that *k == v. Returns + * j if no such occurrence of v is found. + * + * \ingroup search_algorithms + */ +template inline +FI LinearSearch( FI i, FI j, const T& v ) noexcept +{ + for( ; i != j; ++i ) + if ( *i == v ) + break; + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic linear search algorithm. + * + * Returns the first iterator k in the range [i,j) such that p( *k, v ) is + * true. Returns j if no such occurrence of v is found. + * + * \ingroup search_algorithms + */ +template inline +FI LinearSearch( FI i, FI j, const T& v, BP p ) noexcept( noexcept( p ) ) +{ + for( ; i != j; ++i ) + if ( p( *i, v ) ) + break; + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic linear search algorithm (last occurrence). + * + * Returns the last iterator k in the range [i,j) such that *k == v. Returns + * j if no such occurrence of v is found. + * + * \ingroup search_algorithms + */ +template inline +BI LinearSearchLast( BI i, BI j, const T& v ) noexcept +{ + for( BI k = j; i != k; ) + if ( *--k == v ) + return k; + return j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic linear search algorithm (last occurrence). + * + * Returns the last iterator k in the range [i,j) such that *k == v. Returns + * j if no such occurrence of v is found. + * + * \ingroup search_algorithms + */ +template inline +BI LinearSearchLast( BI i, BI j, const T& v, BP p ) noexcept( noexcept( p ) ) +{ + for( BI k = j; i != k; ) + if ( p( *--k, v ) ) + return k; + return j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic binary search algorithm. + * + * Returns the first iterator k in the range [i,j) such that *k == v. Returns j + * if no such occurrence of v is found. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, *j < *i must be false. + * + * \ingroup search_algorithms + */ +template inline +FI BinarySearch( FI i, FI j, const T& v ) noexcept +{ + for ( distance_type n = Distance( i, j ); n > 0; ) + { + distance_type h = n >> 1; + FI m = i; + Advance( m, h ); + + if ( *m < v ) + { + i = ++m; + n -= h+1; + } + else + n = h; + } + + return (i != j && !(v < *i)) ? i : j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic binary search algorithm. + * + * Returns the first iterator k in the range [i,j) such that both p( *k, v ) + * and p( v, *k ) are false. Returns j if no such occurrence of v is found. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, p( *j, *i ) must be false. + * + * \ingroup search_algorithms + */ +template inline +FI BinarySearch( FI i, FI j, const T& v, BP p ) noexcept( noexcept( p ) ) +{ + for ( distance_type n = Distance( i, j ); n > 0; ) + { + distance_type h = n >> 1; + FI m = i; + Advance( m, h ); + + if ( p( *m, v ) ) + { + i = ++m; + n -= h+1; + } + else + n = h; + } + + return (i != j && !p( v, *i )) ? i : j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic binary search algorithm (last occurrence). + * + * Returns the last iterator k in the range [i,j) such that *k == v. Returns j + * if no such occurrence of v is found. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, *j < *i must be false. + * + * \ingroup search_algorithms + */ +template inline +FI BinarySearchLast( FI i, FI j, const T& v ) noexcept +{ + FI k = BinarySearch( i, j, v ); + if ( k != j ) + for( FI l = k; ++l != j && *l == v; ) + ++k; + return k; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic binary search algorithm (last occurrence). + * + * Returns the last iterator k in the range [i,j) such that both p( *k, v ) + * and p( v, *k ) are false. Returns j if no such occurrence of v is found. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, p( *j, *i ) must be false. + * + * \ingroup search_algorithms + */ +template inline +FI BinarySearchLast( FI i, FI j, const T& v, BP p ) noexcept( noexcept( p ) ) +{ + FI k = BinarySearch( i, j, v, p ); + if ( k != j ) + for( FI l = k; ++l != j && !p( *l, v ) && !p( v, *l ); ) + ++k; + return k; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic binary search algorithm. + * + * Returns the first iterator k in the range [i,j) such that both p1( *k, v ) + * and p2( v, *k ) are false. Returns j if no such occurrence of v is found. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, both p1( *j, *i ) and p2( *j, *i ) must be + * false. + * + * \ingroup search_algorithms + */ +template inline +FI BinarySearch( FI i, FI j, const T& v, BP1 p1, BP2 p2 ) noexcept( noexcept( p1 ) && noexcept( p2 ) ) +{ + for ( distance_type n = Distance( i, j ); n > 0; ) + { + distance_type h = n >> 1; + FI m = i; + Advance( m, h ); + + if ( p1( *m, v ) ) + { + i = ++m; + n -= h+1; + } + else + n = h; + } + + return (i != j && !p2( v, *i )) ? i : j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic insertion point algorithm. + * + * Returns an iterator k in the range [i,j) such that: + * + * \li for all a in [i,j) that precedes k, v \< *a is false. + * + * \li for all b in [i,j) that postcedes k, *b \< v is false. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, *j < *i must be false. + * + * The resulting iterator k corresponds to a location where the value \a v could + * be inserted in the [i,j) sequence without breaking the existing order of + * values, as defined by operator <. + * + * \ingroup search_algorithms + */ +template inline +FI InsertionPoint( FI i, FI j, const T& v ) noexcept +{ + for ( distance_type n = Distance( i, j ); n > 0; ) + { + distance_type h = n >> 1; + FI m = i; + Advance( m, h ); + + if ( v < *m ) + n = h; + else + { + i = ++m; + n -= h+1; + } + } + + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Generic insertion point algorithm. + * + * Returns an iterator k in the range [i,j) such that: + * + * \li for all a in [i,j) that precedes k, p( v, *a ) is false. + * + * \li for all b in [i,j) that postcedes k, p( *b, v ) is false. + * + * The sequence [i,j) must be ordered in ascending order: for every pair a,b in + * [i,j) such that i precedes j, p( *j, *i ) must be false. + * + * The resulting iterator k corresponds to a location where the value \a v could + * be inserted in the [i,j) sequence without breaking the existing order of + * values, as defined by the binary predicate p. + * + * \ingroup search_algorithms + */ +template inline +FI InsertionPoint( FI i, FI j, const T& v, BP p ) noexcept( noexcept( p ) ) +{ + for ( distance_type n = Distance( i, j ); n > 0; ) + { + distance_type h = n >> 1; + FI m = i; + Advance( m, h ); + + if ( p( v, *m ) ) + n = h; + else + { + i = ++m; + n -= h+1; + } + } + + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the starting iterator of the first subsequence within the range + * [i1,j1) that is identical to the sequence [i2,j2) when compared element by + * element, or j1 if no such subsequence is found. + * + * \ingroup search_algorithms + */ +template inline +FI1 Search( FI1 i1, FI1 j1, FI2 i2, FI2 j2 ) noexcept +{ + distance_type n1 = Distance( i1, j1 ); + distance_type n2 = Distance( i2, j2 ); + if ( n1 > 0 && n2 > 0 ) + for ( ; n2 <= n1; ++i1, --n1 ) + { + FI1 k1 = i1; + FI2 k2 = i2; + for ( ; *k1 == *k2; ++k1 ) + if ( ++k2 == j2 ) + return i1; + } + return j1; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the starting iterator of the first subsequence within the range + * [i1,j1) that corresponds to the sequence [i2,j2) when the binary predicate p + * is applied element by element, or j1 if no such subsequence is found. + * + * \ingroup search_algorithms + */ +template inline +FI1 Search( FI1 i1, FI1 j1, FI2 i2, FI2 j2, BP p ) noexcept( noexcept( p ) ) +{ + distance_type n1 = Distance( i1, j1 ); + distance_type n2 = Distance( i2, j2 ); + if ( n1 > 0 && n2 > 0 ) + for ( ; n2 <= n1; ++i1, --n1 ) + { + FI1 k1 = i1; + FI2 k2 = i2; + for ( ; p( *k1, *k2 ); ++k1 ) + if ( ++k2 == j2 ) + return i1; + } + return j1; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the starting iterator of the last subsequence within the range + * [i1,j1) that is identical to the sequence [i2,j2) when compared element by + * element, or j1 if no such subsequence is found. + * + * \ingroup search_algorithms + */ +template inline +BI1 SearchLast( BI1 i1, BI1 j1, FI2 i2, FI2 j2 ) noexcept +{ + distance_type n1 = Distance( i1, j1 ); + distance_type n2 = Distance( i2, j2 ); + if ( n1 > 0 && n2 > 0 && n2 <= n1 ) + { + i1.Advance( n1 - n2 ); + for ( ;; ) + { + BI1 k1 = i1; + FI2 k2 = i2; + for ( ; *k1 == *k2; ++k1 ) + if ( ++k2 == j2 ) + return i1; + if ( --n1 < n2 ) + break; + --i1; + } + } + return j1; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the starting iterator of the last subsequence within the range + * [i1,j1) that corresponds to the sequence [i2,j2) when the binary predicate p + * is applied element by element, or j1 if no such subsequence is found. + * + * \ingroup search_algorithms + */ +template inline +BI1 SearchLast( BI1 i1, BI1 j1, FI2 i2, FI2 j2, BP p ) noexcept( noexcept( p ) ) +{ + distance_type n1 = Distance( i1, j1 ); + distance_type n2 = Distance( i2, j2 ); + if ( n1 > 0 && n2 > 0 && n2 <= n1 ) + { + i1.Advance( n1 - n2 ); + for ( ;; ) + { + BI1 k1 = i1; + FI2 k2 = i2; + for ( ; p( *k1, *k2 ); ++k1 ) + if ( ++k2 == j2 ) + return i1; + if ( --n1 < n2 ) + break; + --i1; + } + } + return j1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Search_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Search.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SectionBar.h b/3rdparty/include/pcl/SectionBar.h new file mode 100644 index 0000000..f682959 --- /dev/null +++ b/3rdparty/include/pcl/SectionBar.h @@ -0,0 +1,379 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SectionBar.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_SectionBar_h +#define __PCL_SectionBar_h + +/// \file pcl/SectionBar.h + +#include + +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SectionBar + * \brief A control to manage collapsible sections of interface windows and + * dialogs. + * + * %SectionBar manages collapsible/extensible sections on processing interfaces + * and dialogs. It includes a section title label and an icon that + * represents the current collapsed/extended state. + * + * When a %SectionBar control is clicked, it toggles visibility of a + * section control and adjusts the height of the top-level parent + * window to fit to its new contents. %SectionBar is useful to organize complex + * user interfaces and is extensively used by most standard process interfaces + * in PixInsight. + * + * \sa ProcessInterface, Dialog + */ +class PCL_CLASS SectionBar : public Control +{ +public: + + /*! + * Constructs a %SectionBar as a child control of \a parent. + */ + SectionBar( Control& parent = Null() ); + + /*! + * Destroys a %SectionBar object. + */ + virtual ~SectionBar(); + + /*! + * Returns a reference to the immutable section control managed by + * this %SectionBar. + * + * \sa SetSection() + */ + const Control& Section() const + { + return (m_section != nullptr) ? *m_section : Control::Null(); + } + + /*! + * Returns a reference to the section control managed by this + * %SectionBar. + * + * \sa SetSection() + */ + Control& Section() + { + return (m_section != nullptr) ? *m_section : Control::Null(); + } + + /*! + * Sets the section control managed by this %SectionBar. + * + * \sa Section() + */ + void SetSection( Control& ); + + /*! + * Returns the title of this %SectionBar. + * + * \sa SetTitle() + */ + String Title() const + { + return Title_Label.Text(); + } + + /*! + * Sets the title of this %SectionBar. + * + * \sa Title() + */ + void SetTitle( const String& title ) + { + Title_Label.SetText( title ); + } + + /*! + * Returns true iff this %SectionBar is \e checkable. + * + * \sa EnableTitleCheckBox(), DisableTitleCheckBox(), IsChecked(), OnCheck() + */ + bool HasTitleCheckBox() const + { + return !Title_CheckBox.IsNull(); + } + + /*! + * Creates (or removes) a check box in this %SectionBar. + * + * \sa DisableTitleCheckBox(), HasTitleCheckBox(), IsChecked(), OnCheck() + */ + void EnableTitleCheckBox( bool = true ); + + /*! + * Removes (or creates) the check box in this %SectionBar. + * + * \sa EnableTitleCheckBox(), HasTitleCheckBox(), IsChecked(), OnCheck() + */ + void DisableTitleCheckBox( bool disable = true ) + { + EnableTitleCheckBox( !disable ); + } + + /*! + * Returns true iff there is a check box in this %SectionBar and it is + * currently checked. + * + * \sa SetChecked(), EnableTitleCheckBox(), HasTitleCheckBox(), OnCheck() + */ + bool IsChecked() const + { + return !Title_CheckBox.IsNull() && Title_CheckBox->IsChecked(); + } + + /*! + * Checks or unchecks the check box in this %SectionBar. + * + * The \e enabled state of the section control (if there is one) will be + * automatically toggled according to the state of the check box: the + * section control will be enabled if the check box is checked; it will be + * disabled otherwise. + * + * \note If this %SectionBar is not checkable, this function is ignored. + * + * \sa IsChecked(), EnableTitleCheckBox(), HasTitleCheckBox(), OnCheck() + */ + void SetChecked( bool checked = true ); + + /*! + * A convenient synonym for SetChecked( true ). + */ + void Check() + { + SetChecked( true ); + } + + /*! + * A convenient synonym for SetChecked( false ). + */ + void Uncheck() + { + SetChecked( false ); + } + + /*! + * Returns true iff this %SectionBar object is enabled. + * + * \sa Enable() + */ + virtual bool IsEnabled() const + { + return Title_Label.IsEnabled(); + } + + /*! + * Enables (or disables) this %SectionBar object. + * + * When a SectionBar object is disabled, its section control is also + * disabled, and in case it has a title checkbox, it is also disabled. + * However, the collapse/extend functionality of SectionBar is unaffected by + * its enabled/disabled state. + * + * \sa IsEnabled() + */ + virtual void Enable( bool enabled = true ); + + /*! + * Shows or hides the section control managed by this %SectionBar. + * + * In general, this function should be used instead of simply calling + * Control::SetVisible() (or Control::Show()/Control::Hide()). This function + * ensures that the parent control (typically a process interface) + * regenerates its layout correctly after changing visibility of the section + * control. + * + * \sa ShowSection(), HideSection() + */ + void SetSectionVisible( bool visible = true ); + + /*! + * A convenient synonym for SetSectionVisible( true ). + */ + void ShowSection() + { + SetSectionVisible( true ); + } + + /*! + * A convenient synonym for SetSectionVisible( false ). + */ + void HideSection() + { + SetSectionVisible( false ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnToggleSection( SectionBar& sender, Control& section, bool start ); + + /*! + * \defgroup section_bar_event_handlers SectionBar Event Handlers + */ + + /*! + * Defines the prototype of a section event handler. + * + * A section event is generated when the user clicks on this section bar to + * collapse or extend the managed section control. + * + * For each section event, two \e subevents are generated: one \e before the + * collapse/extend operation, and a second one once the operation has been + * completed. + * + * \param sender The control that sends a section event. + * + * \param section The section control that has been collapsed or extended. + * + * \param start True if this is a first subevent that is being sent before + * the collapse/extend operation; false if it is a second + * subevent, sent after having completed the operation. + * + * \ingroup section_bar_event_handlers + */ + typedef void (Control::*section_event_handler)( SectionBar& sender, Control& section, bool start ); + + /*! + * Sets the section event handler for this %SectionBar control. + * + * \param handler The section event handler. Must be a member function of + * the receiver object's class. + * + * \param receiver The control that will receive section events from this + * %SectionBar. + * + * \ingroup section_bar_event_handlers + */ + void OnToggleSection( section_event_handler handler, Control& receiver ); + + /*! + * Defines the prototype of a check event handler + * + * A check event is generated when the user toggles the state of the check + * box in a checkable section bar, either by clicking it with the mouse, or + * by focusing it and pressing the space bar key. + * + * \param sender The control that sends a check event. + * + * \param checked True if the check box is now checked in the sender section + * bar. False if the check box is currently unchecked. + * + * \ingroup section_bar_event_handlers + */ + typedef void (Control::*check_event_handler)( SectionBar& sender, bool checked ); + + /*! + * Sets the check event handler for this %SectionBar control. + * + * \param handler The check event handler. Must be a member function of + * the receiver object's class. + * + * \param receiver The control that will receive check events from this + * %SectionBar. + * + * \ingroup section_bar_event_handlers + */ + void OnCheck( check_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + section_event_handler onToggleSection = nullptr; + Control* onToggleSectionReceiver = nullptr; + + check_event_handler onCheck = nullptr; + Control* onCheckReceiver = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + Control* m_section = nullptr; + + VerticalSizer Global_Sizer; + HorizontalSizer Title_Sizer; + Label Title_Label; + AutoPointer Title_CheckBox; // non-null for a checkable SectionBar + ToolButton Title_ToolButton; + + void ButtonClick( Button&, bool ); + void MousePress( Control&, const pcl::Point&, int, unsigned, unsigned ); + void ControlShow( Control& ); + void ControlHide( Control& ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SectionBar_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SectionBar.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Selection.h b/3rdparty/include/pcl/Selection.h new file mode 100644 index 0000000..c8749c8 --- /dev/null +++ b/3rdparty/include/pcl/Selection.h @@ -0,0 +1,250 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Selection.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_Selection_h +#define __PCL_Selection_h + +/// \file pcl/Selection.h + +#include + +#include +#include + +// Template formal parameters: +// +// FI Forward iterator +// BI Bidirectional iterator +// RI Random access iterator +// UP Unary predicate +// BP Binary predicate +// T Item type +// F Function + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup selection_algorithms Selection Algorithms + */ + +// ---------------------------------------------------------------------------- + +template inline +RI __pcl_quick_select__( RI i, RI j, distance_type k, T* ) +{ + distance_type n = j - i; + if ( k < 0 || n < 1 || n <= k ) + return j; + + for ( distance_type l = 0, r = n-1; ; ) + { + RI x0 = i + l; + RI y = i + r; + + if ( r <= l+1 ) + { + if ( r == l+1 && *y < *x0 ) + Swap( *x0, *y ); + return i + k; + } + + RI x = x0; + + Swap( *++x, *(i + ((l+r) >> 1)) ); + + if ( *y < *x0 ) + Swap( *x0, *y ); + if ( *y < *x ) + Swap( *x, *y ); + if ( *x < *x0 ) + Swap( *x, *x0 ); + + T v = *x; + + for ( ;; ) + { + while ( *++x < v ); + while ( v < *--y ); + if ( y < x ) + break; + Swap( *x, *y ); + } + + *(x0+1) = *y; + *y = v; + + distance_type dy = y - i; + if ( dy >= k ) + r = dy - 1; + if ( dy <= k ) + l = x - i; + } +} + +/*! + * Generic quick selection algorithm. + * + * Given a range defined by two random access iterators [i,j) and a distance k, + * such that j-i > k, returns an iterator t whose associated value is the k-th + * element in the sorted sequence [i,j) in ascending order. + * + * For example, the following call: + * + * \code t = Select( i, j, (j - i) >> 1 ); \endcode + * + * will return the \e median of the distribution of elements in the [i,j) + * sequence: the central value for which the probabilities that a greater and a + * lesser element exist are equal. + * + * \b References + * + * \li William H. Press et al., Numerical Recipes 3rd Edition: The Art of + * Scientific Computing, Cambridge University Press, 2007, Section 8.5. + * + * \li Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, + * Addison-Wesley Professional, 2011, pp. 345-347. + * + * \warning This function performs a destructive selection search: + * There is no guarantee that the existing order of elements in the [i,j) + * sequence is preserved after calling this function. + * + * \ingroup selection_algorithms + */ +template inline +RI Select( RI i, RI j, distance_type k ) +{ + return __pcl_quick_select__( i, j, k, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +RI __pcl_quick_select__( RI i, RI j, distance_type k, BP p, T* ) +{ + distance_type n = j - i; + if ( k < 0 || n < 1 || n <= k ) + return j; + + for ( distance_type l = 0, r = n-1; ; ) + { + RI x0 = i + l; + RI y = i + r; + + if ( r <= l+1 ) + { + if ( r == l+1 && p( *y, *x0 ) ) + Swap( *x0, *y ); + return i + k; + } + + RI x = x0; + + Swap( *++x, *(i + ((l+r) >> 1)) ); + + if ( p( *y, *x0 ) ) + Swap( *x0, *y ); + if ( p( *y, *x ) ) + Swap( *x, *y ); + if ( p( *x, *x0 ) ) + Swap( *x, *x0 ); + + T v = *x; + + for ( ;; ) + { + while ( p( *++x, v ) ); + while ( p( v, *--y ) ); + if ( y < x ) + break; + Swap( *x, *y ); + } + + *(x0+1) = *y; + *y = v; + + distance_type dy = y - i; + if ( dy >= k ) + r = dy - 1; + if ( dy <= k ) + l = x - i; + } +} + +/*! + * Generic quick selection algorithm. + * + * Given a range defined by two random access iterators [i,j) and a distance k, + * such that j-i > k, returns an iterator t whose associated value is the k-th + * element in the sorted sequence [i,j) in ascending order. Element comparison + * is given by a binary predicate \a p such that p( a, b ) is true for any pair + * a, b of elements such that a precedes b. + * + * See Select( RI, RI, distance_type ) for more information. + * + * \ingroup selection_algorithms + */ +template inline +RI Select( RI i, RI j, distance_type k, BP p ) +{ + return __pcl_quick_select__( i, j, k, p, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Selection_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Selection.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SeparableConvolution.h b/3rdparty/include/pcl/SeparableConvolution.h new file mode 100644 index 0000000..2d5ddc9 --- /dev/null +++ b/3rdparty/include/pcl/SeparableConvolution.h @@ -0,0 +1,488 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SeparableConvolution.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_SeparableConvolution_h +#define __PCL_SeparableConvolution_h + +/// \file pcl/SeparableConvolution.h + +#include +#include + +#include +#include +#include +#include + +#define __PCL_SEPARABLE_CONVOLUTION_TINY_WEIGHT 1.0e-20 + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SeparableConvolution + * \brief Discrete two-dimensional separable convolution in the spatial domain + * + * %SeparableConvolution implements a fully multithreaded, two-dimensional + * discrete separable convolution algorithm. It performs automatic fixing of + * border artifacts by applying Neumann boundary conditions (mirroring). + * + * \sa Convolution, FFTConvolution, SeparableFilter + */ +class PCL_CLASS SeparableConvolution : public InterlacedTransformation, + public ParallelProcess +{ +public: + + /*! + * Represents a filter coefficient. + */ + typedef SeparableFilter::coefficient coefficient; + + /*! + * Represents a one-dimensional filter. + */ + typedef SeparableFilter::coefficient_vector coefficient_vector; + + /*! + * Default constructor. + * + * \note This constructor yields an uninitialized instance that cannot be + * used before explicit association with a SeparableFilter instance. + */ + SeparableConvolution() = default; + + /*! + * Constructs a %SeparableConvolution object with the specified filter. + * + * \param filter Response function, or convolution filter. The + * specified object does not have to remain valid while this + * instance is actively used, since %SeparableConvolution + * owns a private copy of the separable filter (note that + * SeparableFilter is a reference-counted class). + */ + SeparableConvolution( const SeparableFilter& filter ) + { + SetFilter( filter ); + } + + /*! + * Copy constructor. + */ + SeparableConvolution( const SeparableConvolution& x ) + : InterlacedTransformation( x ) + , ParallelProcess( x ) + , m_weight( x.m_weight ) + , m_highPass( x.m_highPass ) + , m_rawHighPass( x.m_rawHighPass ) + , m_rescaleHighPass( x.m_rescaleHighPass ) + , m_convolveRows( x.m_convolveRows ) + , m_convolveCols( x.m_convolveCols ) + { + if ( !x.m_filter.IsNull() ) + m_filter = x.m_filter->Clone(); + } + + /*! + * Move constructor. + */ + SeparableConvolution( SeparableConvolution&& ) = default; + + /*! + * Destroys this %SeparableConvolution object. + */ + virtual ~SeparableConvolution() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SeparableConvolution& operator =( const SeparableConvolution& x ) + { + if ( &x != this ) + { + (void)InterlacedTransformation::operator =( x ); + (void)ParallelProcess::operator =( x ); + if ( x.m_filter.IsNull() ) + m_filter.Destroy(); + else + m_filter = x.m_filter->Clone(); + m_weight = x.m_weight; + m_highPass = x.m_highPass; + m_rawHighPass = x.m_rawHighPass; + m_rescaleHighPass = x.m_rescaleHighPass; + m_convolveRows = x.m_convolveRows; + m_convolveCols = x.m_convolveCols; + } + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SeparableConvolution& operator =( SeparableConvolution&& ) = default; + + /*! + * Returns a constant reference to the separable filter currently associated + * with this %SeparableConvolution object. + * + * \note If this object has not been initialized, this member function + * throws an Error exception. + */ + const SeparableFilter& Filter() const + { + PCL_PRECONDITION( !m_filter.IsNull() ) + return *m_filter; + } + + /*! + * Returns a copy of the internal vector of filter coefficients + * corresponding to the specified \a phase. If \a phase is zero, the + * one-dimensional row filter is returned; otherwise the one-dimensional + * column filter is returned. + * + * \note If this object has not been initialized, this member function + * throws an Error exception. + */ + coefficient_vector Filter( int phase ) const + { + PCL_PRECONDITION( !m_filter.IsNull() ) + return m_filter->Filter( phase ); + } + + /*! + * Sets a new filter to be applied by this %SeparableConvolution object. + */ + void SetFilter( const SeparableFilter& filter ) + { + m_filter = filter.Clone(); + CacheFilterProperties(); + } + + /*! + * Returns the current filter weight. The filter weight is computed each + * time a separable filter is associated with this object. It is only + * applied for low-pass filters as a normalization factor. For more + * information, see the documentation for SeparableFilter::Weight(). + * + * The filter weight and other filter properties are cached in private data + * members for quick reference. + */ + double FilterWeight() const + { + return m_weight; + } + + /*! + * Returns true if the separable filter currently associated with this + * %SeparableConvolution object is a high-pass filter; false if it is a + * low-pass filter. For more information, see the documentation for + * SeparableFilter::IsHighPassFilter(). + * + * Each time a separable filter is associated with this object, its + * high-pass nature is checked and stored, along with other filter + * properties, in private data members. This allows for quick lookup of + * critical filter characteristics without degrading performance. + */ + bool IsHighPassFilter() const + { + return m_highPass; + } + + /*! + * Returns true iff out-of-range values will be rescaled for normalization of + * images after convolution with a high-pass filter. + * + * A high-pass filter has negative coefficients. As a result, some pixels in + * the convolved image may have negative values. Saturated pixels (values + * above one) can also result, depending on the filter coefficients. The + * standard behavior is to truncate out-of-range pixel values to the [0,1] + * range, which preserves the dynamics of the convolved image, so high-pass + * rescaling is disabled by default. When high-pass rescaling is enabled, + * the resulting image is \e normalized (that is, rescaled to [0,1] only if + * there are out-of-range values) and hence all the data after convolution + * are preserved at the cost of reducing the overall contrast of the image. + * Finally, if raw high-pass convolution has been enabled, + * out-of-range values are neither truncated nor rescaled irrespective of + * the value returned by this function. See the documentation for + * IsRawHighPassEnabled() for more information. + */ + bool IsHighPassRescalingEnabled() const + { + return m_rescaleHighPass; + } + + /*! + * Enables (or disables) high-pass rescaling of out-of-range convolved pixel + * values. See the documentation for IsHighPassRescalingEnabled() for more + * information. + */ + void EnableHighPassRescaling( bool enable = true ) + { + m_rescaleHighPass = enable; + } + + /*! + * Disables (or enables) high-pass rescaling of out-of-range convolved pixel + * values. See the documentation for IsHighPassRescalingEnabled() for more + * information. + */ + void DisableHighPassRescaling( bool disable = true ) + { + EnableHighPassRescaling( !disable ); + } + + /*! + * Returns true iff raw high-pass convolution is enabled. When raw + * high-pass convolution is enabled, out-of-range values after convolution + * with a high-pass filter are neither truncated nor normalized. Note that + * this is only relevant to convolution of floating point data. + * + * Raw high-pass convolution is disabled by default. For more information on + * out-of-range convolution results, refer to the documentation for + * IsHighPassRescalingEnabled(). + */ + bool IsRawHighPassEnabled() const + { + return m_rawHighPass; + } + + /*! + * Enables (or disables) raw high-pass convolution. See the documentation + * for IsRawHighPassEnabled() for more information. + */ + void EnableRawHighPass( bool enable = true ) + { + m_rawHighPass = enable; + } + + /*! + * Disables (or enables) raw high-pass convolution. See the documentation + * for IsRawHighPassEnabled() for more information. + */ + void DisableRawHighPass( bool disable = true ) + { + EnableRawHighPass( !disable ); + } + + /*! + * Returns true iff this object will convolve pixel rows on target images. + */ + bool IsRowConvolutionEnabled() const + { + return m_convolveRows; + } + + /*! + * Enables (or disables) convolution of pixel rows. + */ + void EnableRowConvolution( bool enable = true ) + { + m_convolveRows = enable; + } + + /*! + * Disables (or enables) convolution of pixel rows. + * + * This is a convenience function, equivalent to: + * EnableRowConvolution( !disable ) + */ + void DisableRowConvolution( bool disable = true ) + { + EnableRowConvolution( !disable ); + } + + /*! + * Returns true iff this object will convolve pixel columns on target images. + */ + bool IsColumnConvolutionEnabled() const + { + return m_convolveCols; + } + + /*! + * Enables (or disables) convolution of pixel columns. + */ + void EnableColumnConvolution( bool enable = true ) + { + m_convolveCols = enable; + } + + /*! + * Disables (or enables) convolution of pixel columns. + * + * This is a convenience function, equivalent to: + * EnableColumnConvolution( !disable ) + */ + void DisableColumnConvolution( bool disable = true ) + { + EnableColumnConvolution( !disable ); + } + + /*! + * Returns the length in pixels of the overlapping regions between adjacent + * areas processed by parallel execution threads. The overlapping distance + * is a function of the filter size and the interlacing distance. + */ + int OverlappingDistance() const + { + PCL_PRECONDITION( !m_filter.IsNull() ) + return m_filter->Size() + (m_filter->Size() - 1)*(InterlacingDistance() - 1); + } + + /*! + * Returns the minimum filter size in pixels for which separable convolution + * is consistently faster than nonseparable convolution on the current + * PixInsight/PCL platform, for the specified number of parallel execution + * threads. + * + * The values returned by this function have been determined experimentally + * on reference hardware for optimized execution on machines and builds with + * and without AVX2/FMA3 processor instruction support. + * + * \ingroup convolution_speed_limits + */ + static constexpr int FasterThanNonseparableFilterSize( int numThreads ) + { +#ifdef __PCL_COMPATIBILITY + + // No vectorization + + if ( numThreads >= 32 ) + return 15; + if ( numThreads >= 16 ) + return 11; + if ( numThreads >= 8 ) + return 9; + if ( numThreads >= 4 ) + return 7; + return 5; + +#else + + // Vectorization with SSE4.2 / AVX2 and FMA instructions + + if ( numThreads >= 32 ) + return 29; + if ( numThreads >= 28 ) + return 25; + if ( numThreads >= 24 ) + return 21; + if ( numThreads >= 16 ) + return 19; + if ( numThreads >= 8 ) + return 13; + if ( numThreads >= 4 ) + return 11; + if ( numThreads >= 2 ) + return 9; + return 7; + +#endif + } + +protected: + + /* + * The response function for convolution is a separable filter. + */ + AutoPointer m_filter; + + /* + * Cached filter properties. + */ + double m_weight = 0; // filter weight for low-pass normalization + bool m_highPass = false; // true iff this is a high-pass filter + + /* + * User-selectable options. + */ + bool m_rawHighPass = false; // neither truncate nor normalize out-of-range values + bool m_rescaleHighPass = false; // truncate out-of-range values instead of normalize + bool m_convolveRows = true; // perform one-dimensional convolution of pixel rows + bool m_convolveCols = true; // perform one-dimensional convolution of pixel columns + + /* + * In-place 2-D separable convolution algorithm. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; + +private: + + void CacheFilterProperties() + { + PCL_PRECONDITION( !m_filter.IsNull() ) + PCL_PRECONDITION( !m_filter->IsEmpty() ) + ValidateFilter(); + m_highPass = m_filter->IsHighPassFilter(); + m_weight = m_filter->Weight(); + if ( pcl::Abs( m_weight ) < __PCL_SEPARABLE_CONVOLUTION_TINY_WEIGHT ) + m_weight = 1; + } + + void ValidateFilter() const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SeparableConvolution_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SeparableConvolution.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SeparableFilter.h b/3rdparty/include/pcl/SeparableFilter.h new file mode 100644 index 0000000..3f7a70c --- /dev/null +++ b/3rdparty/include/pcl/SeparableFilter.h @@ -0,0 +1,399 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SeparableFilter.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_SeparableFilter_h +#define __PCL_SeparableFilter_h + +/// \file pcl/SeparableFilter.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SeparableFilter + * \brief Separable filter in two dimensions. + * + * %SeparableFilter stores two one-dimensional filter vectors of floating point + * filter coefficients, plus an optional filter name. This class provides + * automatic allocation and deallocation of coefficients, implicit data sharing, + * thread-safe access and a number of utility functions for filter management. + * + * In the same way as the KernelFilter and Convolution PCL classes, + * %SeparableFilter can be used with the SeparableConvolution class. In, + * addition, ATrousWaveletTransform also accepts a %SeparableFilter as the + * implementation of a wavelet scaling function. + * + * The SeparableConvolution PCL class uses separable filters to implement a + * separable convolution algorithm. This allows for important performance + * improvements, since separable convolution has O(N*n) complexity, as opposed + * to O(N*n^2) for non-separable convolution. + * + * \sa SeparableConvolution, ATrousWaveletTransform, KernelFilter + */ +class PCL_CLASS SeparableFilter +{ +public: + + /*! + * Represents a filter coefficient. + */ + typedef float coefficient; + + /*! + * Represents a one-dimensional filter. + */ + typedef GenericVector coefficient_vector; + + /*! + * Represents a two-dimensional filter matrix. + */ + typedef GenericMatrix coefficient_matrix; + + /*! + * Constructs an empty %SeparableFilter object with optional \a name. + */ + SeparableFilter( const String& name = String() ) + : filterName( name ) + { + } + + /*! + * Constructs a %SeparableFilter object with the specified size \a n and + * optional \a name. Filter elements are not initialized, so they will + * contain unpredictable values. + * + * A %SeparableFilter object must be initialized with either a zero size + * (which yields an empty filter), or an odd size >= 3. + */ + SeparableFilter( int n, const String& name = String() ) + : rowFilter( PCL_VALID_KERNEL_SIZE( n ) ) + , colFilter( PCL_VALID_KERNEL_SIZE( n ) ) + , filterName( name ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + } + + /*! + * Constructs a %SeparableFilter object with the specified size \a n, initial + * element value \a x, and optional \a name. + * + * This constructor yields a separable filter corresponding to a box average + * two-dimentional filter whose weight is \a x. + */ + template + SeparableFilter( int n, const T& x, const String& name = String() ) + : rowFilter( x, PCL_VALID_KERNEL_SIZE( n ) ) + , colFilter( x, PCL_VALID_KERNEL_SIZE( n ) ) + , filterName( name ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + } + + /*! + * Constructs a %SeparableFilter object with the specified one-dimensional + * row and column filter vectors \a h and \a v, respectively, and an + * optional \a name. + */ + SeparableFilter( const coefficient_vector& h, const coefficient_vector& v, const String& name = String() ) + : rowFilter( h ) + , colFilter( v ) + , filterName( name ) + { + PCL_PRECONDITION( v.Length() == h.Length() ) + PCL_PRECONDITION( v.IsEmpty() || v.Length() >= 3 ) + PCL_PRECONDITION( v.IsEmpty() || (v.Length() & 1) ) + } + + /*! + * Constructs a %SeparableFilter object with the specified size \a n and + * optional \a name. Copies \a n filter coefficients from the specified + * static arrays \a h and \a v to the one-dimensional row and column filter + * vectors in this object, respectively. + */ + template + SeparableFilter( const T* h, const T* v, int n, const String& name = String() ) + : rowFilter( h, PCL_VALID_KERNEL_SIZE( n ) ) + , colFilter( v, PCL_VALID_KERNEL_SIZE( n ) ) + , filterName( name ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + } + + /*! + * Copy constructor. + */ + SeparableFilter( const SeparableFilter& ) = default; + + /*! + * Move constructor. + */ + SeparableFilter( SeparableFilter&& ) = default; + + /*! + * Destroys a %SeparableFilter object. + */ + virtual ~SeparableFilter() + { + } + + /*! + * Returns a pointer to a dynamically allocated duplicate of this separable + * filter. + * + * \note All derived classes from %SeparableFilter must reimplement this + * virtual member function. + */ + virtual SeparableFilter* Clone() const + { + return new SeparableFilter( *this ); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SeparableFilter& operator =( const SeparableFilter& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SeparableFilter& operator =( SeparableFilter&& ) = default; + + /*! + * Assigns the specified scalar \a x to all filter coefficients. Returns a + * reference to this object. + */ + SeparableFilter& operator =( const coefficient& x ) + { + rowFilter = x; + colFilter = x; + return *this; + } + + /*! + * Returns true iff this %SeparableFilter object is equal to another instance + * \a f. Two %SeparableFilter instances are equal if their name and filter + * coefficients are equal. + */ + bool operator ==( const SeparableFilter& f ) const + { + return Name() == f.Name() && SameCoefficients( f ); + } + + /*! + * Returns the name of this %SeparableFilter object. + */ + String Name() const + { + return filterName; + } + + /*! + * Sets the name of this %SeparableFilter object. + */ + virtual void Rename( const String& newName ) + { + filterName = newName.Trimmed(); + } + + /*! + * Returns the size of this separable filter. The filter size is the length + * of the one-dimensional row and column filter vectors. + */ + int Size() const + { + return rowFilter.Length(); // both 1D filters have the same length + } + + /*! + * Sets the size of this separable filter. Previous filter contents are + * lost; the internal filter coefficient vectors will contain unpredictable + * values after calling this function. + */ + virtual void Resize( int n ) + { + PCL_PRECONDITION( n == 0 || n >= 3 ) + PCL_PRECONDITION( n == 0 || (n & 1) ) + if ( n == 0 ) + colFilter = rowFilter = coefficient_vector(); + else + colFilter = rowFilter = coefficient_vector( PCL_VALID_KERNEL_SIZE( n ) ); + } + + /*! + * Returns true iff this is an empy filter, i.e. if it has no coefficients. + */ + bool IsEmpty() const + { + return rowFilter.IsEmpty(); // both 1D filters have the same length + } + + /*! + * Returns a copy of the internal one-dimensional row filter vector. + */ + coefficient_vector RowFilter() const + { + return rowFilter; + } + + /*! + * Returns a copy of the internal one-dimensional column filter vector. + */ + coefficient_vector ColumnFilter() const + { + return colFilter; + } + + /*! + * This member function is an alias to ColumnFilter(). + */ + coefficient_vector ColFilter() const + { + return colFilter; + } + + /*! + * Returns a copy of the internal one-dimensional filter vector + * corresponding to the specified \a phase. If \a phase is zero, the row + * filter vector is returned; otherwise the column filter vector is returned. + */ + coefficient_vector Filter( int phase ) const + { + return phase ? colFilter : rowFilter; + } + + /*! + * Returns the weight of this separable filter. The weight is equal to the + * product of the sums of components in the row and column filter vectors. + */ + double Weight() const + { + return rowFilter.Sum() * colFilter.Sum(); + } + + /*! + * Returns true if this is a high-pass separable filter; false if this is a + * low-pass separable filter. + * + * A high-pass kernel filter has one or more negative coefficients. A + * low-pass kernel filter is either empty or all of its coefficients are + * positive or zero. For separable low-pass filters, all the nonzero + * coefficients in both the row and column filter vectors have the same + * sign. If this condition doesn't hold (i.e. if coefficient signs differ) + * then the object is a high-pass filter. + */ + bool IsHighPassFilter() const + { + int s = -1; + for ( coefficient_vector::const_iterator i = rowFilter.Begin(); i < rowFilter.End(); ++i ) + if ( *i != 0 ) + for ( s = *i < 0; ++i < rowFilter.End(); ) + if ( *i != 0 && (*i < 0) != s ) + return true; + for ( coefficient_vector::const_iterator i = colFilter.Begin(); i < colFilter.End(); ++i ) + if ( *i != 0 ) + for ( s = (s < 0) ? *i++ < 0 : s; i < colFilter.End(); ++i ) + if ( *i != 0 && (*i < 0) != s ) + return true; + return false; + } + + /*! + * Returns true iff this %SeparableFilter object has the same filter + * coefficients as another instance \a f. + */ + bool SameCoefficients( const SeparableFilter& f ) const + { + return colFilter == f.colFilter && rowFilter == f.rowFilter; + } + + /*! + * Deallocates filter coefficients and yields an empy %SeparableFilter + * object. This member function does not change the current filter name. + */ + virtual void Clear() + { + colFilter = rowFilter = coefficient_vector(); + } + +protected: + + /* + * Horizontal and vertical one-dimensional filters. The 2D filter matrix is + * equal to the product of these two vectors. + */ + coefficient_vector rowFilter; + coefficient_vector colFilter; + + /* + * Identifying name. + */ + String filterName; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SeparableFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SeparableFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SeparableMedianFilter.h b/3rdparty/include/pcl/SeparableMedianFilter.h new file mode 100644 index 0000000..f64388c --- /dev/null +++ b/3rdparty/include/pcl/SeparableMedianFilter.h @@ -0,0 +1,143 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SeparableMedianFilter.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_SeparableMedianFilter_h +#define __PCL_SeparableMedianFilter_h + +/// \file pcl/SeparableMedianFilter.h + +#include +#include + +#include +#include // PCL_VALID_KERNEL_SIZE() +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SeparableMedianFilter + * \brief A two-dimensional separable filter that approximates a median filter. + * + * ### TODO: Write a detailed description for %SeparableMedianFilter. + */ +class PCL_CLASS SeparableMedianFilter : public ImageTransformation, + public ParallelProcess +{ +public: + + /*! + * Constructs a %SeparableMedianFilter object with the specified size. + * + * \param size Size of the separable median filter in pixels. Must be an + * odd integer >= 3 (3, 5, 7, ...). + */ + SeparableMedianFilter( int size = 3 ) + : m_size( PCL_VALID_KERNEL_SIZE( size ) ) + { + PCL_PRECONDITION( size >= 3 && size&1 == 1 ) + } + + /*! + * Copy constructor. + */ + SeparableMedianFilter( const SeparableMedianFilter& ) = default; + + /*! + * Destroys this %SeparableMedianFilter object. + */ + virtual ~SeparableMedianFilter() + { + } + + /*! + * Returns the current size in pixels of this separable median filter. + */ + int Size() const + { + return m_size; + } + + /*! + * Sets a new \a size in pixels for this separable median filter object. The + * specified size must be an odd integer > 3 (3, 5, 7, ...). + */ + void SetSize( int size ) + { + PCL_PRECONDITION( size >= 3 && size&1 == 1 ) + m_size = PCL_VALID_KERNEL_SIZE( size ); + } + +protected: + + int m_size; // filter size + + /* + * In-place 2-D separable median approximation filter. + */ + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SeparableMedianFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SeparableMedianFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Settings.h b/3rdparty/include/pcl/Settings.h new file mode 100644 index 0000000..1406168 --- /dev/null +++ b/3rdparty/include/pcl/Settings.h @@ -0,0 +1,896 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Settings.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_Settings_h +#define __PCL_Settings_h + +/// \file pcl/Settings.h + +#include +#include + +#include +#include + +#ifndef __PCL_NO_FLAGS_SETTINGS_IO +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Settings + * \brief Persistent module settings. + * + * %Settings implements an interface to store and manage module settings that + * can persist across sessions. %Settings makes it possible for a module to + * \e remember its own private data, as specific user preferences and other + * operating parameters. %Settings data items are stored and retrieved as + * \e key/value pairs. + * + * %Module settings can be accessed in two \e spaces. One is the local + * settings space, which is used by a module to read and write its own + * private settings data, or settings \e keys that have been created by the + * module. %Module settings can also be accessed from the global module + * settings space, which refers to settings data created by other modules. + * Thanks to the global module settings space, processes and file formats can + * share their working settings publicly on the whole PixInsight platform. For + * example, a module can learn the current orientation of FITS images by + * reading the value of the \e /FITS/FITSBottomUp key, which is maintained by + * the standard FITS support module. + * + * %Settings provides a high-level, platform-independent mechanism for settings + * management. The PixInsight core application carries out all the necessary + * platform-specific work to store and retrieve module settings data behind the + * scenes. + * + * This class must not be confused with PixInsightSettings, which provides + * access to \e global settings pertaining to the whole PixInsight platform. + * %Settings manages private module settings exclusively. Private module + * settings cannot be retrieved through %PixInsightSettings. + * + * \sa PixInsightSettings + */ +class PCL_CLASS Settings +{ +public: + + /*! + * Default constructor. This constructor is disabled because %Settings is + * not an instantiable class. + */ + Settings() = delete; + + /*! + * Copy constructor. This constructor is disabled because %Settings is not + * an instantiable class. + */ + Settings( const Settings& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %Settings is not an + * instantiable class. + */ + Settings& operator =( const Settings& ) = delete; + + /*! + * Destructor. This destructor is disabled because %Settings is not an + * instantiable class. + */ + ~Settings() = delete; + + /*! + * Reads a sequence of bytes from the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param[out] b Reference to a ByteArray object where existing data will + * be stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to a + * sequence of bytes, in which case the existing data are read and stored in + * the \a b array. Otherwise this function returns false and the previous + * contents of the \a b array are not modified. + */ + static bool Read( const IsoString& key, ByteArray& b ); + + /*! + * Reads a sequence of bytes from the global module settings space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] b Reference to a ByteArray object where existing data will + * be stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to a sequence of bytes, in which case the + * existing data are read and stored in the \a b array. Otherwise this + * function returns false and the previous contents of the \a b array are + * not modified. + */ + static bool ReadGlobal( const IsoString& key, ByteArray& b ); + + /*! + * Reads a Unicode string (UTF-16) from the local settings space of + * the current module. + * + * \param key A settings key for the current module. + * + * \param[out] s Reference to a String object where existing data will be + * stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to a + * Unicode string, in which case the existing data are read and stored in + * the \a s string. Otherwise this function returns false and the previous + * contents of the \a s string are not modified. + */ + static bool Read( const IsoString& key, String& s ); + + /*! + * Reads a Unicode string (UTF-16) from the global module settings + * space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] s Reference to a String object where existing data will be + * stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to a Unicode string, in which case the + * existing data are read and stored in the \a s string. Otherwise this + * function returns false and the previous contents of the \a s string are + * not modified. + */ + static bool ReadGlobal( const IsoString& key, String& s ); + + /*! + * Reads a Boolean value from the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param[out] b Reference to a \c bool variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to + * the \c bool type, in which case the existing data are read and stored in + * the \a b variable. Otherwise this function returns false and the previous + * contents of the \a b variable are not modified. + */ + static bool Read( const IsoString& key, bool& b ); + + /*! + * Reads a Boolean value from the global module settings space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] b Reference to a \c bool variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to the \c bool type, in which case the + * existing data are read and stored in the \a b variable. Otherwise this + * function returns false and the previous contents of the \a b variable are + * not modified. + */ + static bool ReadGlobal( const IsoString& key, bool& b ); + + /*! + * Reads an integer value from the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param[out] i Reference to an \c int variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to + * the \c int type, in which case the existing data are read and stored in + * the \a i variable. Otherwise this function returns false and the previous + * contents of the \a i variable are not modified. + */ + static bool Read( const IsoString& key, int& i ); + + /*! + * Reads an integer value from the global module settings space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] i Reference to an \c int variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to the \c int type, in which case the existing + * data are read and stored in the \a i variable. Otherwise this function + * returns false and the previous contents of the \a i variable are not + * modified. + */ + static bool ReadGlobal( const IsoString& key, int& i ); + + /*! + * Reads an unsigned integer value from the local settings space of + * the current module. + * + * \param key A settings key for the current module. + * + * \param[out] u Reference to an \c unsigned \c int variable where the + * existing value will be stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to + * the \c unsigned type, in which case the existing data are read and stored + * in the \a u variable. Otherwise this function returns false and the + * previous contents of the \a u variable are not modified. + */ + static bool Read( const IsoString& key, unsigned& u ); + + /*! + * Reads an unsigned integer value from the global module settings + * space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] u Reference to an \c unsigned \c int variable where the + * existing value will be stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to the \c unsigned type, in which case the + * existing data are read and stored in the \a u variable. Otherwise this + * function returns false and the previous contents of the \a u variable are + * not modified. + */ + static bool ReadGlobal( const IsoString& key, unsigned& u ); + + /*! + * Reads a \c double value from the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param[out] f Reference to a \c double variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to + * the \c double type, in which case the existing data are read and stored + * in the \a f variable. Otherwise this function returns false and the + * previous contents of the \a f variable are not modified. + */ + static bool Read( const IsoString& key, double& f ); + + /*! + * Reads a \c double value from the global module settings space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] f Reference to a \c double variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to the \c double type, in which case the + * existing data are read and stored in the \a f variable. Otherwise this + * function returns false and the previous contents of the \a f variable are + * not modified. + */ + static bool ReadGlobal( const IsoString& key, double& f ); + + /*! + * Reads a \c float value from the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param[out] f Reference to a \c float variable where the existing value + * will be stored. + * + * This is an overloaded member function, provided for convenience. It + * behaves essentially like the Read( const IsoString&, double& ) member + * function. + */ + static bool Read( const IsoString& key, float& f ) + { + double d; Read( key, d ); + if ( LastReadOK() ) { f = float( d ); return true; } + return false; + } + + /*! + * Reads a \c float value from the global module settings space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] f Reference to a \c float variable where the existing value + * will be stored. + * + * This is an overloaded member function, provided for convenience. It + * behaves essentially like the ReadGlobal( const IsoString&, double& ) + * member function. + */ + static bool ReadGlobal( const IsoString& key, float& f ) + { + double d; ReadGlobal( key, d ); + if ( LastReadOK() ) { f = float( d ); return true; } + return false; + } + +#ifndef __PCL_NO_SETTINGS_TEMPLATES + + /*! + * A generalized function that reads a settings \a key as a \c signed + * \c int, converts that value to type T, and stores it in the specified + * variable \a t. + * + * Returns true iff the \a key exists and its value can be converted to + * \c int. If the function fails (if it returns false), the previous value + * of the \a t variable is not changed. + * + * This is a convenience template member function. It behaves essentially + * like the Read( const IsoString&, int& ) member function. + */ + template + static bool ReadI( const IsoString& key, T& t ) + { + int i; Read( key, i ); + if ( LastReadOK() ) { t = T( i ); return true; } + return false; + } + + + /*! + * A generalized function that reads a settings \a key as an \c unsigned + * \c int, converts that value to type T, and stores it in the specified + * variable \a t. + * + * Returns true iff the \a key exists and its value can be converted to + * \c unsigned \c int. If the function fails (if it returns false), the + * previous value of the \a t variable is not changed. + * + * This is a convenience template member function. It behaves essentially + * like the Read( const IsoString&, unsigned& ) member function. + */ + template + static bool ReadU( const IsoString& key, T& t ) + { + unsigned u; Read( key, u ); + if ( LastReadOK() ) { t = T( u ); return true; } + return false; + } + +#endif + +#ifndef __PCL_NO_FLAGS_SETTINGS_IO + + /*! + * Reads a Flags value from the local settings space of the current + * module. + * + * \param key A settings key for the current module. + * + * \param[out] f Reference to a Flags variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the local + * settings space of the current module and its value can be converted to + * the \c unsigned \c int type, in which case the existing data are read and + * stored in the \a f variable as a flags mask. Otherwise this + * function returns false and the previous contents of the \a f variable are + * not modified. + */ + template + static bool Read( const IsoString& key, Flags& f ) + { + return Read( key, f.m_flags ); + } + + /*! + * Reads a Flags value from the global module settings space. + * + * \param key A module settings key. Should include the name of a + * module, as in /ModuleName/KeyName. + * + * \param[out] f Reference to a Flags variable where the existing value + * will be stored. + * + * Returns true if the specified settings \a key exists in the global module + * settings space, it has not been read-protected by its owner module, and + * its value can be converted to the \c unsigned \c int type, in which case + * the existing data are read and stored in the \a f variable as a flags + * mask. Otherwise this function returns false and the previous + * contents of the \a f variable are not modified. + */ + template + static bool ReadGlobal( const IsoString& key, Flags& f ) + { + return ReadGlobal( key, f.m_flags ); + } + +#endif + + /*! + * Returns true iff the last call to a Read member function successfully + * read a settings key. + */ + static bool LastReadOK(); + + /*! + * Writes a sequence of bytes to the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param b Reference to a ByteArray object whose contents will be + * written as the value associated to \a key. + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a b. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Write( const IsoString& key, const ByteArray& b ); + + /*! + * Writes a sequence of bytes to the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param b Reference to a ByteArray object whose contents will be + * written as the value associated to \a key. + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a b. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void WriteGlobal( const IsoString& key, const ByteArray& b ); + + /*! + * Writes a Unicode string (UTF-16) to the local settings space of + * the current module. + * + * \param key A settings key for the current module. + * + * \param s Reference to a String object whose contents will be written + * as the value associated to \a key. + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a s. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Write( const IsoString& key, const String& s ); + + /*! + * Writes a Unicode string (UTF-16) to the global module settings + * space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param s Reference to a String object whose contents will be written + * as the value associated to \a key. + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a s. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void WriteGlobal( const IsoString& key, const String& s ); + + /*! + * Writes a Boolean value to the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param b A \c bool value that will be written as the value associated + * to \a key. + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a b. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Write( const IsoString& key, bool b ); + + /*! + * Writes a Boolean value to the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param b A \c bool value that will be written as the value associated + * to \a key. + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a b. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void WriteGlobal( const IsoString& key, bool b ); + + /*! + * Writes an integer value to the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param i An \c int value that will be written as the value associated + * to \a key. + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a i. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Write( const IsoString& key, int i ); + + /*! + * Writes an integer value to the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param i An \c int value that will be written as the value associated + * to \a key. + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a i. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void WriteGlobal( const IsoString& key, int i ); + + /*! + * Writes an unsigned integer value to the local settings space of + * the current module. + * + * \param key A settings key for the current module. + * + * \param u An \c unsigned \c int value that will be written as the value + * associated to \a key. + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a u. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Write( const IsoString& key, unsigned u ); + + /*! + * Writes an unsigned integer value to the global module settings + * space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param u An \c unsigned \c int value that will be written as the value + * associated to \a key. + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a u. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void WriteGlobal( const IsoString& key, unsigned u ); + + /*! + * Writes a \c double value to the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param f A \c double value that will be written as the value + * associated to \a key. + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a f. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Write( const IsoString& key, double f ); + + /*! + * Writes a \c double value to the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param f A \c double value that will be written as the value + * associated to \a key. + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a f. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void WriteGlobal( const IsoString& key, double f ); + + /*! + * Writes a \c float value to the local settings space of the + * current module. + * + * \param key A settings key for the current module. + * + * \param f A \c float value that will be written as the value associated + * to \a key. + * + * This is an overloaded member function, provided for convenience. It + * behaves essentially like the Write( const IsoString&, double ) member + * function. + */ + static void Write( const IsoString& key, float f ) + { + Write( key, double( f ) ); + } + + /*! + * Writes a \c float value to the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param f A \c float value that will be written as the value associated + * to \a key. + * + * This is an overloaded member function, provided for convenience. It + * behaves essentially like the WriteGlobal( const IsoString&, double ) + * member function. + */ + static void WriteGlobal( const IsoString& key, float f ) + { + WriteGlobal( key, double( f ) ); + } + +#ifndef __PCL_NO_SETTINGS_TEMPLATES + + /*! + * A generalized function that converts a value of type T to \c signed + * \c int and writes it to the specified settings \a key. + * + * This is a convenience template member function. It behaves essentially + * like the Write( const IsoString&, int ) member function. + */ + template + static void WriteI( const IsoString& key, T t ) + { + Write( key, int( t ) ); + } + + /*! + * A generalized function that converts a value of type T to \c unsigned + * \c int and writes it to the specified settings \a key. + * + * This is a convenience template member function. It behaves essentially + * like the Write( const IsoString&, unsigned ) member function. + */ + template + static void WriteU( const IsoString& key, T t ) + { + Write( key, unsigned( t ) ); + } + +#endif + +#ifndef __PCL_NO_FLAGS_SETTINGS_IO + + /*! + * Writes a Flags value to the local settings space of the current + * module. + * + * \param key A settings key for the current module. + * + * \param f A Flags value that will be written as the value associated to + * \a key (as an \c unsigned \c int value). + * + * If the specified settings \a key does not exist in the local settings + * space of the current module, it is newly created with the specified value + * \a f. If \a key already exists, its previous value is replaced. + * + * In the event of I/O error this member function throws an Error exception. + */ + template + static void Write( const IsoString& key, Flags f ) + { + Write( key, f.m_flags ); + } + + /*! + * Writes a Flags value to the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * \param f A Flags value that will be written as the value associated to + * \a key (as an \c unsigned \c int value). + * + * If the specified settings \a key does not exist in the global module + * settings space, it is newly created with the specified value \a f. If + * \a key already exists, its previous value is replaced. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + template + static void WriteGlobal( const IsoString& key, Flags f ) + { + WriteGlobal( key, f.m_flags ); + } + +#endif + + /*! + * Deletes the specified settings \a key from the local settings + * space of the current module. + * + * In the event of I/O error this member function throws an Error exception. + */ + static void Remove( const IsoString& key ); + + /*! + * Deletes a settings key from the global module settings space. + * + * \param key A module settings key. Should include the name of a module, + * as in /ModuleName/KeyName. + * + * In the event of I/O error, or if the specified \a key is write-protected, + * this member function throws an Error exception. + * + * \note By default, write access to module settings items is not allowed + * unless explicitly enabled through a call to SetGlobalKeyAccess(). + */ + static void RemoveGlobal( const IsoString& key ); + + /*! + * Returns true iff the specified \a key can be read from the global + * module settings space. + * + * By default, a module settings key can be freely read unless its owner + * module explicitly disables global reading by calling the + * SetGlobalKeyAccess() static member function. + */ + static bool CanReadGlobal( const IsoString& key ); + + /*! + * Returns true iff the specified \a key can be written from the global + * module settings space. + * + * By default, global write access to a module settings key is not allowed + * unless its owner module explicitly enables global writing by calling the + * SetGlobalKeyAccess() static member function. + */ + static bool CanWriteGlobal( const IsoString& key ); + + /*! + * Changes global access permissions for the specified settings \a key in + * the local settings space of the current module. + * + * \param key A settings key for the current module. + * + * \param allowRead Whether other modules can read the value of \a key. + * + * \param allowWrite Whether other modules can write the value of \a key + * and delete \a key. + * + * If this function is not called for a particular settings key, only read + * access is possible by default from the global module settings space. + */ + static void SetGlobalKeyAccess( const IsoString& key, bool allowRead, bool allowWrite ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Settings_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Settings.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SharedPixelData.h b/3rdparty/include/pcl/SharedPixelData.h new file mode 100644 index 0000000..90a52c1 --- /dev/null +++ b/3rdparty/include/pcl/SharedPixelData.h @@ -0,0 +1,249 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SharedPixelData.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_SharedPixelData_h +#define __PCL_SharedPixelData_h + +/// \file pcl/SharedPixelData.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SharedPixelData + * \brief Handles transparent, type-independent allocation of local and shared + * pixel data blocks. + * + * \internal This is a low-level class internally used by PCL classes and + * functions. It is not intended to be used directly by user-level modules. + * Unless you are a PixInsight core or PCL maintainer, you should not need or + * attempt to use or instantiate this class. + */ +class PCL_CLASS SharedPixelData +{ +public: + + typedef ColorSpace::value_type color_space; + + /*! + * Constructs a %SharedPixelData object that represents a local image. + */ + SharedPixelData() = default; + + /*! + * References an existing shared image with the specified handle and sample + * data type. + * + * \param handle Handle to a shared image. + * + * \param bitsPerSample Number of bits per pixel sample. + * + * \param floatSample Whether this image stores floating point pixel + * data, or integer pixel data. + * + * \param complexSample Whether this image stores complex pixel data or + * real pixel data. + * + * \note This constructor throws an Error exception if the specified handle + * does not correspond to an existing shared image, or if the existing + * shared image does not have the specified sample data type. + */ + SharedPixelData( void* handle, int bitsPerSample, bool floatSample, bool complexSample ); + + /*! + * Creates a new shared image with the specified geometry, sample data type + * and color space. + * + * \param width %Image width in pixels. + * + * \param height %Image height in pixels. + * + * \param numberOfChannels Number of channels, including nominal channels or + * color components and alpha channels. + * + * \param bitsPerSample Number of bits per pixel sample. + * + * \param floatSample Whether this image stores floating point pixel + * data, or integer pixel data. + * + * \param colorSpace Color space where pixels are represented. + */ + SharedPixelData( int width, int height, int numberOfChannels, + int bitsPerSample, bool floatSample, int colorSpace ); + + /*! + * Copy constructor. + * + * If the argument object \a x represents a shared image, this constructor + * references the same shared image. If \a x is a local image, this function + * just copies the null handle and has no further effect. + */ + SharedPixelData( const SharedPixelData& x ) + : m_handle( x.m_handle ) + { + Attach(); + } + + /*! + * Virtual destructor. + * + * If this object represents a shared image, it is dereferenced. If the + * shared image becomes unreferenced, it will be garbage-collected and + * eventually destroyed by the PixInsight core application. + * + * If this object represents a local image, this destructor has no effect. + */ + virtual ~SharedPixelData() + { + Detach(); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * If this object represents a shared image, it is dereferenced. If the + * specified object \a x represents a shared image, then this object will + * reference it; otherwhise this operator just copies the null handle + * without further effect. + */ + SharedPixelData& operator =( const SharedPixelData& x ) + { + if ( m_handle != x.m_handle ) + { + Detach(); + m_handle = x.m_handle; + Attach(); + } + return *this; + } + + /*! + * Returns true iff this object represents the same shared image as another + * object \a x, or if both objects represent local images. + */ + bool operator ==( const SharedPixelData& x ) const noexcept + { + return m_handle == x.m_handle; + } + + /*! + * Returns the handle to the shared image represented by this object, or + * zero (a null pointer) if this object represents a local image. + */ + void* Handle() const noexcept + { + return m_handle; + } + + /*! + * Returns true if this object represents a shared image; false if it + * represents a local image. Shared images live in the PixInsight core + * application. Local images live in the calling module. + */ + bool IsShared() const noexcept + { + return m_handle != nullptr; + } + + /*! + * Returns true iff the shared image represented by this object is not + * uniquely referenced, i.e. if there exist other %SharedPixelData objects + * representing the same shared image. Returns false if the shared image is + * only referenced by this object, or if this object represents a local + * image. + */ + bool IsAliased() const; + + /*! + * Returns true iff this object is the owner of the represented shared image. + * Returns false if this object does not own the shared image, or if this + * object does not represent a shared image. + */ + bool IsOwner() const; + +private: + + void* m_handle = nullptr; + + void Attach(); + void Detach(); + +protected: + + void* Allocate( size_type sizeInBytes ) const; + void Deallocate( void* ) const; + + void** GetSharedData() const; + void SetSharedData( void** ptrToShared ); + + void GetSharedGeometry( int& width, int& height, int& numberOfChannels ); + void SetSharedGeometry( int width, int height, int numberOfChannels ); + + void GetSharedColor( color_space& colorSpace, RGBColorSystem& RGBWS ); + void SetSharedColor( color_space colorSpace, const RGBColorSystem& RGBWS ); + + template friend class GenericImage; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SharedPixelData_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SharedPixelData.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ShepardInterpolation.h b/3rdparty/include/pcl/ShepardInterpolation.h new file mode 100644 index 0000000..e7f1cb3 --- /dev/null +++ b/3rdparty/include/pcl/ShepardInterpolation.h @@ -0,0 +1,842 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ShepardInterpolation.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_ShepardInterpolation_h +#define __PCL_ShepardInterpolation_h + +/// \file pcl/ShepardInterpolation.h + +#include +#include + +#include +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * Default normalized search radius for local Shepard interpolation. This is an + * initial search radius relative to the unit circle for the adaptive quadtree + * search algorithm. + */ +#define __PCL_SHEPARD_DEFAULT_SEARCH_RADIUS 0.10 + +/* + * Default power parameter for local Shepard interpolation. Larger values tend + * to yield more accurate interpolation devices. Small powers lead to more + * approximating (smoothing) devices. The chosen default value is intermediate. + */ +#define __PCL_SHEPARD_DEFAULT_POWER 4 + +/* + * Default regularization (smoothing) factor for local Shepard interpolation, + * in the range [0,1). This is a clipping fraction for Winsorization of nearby + * function values in the point interpolation routine. + */ +#define __PCL_SHEPARD_DEFAULT_REGULARIZATION 0 + +// ---------------------------------------------------------------------------- + +/*! + * \class ShepardInterpolation + * \brief Two-dimensional surface interpolation with the local Shepard method. + * + * %ShepardInterpolation implements the Shepard method of function + * interpolation/approximation for arbitrarily distributed input nodes in two + * dimensions. + * + * This class implements local Shepard interpolation with Franke-Little + * weights, quadtree structures for fast rectangular search of input nodes, + * optional regularization, and an adaptive local interpolation search routine. + * + * \b References + * + * Shepard, Donald (1968). A two-dimensional interpolation function for + * irregularly-spaced data. Proceedings of the 1968 ACM National + * Conference, pp. 517-524. + * + * Franke, Richard (1982). Scattered data interpolation: tests of some + * methods. Mathematics of Computation 38 (1982), pp. 181-200. + * + * Hanan Samet, Foundations of Multidimensional and Metric Data + * Structures, Morgan Kaufmann, 2006, Section 1.4. + * + * Mark de Berg et al, Computational Geometry: Algorithms and Applications + * Third Edition, Springer, 2010, Chapter 14. + * + * \sa SurfaceSpline, SurfacePolynomial, QuadTree + */ +template +class PCL_CLASS ShepardInterpolation +{ +public: + + /*! + * Represents a vector of coordinates or function values. + */ + typedef GenericVector vector_type; + + /*! + * The numeric type used to represent coordinates and function values. + */ + typedef typename vector_type::scalar scalar; + + /*! + * The class used to implement fast coordinate search operations. + */ + typedef QuadTree search_tree; + + /*! + * The class used to specify interpolation regions. + */ + typedef typename search_tree::rectangle search_rect; + + /*! + * The maximum number of interpolation points in a leaf quadtree node. + */ + constexpr static int BucketCapacity = 16; + + /*! + * Default constructor. Constructs an empty %ShepardInterpolation object. + */ + ShepardInterpolation() = default; + + /*! + * Copy constructor. Copy construction is disabled because this class uses + * internal data structures that cannot be copy-constructed. However, + * %ShepardInterpolation implements move construction and move assignment. + */ + ShepardInterpolation( const ShepardInterpolation& ) = delete; + + /*! + * Move constructor. + */ + ShepardInterpolation( ShepardInterpolation&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~ShepardInterpolation() + { + } + + /*! + * Copy assignment operator. Copy assignment is disabled because this class + * uses internal data structures that cannot be copy-assigned. However, + * %ShepardInterpolation implements move assignment and move construction. + */ + ShepardInterpolation& operator =( const ShepardInterpolation& ) = delete; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + ShepardInterpolation& operator =( ShepardInterpolation&& ) = default; + + /*! + * Returns true iff this object is valid. A valid %ShepardInterpolation + * object has been initialized with a sufficient number of input nodes. + */ + bool IsValid() const + { + return !m_T.IsEmpty(); + } + + /*! + * Sets the power parameter of the local Shepard interpolation. + * + * \param m Power parameter. Must be > 0. + * + * The power parameter is a positive real > 0 that defines the behavior of + * the interpolation/approximation function. For large values of \a m, the + * interpolating surface tends to be uniform within boundaries defined + * around input nodes, and hence is more local. For values of \a m ≤ 2, + * the surface is more global, that is, interpolated values are more + * influenced by nodes far away from the interpolation coordinates. The + * default power parameter value is 4. + * + * If an invalid value \a m ≤ 0 is specified, the default \a m = 4 power + * parameter value will be set. + * + * Calling this member function does not reset this %ShepardInterpolation + * object, since no internal structures built upon initialization depend on + * the power parameter. This facilitates the use of this class to compare + * the results of different power parameter values applied to the same data. + */ + void SetPower( int m ) + { + PCL_PRECONDITION( m > 0 ) + m_mu = (m > 0) ? m : __PCL_SHEPARD_DEFAULT_POWER; + } + + /*! + * Returns the current power parameter of this local Shepard interpolation. + * + * See SetPower() for more information. + */ + int Power() const + { + return m_mu; + } + + /*! + * Sets the normalized search radius of the local Shepard interpolation. + * + * \param R Search radius in the range (0,1]. + * + * The search radius defines a distance from the interpolation point where + * existing input nodes will be used to compute an interpolated function + * value. Larger values of \a R will construct more global interpolation + * surfaces, while smaller values will tend to yield more local + * interpolations. Smaller search radii will also lead to faster + * interpolation devices, since the computational complexity is reduced as + * the number of input nodes used for each interpolation point decreases. + * + * The search radius parameter is normalized to the (0,1] range in this + * implementation, where 1 represents the largest distance between two + * distinct input nodes, or equivalently, the size of the interpolation + * region. The default search radius is 0.1. + * + * If an invalid value \a R ≤ 0 is specified, the default \a R = 0.1 + * search radius parameter value will be set. + * + * Calling this member function does not reset this %ShepardInterpolation + * object, since no internal structures built upon initialization depend on + * the search radius. This facilitates the use of this class to compare the + * results of different search radius values applied to the same data. + */ + void SetRadius( double R ) + { + PCL_PRECONDITION( R > 0 ) + m_R = (R < 0 || 1 + R == 1) ? __PCL_SHEPARD_DEFAULT_SEARCH_RADIUS : R; + } + + /*! + * Returns the current normalized search radius of this local Shepard + * interpolation. See SetRadius() for more information. + */ + double Radius() const + { + return m_R; + } + + /*! + * Sets the smoothing factor of the local Shepard interpolation. + * + * \param r Smoothing factor in the range [0,1). + * + * For \a r > 0, a regularized local interpolation will be applied. The \a r + * argument represents a fraction of the count of nearby function samples + * that will be Winsorized, that is, replaced with their r-th nearest value + * at the top and the tail of the interpolation sample. + * + * For \a r = 0, a normal (unsmoothed) local Shepard interpolation scheme is + * used. This is the default state for newly created instances of + * %ShepardInterpolation. + * + * If an invalid value \a r < 0 or \a r ≥ 1 is specified, the default + * \a r = 0 smoothing factor will be set. + */ + void SetSmoothing( float r ) + { + PCL_PRECONDITION( r >= 0 && r < 1 ) + m_r = (r < 0 || r >= 1) ? __PCL_SHEPARD_DEFAULT_REGULARIZATION : r; + } + + /*! + * Returns the smoothing factor of this local Shepard + * interpolation. See SetSmoothing() for more information. + */ + float Smoothing() const + { + return m_r; + } + + /*! + * Generation of a two-dimensional surface approximation. + * + * \param x X node coordinates. + * + * \param y Y node coordinates. + * + * \param z Node values. + * + * \param n Number of nodes. There must be at least three distinct + * input nodes. + * + * The input nodes can be arbitrarily distributed and don't need to follow + * any specific order. However, all node points should be distinct with + * respect to the machine epsilon for the floating point type T. + * + * This initialization function includes a sanitization routine. If there + * are duplicate points in the specified set of input nodes, only the first + * occurrence of each duplicate will be kept to build the interpolation + * surface, and the rest of duplicate points will be ignored. Two points are + * considered equal if their coordinates don't differ more than the machine + * epsilon for the floating point type T. + */ + void Initialize( const T* x, const T* y, const T* z, int n ) + { + DoInitialize( nullptr/*rect*/, x, y, z, n ); + } + + /*! + * Generation of a two-dimensional surface approximation with a prescribed + * rectangular interpolation region. + * + * \param rect The rectangular region for interpolation. + * + * \param x X node coordinates. + * + * \param y Y node coordinates. + * + * \param z Node values. + * + * \param n Number of nodes. There must be at least three distinct + * input nodes within the specified interpolation region. + * + * The input nodes can be arbitrarily distributed and don't need to follow + * any specific order. However, all node points should be distinct with + * respect to the machine epsilon for the floating point type T. + * + * This initialization function includes a sanitization routine. If there + * are duplicate points in the specified set of input nodes, only the first + * occurrence of each duplicate will be kept to build the interpolation + * surface, and the rest of duplicate points will be ignored. Two points are + * considered equal if their coordinates don't differ more than the machine + * epsilon for the floating point type T. + * + * This function will only take into account input nodes located within the + * specified region \a rect; all points outside this region will be ignored. + * A prescribed interpolation region is useful to ensure that the + * approximation surface can be evaluated on the entire region, for example + * to represent images or other data sets, not necessarily bounded by the + * extreme coordinates in the set of input nodes. Specifying a region also + * allows to use a reduced subset of the available data, to accelerate + * calculations. + */ + void Initialize( const search_rect& rect, const T* x, const T* y, const T* z, int n ) + { + DoInitialize( &rect, x, y, z, n ); + } + + /*! + * Two-dimensional surface interpolation/approximation with the local + * Shepard method. Returns an approximated function value at the specified + * \a x and \a y coordinates. + * + * The interpolation function uses an adaptive point search routine. The + * current search radius is used as an initial parameter. If less than + * three input nodes are found within the search radius distance from the + * desired interpolation point, the radius is increased and a new search is + * performed. This is repeated until at least three nodes are found around + * the specified interpolation point. + * + * In degenerate cases where no valid solution can be found, zero is + * returned conventionally. These cases are rare and may only happen if the + * input nodes are very close together with respect to the machine epsilon + * for the numeric type T. + */ + T operator ()( double x, double y ) const + { + PCL_PRECONDITION( !m_T.IsEmpty() ) + + const double dx = m_r0*(x - m_x0); + const double dy = m_r0*(y - m_y0); + + for ( double R = m_R; ; R += m_R ) + { + int m = 0; + double R2 = R*R; + Array V; + m_T.Search( DRect( dx-R, dy-R, dx+R, dy+R ), + [&]( const vector_type& v, void* ) + { + double x = dx - v[0]; + double y = dy - v[1]; + double r2 = x*x + y*y; + if ( r2 < R2 ) + { + ++m; + double w = PowI( 1 - Sqrt( r2 )/R, m_mu ); + /* + * N.B. The equivalent code below is about 400 times + * slower than the above call to PowI() for m_mu=16. + * Measured on a TR 2990WX. + * + double w = 1 - Sqrt( r2 )/R; + for ( int i = 1; i < m_mu; ++i ) + w *= w; + */ + V << DPoint( w, w*v[2] ); + } + }, + nullptr ); + if ( m >= 3 ) + { + if ( m_r > 0 ) + { + /* + * Regularization by Winsorization of the weighted sample. + */ + int r = Min( TruncInt( m_r * m ), (m >> 1) - (m & 1)^1 ); + if ( r > 0 ) + { + V.Sort( []( const DPoint& v1, const DPoint& v2 ) + { + return v1.y < v2.y; + } ); + for ( int i = 0; i < r; ++i ) + { + V[i].y = V[r].y; + V[m-i-1].y = V[m-r-1].y; + } + } + } + DPoint Wz( 0 ); + for ( const DPoint& v : V ) + Wz += v; + if ( 1 + Wz.x != 1 ) + return T( Wz.y/Wz.x ); + if ( R >= 1 ) + break; // degenerate! + } + } + + return 0; // empty!? + } + + /*! + * Returns an interpolated/approximated function value at the specified + * \a p.x and \a p.y point coordinates. See operator()( double, double ) for + * more information. + */ + template + T operator ()( const GenericPoint& p ) const + { + return operator ()( double( p.x ), double( p.y ) ); + } + + /*! + * Resets this %ShepardInterpolation object, deallocating all internal + * working structures. + */ + void Clear() + { + m_T.Clear(); + } + +protected: + + double m_r0 = 1; // scaling factor for normalization of node coordinates + double m_x0 = 0; // zero offset for normalization of X node coordinates + double m_y0 = 0; // zero offset for normalization of Y node coordinates + int m_mu = __PCL_SHEPARD_DEFAULT_POWER; // power parameter (leveling factor) + double m_R = __PCL_SHEPARD_DEFAULT_SEARCH_RADIUS; // initial search radius + float m_r = __PCL_SHEPARD_DEFAULT_REGULARIZATION; // regularization (clipping fraction) + search_tree m_T; // tree points store input coordinates and function values + + /*! + * Performs input data normalization and sanitization. Builds the point + * search quadtree with normalized node coordinates. + * \internal + */ + void DoInitialize( const search_rect* rect, const T* x, const T* y, const T* z, int n ) + { + PCL_PRECONDITION( x != nullptr && y != nullptr && z != nullptr ) + PCL_PRECONDITION( n > 2 ) + + if ( n < 3 ) + throw Error( "ShepardInterpolation::Initialize(): At least three input nodes must be specified." ); + + Clear(); + + try + { + if ( rect == nullptr ) + { + /* + * Find mean coordinate values. + */ + m_x0 = m_y0 = 0; + for ( int i = 0; i < n; ++i ) + { + m_x0 += x[i]; + m_y0 += y[i]; + } + m_x0 /= n; + m_y0 /= n; + + /* + * Find radius of unit circle. + */ + m_r0 = 0; + for ( int i = 0; i < n; ++i ) + { + double dx = x[i] - m_x0; + double dy = y[i] - m_y0; + double r = Sqrt( dx*dx + dy*dy ); + if ( r > m_r0 ) + m_r0 = r; + } + } + else + { + m_x0 = rect->CenterX(); + m_y0 = rect->CenterY(); + m_r0 = rect->Diagonal()/2; + } + + if ( 1 + m_r0 == 1 ) + throw Error( "ShepardInterpolation::Initialize(): Empty or insignificant interpolation space." ); + m_r0 = 1/m_r0; + + /* + * Build working vector. Transform coordinates to the unit circle. + */ + Array V; + for ( int i = 0; i < n; ++i ) + V << vector_type( m_r0*(x[i] - m_x0), m_r0*(y[i] - m_y0), z[i] ); + + /* + * Find and remove duplicate input nodes. Two nodes are equal if their + * coordinates don't differ more than the machine epsilon for the + * floating point type T. + */ + V.Sort( []( const vector_type& p, const vector_type& q ) + { + return (p[0] != q[0]) ? p[0] < q[0] : p[1] < q[1]; + } ); + Array remove; + for ( int i = 0, j = 1; j < n; ++i, ++j ) + if ( Abs( V[i][0] - V[j][0] ) <= std::numeric_limits::epsilon() ) + if ( Abs( V[i][1] - V[j][1] ) <= std::numeric_limits::epsilon() ) + remove << i; + if ( !remove.IsEmpty() ) + { + Array U; + int i = 0; + for ( int j : remove ) + { + for ( ; i < j; ++i ) + U << V[i]; + ++i; + } + for ( ; i < n; ++i ) + U << V[i]; + if ( U.Length() < 3 ) + throw Error( "ShepardInterpolation::Initialize(): Less than three input nodes left after sanitization." ); + V = U; + } + + /* + * Build the point search tree. + */ + if ( rect == nullptr ) + m_T.Build( V, BucketCapacity ); + else + { + m_T.Build( *rect, V, BucketCapacity ); + if ( m_T.Length() < 3 ) + throw Error( "ShepardInterpolation::Initialize(): Less than three input nodes in the specified search region." ); + } + } + catch ( ... ) + { + Clear(); + throw; + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PointShepardInterpolation + * \brief Vector Shepard interpolation/approximation in two dimensions + * + * The template parameter P represents an interpolation point in two + * dimensions. The type P must implement P::x and P::y data members accessible + * from the current %PointShepardInterpolation template specialization. These + * members must provide the values of the horizontal and vertical coordinates, + * respectively, of an interpolation point. In addition, the scalar types of + * the P::x and P::y point members must support conversion to double semantics. + */ +template +class PCL_CLASS PointShepardInterpolation +{ +public: + + /*! + * Represents an interpolation point in two dimensions. + */ + typedef P point; + + /*! + * Represents a sequence of interpolation points. + */ + typedef Array point_list; + + /*! + * Represents a coordinate interpolating/approximating surface. + */ + typedef ShepardInterpolation surface; + + /*! + * Default constructor. Yields an empty instance that cannot be used without + * initialization. + */ + PointShepardInterpolation() = default; + + /*! + * Copy constructor. + */ + PointShepardInterpolation( const PointShepardInterpolation& ) = default; + + /*! + * Move constructor. + */ + PointShepardInterpolation( PointShepardInterpolation&& ) = default; + + /*! + * Constructs a %PointShepardInterpolation object initialized for the + * specified input data and interpolation parameters. + * + * See the corresponding Initialize() member function for a detailed + * description of parameters. + */ + PointShepardInterpolation( const point_list& P1, const point_list& P2, + int power = __PCL_SHEPARD_DEFAULT_POWER, + double radius = __PCL_SHEPARD_DEFAULT_SEARCH_RADIUS ) + { + Initialize( P1, P2, power, radius ); + } + + /*! + * Constructs a %PointShepardInterpolation object initialized with + * prescribed point surface interpolations. + * + * See the corresponding Initialize() member function for a more detailed + * description of parameters and their required conditions. + */ + PointShepardInterpolation( const surface& Sx, const surface& Sy ) + { + Initialize( Sx, Sy ); + } + + /*! + * Copy assignment operator. Copy assignment has been disabled for this + * class because the ShepardInterpolation class does not implement copy + * assignment. + */ + PointShepardInterpolation& operator =( const PointShepardInterpolation& ) = delete; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PointShepardInterpolation& operator =( PointShepardInterpolation&& ) = default; + + /*! + * Initializes this %PointShepardInterpolation object for the specified + * input data and interpolation parameters. + * + * \param P1 A sequence of distinct interpolation node points. + * + * \param P2 A sequence of interpolation values. For each point in + * \a P1, the coordinates of its counterpart point in + * \a P2 will be used as the interpolation node values in + * the X and Y directions. + * + * \param power Power parameter. Must be > 0. The default value is 4. + * See ShepardInterpolation::SetPower() for a complete + * description of this parameter. + * + * \param radius Normalized search radius. Must be > 0. The default + * value is 0.1. See ShepardInterpolation::SetRadius() for + * a complete description of this parameter. + * + * \param smoothing Smoothing factor. Must be in the range [0,1). The + * default value is zero. See + * ShepardInterpolation::SetSmoothing() for a complete + * description of this parameter. + * + * The input nodes can be arbitrarily distributed and don't need to follow + * any specific order. However, all node points should be distinct with + * respect to the machine epsilon for the floating point type used to + * represent coordinates. + * + * See the ShepardInterpolation::Initialize() member function for a complete + * description of this initialization process. + */ + void Initialize( const point_list& P1, const point_list& P2, + int power = __PCL_SHEPARD_DEFAULT_POWER, + double radius = __PCL_SHEPARD_DEFAULT_SEARCH_RADIUS, + float smoothing = __PCL_SHEPARD_DEFAULT_REGULARIZATION ) + { + PCL_PRECONDITION( P1.Length() >= 3 ) + PCL_PRECONDITION( P1.Length() <= P2.Length() ) + PCL_PRECONDITION( power > 0 ) + PCL_PRECONDITION( radius > 0 ) + PCL_PRECONDITION( smoothing >= 0 && smoothing < 1 ) + + m_Sx.Clear(); + m_Sy.Clear(); + + m_Sx.SetPower( power ); + m_Sy.SetPower( power ); + + m_Sx.SetRadius( radius ); + m_Sy.SetRadius( radius ); + + m_Sx.SetSmoothing( smoothing ); + m_Sy.SetSmoothing( smoothing ); + + if ( P1.Length() < 3 || P2.Length() < 3 ) + throw Error( "PointShepardInterpolation::Initialize(): At least three input nodes must be specified." ); + + if ( P2.Length() < P1.Length() ) + throw Error( "PointShepardInterpolation::Initialize(): Incompatible point array lengths." ); + + DVector X( int( P1.Length() ) ), + Y( int( P1.Length() ) ), + Zx( int( P1.Length() ) ), + Zy( int( P1.Length() ) ); + for ( int i = 0; i < X.Length(); ++i ) + { + X[i] = P1[i].x; + Y[i] = P1[i].y; + Zx[i] = P2[i].x; + Zy[i] = P2[i].y; + } + m_Sx.Initialize( X.Begin(), Y.Begin(), Zx.Begin(), X.Length() ); + m_Sy.Initialize( X.Begin(), Y.Begin(), Zy.Begin(), X.Length() ); + } + + /*! + * Deallocates internal structures, yielding an empty object that cannot be + * used before a new call to Initialize(). + */ + void Clear() + { + m_Sx.Clear(); + m_Sy.Clear(); + } + + /*! + * Returns true iff this is a valid, initialized object ready for + * interpolation. + */ + bool IsValid() const + { + return m_Sx.IsValid() && m_Sy.IsValid(); + } + + /*! + * Returns a reference to the internal object used for interpolation in the + * X plane direction. + */ + const surface& SurfaceX() const + { + return m_Sx; + } + + /*! + * Returns a reference to the internal object used for interpolation in the + * Y plane direction. + */ + const surface& SurfaceY() const + { + return m_Sy; + } + + /*! + * Returns an interpolated point at the specified coordinates. + */ + template + DPoint operator ()( T x, T y ) const + { + return DPoint( m_Sx( x, y ), m_Sy( x, y ) ); + } + + /*! + * Returns an interpolated point at the given \a p.x and \a p.y coordinates. + */ + template + DPoint operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + +private: + + /* + * The surface interpolations in the X and Y plane directions. + */ + surface m_Sx, m_Sy; + + friend class DrizzleData; + friend class DrizzleDataDecoder; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ShepardInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ShepardInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Sizer.h b/3rdparty/include/pcl/Sizer.h new file mode 100644 index 0000000..6a92066 --- /dev/null +++ b/3rdparty/include/pcl/Sizer.h @@ -0,0 +1,644 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Sizer.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_Sizer_h +#define __PCL_Sizer_h + +/// \file pcl/Sizer.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::Align + * \brief Control alignment modes. + * + * + * + * + * + * + * + * + * + *
Align::Expand The item can be expanded to occupy the available space
Align::Left The item aligns to the left side of the available space
Align::Top The item aligns to the top side of the available space
Align::Right The item aligns to the right side of the available space
Align::Bottom The item aligns to the bottom side of the available space
Align::Center The item aligns centered within the available space
Align::Default Default alignment, equal to Align::Expand
+ */ +namespace Align +{ + enum value_type + { + Expand, + Left, + Top = Left, + Right, + Bottom = Right, + Center, + Default = Expand + }; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +class PCL_CLASS Control; + +// ---------------------------------------------------------------------------- + +/*! + * \class Sizer + * \brief Base class for PixInsight sizer objects. + * + * %Sizer allows laying out child controls within their parent controls as + * simple one-dimensional stacks with precise control over orientations, + * margins, distances between items, and item alignments. By distributing + * controls in nested %Sizer objects with horizontal and vertical orientations, + * complex albeit clean user interfaces can be easily defined. + * + * \b Automatic \b Scaling + * + * The %Sizer class provides an automatic scaling feature that simplifies the + * adaptation of existing and new PCL-based UI generation code to varying + * display resolutions. This functionality can be controlled with a Boolean + * \a autoScaling parameter available for the following member functions: + * + * Sizer::SetMargin( int margin, bool autoScaling = true );\n + * Sizer::SetSpacing( int spacing, bool autoScaling = true );\n + * Sizer::AddSpacing( int spacing, bool autoScaling = true );\n + * Sizer::InsertSpacing( int index, int spacing, bool autoScaling = true );\n + * int Margin( bool autoScaling = true );\n + * int Spacing( bool autoScaling = true ); + * + * As you can see, automatic scaling is always enabled by default. On the + * PixInsight platform, the reference display density is 109 dpi, corresponding + * to a 27 inch monitor at QHD resolution (2560x1440 physical pixels). + * + * The automatic scaling feature applies the scaling ratio returned by + * Sizer::DisplayPixelRatio() to convert horizontal and vertical spaces between + * items from device-independent (or \e logical) pixel units to physical device + * pixel units. When this feature is enabled through the corresponding + * \a autoScaling parameters, scaling is applied to both automatic and manual + * spacings between controls, that is, to spacings defined by SetSpacing(), + * SetMargin(), AddSpacing(), and InsertSpacing(). The reverse transformation + * is applied from physical pixels to logical units when dimensions are + * retrieved by Spacing() and Margin(). + * + * \sa HorizontalSizer, VerticalSizer + */ +class PCL_CLASS Sizer : public UIObject +{ +public: + + /*! + * Represents the alignment of a %Sizer item. + */ + typedef Align::value_type item_alignment; + + /*! + * Constructs a %Sizer object. + * + * \param vertical If true, this sizer will lay out items vertically. If + * false, items will be laid out horizontally. + */ + Sizer( bool vertical ); + + /*! + * Destroys a %Sizer object. + */ + virtual ~Sizer() + { + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since sizers are unique objects by definition, calling this member + * function has no effect. + */ + void EnsureUnique() override + { + // Sizers are unique objects by definition + } + + /*! + * Returns a reference to a null %Sizer instance. A null %Sizer does not + * correspond to an existing sizer in the PixInsight core application. + */ + static Sizer& Null(); + + /*! + * Returns a reference to the parent control of this %Sizer object, or + * Control::Null() if this sizer has no parent control. + */ + Control& ParentControl() const; + + /*! + * Returns true iff this %Sizer lays out items vertically. + */ + bool IsVertical() const; + + /*! + * Returns true iff this %Sizer lays out items horizontally. + */ + bool IsHorizontal() const + { + return !IsVertical(); + } + + /*! + * Returns the number of items in this %Sizer object. + */ + int NumberOfItems() const; + + /*! + * Returns the zero-based index of the specified child %Sizer object \a s in + * this sizer, or -1 if the \a s sizer does not belong to this %Sizer. + */ + int IndexOf( const Sizer& s ) const; + + /*! + * Returns the zero-based index of the specified child control \a c in this + * sizer, or -1 if the \a c control does not belong to this %Sizer. + */ + int IndexOf( const Control& c ) const; + + /*! + * Returns true iff the specified child sizer \a s belongs to this %Sizer. + */ + bool Contains( const Sizer& s ) const + { + return IndexOf( s ) >= 0; + } + + /*! + * Returns true iff the specified child control \a c belongs to this %Sizer. + */ + bool Contains( const Control& c ) const + { + return IndexOf( c ) >= 0; + } + + /*! + * Adds a sizer to this %Sizer object. + * + * \param s The %Sizer object to be added. + * + * \param stretchFactor Indicates how much space the sizer \a s will tend + * to occupy within its parent sizer (this sizer), relative to + * the rest of sibling sizer items. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description. + * + * \sa Add( Control&, int, item_alignment ), AddSpacing(), AddStretch(), + * Insert() + */ + void Add( Sizer& s, int stretchFactor = 0 ); + + /*! + * Adds a control to this %Sizer object. + * + * \param c The control to be added. + * + * \param stretchFactor Indicates how much space the control \a c will + * try to occupy within its parent sizer (this sizer), relative + * to the rest of sibling sizer items. A value of zero indicates + * that the added control has no particular preference and can + * be adapted to the existing space, as necessary/possible. + * + * \param align Item alignment. + * + * In the following example: + * + * \code + * PushButton button1; + * PushButton button2; + * PushButton button3; + * // ... + * Sizer fooSizer; + * fooSizer.Add( button1, 25 ); + * fooSizer.Add( button2, 50 ); + * fooSizer.Add( button3, 25 ); + * \endcode + * + * The button1 control will occupy one half of the total available space for + * fooSizer, and each of button1 and button2 will occupy 1/4 of the space + * available in fooSizer. Stretch factors don't have to be expressed as + * percentages necessarily, although using percentage values is usually more + * readable. The stretch factors 2, 4, 2 would have the same meaning as 25, + * 50, 25 in the example above. + * + * \sa Add( Sizer&, int ), AddSpacing(), AddStretch(), Insert() + */ + void Add( Control& c, int stretchFactor = 0, item_alignment align = Align::Default ); + + /*! + * Adds a non-stretchable space of \a size pixels to this %Sizer. + * + * If the \a autoScaling parameter is set to true, the specified \a size + * will be converted from logical device-independent pixel units to physical + * device pixels automatically. If \a autoScaling is false, the specified + * \a size is assumed to be expressed in physical pixel units, and no + * automatic scaling will be performed. + * + * \sa InsertSpacing(), AddStretch(), InsertStretch() + */ + void AddSpacing( int size, bool autoScaling = true ); + + /*! + * Adds a non-stretchable space of \a size logical pixels to this %Sizer. + * This is a convenience member function equivalent to: + * + * \code AddSpacing( size, true ); \endcode + */ + void AddScaledSpacing( int size ) + { + AddSpacing( size, true ); + } + + /*! + * Adds a non-stretchable space of \a size physical pixels to this %Sizer. + * This is a convenience member function equivalent to: + * + * \code AddSpacing( size, false ); \endcode + */ + void AddUnscaledSpacing( int size ) + { + AddSpacing( size, false ); + } + + /*! + * Adds a stretchable space with the specified stretch factor. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description of stretch factors. + * + * \sa AddSpacing(), InsertSpacing(), InsertStretch() + */ + void AddStretch( int stretchFactor = 100 ); + + /*! + * Inserts a sizer in this %Sizer object. + * + * \param index Zero-based index where the sizer \a s will be inserted. + * + * \param s The %Sizer object to be added. + * + * \param stretchFactor Indicates how much space the sizer \a s will tend + * to occupy within its parent sizer (this sizer), relative to + * the rest of sibling sizer items. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description. + * + * \sa Insert( int, Control&, int, item_alignment ), InsertSpacing(), + * InsertStretch(), Add() + */ + void Insert( int index, Sizer& s, int stretchFactor = 0 ); + + /*! + * Inserts a control in this %Sizer object. + * + * \param index Zero-based index where the control \a c will be inserted. + * + * \param c The control to be added. + * + * \param stretchFactor Indicates how much space the control \a c will + * tend to occupy within its parent sizer (this sizer), relative + * to the rest of sibling sizer items. + * + * \param align Item alignment. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description. + * + * \sa Insert( int, Sizer&, int ), InsertSpacing(), InsertStretch(), Add() + */ + void Insert( int index, Control& c, int stretchFactor = 0, item_alignment align = Align::Default ); + + /*! + * Inserts a non-stretchable space of \a size pixels in this %Sizer. + * + * If the \a autoScaling parameter is set to true, the specified \a size + * will be converted from logical device-independent pixel units to physical + * device pixels automatically. If \a autoScaling is false, the specified + * \a size is assumed to be expressed in physical pixel units, and no + * automatic scaling will be performed. + * + * \sa AddSpacing(), InsertStretch(), AddStretch() + */ + void InsertSpacing( int index, int size, bool autoScaling = true ); + + /*! + * Inserts a non-stretchable space of \a size logical pixels in this %Sizer. + * This is a convenience member function equivalent to: + * + * \code InsertSpacing( index, size, true ); \endcode + */ + void InsertScaledSpacing( int index, int size ) + { + InsertSpacing( index, size, true ); + } + + /*! + * Inserts a non-stretchable space of \a size physical pixels in this + * %Sizer. This is a convenience member function equivalent to: + * + * \code InsertSpacing( index, size, false ); \endcode + */ + void InsertUnscaledSpacing( int index, int size ) + { + InsertSpacing( index, size, false ); + } + + /*! + * Inserts a stretchable space with the specified stretch factor. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description of stretch factors. + * + * \sa InsertSpacing(), AddSpacing(), AddStretch() + */ + void InsertStretch( int index, int stretchFactor = 100 ); + + /*! + * Removes the specified sizer \a s from this %Sizer object. If \a s doesn't + * belong to this sizer, nothing happens. + */ + void Remove( Sizer& s ); + + /*! + * Removes the specified control \a c from this %Sizer object. If \a c + * doesn't belong to this sizer, nothing happens. + */ + void Remove( Control& c ); + + /*! + * Changes the stretch factor for a child sizer \a s belonging to this + * %Sizer object. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description of stretch factors. + */ + void SetStretchFactor( Sizer& s, int stretch ); + + /*! + * Changes the stretch factor for a child control \a s belonging to this + * %Sizer object. + * + * See the documentation for Add( Control&, int, item_alignment ) for a + * detailed description of stretch factors. + */ + void SetStretchFactor( Control& c, int stretch ); + + /*! + * Changes the alignment of a child sizer \a s belonging to this %Sizer + * object. + */ + void SetAlignment( Sizer& s, item_alignment align ); + + /*! + * Changes the alignment of a child control \a c belonging to this %Sizer + * object. + */ + void SetAlignment( Control& c, item_alignment align ); + + /*! + * Returns the margin in pixels around this sizer. + * + * The margin is the empty space that is automatically reserved around + * this sizer on its parent control's (or parent sizer's) client area. + * The default margin is always zero pixels for all sizer types, unless + * explicitly changed with this function. + * + * If the \a autoScaling parameter is set to true, the returned value will + * be expressed in logical device-independent pixel units. This means that + * the returned value has been converted from physical device pixels + * automatically. If \a autoScaling is false, the returned value will be + * expressed in physical device pixels, and no automatic scaling is applied. + * + * \sa SetMargin(), Spacing(), SetSpacing() + */ + int Margin( bool autoScaling = true ) const; + + /*! + * Sets the margin in pixels around this sizer. + * + * If the \a autoScaling parameter is set to true, the specified \a margin + * will be converted from logical device-independent pixel units to physical + * device pixels automatically. If \a autoScaling is false, the specified + * \a margin is assumed to be expressed in physical pixel units, and no + * automatic scaling will be performed. + * + * \sa Margin(), Spacing(), SetSpacing() + */ + void SetMargin( int margin, bool autoScaling = true ); + + /*! + * Returns the spacing in pixels between items in this %Sizer object. + * + * If the \a autoScaling parameter is set to true, the returned value will + * be expressed in logical device-independent pixel units. This means that + * the returned value has been converted from physical device pixels + * automatically. If \a autoScaling is false, the returned value will be + * expressed in physical device pixels, and no automatic scaling is applied. + * + * \sa SetSpacing(), Margin(), SetMargin() + */ + int Spacing( bool autoScaling = true ) const; + + /*! + * Sets the spacing in pixels between items in this %Sizer object. + * + * If the \a autoScaling parameter is set to true, the specified \a spacing + * will be converted from logical device-independent pixel units to physical + * device pixels automatically. If \a autoScaling is false, the specified + * \a spacing is assumed to be expressed in physical pixel units, and no + * automatic scaling will be performed. + * + * \sa Spacing(), Margin(), SetMargin() + */ + void SetSpacing( int spacing, bool autoScaling = true ); + + /*! + * Returns the ratio between physical screen pixels and device-independent + * logical units for the parent control of this %Sizer object. This ratio is + * used as a scaling factor by the LogicalPixelsToPhysical() and PhysicalPixelsToLogical() functions, and + * is also applied automatically when \a autoScaling parameters are set to + * true in a number of member functions; see the class description for more + * information. + * + * The returned value is greater than or equal to one. Typical pixel ratios + * are 2.0 for high-dpi displays such as Retina monitors, or 1.0 for normal + * 96 dpi monitors. + * + * \sa LogicalPixelsToPhysical(), PhysicalPixelsToLogical() + */ + double DisplayPixelRatio() const; + + /*! + * Returns the specified \a size in logical device-independent pixel units + * converted to physical device pixels. + * + * \sa DisplayPixelRatio(), PhysicalPixelsToLogical() + */ + int LogicalPixelsToPhysical( int size ) const + { + return RoundInt( DisplayPixelRatio()*size ); + } + + /*! + * Returns the specified \a size in physical device pixels converted to + * logical device-independent pixel units. + * + * \sa DisplayPixelRatio(), LogicalPixelsToPhysical() + */ + int PhysicalPixelsToLogical( int size ) const + { + return RoundInt( size/DisplayPixelRatio() ); + } + +private: + + Sizer( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class Control; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class HorizontalSizer + * \brief Client-side interface to a PixInsight horizontal sizer. + * + * %HorizontalSizer lays out a sequence of items as a horizontal stack. + */ +class PCL_CLASS HorizontalSizer : public Sizer +{ +public: + + /*! + */ + typedef Sizer::item_alignment item_alignment; + + /*! + * Constructs a %HorizontalSizer object. + */ + HorizontalSizer() + : Sizer( false ) + { + } + + /*! + * Destroys a %HorizontalSizer object. + */ + virtual ~HorizontalSizer() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class VerticalSizer + * \brief Client-side interface to a PixInsight vertical sizer. + * + * %VerticalSizer lays out a sequence of as a vertical stack. + */ +class PCL_CLASS VerticalSizer : public Sizer +{ +public: + + /*! + */ + typedef Sizer::item_alignment item_alignment; + + /*! + * Constructs a %VerticalSizer object. + */ + VerticalSizer() + : Sizer( true ) + { + } + + /*! + * Destroys a %VerticalSizer object. + */ + virtual ~VerticalSizer() + { + } +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Sizer_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Sizer.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Slider.h b/3rdparty/include/pcl/Slider.h new file mode 100644 index 0000000..e23ff99 --- /dev/null +++ b/3rdparty/include/pcl/Slider.h @@ -0,0 +1,492 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Slider.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_Slider_h +#define __PCL_Slider_h + +/// \file pcl/Slider.h + +#include + +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::TickStyle + * \brief Slider tick styles. + * + * + * + * + * + * + * + * + *
TickStyle::NoTicks The slider has no ticks
TickStyle::Top Ticks are drawn at the top edge of a horizontal slider
TickStyle::Left Ticks are drawn at the left edge of a vertical slider
TickStyle::Bottom Ticks are drawn at the bottom edge of a horizontal slider
TickStyle::Right Ticks are drawn at the right edge of a vertical slider
TickStyle::BothSides Ticks are drawn at both edges of the slider. Equal to TickStyle::Top|TickStyle::Bottom
+ */ +namespace TickStyle +{ + enum mask_type + { + NoTicks = 0x00, + Top = 0x01, + Bottom = 0x02, + Left = Top, + Right = Bottom, + BothSides = Top|Bottom + }; +} + +/*! + * A collection of slider tick style flags. + */ +typedef Flags TickStyles; + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class Slider + * \brief Client-side interface to a PixInsight %Slider control. + * + * ### TODO: Write a detailed description for %Slider. + */ +class PCL_CLASS Slider : public Control +{ +public: + + /*! + * Constructs a %Slider object as a child control of \a parent. The + * \a vertical parameter indicates the orientation of the slider control + * (vertical or horizontal). + */ + Slider( Control& parent = Control::Null(), bool vertical = false ); + + /*! + * Destroys a %Slider object. + */ + virtual ~Slider() + { + } + + /*! + * Returns the current value of this %Slider control. + */ + int Value() const; + + /*! + * Sets the value of this %Slider control. + */ + void SetValue( int v ); + + /*! + * Returns the current value of this %Slider control as a normalized real + * number in the range [0,1]. + */ + double NormalizedValue() const; + + /*! + * Sets the value of this %Slider control as a normalized real number in the + * range [0,1]. + */ + void SetNormalizedValue( double f ); + + /*! + * Gets the range of values for this %Slider control. + * + * \param[out] minValue, maxValue References to the variables where the + * minimum and maximum values of this %Slider control will be + * copied, respectively. + * + * \sa SetRange(), MinValue(), MaxValue() + */ + void GetRange( int& minValue, int& maxValue ) const; + + /*! + * Returns the minimum value of this %Slider control. + * + * \sa MaxValue(), GetRange() + */ + int MinValue() const + { + int m, dum; GetRange( m, dum ); return m; + } + + /*! + * Returns the maximum value of this %Slider control. + * + * \sa MinValue(), GetRange() + */ + int MaxValue() const + { + int dum, m; GetRange( dum, m ); return m; + } + + /*! + * Sets the range of values for this %Slider control. + * + * \param minValue, maxValue New minimum and maximum values, + * respectively, for this %Slider control. + * + * \sa GetRange(), SetMinValue(), SetMaxValue() + */ + void SetRange( int minValue, int maxValue ); + + /*! + * Sets the minimum value of this %Slider control. + * + * This is a convenience member function, equivalent to + * SetRange( m, MaxValue() ) + * + * \sa SetMaxValue(), SetRange(), MinValue(), MaxValue() + */ + void SetMinValue( int m ) + { + SetRange( m, MaxValue() ); + } + + /*! + * Sets the maximum value of this %Slider control. + * + * This is a convenience member function, equivalent to + * SetRange( MinValue(), m ) + * + * \sa SetMinValue(), SetRange(), MinValue(), MaxValue() + */ + void SetMaxValue( int m ) + { + SetRange( MinValue(), m ); + } + + /*! + * Returns the step size of this %Slider control + * + * The step size is the number of units that are skipped when the user + * presses an arrow key while this %Slider control has the keyboard focus. + * + * \sa SetStepSize() + */ + int StepSize() const; + + /*! + * Sets the step size of this %Slider control + * + * The step size is the number of units that are skipped when the user + * presses an arrow key while this %Slider control has the keyboard focus. + * + * \sa StepSize() + */ + void SetStepSize( int ); + + /*! + * Returns the page size of this %Slider control + * + * The page size is the number of units that are skipped when the user + * clicks on the slider (outside the thumb), or when (s)he presses PgUp or + * PgDn while this %Slider control has the keyboard focus. + * + * \sa SetPageSize() + */ + int PageSize() const; + + /*! + * Sets the page size of this %Slider control + * + * The page size is the number of units that are skipped when the user + * clicks on the slider (outside the thumb), or when (s)he presses PgUp or + * PgDn while this %Slider control has the keyboard focus. + * + * \sa PageSize() + */ + void SetPageSize( int ); + + /*! + * Returns the distance in pixels between two consecutive tick marks. + */ + int TickInterval() const; + + /*! + * Sets the distance in pixels between two consecutive tick marks. + */ + void SetTickInterval( int ); + + /*! + * A synonym for TickInterval(). + */ + int TickFrequency() const + { + return TickInterval(); + } + + /*! + * A synonym for SetTickInterval(). + */ + void SetTickFrequency( int q ) + { + SetTickInterval( q ); + } + + /*! + * Returns the current tick style of this %Slider control. + */ + TickStyles TickStyle() const; + + /*! + * Sets the tick style of this %Slider control. + */ + void SetTickStyle( TickStyles ); + + /*! + * Disables ticks for this %Slider control. + * + * This is a convenience member function, equivalent to + * SetTickStyle( TickStyle::NoTicks ) + */ + void DisableTicks() + { + SetTickStyle( TickStyle::NoTicks ); + } + + /*! + * Returns true iff automatic tracking is currently enabled for this + * %Slider control. + * + * When automatic tracking is enabled, continuous slider value + * events are generated while the user is moving the slider's thumb + * with the mouse. When automatic tracking is disabled, a single slider + * value event is generated when the user releases the mouse button. + * + * \sa EnableTracking(), DisableTracking() + */ + bool IsTrackingEnabled() const; + + /*! + * Enables or disables automatic tracking for this %Slider control. + * + * \sa DisableTracking(), IsTrackingEnabled() + */ + void EnableTracking ( bool = true ); + + /*! + * Disables or enables automatic tracking for this %Slider control. + * + * This is a convenience member function, equivalent to + * EnableTracking( !disable ) + * + * \sa EnableTracking(), IsTrackingEnabled() + */ + void DisableTracking( bool disable = true ) + { + EnableTracking( !disable ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnValueUpdated( Slider& sender, int value ); + // void OnRangeUpdated( Slider& sender, int minValue, int maxValue ); + + /*! + * \defgroup slider_event_handlers Slider Event Handlers + */ + + /*! + * Defines the prototype of a slider value event handler. + * + * A slider value event is generated when the user changes the value of a + * slider control. + * + * \param sender The control that sends a slider value event. + * + * \param value The current value of the slider. + * + * \ingroup slider_event_handlers + */ + typedef void (Control::*value_event_handler)( Slider& sender, int value ); + + /*! + * Defines the prototype of a slider range event handler. + * + * A slider range event is generated when the range of a slider control is + * changed. + * + * \param sender The control that sends a slider range event. + * + * \param minValue, maxValue The current minimum and maximum values of the + * slider, respectively. + * + * \ingroup slider_event_handlers + */ + typedef void (Control::*range_event_handler)( Slider& sender, int minValue, int maxValue ); + + /*! + * Sets the slider value event handler for this %Slider control. + * + * \param handler The slider value event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive slider value events + * from this %Slider. + * + * \ingroup slider_event_handlers + */ + void OnValueUpdated( value_event_handler handler, Control& receiver ); + + /*! + * Sets the slider range event handler for this %Slider control. + * + * \param handler The slider range event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive slider range events + * from this %Slider. + * + * \ingroup slider_event_handlers + */ + void OnRangeUpdated( range_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + value_event_handler onValueUpdated = nullptr; + range_event_handler onRangeUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class SliderEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class HorizontalSlider + * \brief Horizontal slider control. + * + * ### TODO: Write a detailed description for %HorizontalSlider. + */ +class PCL_CLASS HorizontalSlider : public Slider +{ +public: + + /*! + * Constructs a %HorizontalSlider as a child control of \a parent. + */ + HorizontalSlider( Control& parent = Control::Null() ) + : Slider( parent, false ) + { + } + + /*! + * Destroys a %HorizontalSlider control. + */ + virtual ~HorizontalSlider() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class VerticalSlider + * \brief Vertical slider control. + * + * ### TODO: Write a detailed description for %VerticalSlider. + */ +class PCL_CLASS VerticalSlider : public Slider +{ +public: + + /*! + * Constructs a %VerticalSlider as a child control of \a parent. + */ + VerticalSlider( Control& parent = Control::Null() ) + : Slider( parent, true ) + { + } + + /*! + * Destroys a %VerticalSlider control. + */ + virtual ~VerticalSlider() + { + } +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_Slider_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Slider.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Sort.h b/3rdparty/include/pcl/Sort.h new file mode 100644 index 0000000..49cfa9a --- /dev/null +++ b/3rdparty/include/pcl/Sort.h @@ -0,0 +1,573 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Sort.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_Sort_h +#define __PCL_Sort_h + +/// \file pcl/Sort.h + +#include + +#include +#include + +#define __PCL_QS_STACK_SIZE 32 // Stack size for the QuickSort algorithms +#define __PCL_QS_IS_THRESHOLD 11 // QuickSort/InsertionSort switch threshold + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup sorting_algorithms Sorting Algorithms + * + * Template formal parameters: + * + * FI Forward iterator \n + * BI Bidirectional iterator \n + * RI Random access iterator \n + * UP Unary predicate \n + * BP Binary predicate \n + * T Item type \n + * F Function + */ + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_insertion_sort__( BI i, BI j, const T* ) +{ + if ( i != j ) + for ( BI k = i; ++k != j; ) + { + T v = *k; + BI y = k; + for ( BI x = y; y != i && v < *--x; --y ) + *y = *x; + *y = v; + } +} + +/*! + * Generic insertion sort algorithm. + * + * Sorts a range [i,j) in ascending order by the insertion sort + * algorithm. Ordering of elements is defined such that for any pair a, b of + * elements in [i,j) a < b is true if a precedes b. + * + * \ingroup sorting_algorithms + */ +template inline +void InsertionSort( BI i, BI j ) +{ + __pcl_insertion_sort__( i, j, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_insertion_sort__( BI i, BI j, BP p, const T* ) +{ + if ( i != j ) + for ( BI k = i; ++k != j; ) + { + T v = *k; + BI y = k; + for ( BI x = y; y != i && p( v, *--x ); --y ) + *y = *x; + *y = v; + } +} + +/*! + * Generic insertion sort algorithm. + * + * Sorts a range [i,j) in ascending order by the insertion sort + * algorithm. Ordering of elements is defined such that for any pair a, b of + * elements in [i,j) the binary predicate p(a,b) is true if a precedes b. + * + * \ingroup sorting_algorithms + */ +template inline +void InsertionSort( BI i, BI j, BP p ) +{ + __pcl_insertion_sort__( i, j, p, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_quick_sort__( RI i, RI j, T* ) +{ + distance_type n = j - i; + if ( n < 2 ) + return; + + distance_type tos[ 2*__PCL_QS_STACK_SIZE ]; + distance_type* sp = tos; + + for ( distance_type l = 0, r = n-1; ; ) + { + RI x0 = i + l; + RI y = i + r; + + if ( r-l < __PCL_QS_IS_THRESHOLD ) + { + for ( RI x = x0; ++x <= y; ) + { + T v = *x; + RI x1 = x; + for ( ; --x1 >= x0 && v < *x1; ) + *(x1+1) = *x1; + *(x1+1) = v; + } + + if ( sp == tos ) + break; + + r = *--sp; + l = *--sp; + } + else + { + RI x = x0; + + Swap( *++x, *(i + ((l+r) >> 1)) ); + + if ( *y < *x0 ) + Swap( *x0, *y ); + if ( *y < *x ) + Swap( *x, *y ); + if ( *x < *x0 ) + Swap( *x, *x0 ); + + T v = *x; + + for ( ;; ) + { + while ( *++x < v ); + while ( v < *--y ); + if ( y < x ) + break; + Swap( *x, *y ); + } + + *(x0+1) = *y; + *y = v; + + distance_type dx = x - i; + distance_type dy = y - i; + + if ( r-dx+1 >= dy-l ) + { + *sp++ = dx; + *sp++ = r; + r = dy-1; + } + else + { + *sp++ = l; + *sp++ = dy-1; + l = dx; + } + } + } +} + +/*! + * Generic quick sort algorithm. + * + * Sorts a range [i,j) in ascending order by the quick sort algorithm + * (median of three variant). Ordering of elements is defined such that for any + * pair a, b of elements in [i,j) a < b is true if a precedes b. + * + * \ingroup sorting_algorithms + */ +template inline +void QuickSort( RI i, RI j ) +{ + __pcl_quick_sort__( i, j, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_quick_sort__( RI i, RI j, BP p, T* ) +{ + distance_type n = j - i; + if ( n < 2 ) + return; + + distance_type tos[ 2*__PCL_QS_STACK_SIZE ]; + distance_type* sp = tos; + + for ( distance_type l = 0, r = n-1; ; ) + { + RI x0 = i + l; + RI y = i + r; + + if ( r-l < __PCL_QS_IS_THRESHOLD ) + { + for ( RI x = x0; ++x <= y; ) + { + T v = *x; + RI x1 = x; + for ( ; --x1 >= x0 && p( v, *x1 ); ) + *(x1+1) = *x1; + *(x1+1) = v; + } + + if ( sp == tos ) + break; + + r = *--sp; + l = *--sp; + } + else + { + RI x = x0; + + Swap( *++x, *(i + ((l+r) >> 1)) ); + + if ( p( *y, *x0 ) ) + Swap( *x0, *y ); + if ( p( *y, *x ) ) + Swap( *x, *y ); + if ( p( *x, *x0 ) ) + Swap( *x, *x0 ); + + T v = *x; + + for ( ;; ) + { + while ( p( *++x, v ) ); + while ( p( v, *--y ) ); + if ( y < x ) + break; + Swap( *x, *y ); + } + + *(x0+1) = *y; + *y = v; + + distance_type dx = x - i; + distance_type dy = y - i; + + if ( r-dx+1 >= dy-l ) + { + *sp++ = dx; + *sp++ = r; + r = dy-1; + } + else + { + *sp++ = l; + *sp++ = dy-1; + l = dx; + } + } + } +} + +/*! + * Generic quick sort algorithm. + * + * Sorts a range [i,j) in ascending order by the quick sort algorithm + * (median of three variant). Ordering of elements is defined such that for any + * pair a, b of elements in [i,j) the binary predicate p(a,b) is true if a + * precedes b. + * + * \ingroup sorting_algorithms + */ +template inline +void QuickSort( RI i, RI j, BP p ) +{ + __pcl_quick_sort__( i, j, p, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_heap_sort__( RI i, RI j, T* ) +{ + distance_type dj = j - i; + if ( dj < 2 ) + return; + + T v; + distance_type di = 1 + (dj >> 1); + + for ( i += di-1, --j; ; ) + { + if ( di > 1 ) + { + v = *--i; + --di; + } + else + { + v = *j; + *j = *i; + + if ( --dj == 0 ) + { + *i = v; + break; + } + + --j; + } + + RI x = i; + RI y = i; + + for ( distance_type dy2 = di, dy = di; !(dj < (dy <<= 1)); dy2 = dy ) + { + y += dy2; + + if ( dy < dj && *y < *(y+1) ) + { + ++y; + ++dy; + } + + if ( v < *y ) + { + *x = *y; + x = y; + } + else + break; + } + + *x = v; + } +} + +/*! + * Generic heap sort algorithm. + * + * Sorts a range [i,j) in ascending order by the heap sort algorithm. + * Ordering of elements is defined such that for any pair a, b of elements in + * [i,j) a < b is true if a precedes b. + * + * \ingroup sorting_algorithms + */ +template inline +void HeapSort( RI i, RI j ) +{ + __pcl_heap_sort__( i, j, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_heap_sort__( RI i, RI j, BP p, T* ) +{ + distance_type dj = j - i; + if ( dj < 2 ) + return; + + T v; + distance_type di = 1 + (dj >> 1); + + for ( i += di-1, --j; ; ) + { + if ( di > 1 ) + { + v = *--i; + --di; + } + else + { + v = *j; + *j = *i; + + if ( --dj == 0 ) + { + *i = v; + break; + } + + --j; + } + + RI x = i; + RI y = i; + + for ( distance_type dy2 = di, dy = di; !(dj < (dy <<= 1)); dy2 = dy ) + { + y += dy2; + + if ( dy < dj && p( *y, *(y+1) ) ) + { + ++y; + ++dy; + } + + if ( p( v, *y ) ) + { + *x = *y; + x = y; + } + else + break; + } + + *x = v; + } +} + +/*! + * Generic heap sort algorithm. + * + * Sorts a range [i,j) in ascending order by the heap sort algorithm. + * Ordering of elements is defined such that for any pair a, b of elements in + * [i,j) the binary predicate p(a,b) is true if a precedes b. + * + * \ingroup sorting_algorithms + */ +template inline +void HeapSort( RI i, RI j, BP p ) +{ + __pcl_heap_sort__( i, j, p, ItemType( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_sort__( BI i, BI j, BidirectionalIterator ) +{ + InsertionSort( i, j ); +} + +template inline +void __pcl_sort__( RI i, RI j, RandomAccessIterator ) +{ +#ifdef __PCL_PREFER_HEAPSORT + HeapSort( i, j ); +#else + QuickSort( i, j ); +#endif +} + +/*! + * Generic sort algorithm. + * + * Sorts a range [i,j) in ascending order. Ordering of elements is defined such + * that for any pair a, b of elements in [i,j) a < b is true if a precedes b. + * + * This function sorts the specified input sequence employing the fastest + * (known) sorting algorithm for the iterator class BI. Insertion sort is + * used for bidirectional iterators without random access, and the quick sort + * algorithm (median of three variant) is used for random access iterators. + * + * If you want to use the heap sort algorithm instead of quick sort (e.g. for + * performance testing purposes), define the __PCL_PREFER_HEAPSORT macro. + * + * \ingroup sorting_algorithms + */ +template inline +void Sort( BI i, BI j ) +{ + __pcl_sort__( i, j, IteratorClass( i ) ); +} + +// ---------------------------------------------------------------------------- + +template inline +void __pcl_sort__( BI i, BI j, BP p, BidirectionalIterator ) +{ + InsertionSort( i, j, p ); +} + +template inline +void __pcl_sort__( RI i, RI j, BP p, RandomAccessIterator ) +{ +#ifdef __PCL_PREFER_HEAPSORT + HeapSort( i, j, p ); +#else + QuickSort( i, j, p ); +#endif +} + +/*! + * Generic sort algorithm. + * + * Sorts a range [i,j) in ascending order. Ordering of elements is defined such + * that for any pair a, b of elements in [i,j) the binary predicate p(a,b) is + * true if a precedes b. + * + * This function sorts the specified input sequence employing the fastest + * (known) sorting algorithm for the iterator class BI. Insertion sort is + * used for bidirectional iterators without random access, and the quick sort + * algorithm (median of three variant) is used for random access iterators. + * + * If you want to use the heap sort algorithm instead of quick sort (e.g. for + * performance testing purposes), define the __PCL_PREFER_HEAPSORT macro. + * + * \ingroup sorting_algorithms + */ +template inline +void Sort( BI i, BI j, BP p ) +{ + __pcl_sort__( i, j, p, IteratorClass( i ) ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Sort_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Sort.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SortedArray.h b/3rdparty/include/pcl/SortedArray.h new file mode 100644 index 0000000..4f2c0b5 --- /dev/null +++ b/3rdparty/include/pcl/SortedArray.h @@ -0,0 +1,1104 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SortedArray.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_SortedArray_h +#define __PCL_SortedArray_h + +/// \file pcl/SortedArray.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SortedArray + * \brief Generic dynamic sorted array. + * + * %SortedArray is a generic, finite sorted sequence of objects, implemented as + * a reference-counted, dynamic array of T instances with automatic sorting of + * inserted array elements. The type A provides dynamic allocation for + * contiguous sequences of elements of type T (StandardAllocator is used by + * default). + * + * \sa Array, ReferenceArray, ReferenceSortedArray, IndirectArray, + * IndirectSortedArray + * \ingroup dynamic_arrays + */ +template +class PCL_CLASS SortedArray : public DirectSortedContainer +{ +public: + + /*! # + */ + typedef Array array_implementation; + + /*! # + */ + typedef typename array_implementation::block_allocator + block_allocator; + + /*! # + */ + typedef typename array_implementation::allocator + allocator; + + /*! # + */ + typedef typename array_implementation::iterator + iterator; + + /*! # + */ + typedef typename array_implementation::const_iterator + const_iterator; + + /*! # + */ + typedef typename array_implementation::reverse_iterator + reverse_iterator; + + /*! # + */ + typedef typename array_implementation::const_reverse_iterator + const_reverse_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty sorted array. + */ + SortedArray() = default; + + /*! + * Constructs a sorted array of \a n default-constructed objects. + */ + explicit + SortedArray( size_type n ) + : m_array( n ) + { + } + + /*! + * Constructs a sorted array of \a n copies of an object \a v. + */ + SortedArray( size_type n, const T& v ) + : m_array( n, v ) + { + } + + /*! + * Constructs a sorted array that stores a sorted copy of the sequence of + * objects defined by the range [i,j) of forward iterators. + */ + template + SortedArray( FI i, FI j ) + : m_array( i, j ) + { + Sort(); + } + + /*! + * Constructs a sorted array that stores a sorted copy of the objects in the + * specified initializer list \a l. + * + * This constructor is equivalent to: + * + * \code SortedArray( l.begin(), l.end() ) \endcode + */ + template + SortedArray( std::initializer_list l ) + : SortedArray( l.begin(), l.end() ) + { + } + + /*! + * Copy constructor. + */ + SortedArray( const SortedArray& ) = default; + + /*! + * Move constructor. + */ + SortedArray( SortedArray&& ) = default; + + /*! + * Destroys a %SortedArray object. Destroys and deallocates all contained + * objects. + */ + ~SortedArray() + { + } + + /*! + * Returns true iff this array uniquely references its contained data. + */ + bool IsUnique() const + { + return m_array.IsUnique(); + } + + /*! + * Returns true iff this sorted array is an alias of a sorted array \a x. + * + * Two objects are aliases if both of them share the same data. + */ + bool IsAliasOf( const SortedArray& x ) const + { + return m_array.IsAliasOf( x.m_array ); + } + + /*! + * Ensures that this array uniquely references its contained data. + * + * If necessary, this member function generates a duplicate of the array + * data, references it, and then decrements the reference counter of the + * original array data. + */ + void EnsureUnique() + { + m_array.EnsureUnique(); + } + + /*! + * Returns the total number of bytes required to store the objects contained + * by this sorted array. + */ + size_type Size() const + { + return m_array.Size(); + } + + /*! + * Returns the length of this sorted array. + */ + size_type Length() const + { + return m_array.Length(); + } + + /*! # + */ + size_type Capacity() const + { + return m_array.Capacity(); + } + + /*! # + */ + size_type Available() const + { + return m_array.Available(); + } + + /*! # + */ + bool IsValid() const + { + return m_array.IsValid(); + } + + /*! # + */ + bool IsEmpty() const + { + return m_array.IsEmpty(); + } + + /*! # + */ + size_type LowerBound() const + { + return m_array.LowerBound(); + } + + /*! # + */ + size_type UpperBound() const + { + return m_array.UpperBound(); + } + + /*! # + */ + const allocator& Allocator() const + { + return m_array.Allocator(); + } + + /*! # + */ + void SetAllocator( const allocator& a ) + { + m_array.SetAllocator( a ); + } + + /*! # + */ + const_iterator At( size_type i ) const + { + return m_array.At( i ); + } + + /*! # + */ + iterator MutableAt( size_type i ) + { + return m_array.At( i ); + } + + /*! # + */ + iterator MutableIterator( const_iterator i ) + { + return m_array.MutableIterator( i ); + } + + /*! # + */ + const T& operator []( size_type i ) const + { + return m_array[i]; + } + + /*! # + */ + const T& operator *() const + { + return *Begin(); + } + + /*! # + */ + const_iterator Begin() const + { + return m_array.ConstBegin(); + } + + /*! # + */ + iterator MutableBegin() + { + return m_array.Begin(); + } + + /*! # + */ + const_iterator End() const + { + return m_array.ConstEnd(); + } + + /*! # + */ + iterator MutableEnd() + { + return m_array.End(); + } + + /*! # + */ + const_reverse_iterator ReverseBegin() const + { + return m_array.ConstReverseBegin(); + } + + /*! # + */ + reverse_iterator MutableReverseBegin() + { + return m_array.ReverseBegin(); + } + + /*! # + */ + const_reverse_iterator ReverseEnd() const + { + return m_array.ConstReverseEnd(); + } + + /*! # + */ + reverse_iterator MutableReverseEnd() + { + return m_array.ReverseEnd(); + } + + /*! + * Ensures that the specified iterator points to a uniquely referenced + * object. If necessary, this function builds a new, uniquely referenced + * copy of this array by calling EnsureUnique(). + * + * If the iterator \a i is changed, it is guaranteed to point to the object + * at the same array index it was pointing to before calling this function. + */ + void UniquifyIterator( iterator& i ) + { + return m_array.UniquifyIterator( i ); + } + + /*! + * Ensures that the specified iterators point to uniquely referenced + * objects. If necessary, this function builds a new, uniquely referenced + * copy of this array by calling EnsureUnique(). + * + * If the iterators \a i and \a j are changed, they are guaranteed to point + * to the objects at the same array indices they were pointing to before + * calling this function. + */ + void UniquifyIterators( iterator& i, iterator& j ) + { + return m_array.UniquifyIterators( i, j ); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Copy assignment operator. + * + * Causes this sorted array to reference the same data as another sorted + * array \a x. Returns a reference to this object. + */ + SortedArray& operator =( const SortedArray& x ) + { + Assign( x ); + return *this; + } + + /*! # + */ + void Assign( const SortedArray& x ) + { + m_array.Assign( x.m_array ); + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SortedArray& operator =( SortedArray&& x ) + { + Transfer( x ); + return *this; + } + + /*! # + */ + void Transfer( SortedArray& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! # + */ + void Transfer( SortedArray&& x ) + { + m_array.Transfer( x.m_array ); + } + + /*! # + */ + SortedArray& operator =( const array_implementation& x ) + { + Assign( x ); + return *this; + } + + /*! # + */ + void Assign( const array_implementation& x ) + { + m_array.Assign( x ); + Sort(); + } + + /*! # + */ + SortedArray& operator =( array_implementation&& x ) + { + Transfer( x ); + return *this; + } + + /*! # + */ + void Transfer( array_implementation& x ) + { + m_array.Transfer( x ); + Sort(); + } + + /*! # + */ + void Transfer( array_implementation&& x ) + { + m_array.Transfer( x ); + Sort(); + } + + /*! # + */ + void Assign( const T& v, size_type n = 1 ) + { + m_array.Assign( v, n ); + } + + /*! # + */ + template + void Assign( FI i, FI j ) + { + m_array.Assign( i, j ); + Sort(); + } + + /*! # + */ + void Import( iterator i, iterator j ) + { + m_array.Import( i, j ); + Sort(); + } + + /*! # + */ + iterator Release() + { + return m_array.Release(); + } + + /*! # + */ + void Add( const SortedArray& x ) + { + const_iterator p = x.Begin(), q = x.End(); + for ( iterator i = m_array.Begin(); i < m_array.End() && p < q; ++i ) + if ( *p < *i ) + i = m_array.Insert( i, *p++ ); + if ( p < q ) + m_array.Append( p, q ); + } + + /*! # + */ + void Add( const Array& x ) + { + Add( x.Begin(), x.End() ); + } + + /*! # + */ + const_iterator Add( const T& v, size_type n = 1 ) + { + return m_array.Insert( pcl::InsertionPoint( m_array.Begin(), m_array.End(), v ), v, n ); + } + + /*! # + */ + template + void Add( FI i, FI j ) + { + if ( i != j ) + { + m_array.EnsureUnique(); + for ( iterator l = m_array.Begin(), r = m_array.End(); ; ) + { + FI h = i; + iterator m = m_array.Insert( pcl::InsertionPoint( l, r, *i ), *i ); + + if ( ++i == j ) + break; + + if ( *i < *h ) + { + l = m_array.Begin(); + r = m; + } + else + { + l = m + 1; + r = m_array.End(); + } + } + } + } + + /*! # + */ + void Remove( const_iterator i, size_type n = 1 ) + { + m_array.Remove( const_cast( i ), n ); + } + + /*! # + */ + void Remove( const_iterator i, const_iterator j ) + { + m_array.Remove( const_cast( i ), const_cast( j ) ); + } + + /*! + * Destroys and removes a trailing sequence of contiguous objects from the + * specified iterator of this array. This operation is equivalent to: + * + * \code Remove( i, End() ) \endcode + * + * If the specified iterator \a i is located at or after the end of this + * array, this function does nothing. Otherwise the iterator is constrained + * to stay in the range [Begin(),End()) of existing array elements. + */ + void Truncate( const_iterator i ) + { + m_array.Truncate( const_cast( i ) ); + } + + /*! + * Removes a contiguous trailing sequence of \a n existing objects from this + * sorted array. This operation is equivalent to: + * + * \code Truncate( End() - n ) \endcode + * + * If the specified count \a n is greater than or equal to the length of + * this array, this function calls Clear() to yield an empty array. + */ + void Shrink( size_type n = 1 ) + { + m_array.Shrink( n ); + } + + /*! # + */ + void Remove( const T& v ) + { + const_iterator i = pcl::BinarySearch( Begin(), End(), v ); + if ( i != End() ) + Remove( i, pcl::InsertionPoint( i+1, End(), v ) ); + } + + /*! # + */ + void Clear() + { + m_array.Clear(); + } + + /*! # + */ + void Reserve( size_type n ) + { + m_array.Reserve( n ); + } + + /*! # + */ + void Squeeze() + { + m_array.Squeeze(); + } + + /*! + * Sets all objects contained by this array equal to \a v. + */ + void Fill( const T& v ) + { + m_array.Fill( v ); + } + + /*! # + */ + template + void Apply( F f ) const + { + pcl::Apply( Begin(), End(), f ); + } + + /*! # + */ + template + const_iterator FirstThat( F f ) const + { + return pcl::FirstThat( Begin(), End(), f ); + } + + /*! # + */ + template + const_iterator LastThat( F f ) const + { + return pcl::LastThat( Begin(), End(), f ); + } + + /*! # + */ + size_type Count( const T& v ) const + { + const_iterator i = pcl::BinarySearch( Begin(), End(), v ); + return (i != End()) ? pcl::InsertionPoint( i+1, End(), v ) - i : 0; + } + + /*! # + */ + template + size_type Count( const T& v, BP p ) const + { + return m_array.Count( v, p ); + } + + /*! # + */ + template + size_type CountIf( UP p ) const + { + return m_array.CountIf( p ); + } + + /*! # + */ + const_iterator MinItem() const + { + return Begin(); + } + + /*! # + */ + template + const_iterator MinItem( BP p ) const + { + return pcl::MinItem( Begin(), End(), p ); + } + + /*! # + */ + const_iterator MaxItem() const + { + return IsEmpty() ? End() : End()-1; + } + + /*! # + */ + template + const_iterator MaxItem( BP p ) const + { + return pcl::MaxItem( Begin(), End(), p ); + } + + /*! # + */ + const_iterator Search( const T& v ) const + { + return pcl::BinarySearch( Begin(), End(), v ); + } + + /*! # + */ + template + const_iterator Search( const T& v, BP p ) const + { + return m_array.Search( v, p ); + } + + /*! # + */ + const_iterator SearchLast( const T& v ) const + { + return pcl::BinarySearchLast( Begin(), End(), v ); + } + + /*! # + */ + template + const_iterator SearchLast( const T& v, BP p ) const + { + return m_array.SearchLast( v, p ); + } + + /*! # + */ + bool Contains( const T& v ) const + { + return Search( v ) != End(); + } + + /*! # + */ + template + bool Contains( const T& v, BP p ) const + { + return Search( v, p ) != End(); + } + + /*! # + */ + void Sort() + { + m_array.Sort(); + } + + /*! + * Exchanges two sorted arrays \a x1 and \a x2. + */ + friend void Swap( SortedArray& x1, SortedArray& x2 ) + { + pcl::Swap( x1.m_array, x2.m_array ); + } + + /*! + * Returns true only if two sorted arrays \a x1 and \a x2 are equal. + * \ingroup array_relational_operators + */ + friend bool operator ==( const SortedArray& x1, const SortedArray& x2 ) + { + return x1.m_array == x2.m_array; + } + + /*! + * Returns true only if a sorted array \a x1 is equal to an array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator ==( const SortedArray& x1, const array_implementation& x2 ) + { + return x1.m_array == x2; + } + + /*! + * Returns true only if an array \a x1 is equal to a sorted array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator ==( const array_implementation& x1, const SortedArray& x2 ) + { + return x1 == x2.m_array; + } + + /*! + * Returns true only if a sorted array \a x1 precedes another sorted array + * \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const SortedArray& x1, const SortedArray& x2 ) + { + return x1.m_array < x2.m_array; + } + + /*! + * Returns true only if a sorted array \a x1 precedes an array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const SortedArray& x1, const array_implementation& x2 ) + { + return x1.m_array < x2; + } + + /*! + * Returns true only if an array \a x1 precedes a sorted array \a x2. + * \ingroup array_relational_operators + */ + friend bool operator <( const array_implementation& x1, const SortedArray& x2 ) + { + return x1 < x2.m_array; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each element in this array, this function appends a string + * representation (known as a \e token) to the target string \a s. If the + * array contains more than one element, successive tokens are separated + * with the specified \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform an array element to a string. The + * standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + return m_array.ToSeparated( s, separator ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each element x in this array, this function appends a string + * representation (known as a \e token) to the target string \a s by + * calling the \a append function: + * + *\code append( s, S( x ) ); \endcode + * + * If the array contains more than one element, successive tokens are + * separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform an + * array element to a string. The standard String and IsoString PCL classes + * provide the required functionality for most scalar types, although it is + * probably easier to use String::ToSeparated() and IsoString::ToSeparated() + * instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + return m_array.ToSeparated( s, separator, append ); + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return m_array.ToCommaSeparated( s ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return m_array.ToSpaceSeparated( s ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return m_array.ToTabSeparated( s ); + } + + /*! + * Generates a newline-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\n' ); \endcode + */ + template + S& ToNewLineSeparated( S& s ) const + { + return m_array.ToNewLineSeparated( s ); + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this array. + * + * This function calls pcl::Hash64() for the internal array buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const + { + return m_array.Hash64( seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this array. + * + * This function calls pcl::Hash32() for the internal array buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const + { + return m_array.Hash32( seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this array. This + * function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const + { + return Hash64( seed ); + } + + // ------------------------------------------------------------------------- + +private: + + array_implementation m_array; +}; + +// ---------------------------------------------------------------------------- + +/*! + * Adds an object \a v to a sorted array \a x. Returns a reference to the + * sorted array. + * + * The template argument type T must have conversion semantics from the type V, + * such as T::T( const V& ) or equivalent. + * \ingroup array_insertion_operators + */ +template inline +SortedArray& operator <<( SortedArray& x, const V& v ) +{ + x.Add( T( v ) ); + return x; +} + +/*! + * Adds an object \a v to a temporary sorted array \a x. Returns a reference to + * the sorted array. + * + * The template argument type T must have conversion semantics from the type V, + * such as T::T( const V& ) or equivalent. + * \ingroup array_insertion_operators + */ +template inline +SortedArray& operator <<( SortedArray&& x, const V& v ) +{ + x.Add( T( v ) ); + return x; +} + +/*! + * Adds a sorted array \a x2 to a sorted array \a x1. Returns a reference to + * the left-hand sorted array \a x1. + * \ingroup array_insertion_operators + */ +template inline +SortedArray& operator <<( SortedArray& x1, const SortedArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds a sorted array \a x2 to a temporary sorted array \a x1. Returns a + * reference to the left-hand sorted array \a x1. + * \ingroup array_insertion_operators + */ +template inline +SortedArray& operator <<( SortedArray&& x1, const SortedArray& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds an array \a x2 to a sorted array \a x1. Returns a reference to the + * left-hand sorted array \a x1. + * \ingroup array_insertion_operators + */ +template inline +SortedArray& operator <<( SortedArray& x1, const Array& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +/*! + * Adds an array \a x2 to a temporary sorted array \a x1. Returns a reference + * to the left-hand sorted array \a x1. + * \ingroup array_insertion_operators + */ +template inline +SortedArray& operator <<( SortedArray&& x1, const Array& x2 ) +{ + x1.Add( x2 ); + return x1; +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SortedArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SortedArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SphericalRotation.h b/3rdparty/include/pcl/SphericalRotation.h new file mode 100644 index 0000000..9715088 --- /dev/null +++ b/3rdparty/include/pcl/SphericalRotation.h @@ -0,0 +1,131 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SphericalRotation.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_SphericalRotation_h +#define __PCL_SphericalRotation_h + +/// \file pcl/SphericalRotation.h + +#include + +#include +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SphericalRotation + * \brief Rotation in spherical coordinates + * + * \ingroup astrometry_support + */ +class PCL_CLASS SphericalRotation +{ +public: + + constexpr static double Tolerance = 1.0e-05; + + /*! + * Default constructor. + */ + SphericalRotation() = default; + + /*! + * Copy constructor. + */ + SphericalRotation( const SphericalRotation& ) = default; + + /*! + * + */ + SphericalRotation( double lng0, double lat0, double phi0, double theta0, double phip, + const Optional& latpole ); + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SphericalRotation& operator =( const SphericalRotation& ) = default; + + /*! + * + */ + DPoint NativeToCelestial( const DPoint& np ) const; + + /*! + * + */ + DPoint CelestialToNative( const DPoint& cp ) const; + +private: + + double m_latpole; + double m_alphaP; + double m_deltaP; + double m_phiP; + double m_cosdeltaP; + double m_sindeltaP; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SphericalRotation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SphericalRotation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SpinBox.h b/3rdparty/include/pcl/SpinBox.h new file mode 100644 index 0000000..1ea538f --- /dev/null +++ b/3rdparty/include/pcl/SpinBox.h @@ -0,0 +1,484 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SpinBox.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_SpinBox_h +#define __PCL_SpinBox_h + +/// \file pcl/SpinBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SpinBox + * \brief Client-side interface to a PixInsight %SpinBox control. + * + * ### TODO: Write a detailed description for %Sizer. + */ +class PCL_CLASS SpinBox : public Control +{ +public: + + /*! + * Constructs a %SpinBox as a child control of \a parent. + */ + SpinBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %SpinBox object. + */ + virtual ~SpinBox() + { + } + + /*! + * Returns the current value of this %SpinBox control. + * + * \sa SetValue(), NormalizedValue(), SetNormalizedValue() + */ + int Value() const; + + /*! + * Sets the value of this %SpinBox control. + * + * \sa Value(), NormalizedValue(), SetNormalizedValue() + */ + void SetValue( int v ); + + /*! + * Returns the current value of this %SpinBox control as a normalized real + * value in the range [0,1]. + * + * \sa SetNormalizedValue(), Value() + */ + double NormalizedValue() const; + + /*! + * Sets the value of this %SpinBox control as a normalized real value in the + * range [0,1]. + * + * \sa NormalizedValue(), SetValue() + */ + void SetNormalizedValue( double f ); + + /*! + * Gets the range of values for this %SpinBox control. + * + * \param[out] minValue, maxValue References to the variables where the + * minimum and maximum values of this %SpinBox control will be + * copied, respectively. + * + * \sa SetRange(), MinValue(), MaxValue() + */ + void GetRange( int& minValue, int& maxValue ) const; + + /*! + * Returns the minimum value of this %SpinBox control. + * + * \sa MaxValue(), GetRange() + */ + int MinValue() const + { + int m, dum; GetRange( m, dum ); return m; + } + + /*! + * Returns the maximum value of this %SpinBox control. + * + * \sa MinValue(), GetRange() + */ + int MaxValue() const + { + int dum, m; GetRange( dum, m ); return m; + } + + /*! + * Sets the range of values for this %SpinBox control. + * + * \param minValue, maxValue New minimum and maximum values, + * respectively, for this %SpinBox control. + * + * \sa GetRange(), SetMinValue(), SetMaxValue() + */ + void SetRange( int minValue, int maxValue ); + + /*! + * Sets the minimum value of this %SpinBox control. + * + * This is a convenience member function, equivalent to + * SetRange( m, MaxValue() ) + * + * \sa SetMaxValue(), SetRange(), MinValue(), MaxValue() + */ + void SetMinValue( int m ) + { + SetRange( m, MaxValue() ); + } + + /*! + * Sets the maximum value of this %SpinBox control. + * + * This is a convenience member function, equivalent to + * SetRange( MinValue(), m ) + * + * \sa SetMinValue(), SetRange(), MinValue(), MaxValue() + */ + void SetMaxValue( int m ) + { + SetRange( MinValue(), m ); + } + + /*! + * Returns the step size of this %SpinBox control + * + * The step size is the number of units that are skipped when the user + * clicks an arrow icon on this %SpinBox control. + * + * \sa SetStepSize() + */ + int StepSize() const; + + /*! + * Sets the step size of this %SpinBox control + * + * The step size is the number of units that are skipped when the user + * clicks an arrow icon on this %SpinBox control. + * + * \sa StepSize() + */ + void SetStepSize( int ); + + /*! + * Returns true iff wrapping mode is enabled for this %SpinBox + * control. + * + * When wrapping is enabled, a %SpinBox can wrap around its minimum + * and maximum values: stepping down from MinValue() sets the spin box's + * value to its MaxValue(), and stepping up from MaxValue() will set its + * value to MinValue(). + * + * \sa EnableWrapping(), DisableWrapping() + */ + bool IsWrappingEnabled() const; + + /*! + * Enables or disables wrapping mode for this %SpinBox control. + * + * See IsWrappingEnabled() for a description of %SpinBox's wrapping mode. + * + * \sa IsWrappingEnabled(), DisableWrapping() + */ + void EnableWrapping( bool = true ); + + /*! + * Disables or enables wrapping mode for this %SpinBox control. + * + * See IsWrappingEnabled() for a description of %SpinBox's wrapping mode. + * + * This is a convenience member function, equivalent to + * EnableWrapping( !disable ) + * + * \sa IsWrappingEnabled(), EnableWrapping() + */ + void DisableWrapping( bool disable = true ) + { + EnableWrapping( !disable ); + } + + /*! + * Returns true iff this %SpinBox control is \e editable. + * + * An editable spin box allows the user to enter its current value directly + * on its Edit part. The value of a non-editable spin box can only be + * changed by clicking on its arrow icons, or by pressing the Up and Down + * keys when it has the keyboard focus. + * + * \sa SetEditable() + */ + bool IsEditable() const; + + /*! + * Enables or disables the editable state of this %SpinBox control. + * + * \sa IsEditable() + */ + void SetEditable( bool = true ); + + /*! + * Returns the prefix string of this %SpinBox control. + * + * The prefix is shown prepended to the spin box's text. It is useful to + * shown measuring or currency units. By default no prefix is shown in + * spin boxes. + * + * \sa SetPrefix(), Suffix(), SetSuffix(), MinimumValueText() + */ + String Prefix() const; + + /*! + * Sets the prefix string of this %SpinBox control. + * + * \sa Prefix(), Suffix(), SetSuffix(), MinimumValueText() + */ + void SetPrefix( const String& prefix ); + + /*! + * Disables (clears) the prefix string of this %SpinBox control. + * + * This is a convenience member function, equivalent to + * SetPrefix( String() ) + */ + void ClearPrefix() + { + SetPrefix( String() ); + } + + /*! + * Returns the suffix string of this %SpinBox control. + * + * The suffix is shown appended to the spin box's text. It is useful to + * shown measuring or currency units. By default no suffix is shown in + * spin boxes. + * + * \sa SetSuffix(), Prefix(), SetPrefix(), MinimumValueText() + */ + String Suffix() const; + + /*! + * Sets the suffix string of this %SpinBox control. + * + * \sa Suffix(), Prefix(), SetPrefix(), MinimumValueText() + */ + void SetSuffix( const String& ); + + /*! + * Disables (clears) the suffix string of this %SpinBox control. + * + * This is a convenience member function, equivalent to + * SetSuffix( String() ) + */ + void ClearSuffix() + { + SetSuffix( String() ); + } + + /*! + * Returns the minimum value text string for this %SpinBox control. + * + * When it is set to a non-empty string, the minimum value text is shown + * instead of the usual numeric literal when the spin box's value is equal + * to its minimum value. + * + * \sa SetMinimumValueText(), Prefix(), Suffix() + */ + String MinimumValueText() const; + + /*! + * Sets the minimum value text string for this %SpinBox control. + * + * \sa MinimumValueText(), Prefix(), Suffix() + */ + void SetMinimumValueText( const String& ); + + /*! + * Disables (clears) the minimum value text of this %SpinBox control. + * + * This is a convenience member function, equivalent to + * SetMinimumValueText( String() ) + */ + void ClearMinimumValueText() + { + SetMinimumValueText( String() ); + } + + /*! + * Returns true iff the text in this %SpinBox control is right-aligned. + * + * \sa SetRightAlignment(), IsLeftAligned() + */ + bool IsRightAligned() const; + + /*! + * Returns true iff the text in this %SpinBox control is left-aligned. + * + * This is a convenience member function, equivalent to + * !IsRightAligned() + * + * \sa SetLeftAlignment(), IsRightAligned() + */ + bool IsLeftAligned() const + { + return !IsRightAligned(); + } + + /*! + * Enables or disables right alignment for the text in this %SpinBox + * control. + * + * \sa IsRightAligned() + */ + void SetRightAlignment( bool = true ); + + /*! + * Enables or disables left alignment for the text in this %SpinBox + * control. + * + * This is a convenience member function, equivalent to + * SetRightAlignment( !left ) + * + * \sa IsLeftAligned() + */ + void SetLeftAlignment( bool left = true ) + { + SetRightAlignment( !left ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnValueUpdated( SpinBox& sender, int value ); + // void OnRangeUpdated( SpinBox& sender, int minValue, int maxValue ); + + /*! + * \defgroup spin_box_event_handlers SpinBox Event Handlers + */ + + /*! + * Defines the prototype of a spin box value event handler. + * + * A spin box value event is generated when the user changes the value of a + * spin box control. + * + * \param sender The control that sends a spin box value event. + * + * \param value The current value of the spin box. + * + * \ingroup spin_box_event_handlers + */ + typedef void (Control::*value_event_handler)( SpinBox& sender, int value ); + + /*! + * Defines the prototype of a spin box range event handler. + * + * A spin box range event is generated when the range of a spin box control + * is changed. + * + * \param sender The control that sends a spin box range event. + * + * \param minValue, maxValue The current minimum and maximum values of the + * spin box, respectively. + * + * \ingroup slider_event_handlers + */ + typedef void (Control::*range_event_handler)( SpinBox& sender, int minValue, int maxValue ); + + /*! + * Sets the spin box value event handler for this %SpinBox control. + * + * \param handler The spin box value event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive spin box value events + * from this %SpinBox. + * + * \ingroup spin_box_event_handlers + */ + void OnValueUpdated( value_event_handler handler, Control& receiver ); + + /*! + * Sets the slider range event handler for this %SpinBox control. + * + * \param handler The slider range event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive slider range events + * from this %SpinBox. + * + * \ingroup spin_box_event_handlers + */ + void OnRangeUpdated( range_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + value_event_handler onValueUpdated = nullptr; + range_event_handler onRangeUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class SpinBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_SpinBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SpinBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SpinStatus.h b/3rdparty/include/pcl/SpinStatus.h new file mode 100644 index 0000000..bbaf403 --- /dev/null +++ b/3rdparty/include/pcl/SpinStatus.h @@ -0,0 +1,203 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SpinStatus.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_SpinStatus_h +#define __PCL_SpinStatus_h + +/// \file pcl/SpinStatus.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SpinStatus + * \brief A status monitoring callback that shows a spinning character + * animation on the processing console. + * + * %SpinStatus is a StatusCallback derived class that generates a spinning + * character animation on the processing console. The spinning animation + * consists of successively writing the four - \ | / characters at the same + * position on the console. This is a classical form of text-based animation + * that provides a nice feedback to the user while a long process is running. + * + * %SpinStatus is suitable for processes where a total status monitoring + * count cannot be computed in advance. For example, this happens with + * processes that perform an unpredictable number of iterations while a given + * contition is not fulfilled. When a status monitoring count is available + * before running a process, the StandardStatus monitoring class is preferable. + * + * %SpinStatus and %StandardStatus are used by all standard PixInsight + * processes and file formats. Unless a specific module has an extremely good + * reason to proceed otherwise, we recommend that all modules also use these + * monitoring classes. This ensures that efficient and coherent feedback is + * provided to the user on the entire PixInsight platform. + * + * As %StandardStatus, %SpinStatus also allows the PixInsight core application + * to process mouse, keyboard and screen update events. In this way the + * application's GUI remains responsive in case the user requests aborting + * or suspending the monitored process. + * + * \sa StatusCallback, StatusMonitor, Console, StandardStatus, + * ProgressBarStatus, MuteStatus + */ +class PCL_CLASS SpinStatus : public StatusCallback +{ +public: + + /*! + * Constructs a default %SpinStatus object. + */ + SpinStatus() = default; + + /*! + * Copy constructor. + */ + SpinStatus( const SpinStatus& x ) + : StatusCallback( x ) + , m_spinCount( x.m_spinCount ) + { + } + + /*! + * Move constructor. + */ + SpinStatus( SpinStatus&& x ) + : StatusCallback( std::move( x ) ) + , m_console( std::move( x.m_console ) ) + , m_spinCount( x.m_spinCount ) + , m_thread( x.m_thread ) + { + x.m_thread = nullptr; + } + + /*! + * Destroys a %SpinStatus instance. + */ + virtual ~SpinStatus() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SpinStatus& operator =( const SpinStatus& x ) + { + (void)StatusCallback::operator =( x ); + m_spinCount = x.m_spinCount; + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SpinStatus& operator =( SpinStatus&& x ) + { + if ( this != &x ) + { + (void)StatusCallback::operator =( std::move( x ) ); + m_console = std::move( x.m_console ); + m_spinCount = x.m_spinCount; + m_thread = x.m_thread; + x.m_thread = nullptr; + } + return *this; + } + + /*! + * This function is called by a status monitor object \a m when a new + * monitored process is about to start. + */ + int Initialized( const StatusMonitor& m ) const override; + + /*! + * Function called by a status monitor object \a m to signal an update of + * the progress count for the current process. + */ + int Updated( const StatusMonitor& m ) const override; + + /*! + * Function called by a status monitor object \a m to signal that the + * current process has finished. + */ + int Completed( const StatusMonitor& m ) const override; + + /*! + * Function called by a status monitor object \a m when the progress + * information for the current process has been changed. + */ + void InfoUpdated( const StatusMonitor& m ) const override; + +private: + + mutable pcl::Console m_console; + mutable unsigned m_spinCount = 0; + mutable void* m_thread = nullptr; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_SpinStatus_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SpinStatus.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StandardAllocator.h b/3rdparty/include/pcl/StandardAllocator.h new file mode 100644 index 0000000..63cbade --- /dev/null +++ b/3rdparty/include/pcl/StandardAllocator.h @@ -0,0 +1,349 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StandardAllocator.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_StandardAllocator_h +#define __PCL_StandardAllocator_h + +/// \file pcl/StandardAllocator.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class StandardAllocator + * \brief A block allocator class that uses the standard new and delete + * operators. + * + * %StandardAllocator is a block allocator class. It is used by + * default for all container classes in PCL. It defines default block sizing + * and growing strategies that work efficiently in most cases. + * + * For a complete description of block allocators and their fundamental role in + * PCL, read the documentation for the Allocator class. + * + * \sa Allocator, AlignedAllocator + */ +class PCL_CLASS StandardAllocator +{ +public: + + /*! + * Constructs a %StandardAllocator object. + * + * \param fastGrowth Whether to enable the fast block size growing policy + * for this allocator. + * + * \param canShrink Whether to enable the block shrinking policy for + * this allocator. + * + * See the IsFastGrowthEnabled() and IsShrinkingEnabled() member functions + * for more information on block allocation policies. + */ + StandardAllocator( bool fastGrowth = true, bool canShrink = true ) + : m_fastGrowth( fastGrowth ) + , m_canShrink( canShrink ) + { + } + + /*! + * Copy constructor. + */ + StandardAllocator( const StandardAllocator& ) = default; + + /*! + * Returns the size in bytes of the largest contiguous block that this + * object is able to allocate. + * + * %StandardAllocator can (theoretically) allocate ~size_type( 0 ) bytes. + * This poses no practical limit on 64-bit systems. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + */ + size_type MaxSize() const + { + return ~size_type( 0 ); + } + + /*! + * Returns the size in bytes of an allocation block suitable for + * storage of at least \a n bytes. + * + * See IsFastGrowthEnabled() for more information about block size growing + * policies in %StandardAllocator. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + * + * \sa ReallocatedBlockSize(), IsFastGrowthEnabled() + */ + size_type BlockSize( size_type n ) const + { + // Check for null allocation attempts. + if ( n == 0 ) + return 0; + + // Take into account a reasonable upper limit for the size in bytes of an + // allocation block header. + const size_type blockHeaderSize = 4*sizeof( void* ); + n += blockHeaderSize; + + // Grow linearly by 8-byte chunks for n < 64 bytes. + if ( n < 64 ) + return ((n >> 3) << 3) + 8 - blockHeaderSize; + + // Grow exponentially by doubling container capacity if fast growing is + // enabled or n < 64 KiB. + if ( IsFastGrowthEnabled() || n < 65536 ) + { + size_type nn = 64; + while ( nn < n ) + nn <<= 1; + return nn - blockHeaderSize; + } + + // If fast growing is disabled or n >= 64 KiB, grow linearly by 4 KiB + // chunks. + return ((n >> 12) << 12) + 4096 - blockHeaderSize; + } + + /*! + * Returns the size in bytes of a reallocated data block. + * + * \param currentSize The current size in bytes of an allocated data block. + * + * \param newSize The new size in bytes of the reallocated data block. + * + * See IsFastGrowthEnabled() and IsShrinkingEnabled() for information about + * block size allocation and reallocation policies in %StandardAllocator. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + * + * \sa BlockSize(), IsShrinkingEnabled(), IsFastGrowthEnabled() + */ + size_type ReallocatedBlockSize( size_type currentSize, size_type newSize ) const + { + return (currentSize < newSize || m_canShrink) ? BlockSize( newSize ) : currentSize; + } + + /*! + * Custom allocation routine. Allocates a contiguous memory block of the + * specified \a size in bytes, and returns the address of the first byte in + * the newly allocated block. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + * + * \sa DeallocateBlock() + */ + void* AllocateBlock( size_type size ) + { + PCL_PRECONDITION( size != 0 ) + return ::operator new( size ); + } + + /*! + * Custom deallocation routine. Deallocates a previously allocated + * contiguous memory block that begins at the specified location \a p. + * + * \note This member function is mandatory for a block allocator to be + * usable by the Allocator class. + * + * \sa AllocateBlock() + */ + void DeallocateBlock( void* p ) + { + PCL_PRECONDITION( p != nullptr ) + ::operator delete( p ); + } + + /*! + * Returns true iff fast growth is currently enabled for this + * allocator. + * + * When fast growth is enabled, %StandardAllocator provides block sizes + * that grow exponentially above 64 bytes: 128, 256, 512, 1K, ... 512K, 1M, + * and so on. This maximizes speed of dynamic allocation operations, but at + * the cost of more memory wasted by partially used blocks in + * contiguous-storage containers such as Array or String. + * + * With fast growth disabled, %StandardAllocator follows a more conservative + * scheme to provide reasonable block sizes while preventing excessive + * memory consumption. For block sizes below 64 kilobytes, blocks grow + * exponentially to improve efficiency of allocation for small objects, such + * as short strings. For blocks larger than 64K, block sizes grow by + * constant chunks of 4K. + * + * The fast block size growing policy is always enabled by default. + * + * \sa EnableFastGrowth(), DisableFastGrowth(), BlockSize() + */ + bool IsFastGrowthEnabled() const + { + return m_fastGrowth; + } + + /*! + * Enables the fast block size growing policy for %StandardAllocator. + * + * See IsFastGrowthEnabled() for more information about block size growing + * policies. + * + * \sa IsFastGrowthEnabled(), DisableFastGrowth() + */ + void EnableFastGrowth( bool enable = true ) + { + m_fastGrowth = enable; + } + + /*! + * Disables the fast block size growing policy for %StandardAllocator. + * + * See IsFastGrowthEnabled() for more information about block size growing + * policies. + * + * \sa IsFastGrowthEnabled(), EnableFastGrowth() + */ + void DisableFastGrowth( bool disable = true ) + { + EnableFastGrowth( !disable ); + } + + /*! + * Returns true iff block shrinking is currently enabled for this + * allocator. + * + * When block shrinking is enabled, %StandardAllocator allows size + * reductions for reallocated blocks in calls to the ReallocatedBlockSize(). + * When block shrinking is disabled, already allocated blocks can only be + * reallocated with increased lengths. + * + * The block shrinking policy is always enabled by default. + * + * \sa EnableShrinking(), DisableShrinking(), ReallocatedBlockSize() + */ + bool IsShrinkingEnabled() const + { + return m_canShrink; + } + + /*! + * Enables a block shrinking policy for %StandardAllocator. + * + * See IsShrinkingEnabled() for more information about block shrinking + * policies. + * + * \sa IsShrinkingEnabled(), DisableShrinking() + */ + void EnableShrinking( bool enable = true ) + { + m_canShrink = enable; + } + + /*! + * Disables a block shrinking policy for %StandardAllocator. + * + * See IsShrinkingEnabled() for more information about block shrinking + * policies. + * + * \sa IsShrinkingEnabled(), EnableShrinking() + */ + void DisableShrinking( bool disable = true ) + { + EnableShrinking( !disable ); + } + +private: + + bool m_fastGrowth : 1; + bool m_canShrink : 1; +}; + +} // pcl + +// ---------------------------------------------------------------------------- + +/*! + * Placement new operator for class StandardAllocator. Returns the specified + * address \a p. + */ +inline void* operator new( pcl::size_type, void* p, pcl::StandardAllocator& ) +{ + PCL_PRECONDITION( p != nullptr ) + return p; +} + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable: 4100 ) // 'unreferenced formal parameter' + +inline void operator delete( void* p, void*, pcl::StandardAllocator& ) +{ + PCL_PRECONDITION( p != nullptr ) +} + +#pragma warning( pop ) +#endif // _MSC_VER + +// ---------------------------------------------------------------------------- + +#endif // __PCL_StandardAllocator_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StandardAllocator.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StandardStatus.h b/3rdparty/include/pcl/StandardStatus.h new file mode 100644 index 0000000..1f205f5 --- /dev/null +++ b/3rdparty/include/pcl/StandardStatus.h @@ -0,0 +1,202 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StandardStatus.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_StandardStatus_h +#define __PCL_StandardStatus_h + +/// \file pcl/StandardStatus.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class StandardStatus + * \brief A status monitoring callback that sends progress information to the + * process console. + * + * %StandardStatus uses the processing console associated with the current + * processing thread to provide feedback and progress information on a + * process being monitored by a StatusMonitor object. + * + * %StandardStatus is suitable for processes where a total status + * monitoring count can be computed in advance. For example, this happens + * with processes that operate on a pixel-by-pixel basis and perform a fixed + * number of iterations, or a number of iterations that can be predicted before + * running the process. For cases where a total count is not available or + * cannot be computed, the SpinStatus class is more suitable. + * + * %StandardStatus and %SpinStatus are used by all standard PixInsight + * processes and file formats. Unless a specific module has an extremely good + * reason to proceed otherwise, we recommend that all modules also use these + * monitoring classes. This ensures that efficient and coherent feedback is + * provided to the user on the entire PixInsight platform. + * + * In addition, using %StandardStatus (and also %SpinStatus) allows the + * PixInsight core application to process mouse, keyboard and screen update + * events. In this way the application's GUI can be responsive if the user + * requests aborting or suspending the monitored process. + * + * \sa StatusCallback, StatusMonitor, Console, SpinStatus, ProgressBarStatus, + * MuteStatus + */ +class PCL_CLASS StandardStatus : public StatusCallback +{ +public: + + /*! + * Constructs a default %StandardStatus object. + */ + StandardStatus() = default; + + /*! + * Copy constructor. + */ + StandardStatus( const StandardStatus& x ) + : StatusCallback( x ) + , m_last( x.m_last ) + { + } + + /*! + * Move constructor. + */ + StandardStatus( StandardStatus&& x ) + : StatusCallback( std::move( x ) ) + , m_console( std::move( x.m_console ) ) + , m_last( x.m_last ) + , m_thread( x.m_thread ) + { + x.m_thread = nullptr; + } + + /*! + * Destroys a %StandardStatus instance. + */ + virtual ~StandardStatus() + { + } + + /*! + * Copy constructor. Returns a reference to this object. + */ + StandardStatus& operator =( const StandardStatus& x ) + { + (void)StatusCallback::operator =( x ); + m_last = x.m_last; + return *this; + } + + /*! + * Move constructor. Returns a reference to this object. + */ + StandardStatus& operator =( StandardStatus&& x ) + { + if ( this != &x ) + { + (void)StatusCallback::operator =( std::move( x ) ); + m_console = std::move( x.m_console ); + m_last = x.m_last; + m_thread = x.m_thread; + x.m_thread = nullptr; + } + return *this; + } + + /*! + * This function is called by a status \a monitor object when a new + * monitored process is about to start. + */ + int Initialized( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object to signal an update of the + * progress count for the current process. + */ + int Updated( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object to signal that the current + * process has finished. + */ + int Completed( const StatusMonitor& monitor ) const override; + + /*! + * Function called by a status \a monitor object when the progress + * information for the current process has been changed. + */ + void InfoUpdated( const StatusMonitor& monitor ) const override; + +private: + + mutable pcl::Console m_console; + mutable int m_last = -1; + mutable void* m_thread = nullptr; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_StandardStatus_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StandardStatus.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StarDatabaseFile.h b/3rdparty/include/pcl/StarDatabaseFile.h new file mode 100644 index 0000000..70ad829 --- /dev/null +++ b/3rdparty/include/pcl/StarDatabaseFile.h @@ -0,0 +1,746 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StarDatabaseFile.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_StarDatabaseFile_h +#define __PCL_StarDatabaseFile_h + +/// \file pcl/StarDatabaseFile.h + +#include + +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup point_source_databases Star Catalogs and Point Source Databases + */ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS StarDatabaseFile; + +/*! + * \class XPSD + * \brief Base class of point source database implementations. + * + * This class defines a set of fundamental data structures, properties and + * support routines associated with point source database files (XPSD format). + * + * \ingroup point_source_databases + */ +class PCL_CLASS XPSD +{ +public: + + /*! + * \struct pcl::XPSD::Metadata + * \brief %Metadata items available in point source database files. + * + * This structure holds metadata items that can be stored in point source + * database files (current XPSD format version 1.0). For an existing + * database file, available metadata are extracted directly from %XML file + * headers. Currently all items are optional, so all data members of this + * structure can be empty strings. + * + * For generation of new XPSD files, the creationTime and creatorOS members + * of this structure will be ignored, since the corresponding metadata items + * will always be defined automatically by the StarDatabaseFile::Serialize() + * routine. The specified creatorApplication member, if empty, will be + * replaced in the same routine with a default value identifying the current + * PCL version. + * + * \ingroup point_source_databases + */ + struct Metadata + { + TimePoint creationTime; //!< The date this file was created. + String creatorOS; //!< The operating system on which this file was created. + String creatorApplication; //!< The software application or program that created this file. + String databaseIdentifier; //!< The unique identifier of the database this file belongs to. + String databaseVersion; //!< The version of the database this file belongs to. + String title; //!< A title that represents or identifies this XPSD file. + String briefDescription; //!< A brief (single-line) description of this XPSD file. + String description; //!< A full description of the data stored in this XPSD file. + String organizationName; //!< The name of the organization responsible for this file. + String authors; //!< The names of one or more persons or groups that have created the data in this file. + String copyright; //!< Copyright information applicable to the data stored in this XPSD file. + }; + + /*! + * \struct pcl::XPSD::Statistics + * \brief Structural and statistical data about an XPSD database file. + * + * This structure provides information about the number of sources included + * in an XPSD file, as well as critical data about its tree-based database + * index structure. + * + * \ingroup point_source_databases + */ + struct Statistics + { + uint64 totalSources = 0; //!< The total number of sources included in this database. + uint32 totalNodes = 0; //!< Number of quadtree index nodes, including structural and leaf nodes. + uint32 totalLeaves = 0; //!< Number of quadtree index leaf nodes. + float medianLeafLength = 0; //!< The median of quadtree leaf node lengths. + uint32 minimumLeafLength = 0; //!< Minimum quadtree leaf node length. + uint32 maximumLeafLength = 0; //!< Maximum quadtree leaf node length. + }; + + /*! + * \struct SearchData + * \brief Data items and parameters for catalog search operations. + * + * The StarData template parameter represents a catalog-specific structure + * to hold the data associated with a point source extracted during a + * database search operation. + * + * \ingroup point_source_databases + */ + template + struct SearchData + { + double centerRA = 0; //!< Field center right ascension coordinate in degrees (search parameter). + double centerDec = 0; //!< Field center declination coordinate in degrees (search parameter). + double radius = 1; //!< Field radius in degrees (search parameter). + float magnitudeLow = -1.5; /*!< Low magnitude (search parameter). Only stars of magnitude greater + than or equal to this value will be included in the stars list. */ + float magnitudeHigh = 26; /*!< High magnitude (search parameter). Only stars of magnitude less + than or equal to this value will be included in the stars list. */ + uint32 sourceLimit = uint32_max; /*!< The search will not include more objects than this limit + in the stars list (search parameter). */ + uint32 requiredFlags = 0u; /*!< Required flags (search parameter). If non-zero, only stars with + \e all of these flags set will be included in the stars list. */ + uint32 inclusionFlags = 0u; /*!< Inclusion flags (search parameter). If non-zero, only stars with + \e any of these flags set will be included in the stars list. */ + uint32 exclusionFlags = 0u; /*!< Exclusion flags (search parameter). Stars with \e any of these flags + set will \e not be included in the stars list. */ + + Array stars; //!< The list of stars found by the search operation (output data). + uint32 excessCount = 0u; /*!< When \a sourceLimit is exceeded, this is the number of + additional objects found but not included in the stars list (output data). */ + uint32 rejectCount = 0u; /*!< Total number of rejected objects (output data). This refers to + point sources that have been tested for inclusion in the search + result, but have not matched the search criteria. */ + double timeTotal = 0; //!< Total search time in seconds (output data). + double timeIO = 0; //!< Time consumed by I/O operations in seconds (output data). + uint32 countIO = 0u; //!< Total number of I/O operations performed (output data). + double timeUncompress = 0; //!< Time consumed by data uncompression in seconds (output data). + double timeDecode = 0; //!< Time consumed by data decoding in seconds (output data). + + /*! + * Sets all search result data items to null values. + */ + void ResetSearchResults() + { + stars.Clear(); + excessCount = rejectCount = 0u; + timeTotal = timeIO = 0; + countIO = 0u; + timeUncompress = timeDecode = 0; + } + }; + +protected: + + struct ChildNodeData + { + // Zero-based quadtree child node positions in an index node array. + uint32 nw; // top-left child node + uint32 ne; // top-right child node + uint32 sw; // bottom-left child node + uint32 se; // bottom-right child node + }; + +#ifdef _MSC_VER + /* + * Our favorite brain-damaged thing does not know how to implement bit + * fields. Oh well... + */ + struct LeafNodeData + { + uint64 blockOffsetAndLeafFlag; + uint32 blockSize; + uint32 compressedBlockSize; + }; +#else + struct LeafNodeData + { + uint64 blockOffset : 63; // position of source data block, byte offset + bool leafFlag : 1; // quadtree node type: 0=structural 1=leaf + uint32 blockSize; // size of point source data, in bytes + uint32 compressedBlockSize; // size of compressed data, in bytes + }; +#endif + + /* + * Quadtree index node (48 bytes). + */ + struct IndexNode + { + // Projected coordinates of quadtree node rectangle. + double x0; // left + double y0; // top + double x1; // right + double y1; // bottom + + // Quadtree child node indexes or leaf node data. + union { ChildNodeData child; + LeafNodeData leaf; } index; + + IndexNode() + { + static_assert( sizeof( *this ) == 48, "Invalid sizeof( XPSD::IndexNode )" ); + static_assert( sizeof( ChildNodeData ) == 16, "Invalid sizeof( XPSD::ChildNodeData )" ); + static_assert( sizeof( LeafNodeData ) == 16, "Invalid sizeof( XPSD::LeafNodeData )" ); + static_assert( sizeof( index ) == 16, "Invalid sizeof( XPSD::IndexNode::index )" ); + + index.child.nw = index.child.ne = index.child.sw = index.child.se = 0; + } + + bool IsLeaf() const + { +#ifdef _MSC_VER + return (index.leaf.blockOffsetAndLeafFlag & 0x8000000000000000) != 0; +#else + return index.leaf.leafFlag; +#endif + } + + uint64 BlockOffset() const + { +#ifdef _MSC_VER + return index.leaf.blockOffsetAndLeafFlag & 0x7FFFFFFFFFFFFFFF; +#else + return index.leaf.blockOffset; +#endif + } + + uint32 BlockSize() const + { + return index.leaf.blockSize; + } + + uint32 CompressedBlockSize() const + { + return index.leaf.compressedBlockSize; + } + }; + + static double Distance( double lon1, double lat1, double lon2, double lat2 ) + { + return Vector::FromSpherical( Rad( lon1 ), Rad( lat1 ) ).Angle3D( Vector::FromSpherical( Rad( lon2 ), Rad( lat2 ) ) ); + } + + static double CrossTrackDistance( double lon, double lat, double lon1, double lat1, double lon2, double lat2 ) + { + if ( lon == lon1 ) + if ( lat == lat1 ) + return 0; + + Vector p = Vector::FromSpherical( Rad( lon ), Rad( lat ) ); + Vector c = Vector::FromSpherical( Rad( lon1 ), Rad( lat1 ) ).Cross( Vector::FromSpherical( Rad( lon2 ), Rad( lat2 ) ) ); + return c.Angle3D( p ) - Pi()/2; + } + + static bool WithinExtent( double lon, double lat, double lon1, double lat1, double lon2, double lat2 ) + { + if ( lon1 == lon2 ) + if ( lat1 == lat2 ) + return lon == lon1 && lat == lat1; // null segment + + Vector n0 = Vector::FromSpherical( Rad( lon ), Rad( lat ) ); + Vector n1 = Vector::FromSpherical( Rad( lon1 ), Rad( lat1 ) ); + Vector n2 = Vector::FromSpherical( Rad( lon2 ), Rad( lat2 ) ); + + // Get vectors representing p0->p1, p0->p2, p1->p2, p2->p1 + Vector d10 = n0 - n1, d12 = n2 - n1; + Vector d20 = n0 - n2, d21 = n1 - n2; + + // Dot product d10*d12 tells us if p0 is on p2 side of p1, similarly for d20*d21 + if ( d10 * d12 >= 0 ) + if ( d20 * d21 >= 0 ) + return (n0 * n1) >= 0 && (n0 * n2) >= 0; // same hemisphere + + return false; + } + + static bool InRegion( double lon, double lat, + double lon1, double lat1, double lon2, double lat2, + double lon3, double lat3, double lon4, double lat4 ) + { + Vector p = Vector::FromSpherical( Rad( lon ), Rad( lat ) ); + Vector v1 = p - Vector::FromSpherical( Rad( lon1 ), Rad( lat1 ) ); + Vector v2 = p - Vector::FromSpherical( Rad( lon2 ), Rad( lat2 ) ); + Vector v3 = p - Vector::FromSpherical( Rad( lon3 ), Rad( lat3 ) ); + Vector v4 = p - Vector::FromSpherical( Rad( lon4 ), Rad( lat4 ) ); + return Abs( v1.Angle3D( v2, p ) + v2.Angle3D( v3, p ) + v3.Angle3D( v4, p ) + v4.Angle3D( v1, p ) ) > Pi(); + } + + enum projection_type { Equirectangular, TransverseEquirectangular, AzimuthalEquidistant }; + + static String ProjectionToAttributeValue( int ); + static projection_type ProjectionFromAttributeValue( const String& ); + + class IndexTree + { + public: + + IndexTree( StarDatabaseFile* parent, + projection_type projection, double centerRA, double centerDec, + const Array& nodes ) + : m_parent( parent ) + , m_projection( projection ) + , m_centerRA( centerRA ) + , m_centerDec( centerDec ) + , m_nodes( nodes ) + { + } + + IndexTree() = default; + IndexTree( const IndexTree& ) = default; + + void Project( double& x, double& y, double ra, double dec ) const + { + switch( m_projection ) + { + default: // ?! + case Equirectangular: + x = ra - m_centerRA; + y = dec; + break; + case AzimuthalEquidistant: + { + double sa, ca; + SinCos( Rad( ra ), sa, ca ); + double r = 90 - Abs( dec ); + x = r*sa; + y = r*ca; + } + break; + case TransverseEquirectangular: + { + double sa, ca; + SinCos( Rad( ra ), sa, ca ); + double sd, cd; + SinCos( Rad( Abs( dec ) ), sd, cd ); + x = Deg( ArcSin( cd*sa ) ); + y = Deg( ArcTan( sd, cd*ca ) ) - 90; + } + break; + } + } + + void Unproject( double& ra, double& dec, double x, double y ) const + { + switch( m_projection ) + { + default: // ?! + case Equirectangular: + ra = x + m_centerRA; + dec = y; + break; + case AzimuthalEquidistant: + x = Rad( x ); + y = Rad( y ); + ra = Deg( ArcTan( x, y ) ); + if ( ra < 0 ) + ra += 360; + dec = Deg( ArcSin( Cos( Sqrt( x*x + y*y ) ) ) ); + if ( m_centerDec < 0 ) + dec = -dec; + break; + case TransverseEquirectangular: + { + double sx, cx; + SinCos( Rad( x ), sx, cx ); + double sy, cy; + SinCos( Rad( y + 90 ), sy, cy ); + ra = Deg( ArcTan( sx, cx*cy ) ); + if ( ra < 0 ) + ra += 360; + dec = Deg( ArcSin( sy*cx ) ); + if ( m_centerDec < 0 ) + dec = -dec; + } + break; + } + } + + void Search( double ra, double dec, double r, void* searchData ) const + { + SearchRecursive( 0, ra, dec, r, searchData ); + } + + private: + + StarDatabaseFile* m_parent = nullptr; + projection_type m_projection = Equirectangular; + double m_centerRA = 0; + double m_centerDec = 0; + Array m_nodes; + + void GetNodeBounds( double& ra1, double& dec1, double& ra2, double& dec2, + double& ra3, double& dec3, double& ra4, double& dec4, const IndexNode& node ) const + { + Unproject( ra1, dec1, node.x0, node.y0 ); + Unproject( ra2, dec2, node.x1, node.y0 ); + Unproject( ra3, dec3, node.x1, node.y1 ); + Unproject( ra4, dec4, node.x0, node.y1 ); + } + + bool InNodeRegion( double ra, double dec, const IndexNode& node ) const + { + double ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4; + GetNodeBounds( ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4, node ); + return InRegion( ra, dec, ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4 ); + } + + bool IntersectsNodeRegion( double ra, double dec, double r, const IndexNode& node ) const + { + double ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4; + GetNodeBounds( ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4, node ); + double rr = Rad( r ); + return InRegion( ra, dec, ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4 ) + || Distance( ra, dec, ra1, dec1 ) < rr + || Distance( ra, dec, ra2, dec2 ) < rr + || Distance( ra, dec, ra3, dec3 ) < rr + || Distance( ra, dec, ra4, dec4 ) < rr + || WithinExtent( ra, dec, ra1, dec1, ra2, dec2 ) && CrossTrackDistance( ra, dec, ra1, dec1, ra2, dec2 ) < rr + || WithinExtent( ra, dec, ra2, dec2, ra3, dec3 ) && CrossTrackDistance( ra, dec, ra2, dec2, ra3, dec3 ) < rr + || WithinExtent( ra, dec, ra3, dec3, ra4, dec4 ) && CrossTrackDistance( ra, dec, ra3, dec3, ra4, dec4 ) < rr + || WithinExtent( ra, dec, ra4, dec4, ra1, dec1 ) && CrossTrackDistance( ra, dec, ra4, dec4, ra1, dec1 ) < rr; + } + + // Defined after StarDatabaseFile declaration. + void SearchRecursive( uint32 nodeIndex, double ra, double dec, double r, void* searchData ) const; + + friend class StarDatabaseFile; + }; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class StarDatabaseFile + * \brief Point source and star catalog database files (XPSD format). + * + * This class implements fast access to point source data stored in XPSD files + * (Extensible Point Source Database format). It also implements serialization + * of new XPSD files from existing point source or star catalog data. + * + * On the PixInsight/PCL platform, the XPSD file format allows for fast and + * efficient access to large star catalogs, such as Gaia (as of writing this + * documentation the Gaia DR2 and EDR3 catalogs are available) or PPMXL. The + * XPSD format allows for serialization of general purpose star catalogs, with + * special emphasis on astrometric and photometric data. + * + * \ingroup point_source_databases + */ +class PCL_CLASS StarDatabaseFile : public XPSD +{ +public: + + /*! + * Default constructor. + * + * Constructs an invalid instance that cannot be used until initialized by + * calling the Open() member function. + */ + StarDatabaseFile() = default; + + /*! + * Constructs a &StarDatabaseFile instance initialized from the specified + * point source database file in XPSD format. + * + * In the event of errors or invalid data, this constructor will throw the + * appropriate Error exception. + */ + StarDatabaseFile( const String& filePath ) + { + Open( filePath ); + } + + /*! + * Move constructor. + */ + StarDatabaseFile( StarDatabaseFile&& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + StarDatabaseFile& operator =( StarDatabaseFile&& ) = default; + + /*! + * Deleted copy constructor. %StarDatabaseFile instances are unique, hence + * cannot be copied. + */ + StarDatabaseFile( const StarDatabaseFile& ) = delete; + + /*! + * Deleted copy assignment operator. %StarDatabaseFile instances are unique, + * hence cannot be copied. + */ + StarDatabaseFile& operator =( const StarDatabaseFile& ) = delete; + + /*! + * Virtual destructor. + */ + virtual ~StarDatabaseFile() noexcept( false ) + { + } + + /*! + * Initializes this object to provide access to the specified point source + * database file in XPSD format. + * + * This member function opens an existing file at the specified \a filePath, + * loads and parses its XML header, and loads the file indexes ready for + * fast access to point source data. The file will remain open until this + * object is destroyed, or until a new call to this function is made. + * + * If a previous file was already opened by this instance, it will be closed + * and all associated control and file indexing structures will be destroyed + * and deallocated, before accessing the new file. + */ + void Open( const String& filePath ); + + /*! + * Closes the point source database file represented by this object and + * resets all internal structures to a default, uninitialized state. + * + * If a previous file was already opened by this instance, it will be closed + * and all associated control and file indexing structures will be destroyed + * and deallocated. If no file is currently open, calling this member has no + * effect. + */ + void Close(); + + /*! + * Returns true iff this object has an open database file and is ready for + * point source data retrieval. + */ + bool IsOpen() const + { + return m_file.IsOpen(); + } + + /*! + * Returns the path of the point source database file represented by this + * object. Returned file paths are always absolute, full file paths. + */ + const String& FilePath() const + { + return m_file.FilePath(); + } + + /*! + * Returns the low limiting magnitude of this database file. All contained + * sources should have magnitudes greater than the value returned by this + * function. + */ + float MagnitudeLow() const + { + return m_magnitudeLow; + } + + /*! + * Returns the high limiting magnitude of this database file. All contained + * sources should have magnitudes less than or equal to the value returned + * by this function. + */ + float MagnitudeHigh() const + { + return m_magnitudeHigh; + } + + /*! + * Returns a reference to the (immutable) set of metadata items available in + * the point source database file loaded by this object. + */ + const XPSD::Metadata& Metadata() const + { + return m_metadata; + } + + /*! + * Returns a reference to the (immutable) set of statistical and structural + * information items available in the point source database file loaded by + * this object. + */ + const XPSD::Statistics& Statistics() const + { + return m_statistics; + } + + /*! + * Generates a file to store a point source database in XPSD format. + * + * \param filePath Path to the file that will be generated in the local + * filesystem. The file name should carry the '.xpsd' + * suffix. + * + * \param metadata Reference to an XPSD::Metadata structure with + * optional metadata information that will be included + * in the generated XPSD file. + * + * \param statistics Reference to an XPSD::Statistics structure with + * statistical and structural information about the + * XPSD database, which will be included in the + * generated XPSD file. + * + * \param magnitudeLow Low limiting magnitude. All point sources serialized + * in the \a data array should have magnitudes greater + * than the value of this parameter. + * + * \param magnitudeHigh High limiting magnitude. All point sources + * serialized in the \a data array should have + * magnitudes less than or equal to the value of this + * parameter. + * + * \param index Array of quadtree index structures. + * + * \param data Serialized point source data. + * + * \param compression Pointer to a Compression object used to compress + * point source data blocks (leaf node data), or + * nullptr if no compression has been applied. If + * specified, this object will be used exclusively to + * gather information about the compression algorithm + * and parameters used, \e not to compress any data. + * + * In the event of invalid, incongruent or malformed data, or if an I/O + * error occurs, this function will throw an Error exception. + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + static void Serialize( const String& filePath, + const XPSD::Metadata& metadata, + const XPSD::Statistics& statistics, + float magnitudeLow, float magnitudeHigh, + const Array& index, + const ByteArray& data, + const Compression* compression = nullptr ); + +protected: + + mutable File m_file; + XPSD::Metadata m_metadata; + XPSD::Statistics m_statistics; + float m_magnitudeLow = 0; + float m_magnitudeHigh = 0; + Array m_index; + uint64 m_dataPosition = 0; + AutoPointer m_compression; + + virtual void LoadData( void* block, uint64 offset, uint32 size, void* ) const + { + m_file.SetPosition( m_dataPosition + offset ); + m_file.Read( block, size ); + } + + virtual void Uncompress( ByteArray& block, uint32 uncompressedSize, void* ) const + { + if ( m_compression ) + block = m_compression->Uncompress( block, uncompressedSize ); + } + + virtual void GetEncodedData( const ByteArray&, const XPSD::IndexTree&, const XPSD::IndexNode&, void* ) const = 0; + + friend class XPSD::IndexTree; +}; + +// ---------------------------------------------------------------------------- + +inline void +XPSD::IndexTree::SearchRecursive( uint32 nodeIndex, double ra, double dec, double r, void* searchData ) const +{ + const IndexNode& node = m_nodes[nodeIndex]; + if ( IntersectsNodeRegion( ra, dec, r, node ) ) + { + if ( node.IsLeaf() ) + { + ByteArray block( size_type( node.CompressedBlockSize() ) ); + m_parent->LoadData( block.Begin(), node.BlockOffset(), node.CompressedBlockSize(), searchData ); + if ( node.CompressedBlockSize() != node.BlockSize() ) + m_parent->Uncompress( block, node.BlockSize(), searchData ); + m_parent->GetEncodedData( block, *this, node, searchData ); + } + else + { + if ( node.index.child.nw != 0 ) + SearchRecursive( node.index.child.nw, ra, dec, r, searchData ); + if ( node.index.child.ne != 0 ) + SearchRecursive( node.index.child.ne, ra, dec, r, searchData ); + if ( node.index.child.sw != 0 ) + SearchRecursive( node.index.child.sw, ra, dec, r, searchData ); + if ( node.index.child.se != 0 ) + SearchRecursive( node.index.child.se, ra, dec, r, searchData ); + } + } +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_StarDatabaseFile_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StarDatabaseFile.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StarDetector.h b/3rdparty/include/pcl/StarDetector.h new file mode 100644 index 0000000..122c33b --- /dev/null +++ b/3rdparty/include/pcl/StarDetector.h @@ -0,0 +1,664 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StarDetector.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_StarDetector_h +#define __PCL_StarDetector_h + +/// \file pcl/StarDetector.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class StarDetector + * \brief Automatic star detection + * \sa PSFFit, PSFSignalEstimator + */ +class PCL_CLASS StarDetector : public ParallelProcess +{ +public: + + /*! + * Represents a point spread function type. + */ + typedef PSFFit::psf_function psf_function; + + /*! + * \struct pcl::StarDetector::Star + * \brief Structure to hold the data of a detected star. + */ + struct Star + { + /*! + * The type of a coordinate used to represent star positions (barycenter + * or PSF centroid coordinates). + */ + typedef DPoint::component component; + + DPoint pos = 0.0; /*!< Star position in image coordinates. Corresponds to the centroid of + the fitted PSF when PSF fitting is enabled; to the barycenter + calculated by the star detection algorithm otherwise. */ + Rect rect = 0; //!< Detection region in pixels, image coordinates. + float flux = 0; //!< Total flux minus local background. + float signal = 0; /*!< Estimated mean signal over the local background within the PSF + fitting region. Nonzero only when PSF fitting is enabled. */ + float mad = 0; /*!< Robust average absolute deviation of the fitted PSF with respect + to sampled image data. */ + Star* ref = nullptr; //!< Referenced star, useful for cross-referencing applications. + + /*! + * Default constructor. + */ + Star() = default; + + /*! + * Constructs a new %Star object with the specified position \a p in + * image coordinates, total flux \a f, mean signal \a s and PSF average + * deviation \a m. + */ + Star( const DPoint& p, const Rect& r, float f = 0, float s = 0, float m = 0 ) + : pos( p ), rect( r ), flux( f ), signal( s ), mad( m ) + { + } + + /*! + * Copy constructor. + */ + Star( const Star& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + Star& operator =( const Star& ) = default; + + /*! + * Equality operator. Two stars are equal iff they are located at the + * same coordinates, i.e at the same barycenter or centroid position. + */ + bool operator ==( const Star& s ) const + { + return pos == s.pos; + } + + /*! + * Less-than relational operator. By default stars are sorted by + * brightness in descending order. Stars with larger flux values come + * first in a sorted list. + */ + bool operator <( const Star& s ) const + { + return flux > s.flux; + } + + /*! + * Array subscript operator for coordinate selection, compatible with + * pcl::QuadTree. + */ + component operator []( int i ) const + { + return pos[i]; + } + }; + + /*! + * A dynamic array of detected pcl::StarDetector::Star structures. + */ + typedef Array star_list; + + /*! + * Default constructor. + */ + StarDetector() = default; + + /*! + * Copy constructor. + */ + StarDetector( const StarDetector& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + StarDetector& operator =( const StarDetector& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~StarDetector() + { + } + + /*! + * Number of (dyadic) wavelet layers used for structure detection. + * + * This parameter determines the size in pixels of the largest image + * structures that can be detected. With more layers, larger stars (and + * perhaps also some nonstellar objects) will be detected. The default value + * is 5, which corresponds to structures in the scale of 32 pixels. + * + * \note Although the current star detection algorithm does not use a + * wavelet transform for structure detection, this parameter is still + * expressed as a number of dyadic wavelet layers for convenience and + * compatibility with existing implementations. + */ + int StructureLayers() const + { + return m_structureLayers; + } + + /*! + * Sets the number of wavelet layers used for structure detection. See + * StructureLayers() for a description of this parameter. + */ + void SetStructureLayers( int n ) + { + PCL_PRECONDITION( n > 0 && n <= 8 ) + m_structureLayers = Range( n, 1, 8 ); + } + + /*! + * Number of (dyadic) wavelet layers used for noise reduction. + * + * Noise reduction prevents detection of bright noise structures as false + * stars, including hot pixels and cosmic rays. This parameter can also be + * used to control the sizes of the smallest detected stars (increase it to + * exclude more stars), although the minimum structure size + * parameter can be more efficient for this purpose. The default value is 0, + * which effectively disables this noise reduction feature. + * + * \note Although the current star detection algorithm does not use a + * wavelet transform for structure detection, this parameter is still + * expressed as a number of dyadic wavelet layers for convenience and + * compatibility with existing implementations. + */ + int NoiseLayers() const + { + return m_noiseLayers; + } + + /*! + * Sets the number of wavelet layers used for noise reduction. See + * NoiseLayers() for a description of this parameter. + */ + void SetNoiseLayers( int n ) + { + PCL_PRECONDITION( n >= 0 && n <= 4 ) + m_noiseLayers = Range( n, 0, 4 ); + } + + /*! + * Size of the hot pixel removal filter. + * + * This is the radius in pixels of a median filter applied by the star + * detector before the structure detection phase. A median filter is very + * efficient to remove hot pixels. To disable hot pixel removal, set this + * parameter to zero. The default value is 1 pixel. + */ + int HotPixelFilterRadius() const + { + return m_hotPixelFilterRadius; + } + + /*! + * Sets the size of the hot pixel removal filter. See HotPixelFilterRadius() + * for a description of this parameter. + */ + void SetHotPixelFilterRadius( int n ) + { + PCL_PRECONDITION( n >= 0 && n <= 3 ) + m_hotPixelFilterRadius = Range( n, 0, 3 ); + } + + /*! + * Size of the noise reduction filter. + * + * This is the radius in pixels of a Gaussian convolution filter applied to + * the working image used for calculation of star positions during the star + * detection phase. Use it only for very low SNR images, where the star + * detector cannot find reliable stars with default parameters. + * + * Be aware that noise reduction will modify star profiles and hence the way + * star positions are calculated, resulting in a less accurate centroid + * determination. Under extreme low-SNR conditions, however, this is + * probably better than working with the actual data anyway. + * + * The default value is zero, which effectively disables this feature. + */ + int NoiseReductionFilterRadius() const + { + return m_noiseReductionFilterRadius; + } + + /*! + * Sets the size in pixels of the noise reduction filter. See + * NoiseReductionFilterRadius() for a description of this parameter. + */ + void SetNoiseReductionFilterRadius( int n ) + { + PCL_PRECONDITION( n >= 0 && n <= 64 ) + m_noiseReductionFilterRadius = Range( n, 0, 64 ); + } + + /*! + * Minimum size of a detectable star structure in square pixels. + * + * This parameter can be used to prevent detection of small and bright image + * artifacts as stars. This can be useful to work with uncalibrated or + * wrongly calibrated data, especially demosaiced CFA frames where hot + * pixels have generated large bright artifacts that cannot be removed with + * a median filter, poorly focused images, and images with poor tracking. + * + * The default value is zero, which effectively disables this feature. + */ + int MinStructureSize() const + { + return m_minStructureSize; + } + + /*! + * Sets the minimum size of a detectable star structure in square pixels. + * See MinStructureSize() for a description of this parameter. + */ + void SetMinStructureSize( int n ) + { + PCL_PRECONDITION( n >= 0 ) + m_minStructureSize = Max( 0, n ); + } + + /*! + * Star detection sensitivity. + * + * The sensitivity of the star detection algorithm is measured with respect + * to the local background of each detected star. Given a star with + * estimated brightness \e s and local background \e b, sensitivity is the + * minimum value of (\e s - \e b)/\e b necessary to trigger star detection. + * + * Decrease this value to favor detection of fainter stars. Increase it to + * restrict detection to brighter stars. The default value is 0.1. + */ + float Sensitivity() const + { + return m_sensitivity; + } + + /*! + * Sets the star detection sensitivity. See Sensitivity() for a description + * of this parameter. + */ + void SetSensitivity( float s ) + { + PCL_PRECONDITION( s >= 0.001 && s <= 1000 ) + m_sensitivity = Range( s, 0.001F, 1000.0F ); + } + + /*! + * Star peak response. + * + * If you decrease this value, stars will need to have stronger (or more + * prominent) peaks to be detected by the star detection algorithm. This is + * useful to prevent detection of saturated stars, as well as small + * nonstellar features. By increasing this parameter, the star detection + * algorithm will be more sensitive to \e peakedness, and hence more + * tolerant with relatively flat image features. The default value is 0.8. + */ + float PeakResponse() const + { + return m_peakResponse; + } + + /*! + * Sets the star peak response. See PeakResponse() for a description of this + * parameter. + */ + void SetPeakResponse( float r ) + { + PCL_PRECONDITION( r >= 0 && r <= 1 ) + m_peakResponse = Range( r, 0.0F, 1.0F ); + } + + /*! + * Maximum star distortion. + * + * Star distortion is measured with respect to a perfect square, whose + * distortion is 1. Lower values mean more distortion. The distortion of a + * perfectly circular star is about 0.8 (actually, π/4). Use this + * parameter, if necessary, to control inclusion of elongated stars, + * multiple stars, and nonstellar image features. The default value is 0.5. + */ + float MaxDistortion() const + { + return m_maxDistortion; + } + + /*! + * Sets the maximum star distortion. See MaxDistortion() for a description + * of this parameter. + */ + void SetMaxDistortion( float d ) + { + PCL_PRECONDITION( d >= 0 && d <= 1 ) + m_maxDistortion = Range( d, 0.0F, 1.0F ); + } + + /*! + * Upper star detection limit in the normalized [0,1] range. + * + * Stars with peak values larger than this value won't be detected. This can + * be useful to reject all stars brighter than a fixed level systematically. + * The default value is 1.0, which effectively disables this feature. + */ + float UpperLimit() const + { + return m_upperLimit; + } + + /*! + * Sets the upper star detection limit. See UpperLimit() for a description + * of this parameter. + */ + void SetUpperLimit( float u ) + { + PCL_PRECONDITION( u >= 0 && u <= 1 ) + m_upperLimit = Range( u, 0.0F, 1.0F ); + } + + /*! + * Returns true iff image inversion is enabled for this star detector. + * + * When inversion is enabled, the star detector algorithm will look for dark + * stars over a bright background. This feature is disabled by default. + */ + bool IsImageInversionEnabled() const + { + return m_invert; + } + + /*! + * Enables image inversion. See IsImageInversionEnabled() for a description + * of this parameter. + */ + void EnableImageInversion( bool enabled = true ) + { + m_invert = enabled; + } + + /*! + * Disables image inversion. See IsImageInversionEnabled() for a description + * of this parameter. + */ + void DisableImageInversion( bool disable = true ) + { + EnableImageInversion( !disable ); + } + + /*! + * Returns true iff PSF fitting is enabled for this star detector. + * + * When PSF fitting is enabled, a point spread function of the type + * specified by PSFType() will be fitted numerically for each detected star. + * The Levenberg-Marquardt non-linear least squares algorithm will be used + * to minimize the difference between the fitted function and the pixel + * sample values in the detection region. See the PSFFit class for complete + * information on our PSF fitting implementation. + * + * When PSF fitting is enabled, the \c pos data member of the + * pcl::StarDetector::Star corresponds to the centroid of the fitted PSF + * instead of the barycenter position calculated by the star detection + * algorithm, and the \c signal member is a robust estimate of the mean + * signal evaluated over the local background, also from the fitted PSF. + * + * PSF fitting is disabled by default. + */ + bool IsPSFFittingEnabled() const + { + return m_fitPSF; + } + + /*! + * Enables PSF fitting for this star detector. See IsPSFFittingEnabled() for + * a description of this parameter. + */ + void EnablePSFFitting( bool enable = true ) + { + m_fitPSF = enable; + } + + /*! + * Disables PSF fitting for this star detector. See IsPSFFittingEnabled() + * for a description of this parameter. + */ + void DisablePSFFitting( bool disable = true ) + { + EnablePSFFitting( !disable ); + } + + /*! + * Returns the type of point spread function (PSF) fitted numerically when + * PSF fitting is enabled. See IsPSFFittingEnabled() and the pcl::PSFunction + * namespace. + */ + psf_function PSFType() const + { + return m_psfType; + } + + /*! + * Sets the type of point spread function (PSF) fitted numerically when PSF + * fitting is enabled. See PSFType(). + */ + void SetPSFType( psf_function type ) + { + m_psfType = type; + } + + /*! + * Returns true if elliptical point spread functions (PSFs) will be fitted + * when PSF fitting is enabled. Returns false if circular functions will be + * fitted. Elliptical PSFs are disabled by default. + */ + bool IsEllipticPSF() const + { + return m_psfElliptic; + } + + /*! + * Enables elliptical PSF fits. See IsEllipticPSF(). + */ + void EnableEllipticPSF( bool enable = true ) + { + m_psfElliptic = enable; + } + + /*! + * Disables elliptical PSF fits. See IsEllipticPSF(). + */ + void DisableEllipticPSF( bool disable = true ) + { + EnableEllipticPSF( !disable ); + } + + /*! + * Returns the centroid tolerance in pixels. + * + * The centroid tolerance is the maximum allowed distance in pixels between + * a detected star position (or \e barycenter) and the centroid position of + * the corresponding fitted PSF. Stars where that distance is greater than + * the value returned by this function will be rejected and excluded for + * signal estimation. This allows preventing PSF fits departing too much + * from detected star coordinates, which enforces robustness and stability + * of the PSF fitting process. + * + * The default centroid tolerance is 1.5 pixels. + */ + float PSFCentroidTolerance() const + { + return m_psfCentroidTolerance; + } + + /*! + * Sets the centroid tolerance in pixels. See PSFCentroidTolerance() for a + * description of this parameter. + */ + void SetPSFCentroidTolerance( float t ) + { + PCL_PRECONDITION( t >= 0 ) + m_psfCentroidTolerance = Max( 0.0F, t ); + } + + /*! + * Returns a pointer to the current star detection mask image, or nullptr if + * no detection mask is being used. + * + * If a detection mask is used, star detection will only consider source + * pixels for which the corresponding mask pixels are nonzero. This allows + * for the implementation of partial star detection tasks limited to + * arbitrary regions of interest. + */ + const UInt8Image* DetectionMask() const + { + return m_mask; + } + + /*! + * Sets the detection \a mask image. See DetectionMask() for a description + * of this parameter. + * + * If the specified \a mask pointer is nullptr, no mask will be used in + * subsequent star detection tasks performed by this object. Otherwise, the + * specified \a mask image must have the same dimensions as the image(s) + * that will be specified for star detection, and must remain valid while + * this object performs star detection tasks. + */ + void SetDetectionMask( const UInt8Image* mask ) + { + if ( mask != nullptr ) + if ( mask->IsEmpty() ) + mask = nullptr; + m_mask = mask; + } + + /*! + * Performs star detection with the current parameters. Returns a dynamic + * array of Star structures sorted by brightness (flux) in descending order. + * + * \note This function is thread-safe. + */ + star_list DetectStars( const ImageVariant& image ) const; + + /*! + * Performs star detection with the current parameters. Returns a dynamic + * array of Star structures sorted by brightness (flux) in descending order. + * + * This operator is equivalent to the DetectStars( const ImageVariant& ) + * member function. + * + * \note This function is thread-safe. + */ + star_list operator()( const ImageVariant& image ) const + { + return DetectStars( image ); + } + + /*! + * Computes a binary map of star detection structures for the specified + * \a image and the current set of star detection parameters. + * + * Returns the star detection map as a new image. + */ + Image StructureMap( const ImageVariant& image ) const; + + /*! + * Isolates star detection structures for the specified \a image. + * + * Returns a new image which is the result of multiplying the specified + * \a image by the binarized structure map generated with the current star + * detection parameters. + */ + Image Structures( const ImageVariant& image ) const; + +protected: + + int m_structureLayers = 5; + int m_noiseLayers = 0; + int m_hotPixelFilterRadius = 1; + int m_noiseReductionFilterRadius = 0; + int m_minStructureSize = 0; + float m_sensitivity = 0.1F; + float m_peakResponse = 0.8F; + float m_maxDistortion = 0.5F; + float m_upperLimit = 1.0F; + bool m_invert = false; + bool m_fitPSF = false; + psf_function m_psfType = PSFunction::Gaussian; + bool m_psfElliptic = false; + float m_psfCentroidTolerance = 1.5F; + const UInt8Image* m_mask = nullptr; + +private: + + star_list DetectStars( Image& image ) const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_StarDetector_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StarDetector.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StatusMonitor.h b/3rdparty/include/pcl/StatusMonitor.h new file mode 100644 index 0000000..3f7a482 --- /dev/null +++ b/3rdparty/include/pcl/StatusMonitor.h @@ -0,0 +1,619 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StatusMonitor.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_StatusMonitor_h +#define __PCL_StatusMonitor_h + +/// \file pcl/StatusMonitor.h + +#include + +#include +#include +#include + +namespace pcl +{ + +class PCL_CLASS StatusMonitor; + +// ---------------------------------------------------------------------------- + +/*! + * \class StatusCallback + * \brief Provides status monitoring callback functions. + * + * %StatusCallback is an abstract base class providing a set of pure virtual + * functions that must be reimplemented in derived classes. These virtual + * functions must provide feedback to the user as part of the status + * monitoring of a process. + * + * Status monitoring consists of a set of PCL classes and functions to provide + * feedback and progress information about ongoing processes. Each instance of + * a %StatusCallback subclass is directly managed by a status monitor + * object. A status monitor object is an instance of the StatusMonitor class. + * + * Status monitors provide a generalized mechanism to generate progress + * information while a process is running. A %StatusCallback subclass receives + * that progress information and provides feedback to the user, controlling the + * information provided, its format and its appearance. + * + * The best example of %StatusCallback subclass is the StandardStatus class. + * StandardStatus reimplements %StatusCallback's pure virtual functions to show + * processing progress information on the processing console of the current + * processing thread. + * + * \sa StatusMonitor, StandardStatus, SpinStatus, ProgressBarStatus, + * MuteStatus, Console, Thread + */ +class PCL_CLASS StatusCallback +{ +public: + + /*! + * Constructs a default %StatusCallback object. + */ + StatusCallback() = default; + + /*! + * Copy constructor. + */ + StatusCallback( const StatusCallback& ) = default; + + /*! + * Move constructor. + */ + StatusCallback( StatusCallback&& ) = default; + + /*! + * Destroys this %StatusCallback instance. + */ + virtual ~StatusCallback() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + StatusCallback& operator =( const StatusCallback& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + StatusCallback& operator =( StatusCallback&& ) = default; + + /*! + * This function is called by a status \a monitor object when a new + * monitored process is about to start. + * + * The progress total count can be obtained by calling + * StatusMonitor::Total() for the passed \a monitor object. Similarly, the + * progress information string is given by StatusMonitor::Info(). + * + * This function must return zero if the process can continue. If this + * function returns a nonzero value, the new process is aborted by throwing + * a ProcessAborted exception. + */ + virtual int Initialized( const StatusMonitor& monitor ) const = 0; + + /*! + * Function called by a status \a monitor object to signal an update of the + * progress count for the current process. + * + * The progress count can be obtained by calling + * StatusMonitor::Count() for the passed \a monitor object. Similarly, the + * total count is given by StatusMonitor::Total(). + * + * This function is called repeatedly at regular time intervals until the + * progress count reaches the total count, or until the process is aborted. + * + * This function must return zero if the process can continue. If this + * function returns a nonzero value, the current process is aborted by + * throwing a ProcessAborted exception. + */ + virtual int Updated( const StatusMonitor& monitor ) const = 0; + + /*! + * Function called by a status \a monitor object to signal that the current + * process has finished. + * + * When this function is invoked by the status \a monitor, its progress + * count has already reached its total count. + * + * This function must return zero if the process can continue. If this + * function returns a nonzero value, the current process is aborted by + * throwing a ProcessAborted exception. + * + * \note This function allows aborting a process even when it has + * finished. This makes sense, since after a process has finished, the + * PixInsight core application still has some important work to do: update + * the target view's processing history, organize temporary swap files, send + * notifications, update masking relations, etc. + */ + virtual int Completed( const StatusMonitor& monitor ) const = 0; + + /*! + * Function called by a status \a monitor object when the progress + * information for the current process has been changed. + * + * The progress information is a string that can be obtained by + * calling StatusMonitor::Info() for the passed \a monitor object. + */ + virtual void InfoUpdated( const StatusMonitor& monitor ) const = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class StatusMonitor + * \brief An asynchronous status monitoring system. + * + * Status monitoring consists of a set of PCL classes and functions to manage + * progress information about ongoing processes. A status monitor is + * an instance of the %StatusMonitor class. + * + * Status monitors provide a generalized mechanism to generate and manage + * progress information while a process is running. A status monitor sends + * progress \e events to an instance of a StatusCallback subclass, whose + * primary responsibility is to provide feedback to the user. Progress feedback + * typically consists of a running percentage or similar text-based information + * written to the standard console. + * + * Along with providing progress feedback, the status monitoring concept is + * quite flexible and has other control applications in PCL, some of them quite + * sophisticated. For example, many standard tools use specialized status + * monitors to implement their real-time preview routines as asynchronously + * interruptible processes. + * + * %StatusMonitor utilizes a low-priority timing thread to generate callback + * monitoring calls asynchronously at constant time intervals. This has + * virtually zero impact on the performance of the monitored processes. + * + * \sa StatusCallback, StandardStatus, SpinStatus, MuteStatus, Console, Thread + */ +class PCL_CLASS StatusMonitor +{ +public: + + /*! + * Constructs a default %StatusMonitor object. + */ + StatusMonitor() = default; + + /*! + * Constructs a %StatusMonitor object as a duplicate of an existing + * instance. + */ + StatusMonitor( const StatusMonitor& x ) + { + Assign( x ); + } + + /*! + * Destroys this %StatusMonitor object. + */ + virtual ~StatusMonitor() + { + Clear(); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + StatusMonitor& operator =( const StatusMonitor& x ) + { + if ( this != &x ) + Assign( x ); + return *this; + } + + /*! + * Initializes this status monitor to start a new monitoring procedure. + * + * \param info Progress information. + * + * \param count Total progress count. If a zero total progress count is + * specified, this monitor will be unbounded. That + * means that the monitor will never reach a completed state + * by increasing or incrementing it. To complete an unbounded + * status monitor, the Complete() member function must be + * called explicitly. + * + * If this monitor has an associated status callback object, this function + * will call the StatusCallback::Initialized() virtual member function of + * the associated callback object. + * + * If this function is invoked while an ongoing monitoring procedure is + * active, it is interrupted and a new monitoring procedure is initialized. + */ + void Initialize( const String& info, size_type count = 0 ); + + /*! + * Increments the initialization disabling counter for this status monitor. + * + * When the disabling counter is greater than zero, initialization is + * disabled for this monitor, and subsequent calls to the Initialize() + * member function have no effect. + * + * This is useful if your process calls other subroutines that try to + * initialize private monitoring procedures. If such subroutines are called + * as independent processes, they can perform initialization, but if they + * are used as part of a higher level process, they should update a common + * status monitor without reinitializing it. + * + * Here is an example: + * + * \code + * FunctionA( StatusMonitor& m ) + * { + * if ( m.IsInitializationEnabled() ) + * m.Initialize( "This is function A...", 100 ); + * // ... + * for ( int i = 0; i < 100; ++i, ++m ) + * // ... + * } + * + * FunctionB( StatusMonitor& m ) + * { + * if ( m.IsInitializationEnabled() ) + * m.Initialize( "This is function B...", 100 ); + * // ... + * for ( int i = 0; i < 10; ++i, m += 10 ) + * // ... + * } + * + * ALargerFunction( StatusMonitor& m ) + * { + * m.Initialize( "This is some high-level routine...", 200 ); + * m.DisableInitialization(); + * // ... + * FunctionA( m ); + * FunctionB( m ); + * // ... + * m.EnableInitialization(); + * } + * \endcode + * + * In this example, both FunctionA() and FunctionB() update a %StatusMonitor + * object by a total count of 100 steps. However, these functions don't try + * to initialize the passed monitor if initialization has been disabled. + * + * ALargerFunction() initializes a status monitor with a total count of 200 + * and its own information string, then disables monitor initialization. The + * subsequent calls to FunctionA() and FunctionB() will update the monitor + * by 100 steps each, without reinitializing it. + * + * The final call to EnableInitialization() in ALargerFunction() is + * necessary to return the status monitor to its initial enabled or disabled + * state. + */ + void DisableInitialization() + { + ++m_initDisableCount; + } + + /*! + * Decrements the initialization disabling counter for this status monitor. + * + * When the disabling counter is equal or less than zero, initialization is + * enabled for this monitor. + * + * See DisableInitialization() for further information on the initialization + * enabled/disabled states and a source code example. + */ + void EnableInitialization() + { + --m_initDisableCount; + } + + /*! + * Returns true iff monitor initialization has been disabled for this status + * monitor object. + * + * See DisableInitialization() for further information on the initialization + * enabled/disabled states and a source code example. + */ + bool IsInitializationEnabled() const + { + return m_initDisableCount <= 0; + } + + /*! + * Returns true iff this status monitor has been initialized. + * + * A status monitor is initialized by a call to its Initialize() member + * function. + */ + bool IsInitialized() const + { + return m_initialized; + } + + /*! + * Returns true iff this status monitor has completed a monitoring procedure. + * + * A monitoring procedure is completed if the current monitoring counter + * reaches the total count, or if the Complete() member function is called. + */ + bool IsCompleted() const + { + return m_completed; + } + + /*! + * Returns true iff a monitoring procedure has been aborted. + * + * When a monitoring procedure is aborted, the status monitor object throws + * a ProcessAborted exception. + * + * A monitoring procedure can only be aborted by its associated status + * callback object. This is done by returning a nonzero value from the + * StatusCallback::Initialized(), StatusCallback::Updated(), or + * StatusCallback::Completed() virtual member functions implemented by + * a StatusCallback descendant class. + */ + bool IsAborted() const + { + return m_aborted; + } + + /*! + * Changes the progress information text for this status monitor. + * + * If there is a status callback object associated with this monitor, its + * StatusCallback::InfoUpdated() member function is invoked. + */ + void SetInfo( const String& s ) + { + m_info = s; + if ( m_callback != nullptr ) + m_callback->InfoUpdated( *this ); + } + + /*! + * Increments the progress counter of this status monitor. + * + * If the progress counter reaches Total(), and this monitor has an + * associated status callback object, its StatusCallback::Completed() member + * function is invoked. If the progress counter is less than Total(), the + * StatusCallback::Updated() member function will be invoked by the + * monitoring thread asynchronously. + * + * Note that for \e unbounded monitors the completed state is never reached + * unless a explicit call to Complete() is made, hence the + * StatusCallback::Completed() member function of the status callback + * object, if any, will never be called by this increment operator. + */ + void operator ++() + { + if ( ++m_count == m_total || m_needsUpdate ) + Update(); + } + + /*! + * Increments the progress counter of this status monitor by the specified + * number \a n of progress steps. + * + * This function behaves essentially like the operator ++() function. + */ + void operator +=( size_type n ) + { + m_count += n; + if ( m_total != 0 ) // if not an unbounded monitor + if ( m_count > m_total ) + m_count = m_total; + if ( m_needsUpdate || m_count == m_total ) + Update(); + } + + /*! + * Forces this monitor to complete the current monitoring procedure, by + * assigning the total progress count to the progress counter. + * + * This function forces a call to StatusCallback::Completed(), if this + * monitor has an associated status callback object. + */ + void Complete() + { + m_count = m_total; + Update(); + } + + /*! + * Returns the address of the immutable status callback object associated + * with this status monitor. Returns zero if this monitor has no associated + * status callback object. + */ + const StatusCallback* Callback() const + { + return m_callback; + } + + /*! + * Returns the address of the status callback object associated with this + * status monitor. Returns zero if this monitor has no associated status + * callback object. + */ + StatusCallback* Callback() + { + return m_callback; + } + + /*! + * Associates a status callback object with this status monitor. + * + * Calling this function forces a call to Clear(), which interrupts the + * current monitoring procedure, if any, and reinitializes the internal + * state of this monitor. + * + * To associate no status callback object with this monitor, pass \c nullptr + * as the argument to this function. + */ + void SetCallback( StatusCallback* callback ) + { + Reset(); + m_callback = callback; + } + + /*! + * Returns the last status callback return value. + * + * The returned value is the return value of the last call to + * StatusCallback::Initialized(), StatusCallback::Updated() or + * StatusCallback::Completed() for the associated status callback object, or + * zero if no status callback object has been associated with this monitor. + * + * If a nonzero value is returned, then the current monitoring procedure has + * already been aborted. + */ + int ReturnValue() const + { + return m_retVal; + } + + /*! + * Returns the progress information string that has been set for this status + * monitor object. + */ + String Info() const + { + return m_info; + } + + /*! + * Returns the progress counter for the current monitoring procedure. + * + * When the progress counter reaches the total count, the monitoring + * procedure has been completed. + */ + size_type Count() const + { + return m_count; + } + + /*! + * Returns the total progress count for the current monitoring procedure. + * + * When the progress counter reaches the total count, the monitoring + * procedure has been completed. + */ + size_type Total() const + { + return m_total; + } + + /*! + * Interrupts the current monitoring procedure, if any, and reinitializes + * the internal state of this status monitor. + */ + void Clear() + { + Reset(); + } + + /*! + * Returns the progress monitoring refresh rate in milliseconds. + * + * The StatusCallback::Updated() member functions of all active status + * callback objects are called asynchronously by a low-priority thread. The + * refresh rate is the interval between successive callback update calls. It + * can be in the range from 25 to 999 milliseconds. + */ + static unsigned RefreshRate() + { + return s_msRefreshRate; + } + + /*! + * Sets a new progress monitoring refresh rate in milliseconds. + * + * \param ms New monitoring refresh rate in milliseconds. The specified + * value must be between 25 and 999 milliseconds. If the passed + * value is outside that range, it is discarded and the nearest + * valid bound is set. + * + * The default refresh rate is 250 milliseconds, or 4 monitoring events per + * second. The new refresh rate does take effect immediately, even if there + * are active status monitors. + */ + static void SetRefreshRate( unsigned ms ); + +private: + + StatusCallback* m_callback = nullptr; + bool m_initialized = false; + bool m_completed = false; + bool m_aborted = false; + bool m_needsUpdate = false; // thread-safe flag set by the dispatcher + int m_initDisableCount = 0; + int m_retVal = 0; + String m_info; + size_type m_total = 0; + size_type m_count = 0; + + static unsigned s_msRefreshRate; + + void Reset(); + void Assign( const StatusMonitor& ); + void Update(); + + friend class PCL_CLASS AutoStatusCallbackRestorer; + friend class MonitorDispatcherThread; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_StatusMonitor_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StatusMonitor.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/String.h b/3rdparty/include/pcl/String.h new file mode 100644 index 0000000..10eef7b --- /dev/null +++ b/3rdparty/include/pcl/String.h @@ -0,0 +1,13714 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/String.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_String_h +#define __PCL_String_h + +/// \file pcl/String.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __PCL_ALIGNED_STRING_ALLOCATION +# include +# define PCL_STRING_ALLOCATOR AlignedAllocator +#else +# include +# define PCL_STRING_ALLOCATOR StandardAllocator +#endif + +#ifndef __PCL_NO_STRING_COMPLEX +# include +#endif + +#ifndef __PCL_NO_STRING_OSTREAM +# ifndef _MSC_VER +# define _GLIBCXX_USE_WCHAR_T 1 +# endif +# include +#endif + +#ifdef __PCL_QT_INTERFACE +# include +# include +# include +# define PCL_GET_CHARPTR_FROM_QSTRING( qs ) (qs.toLatin1().data()) +# define PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ((char16_type*)( qs.utf16() )) +# define PCL_GET_QSTRING_FROM_CHAR16PTR( s ) (QString::fromUtf16( (const ushort*)(s) )) +# define PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) (qb.data()) +# define PCL_QDATE_FMT_STR "yyyy/MM/dd" +# define PCL_QDATETIME_FMT_STR "yyyy/MM/dd hh:mm:ss" +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::RandomizationOption + * \brief String randomization options + * + * + * + * + * + * + * + * + * + * + * + *
RandomizationOption::Lowercase Generate random lowercase alphabetic characters: [a..z]
RandomizationOption::Uppercase Generate random uppercase alphabetic characters: [A..Z]
RandomizationOption::Alpha Generate random lowercase and uppercase alphabetic characters: [a..zA..Z]
RandomizationOption::Digits Generate random decimal digits: [0..9]
RandomizationOption::Symbols Generate random symbol characters: .#/[]() etc.
RandomizationOption::HexDigits Generate random hexadecimal digits: [0..9a..f], or [0..9A..F] if Uppercase is set.
RandomizationOption::BinDigits Generate random binary digits: [01].
RandomizationOption::FullRange Generate random characters in the whole range of code points except zero.
RandomizationOption::Default Default options: Alpha|Digits
+ */ +namespace RandomizationOption +{ + enum mask_type + { + Lowercase = 0x00000001, // Generate random lowercase alphabetic characters: a..z + Uppercase = 0x00000002, // Generate random uppercase alphabetic characters: A..Z + Alpha = Lowercase|Uppercase, // Generate random alphabetic characters: a..zA..Z + Digits = 0x00000004, // Generate random decimal digits: 0..9 + Symbols = 0x00000008, // Generate random symbol characters: .#/[]() etc + HexDigits = 0x00000010, // Generate hexadecimal digits: 0..9a..f or 0..9A..F + BinDigits = 0x00000020, // Generate binary digits: 0 and 1 + FullRange = 0x80000000, // Generate random characters in the whole range of code points except zero + Default = Alpha|Digits + }; +}; + +/*! + * \class pcl::RandomizationOptions + * \brief A collection of string randomization options. + */ +typedef Flags RandomizationOptions; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup sexagesimal_conversion Sexagesimal String Representation and Parsing + */ + +/*! + * \struct SexagesimalConversionOptions + * \brief Formatting options for string sexagesimal representations. + * + * \ingroup sexagesimal_conversion + * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), + * AngleConversionOptions, LongitudeConversionOptions, RAConversionOptions, + * LatitudeConversionOptions, DecConversionOptions + */ +struct PCL_CLASS SexagesimalConversionOptions +{ + /*! + * Number of represented items. Can be 1, 2 or 3. All items but the last one + * are represented as integer values. The last item is represented as a + * floating point value with the specified precision. The default value is + * three items. + */ + unsigned items : 2; + + /*! + * Number of decimal digits for the last represented sexagesimal item. The + * default value is two decimal digits. + */ + unsigned precision : 4; + + /*! + * Whether to always prepend a sign character to the first represented item, + * even '+' for positive values. This is false by default. + */ + bool sign : 1; + + /*! + * Width of the integer part of the first represented item in characters, + * including the sign when applicable. When the specified width is larger + * than the length of the represented item, it is left-padded with padding + * characters as necessary. The default is zero, which means that no padding + * is performed for the first item by default. + */ + unsigned width : 4; + + /*! + * A single character used for separation of sexagesimal components. The + * default separator is a colon character, ':'. + */ + char separator; + + /*! + * A single character used for padding right-justified representations of + * first sexagesimal components. See the width member. The default padding + * character is the white space, ' '. + */ + char padding; + + /*! + * Default constructor. + */ + constexpr SexagesimalConversionOptions( unsigned items_ = 3, + unsigned precision_ = 2, + bool sign_ = false, + unsigned width_ = 0, + char separator_ = ':', + char padding_ = ' ' ) + : items( items_ ) + , precision( precision_ ) + , sign( sign_ ) + , width( width_ ) + , separator( separator_ ) + , padding( padding_ ) + { + } + + /*! + * Copy constructor. + */ + SexagesimalConversionOptions( const SexagesimalConversionOptions& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SexagesimalConversionOptions& operator =( const SexagesimalConversionOptions& ) = default; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct AngleConversionOptions + * \brief A set of options specific for string representations of angles. + * + * This is a convenience structure to ease string representations of angles in + * the range [0°,360°) as degrees, minutes and seconds of arc. + * + * \ingroup sexagesimal_conversion + * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), + * SexagesimalConversionOptions, LongitudeConversionOptions, + * RAConversionOptions, LatitudeConversionOptions, DecConversionOptions + */ +struct PCL_CLASS AngleConversionOptions : public SexagesimalConversionOptions +{ + /*! + * Constructs an %AngleConversionOptions structure initialized for the + * specified \a precision and first item \a width and \a padding character. + * The string representation will consist of three items separated by + * spaces. If \a width is nonzero, the first item will be represented + * right-justified within a field of \a width \a padding characters. + */ + constexpr AngleConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' ) + : SexagesimalConversionOptions( 3/*items*/, precision, false/*sign*/, width, ' '/*separator*/, padding ) + {} +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct LongitudeConversionOptions + * \brief A set of options specific for string representations of longitude + * angles. + * + * This is a convenience structure to ease string representations of angles in + * the range [-180°,+180°] as degrees, minutes and seconds of arc. + * + * \ingroup sexagesimal_conversion + * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), + * SexagesimalConversionOptions, AngleConversionOptions, RAConversionOptions, + * LatitudeConversionOptions, DecConversionOptions + */ +struct PCL_CLASS LongitudeConversionOptions : public SexagesimalConversionOptions +{ + /*! + * Constructs a %LongitudeConversionOptions structure initialized for the + * specified \a precision and first item \a width and \a padding character. + * The string representation will consist of three items separated by + * spaces. If \a width is nonzero, the first item will be represented + * right-justified within a field of \a width \a padding characters, + * including a leading sign character. + */ + constexpr LongitudeConversionOptions( unsigned precision = 2, unsigned width = 4, char padding = ' ' ) + : SexagesimalConversionOptions( 3/*items*/, precision, true/*sign*/, width, ' '/*separator*/, padding ) + {} +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct RAConversionOptions + * \brief A set of options specific for string representations of right + * ascensions. + * + * This is a convenience structure to ease string representations of hour + * angles in the range [0h,24h) as hours, minutes and + * seconds. + * + * \ingroup sexagesimal_conversion + * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), + * SexagesimalConversionOptions, AngleConversionOptions, + * LongitudeConversionOptions, LatitudeConversionOptions, DecConversionOptions + */ +struct PCL_CLASS RAConversionOptions : public SexagesimalConversionOptions +{ + /*! + * Constructs a %RAConversionOptions structure initialized for the specified + * \a precision and first item \a width and \a padding character. The string + * representation will consist of three items separated by spaces. If + * \a width is nonzero, the first item will be represented right-justified + * within a field of \a width \a padding characters. + */ + constexpr RAConversionOptions( unsigned precision = 3, unsigned width = 2, char padding = ' ' ) + : SexagesimalConversionOptions( 3/*items*/, precision, false/*sign*/, width, ' '/*separator*/, padding ) + {} +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct LatitudeConversionOptions + * \brief A set of options specific for string representations of latitude + * angles. + * + * This is a convenience structure to ease string representations of angles in + * the range [-90°,+90°] as degrees, minutes and seconds of arc. + * + * \ingroup sexagesimal_conversion + * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), + * SexagesimalConversionOptions, AngleConversionOptions, + * LongitudeConversionOptions, RAConversionOptions, DecConversionOptions + */ +struct PCL_CLASS LatitudeConversionOptions : public SexagesimalConversionOptions +{ + /*! + * Constructs a %LatitudeConversionOptions structure initialized for the + * specified \a precision and first item \a width and \a padding character. + * The string representation will consist of three items separated by + * spaces. If \a width is nonzero, the first item will be represented + * right-justified within a field of \a width \a padding characters, + * including a leading sign character. + */ + constexpr LatitudeConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' ) + : SexagesimalConversionOptions( 3/*items*/, precision, true/*sign*/, width, ' '/*separator*/, padding ) + {} +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct DecConversionOptions + * \brief A set of options specific for string representations of declination + * angles. + * + * This structure is a convenience alias of LatitudeConversionOptions. + * + * \ingroup sexagesimal_conversion + * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), + * SexagesimalConversionOptions, AngleConversionOptions, + * LongitudeConversionOptions, RAConversionOptions, LatitudeConversionOptions + */ +struct PCL_CLASS DecConversionOptions : public LatitudeConversionOptions +{ + /*! + * Constructs a %DecConversionOptions structure initialized for the + * specified \a precision and first item \a width and \a padding character. + * The string representation will consist of three items separated by + * spaces. If \a width is nonzero, the first item will be represented + * right-justified within a field of \a width \a padding characters, + * including a leading sign character. + */ + constexpr DecConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' ) + : LatitudeConversionOptions( precision, width, padding ) + {} +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct ISO8601ConversionOptions + * \brief Formatting options for string representations of dates and times in + * ISO 8601 format. + * + * \sa IsoString::ToISO8601DateTime(), String::ToISO8601DateTime() + */ +struct PCL_CLASS ISO8601ConversionOptions +{ + /*! + * Number of represented time items. Can be 0, 1, 2 or 3. All items but the + * last one are represented as integer values. The last item is represented + * as a floating point value with the specified precision. The default value + * is three time items. + */ + unsigned timeItems : 2; + + /*! + * Number of decimal digits for the last represented time item. The default + * value is three decimal digits. + */ + unsigned precision : 4; + + /*! + * Whether to append a time zone specifier to the ISO 8601 representation. + * The default value is true. + */ + bool timeZone : 1; + + /*! + * Whether to append the 'Z' special time zone specifier for UTC time, or + * the '+00:00' specifier otherwise. The default value is true. + */ + bool zuluTime : 1; + + /*! + * Default constructor. + */ + constexpr ISO8601ConversionOptions( unsigned timeItems_ = 3, + unsigned precision_ = 3, + bool timeZone_ = true, + bool zuluTime_ = true ) + : timeItems( timeItems_ ) + , precision( precision_ ) + , timeZone( timeZone_ ) + , zuluTime( zuluTime_ ) + { + } + + /*! + * Copy constructor. + */ + ISO8601ConversionOptions( const ISO8601ConversionOptions& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + ISO8601ConversionOptions& operator =( const ISO8601ConversionOptions& ) = default; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericString + * \brief Generic character string. + * + * %GenericString is a finite, ordered sequence of characters implemented as a + * reference-counted, dynamic array of objects of type T, whose fundamental + * behavior is specified by an instantiation type R of GenericCharTraits for + * the character type T (typically GenericCharTraits, or a derived class such + * as CharTraits or IsoCharTraits), and where the type A provides dynamic + * allocation for contiguous sequences of elements of type T (StandardAllocator + * is used by default). + * + * On the PixInsight platform, all dynamically allocated strings have been + * implemented as two instantiations of the %GenericString template class, + * namely the String (UTF-16 string) and IsoString (UTF-8 or ISO/IEC-8859-1 + * string) classes. + * + * \sa String, IsoString, CharTraits, IsoCharTraits + */ +template +class PCL_CLASS GenericString : public DirectContainer +{ +public: + + /*! + * Represents a string character. + */ + typedef T char_type; + + /*! + * The character traits class used by this string class. + */ + typedef R char_traits; + + /*! + * The block allocator used by this string class. + */ + typedef A block_allocator; + + /*! + * The allocator class used by this string class. + */ + typedef pcl::Allocator allocator; + + /*! + * Null-terminated string of char_type characters. + */ + typedef T* c_string; + + /*! + * Immutable null-terminated string of char_type characters. + */ + typedef const T* const_c_string; + + /*! + * String iterator. + */ + typedef T* iterator; + + /*! + * Immutable string iterator. + */ + typedef const T* const_iterator; + + /*! + * Reverse string iterator. + */ + typedef ReverseRandomAccessIterator + reverse_iterator; + + /*! + * Reverse immutable string iterator. + */ + typedef ReverseRandomAccessIterator + const_reverse_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constant used to signal unsuccessful search operations. + */ + static const size_type notFound = ~size_type( 0 ); + + /*! + * Corresponds to the maximum possible character index in a string. + */ + static const size_type maxPos = ~size_type( 0 ); + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty string. + */ + GenericString() + { + m_data = Data::New(); + } + + /*! + * Copy constructor. Increments the reference counter of the string \a s. + */ + GenericString( const GenericString& s ) + : m_data( s.m_data ) + { + m_data->Attach(); + } + + /*! + * Move constructor. + */ + GenericString( GenericString&& s ) + : m_data( s.m_data ) + { + s.m_data = nullptr; + } + + /*! + * Constructs a string with a copy of the null-terminated character sequence + * stored in the specified array \a t. + */ + GenericString( const_c_string t ) + { + size_type len = R::Length( t ); + if ( len > 0 ) + { + m_data = Data::New( len ); + R::Copy( m_data->string, t, len ); + } + else + m_data = Data::New(); + } + + /*! + * Constructs a string with a copy of the character sequence defined by the + * range [i,j). + * + * If \a i is greater than or equal to \a j, this constructor creates an + * empty string. Otherwise it will assign the specified sequence of + * characters. + * + * \b Important - Note that this constructor is \e not equivalent to: + * + * \code GenericString( i, 0, j-i ); \endcode + * + * because the above call would assign a null-terminated sequence, while + * this function assigns the specified range unconditionally, even if it + * contains null characters. Since this constructor does not have to scan + * for a terminating character, it is potentially more efficient. + */ + GenericString( const_iterator i, const_iterator j ) + { + if ( i < j ) + { + size_type len = j - i; + m_data = Data::New( len ); + R::Copy( m_data->string, i, len ); + } + else + m_data = Data::New(); + } + + /*! + * Constructs a string and initializes it with characters taken from the + * specified initializer list \a l. + * + * This constructor is equivalent to: + * + * \code GenericString( l.begin(), l.end() ) \endcode + */ + GenericString( std::initializer_list l ) + : GenericString( l.begin(), l.end() ) + { + } + + /*! + * Constructs a string with a copy of at most \a n characters stored in the + * null-terminated sequence \a t, starting from its \a i-th character. + */ + GenericString( const_c_string t, size_type i, size_type n ) + { + size_type len = R::Length( t ); + if ( i < len && (n = pcl::Min( n, len-i )) > 0 ) + { + m_data = Data::New( n ); + R::Copy( m_data->string, t+i, n ); + } + else + m_data = Data::New(); + } + + /*! + * Constructs a string with \a n copies of a character \a c. + */ + GenericString( char_type c, size_type n = 1 ) + { + if ( n > 0 ) + { + m_data = Data::New( n ); + R::Fill( m_data->string, c, n ); + } + else + m_data = Data::New(); + } + + /*! + * Destroys this string. Decrements the reference counter of the string data + * and, if it becomes unreferenced, it is destroyed and deallocated. + */ + ~GenericString() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + /*! + * Returns true iff this string uniquely references its string data. + * + * \sa EnsureUnique(), IsAliasOf() + */ + bool IsUnique() const noexcept + { + return m_data->IsUnique(); + } + + /*! + * Returns true iff this string is an alias of another string \a s. + * + * Two strings are aliases if both share the same string data. + * + * \sa IsUnique(), EnsureUnique() + */ + bool IsAliasOf( const GenericString& s ) const noexcept + { + return m_data == s.m_data; + } + + /*! + * Ensures that this string uniquely references its string data. + * + * If necessary, this member function generates a duplicate of the string + * data, references it, and then decrements the reference counter of the + * original string data. + * + * \sa IsUnique(), IsAliasOf() + */ + void EnsureUnique() + { + if ( !IsUnique() ) + { + size_type len = Length(); + Data* newData = Data::New( len ); + if ( len > 0 ) + R::Copy( newData->string, m_data->string, len ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the number of bytes necessary to store a single character in this + * string. + * + * This member function returns the R::BytesPerChar() static member function + * of the char traits class R. + */ + static size_type BytesPerChar() noexcept + { + return R::BytesPerChar(); + } + + /*! + * Returns the total number of bytes required to store the string data + * referenced by this string, \e excluding the terminating null character. + * + * \sa Length(), Capacity() + */ + size_type Size() const noexcept + { + return Length()*BytesPerChar(); + } + + /*! + * Returns the length of this string in characters. This \e excludes the + * terminating null character. + * + * \sa IsEmpty(), Available(), Capacity(), Size() + */ + size_type Length() const noexcept + { + return m_data->end - m_data->string; + } + + /*! + * Returns the total capacity of this string in characters. + * + * The capacity of a string is the maximum number of characters that can be + * stored before requiring a reallocation of string data. + * + * \sa Available(), Length(), Size() + */ + size_type Capacity() const noexcept + { + return m_data->capacity - m_data->string; + } + + /*! + * Returns the number of characters available in this string. + * + * The number of available characters is equal to Capacity() - Length(). + * + * \sa Capacity(), Length(), Size() + */ + size_type Available() const noexcept + { + return m_data->capacity - m_data->end; + } + + /*! + * Returns true only if this string is valid. A string is valid if it + * references an internal string structure, even if it is an empty string. + * + * In general, all %GenericString objects are valid with only two + * exceptions: + * + * \li Objects that have been move-copied or move-assigned to other strings. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid string object cannot be used and should be destroyed + * immediately. Invalid strings are always destroyed automatically during + * move construction and move assignment operations. + * + * \sa IsEmpty() + */ + bool IsValid() const noexcept + { + return m_data != nullptr; + } + + /*! + * Returns true only if this string is empty. + * + * An empty string has zero length and stores no characters. + * + * \sa IsValid(), Length(), Available(), Capacity(), Size() + */ + bool IsEmpty() const noexcept + { + return m_data->string == m_data->end; + } + + /*! + * Returns the minimum valid character index. + * + * This member function exists for compatibility with PCL containers. It + * always returns zero. + * + * \sa UpperBound(), Length() + */ + size_type LowerBound() const noexcept + { + return 0; + } + + /*! + * Returns the maximum valid character index. + * + * The returned value is equal to Length()-1. If this string is empty, the + * index returned by this member function is invalid and equal to maxPos. + * + * \sa LowerBound(), Length() + */ + size_type UpperBound() const noexcept + { + PCL_PRECONDITION( !IsEmpty() ) + return Length()-1; + } + + /*! + * Returns a reference to the (immutable) allocator object in this string. + * + * \sa SetAllocator() + */ + const allocator& Allocator() const noexcept + { + return m_data->alloc; + } + + /*! + * Sets the allocator object used by this string to a copy of the specified + * allocator \a a. + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * \sa Allocator() + */ + void SetAllocator( const allocator& a ) + { + EnsureUnique(); + m_data->alloc = a; + } + + /*! + * Returns an iterator located at the \a i-th character of this string. + * The character index \a i must be in the range [0,Length()). + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * If this string is empty, or if the specified index \a i is out of range, + * calling this member function is an error that leads to an invalid result. + * + * \sa operator []( size_type ) + */ + iterator At( size_type i ) + { + PCL_PRECONDITION( i < Length() ) + EnsureUnique(); + return m_data->string + i; + } + + /*! + * Returns an immutable iterator located at the \a i-th character in this + * string. The character index \a i must be in the range [0,Length()). + * + * If this string is empty, or if the specified index \a i is out of range, + * calling this member function is an error that leads to an invalid result. + * + * \sa operator []( size_type ) const + */ + const_iterator At( size_type i ) const noexcept + { + PCL_PRECONDITION( i < Length() ) + return m_data->string + i; + } + + /*! + * Returns a reference to the \a i-th character in this string. The + * character index \a i must be in the range [0,Length()). + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * If this string is empty, or if the specified index \a i is out of range, + * calling this member function is an error that leads to an invalid result. + * + * \sa At(), operator *() + */ + char_type& operator []( size_type i ) + { + return *At( i ); + } + + /*! + * Returns a copy of the \a i-th character in this string. The character + * index \a i must be in the range [0,Length()). + * + * If this string is empty, or if the specified index \a i is out of range, + * calling this member function is an error that leads to an invalid result. + * + * \sa At() const, operator *() const + */ + char_type operator []( size_type i ) const noexcept + { + return *At( i ); + } + + /*! + * Returns a reference to the first character in this string. + * + * This is a convenience member function, equivalent to *At( 0 ). + * + * \sa operator []( size_type ), At() + */ + char_type& operator *() + { + EnsureUnique(); + return *m_data->string; + } + + /*! + * Returns a copy of the first character in this string. + * + * This is a convenience member function, equivalent to *At( 0 ). + * + * \sa operator []( size_type ) const, At() + */ + char_type operator *() const noexcept + { + return *m_data->string; + } + + /*! + * Returns a mutable iterator pointing to the first character of this + * string. + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * If this string is empty, this member function returns \c nullptr. + * + * \sa End() + */ + iterator Begin() + { + EnsureUnique(); + return m_data->string; + } + + /*! + * Returns an immutable iterator pointing to the first character of this + * string. + * + * If this string is empty, this member function returns \c nullptr. + * + * \sa End() const + */ + const_iterator Begin() const noexcept + { + return m_data->string; + } + + /*! + * Returns a mutable iterator pointing to the end of this string. The + * returned iterator points to the next-to-last character of this string. + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * If this string is empty, this member function returns \c nullptr. + * + * \sa Begin() + */ + iterator End() + { + EnsureUnique(); + return m_data->end; + } + + /*! + * Returns an immutable iterator pointing to the end of this string. The + * returned iterator points to the next-to-last character of this string. + * + * If this string is empty, this member function returns \c nullptr. + * + * \sa Begin() const + */ + const_iterator End() const noexcept + { + return m_data->end; + } + + /*! + * Returns a reverse mutable iterator pointing to the reverse + * beginning of this string. The returned iterator points to the last + * character of this string. + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * If this string is empty, this member function returns a null reverse + * iterator. + * + * \sa ReverseEnd() + */ + reverse_iterator ReverseBegin() + { + EnsureUnique(); + return (m_data->string < m_data->end) ? m_data->end-1 : nullptr; + } + + /*! + * Returns an immutable reverse iterator pointing to the reverse + * beginning of this string. The returned iterator points to the last + * character of this string. + * + * If this string is empty, this member function returns a null reverse + * iterator. + * + * \sa ReverseEnd() const + */ + const_reverse_iterator ReverseBegin() const noexcept + { + return (m_data->string < m_data->end) ? m_data->end-1 : nullptr; + } + + /*! + * Returns a reverse mutable iterator pointing to the reverse end + * of this string. The returned iterator points to the + * previous-to-first character of this string. + * + * If this string is not unique, it is made unique before returning from + * this member function. + * + * If this string is empty, this member function returns a null reverse + * iterator. + * + * \sa ReverseBegin() + */ + reverse_iterator ReverseEnd() + { + EnsureUnique(); + return (m_data->string < m_data->end) ? m_data->string-1 : nullptr; + } + + /*! + * Returns an immutable reverse iterator pointing to the reverse + * end of this string. The returned iterator points to the + * previous-to-first character of this string. + * + * If this string is empty, this member function returns a null reverse + * iterator. + * + * \sa ReverseBegin() const + */ + const_reverse_iterator ReverseEnd() const noexcept + { + return (m_data->string < m_data->end) ? m_data->string-1 : nullptr; + } + + /*! + * Returns the zero-based character index corresponding to a valid iterator + * \a i in this string. This is equivalent to \a i - Begin(). + * + * The specified iterator must be posterior to or located at the starting + * iterator of this string, as returned by Begin(). However, for performance + * reasons this condition is neither enforced nor verified. If an invalid + * iterator is specified, then this function, as well as any subsequent use + * of the returned character index, may invoke undefined behavior. + */ + size_type IndexAt( const_iterator i ) const noexcept + { + PCL_PRECONDITION( i >= m_data->string ) + return i - m_data->string; + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const noexcept + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + iterator end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const noexcept + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Returns a pointer to the immutable internal data array of this string. + * + * If this string is empty, this member function returns a pointer to a + * static, null-terminated, unmodifiable empty string (the "" C string). + * This function always returns a valid pointer to existing character data. + */ + const_c_string c_str() const noexcept + { + static const char_type theNullChar = char_traits::Null(); + return IsEmpty() ? &theNullChar : Begin(); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * This operator calls Assign() with the specified source string \a s. + */ + GenericString& operator =( const GenericString& s ) + { + Assign( s ); + return *this; + } + + /*! + * Assigns a string \a s to this string. + * + * If this instance and the specified source instance \a s reference + * different string data, then the data previously referenced by this object + * is dereferenced. If the previous data becomes unreferenced, it is + * destroyed and deallocated. Then the data being referenced by \a s is also + * referenced by this object. + * + * If this instance and the specified source instance \a s already reference + * the same string data, then this function does nothing. + * + * \sa Transfer() + */ + void Assign( const GenericString& s ) + { + s.m_data->Attach(); + DetachFromData(); + m_data = s.m_data; + } + + /*! + * Move assignment operator. Returns a reference to this object. + * + * This operator calls Transfer() with the specified source string \a s. + */ + GenericString& operator =( GenericString&& s ) + { + Transfer( s ); + return *this; + } + + /*! + * Transfers data from another object \a s to this string. + * + * Decrements the reference counter of the current string data. If the data + * becomes unreferenced, it is destroyed and deallocated. The string data + * referenced by the source object \a s is then transferred to this object. + * + * \warning The source string \a s will be an invalid object after calling + * this function, and hence should be destroyed immediately. Any attempt to + * access an invalid object will most likely lead to a crash. + * + * \sa Assign() + */ + void Transfer( GenericString& s ) + { + DetachFromData(); + m_data = s.m_data; + s.m_data = nullptr; + } + + /*! + * Transfers data from another object \a s to this string. + * + * See Transfer( GenericString& ) for detailed information. + */ + void Transfer( GenericString&& s ) + { + DetachFromData(); + m_data = s.m_data; + s.m_data = nullptr; + } + + /*! + * Assigns a copy of the null-terminated character sequence stored in the + * specified array \a t to this string. Returns a reference to this object. + */ + GenericString& operator =( const_c_string t ) + { + Assign( t ); + return *this; + } + + /*! + * Assigns a single character \a c to this string. Returns a reference to + * this object. + */ + GenericString& operator =( char_type c ) + { + Assign( c, 1 ); + return *this; + } + + /*! + * Assigns a substring of at most \a n characters from a source string \a s, + * starting from its \a i-th character, to this string. + */ + void Assign( const GenericString& s, size_type i, size_type n ) + { + Transfer( s.Substring( i, n ) ); + } + + /*! + * Assigns a copy of the null-terminated character sequence stored in the + * specified array \a t to this string. + * + * If \a t is a pointer to the contents of this string (or, equivalently, an + * iterator on this string), this function invokes undefined behavior. + */ + void Assign( const_c_string t ) + { + size_type len = R::Length( t ); + if ( len > 0 ) + { + MaybeReallocate( len ); + R::Copy( m_data->string, t, len ); + } + else + Clear(); + } + + /*! + * Assigns a copy of the character sequence defined by the range [i,j) to + * this string. + * + * If \a i is greater than or equal to \a j, this function empties the string + * by calling Clear(). Otherwise this function will assign the specified + * sequence of characters. + * + * If \a i and/or \a j are iterators on this string, this function invokes + * undefined behavior. + * + * \b Important - Note that this function is \e not equivalent to: + * + * \code Assign( i, 0, j-i ); \endcode + * + * because the above call would assign a null-terminated sequence, while + * this function assigns the specified range unconditionally, even if it + * contains null characters. Since this function does not have to scan for + * a terminating character, it is potentially much more efficient. + */ + void Assign( const_iterator i, const_iterator j ) + { + if ( i < j ) + { + size_type len = j - i; + MaybeReallocate( len ); + R::Copy( m_data->string, i, len ); + } + else + Clear(); + } + + /*! + * Assigns a sequence of characters defined by the specified initializer + * list \a l to this string. This function is equivalent to: + * + * \code Assign( l.begin(), l.end() ) \endcode + */ + void Assign( std::initializer_list l ) + { + Assign( l.begin(), l.end() ); + } + + /*! + * Assigns a copy of at most \a n characters stored in the null-terminated + * sequence \a t, starting from its \a i-th character, to this string. + * + * If \a t is the null pointer, or \a i is greater than the length of \a t, + * or \a n is zero, this function empties the string by calling Clear(). + * + * If \a t is a pointer to the contents of this string (or, equivalently, an + * iterator on this string), this function invokes undefined behavior. + * + * The character count \a n will be constrained to copy existing characters + * from the null-terminated source sequence. + */ + void Assign( const_c_string t, size_type i, size_type n ) + { + size_type len = R::Length( t ); + if ( i < len && (n = pcl::Min( n, len-i )) > 0 ) + { + MaybeReallocate( n ); + R::Copy( m_data->string, t+i, n ); + } + else + Clear(); + } + + /*! + * Assigns \a n copies of the specified character \a c to this string. If + * either \a c is the null character or \a n is zero, this function empties + * the string by calling Clear(). + */ + void Assign( char_type c, size_type n = 1 ) + { + if ( !R::IsNull( c ) && n > 0 ) + { + MaybeReallocate( n ); + R::Fill( m_data->string, c, n ); + } + else + Clear(); + } + + /*! + * Exchanges this string with another string \a s. + */ + void Swap( GenericString& s ) noexcept + { + pcl::Swap( m_data, s.m_data ); + } + + /*! + * Fills this string (if not empty) with the specified character \a c. + * + * \note The null terminating character can legally be specified as a + * filling character with this function. In this case the internal string + * pointer will be seen as an empty string by C library routines (such as + * strlen or strcpy) and other applications after calling this function, + * although it will continue storing the same allocated data block. + */ + void Fill( char_type c ) + { + size_type len = Length(); + if ( len > 0 ) + { + if ( !IsUnique() ) + { + Data* newData = Data::New( len ); + DetachFromData(); + m_data = newData; + } + R::Fill( m_data->string, c, len ); + } + } + + /*! + * Fills a segment of at most \a n contiguous characters in this string with + * the specified character \a c, starting from the \a i-th character. + * + * If \a i is greater than or equal to the length of this string, then + * calling this function has no effect. Otherwise the character count \a n + * will be constrained to replace existing characters in this string. + * + * \note The null terminating character can legally be specified as a + * filling character with this function. In this case the internal string + * pointer will be seen as an empty string by C library routines (such as + * strlen or strcpy) and other applications after calling this function, + * although it will continue storing the same allocated data block. + */ + void Fill( char_type c, size_type i, size_type n = maxPos ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n < len ) + EnsureUnique(); + else if ( !IsUnique() ) + { + Data* newData = Data::New( len ); + DetachFromData(); + m_data = newData; + } + R::Fill( m_data->string+i, c, n ); + } + } + + /*! + * Securely fills this string and all instances sharing its string data with + * the specified character \a c. + * + * If no filling character \a c is specified, the string will be filled with + * zeros, or null characters. + * + * The normal data sharing mechanism is ignored on purpose by this function, + * so if there are other objects sharing the same string data, all of them + * will be affected unconditionally after calling this function. + * + * This function is useful to ensure that sensitive data, such as user + * passwords and user names, are destroyed without the risk of surviving + * duplicates as a result of implicit data sharing. + * + * \note If the specified filling character \a c is zero, or the null + * character (the default value), the internal string pointer will be seen + * as an empty string by C library routines (such as strlen or strcpy) and + * other applications after calling this function, although it will continue + * storing the same allocated data block. + */ + void SecureFill( char c = '\0' ) noexcept + { + volatile char* s = reinterpret_cast( m_data->string ); + for ( size_type n = Capacity()*sizeof( char_type ); n > 0; --n ) + *s++ = c; + } + + /*! + * Ensures that this string has enough capacity to store \a n characters + * plus a terminating null character. + * + * After calling this member function with \a n > 0, this object is + * guaranteed to uniquely reference its string data. + */ + void Reserve( size_type n ) + { + if ( n > 0 ) + if ( IsUnique() ) + { + if ( Capacity() < n+1 ) + { + iterator old = m_data->string; + size_type len = Length(); + m_data->Reserve( len, n ); + if ( old != nullptr ) + { + if ( len > 0 ) + R::Copy( m_data->string, old, len ); + m_data->alloc.Deallocate( old ); + } + } + } + else + { + size_type len = Length(); + Data* newData = Data::New(); // ### FIXME: unlikely, but this is a potential leak + newData->Reserve( len, pcl::Max( len, n ) ); + if ( len > 0 ) + R::Copy( newData->string, m_data->string, len ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Causes this string to have the specified length \a n in characters. + * + * If \a n is zero, this function calls Clear() to empty the string. + * Otherwise the string data will be shrunk or extended, and possibly + * reallocated. If the resulting string is larger than the original, newly + * allocated or reserved characters won't be initialized and will have + * unpredictable values; in this case it is the caller's responsibility to + * write them as appropriate. + * + * After calling this member function, this object is guaranteed to uniquely + * reference its string data. + */ + void SetLength( size_type n ) + { + if ( n != Length() ) + { + if ( n > 0 ) + { + if ( !IsUnique() || m_data->ShouldReallocate( n ) ) + { + Data* newData = Data::New( n ); + size_type m = Capacity(); + if ( m > 0 ) + R::Copy( newData->string, m_data->string, pcl::Min( n, m ) ); + DetachFromData(); + m_data = newData; + } + else + m_data->SetLength( n ); + } + else + Clear(); + } + else + EnsureUnique(); + } + + /*! + * Returns a copy of this string resized to have the specified length \a n + * in characters. This function is a wrapper for SetLength(); see that + * function for important information. + */ + GenericString SetToLength( size_type n ) const + { + // NB: This can be done more efficiently if this string is unique. + GenericString s( *this ); + s.SetLength( n ); + return s; + } + + /*! + * Resizes this string to match the length of the internal null-terminated + * string buffer. + * + * This member function scans the internal string buffer for a terminating + * null character, then calls SetLength() to set the corresponding length in + * characters. + */ + void ResizeToNullTerminated() + { + SetLength( R::Length( m_data->string ) ); + } + + /*! + * Returns a copy of this string resized to match the length of its internal + * null-terminated string buffer. + */ + GenericString ResizedToNullTerminated() const + { + GenericString s( *this ); + s.ResizeToNullTerminated(); + return s; + } + + /*! + * Causes this string to allocate the exact required memory space to store + * its contained characters, plus a terminating null character. + * + * If the string has excess capacity, a new copy of its existing characters + * is generated and stored in a newly allocated memory block that fits them + * exactly, then the previous memory block is deallocated. + * + * If the string is empty, calling this function is equivalent to Clear(). + * Note that in this case a previously allocated memory block (by a call to + * Reserve()) may also be deallocated. + */ + void Squeeze() + { + if ( Available() > 0 ) + { + size_type len = Length(); + if ( len > 0 ) + { + if ( IsUnique() ) + { + iterator old = m_data->string; + m_data->Allocate( len, 0 ); + R::Copy( m_data->string, old, len ); + m_data->alloc.Deallocate( old ); + } + else + { + Data* newData = Data::New( len, 0 ); + R::Copy( newData->string, m_data->string, len ); + DetachFromData(); + m_data = newData; + } + } + else + Clear(); + } + } + + /*! + * Returns a copy of this string allocated to the exact required memory + * space to store its contained characters and a terminating null character. + */ + GenericString Squeezed() const + { + // NB: This can be done more efficiently if this string is unique. + GenericString s( *this ); + s.Squeeze(); + return s; + } + + /*! + * Releases the data in this string. + * + * This member function returns a pointer to the string data block + * referenced by this object, after ensuring that it is uniquely referenced. + * If the string is empty, this function may return the null pointer. + * + * Before returning, this member function empties this string without + * deallocating its string data. The caller is then responsible for + * destructing and/or deallocating the returned block when it is no longer + * required. + */ + c_string Release() + { + EnsureUnique(); + iterator string = m_data->string; + m_data->Reset(); + return string; + } + + /*! + * Copies characters from this string to a null-terminated character array. + * + * \param[out] dst Destination character array. + * + * \param maxCharsToCopy The total number of characters that can be stored + * at the \a dst array, \e including a null terminating + * character. + * + * \param i Index of the first character to be copied from this + * string. + * + * This function copies at most \a maxCharsToCopy-1 characters from this + * string (or Length()-i, whichever is less) to the \a dst array. Then a + * null terminating character is appended to \a dst. + */ + void c_copy( iterator dst, size_type maxCharsToCopy, size_type i = 0 ) const noexcept + { + if ( dst != nullptr ) + if ( maxCharsToCopy > 0 ) + { + if ( --maxCharsToCopy > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + size_type n = pcl::Min( maxCharsToCopy, len-i ); + R::Copy( dst, m_data->string+i, n ); + dst += n; + } + } + + *dst = R::Null(); + } + } + + /*! + * Inserts a copy of the string \a s at the index \a i in this string. + */ + template + void Insert( size_type i, const GenericString& s ) + { + size_type n = s.Length(); + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + R::Copy( m_data->string+i, s.m_data->string, n ); + } + } + + /*! + * Inserts a copy of the character sequence defined by the range [p,q) at + * the index \a i in this string. + * + * If \a p is greater than or equal to \a q, calling this member function + * has no effect. + */ + void Insert( size_type i, const_iterator p, const_iterator q ) + { + if ( p < q ) + { + size_type n = q - p; + UninitializedGrow( i, n ); // -> 0 <= i <= len + R::Copy( m_data->string+i, p, n ); + } + } + + /*! + * Inserts a null-terminated character sequence \a t at the index \a i in + * this string. + */ + void Insert( size_type i, const_c_string t ) + { + size_type n = R::Length( t ); + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + R::Copy( m_data->string+i, t, n ); + } + } + + /*! + * Inserts at most the first \a n characters of a null-terminated character + * sequence \a t at the index \a i in this string. + */ + void Insert( size_type i, const_c_string t, size_type n ) + { + if ( (n = pcl::Min( n, R::Length( t ) )) > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + R::Copy( m_data->string+i, t, n ); + } + } + + /*! + * Inserts \a n copies of a character \a c at the index \a i in this string. + */ + void Insert( size_type i, char_type c, size_type n = 1 ) + { + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + R::Fill( m_data->string+i, c, n ); + } + } + + /*! + * Appends a copy of the specified string \a s to this string. + */ + template + void Append( const GenericString& s ) + { + Insert( maxPos, s ); + } + + /*! + * Appends a copy of a string by calling Append( s ). Returns a reference to + * this object. + */ + template + GenericString& operator +=( const GenericString& s ) + { + Append( s ); + return *this; + } + + /*! + * Appends a copy of the character sequence defined by the range [i,j) to + * this string. + * + * If \a i is greater than or equal to \a j, calling this member function + * has no effect. + */ + void Append( const_iterator i, const_iterator j ) + { + Insert( maxPos, i, j ); + } + + /*! + * Appends a copy of the first \a n characters of a null-terminated + * character sequence \a t to this string. + */ + void Append( const_c_string t, size_type n ) + { + Insert( maxPos, t, n ); + } + + /*! + * Appends a copy of a null-terminated character sequence to this string. + */ + void Append( const_c_string t ) + { + Insert( maxPos, t ); + } + + /*! + * Appends a copy of a null-terminated string by calling Append( t ). + * Returns a reference to this object. + */ + GenericString& operator +=( const_c_string t ) + { + Append( t ); + return *this; + } + + /*! + * Appends \a n copies of a character \a c to this string. + */ + void Append( char_type c, size_type n = 1 ) + { + Insert( maxPos, c, n ); + } + + /*! + * A synonym for Append( const GenericString& ), provided for compatibility + * with PCL container classes. + */ + template + void Add( const GenericString& s ) + { + Append( s ); + } + + /*! + * A synonym for Append( const_iterator, const_iterator ), provided for + * compatibility with PCL container classes. + */ + void Add( const_iterator i, const_iterator j ) + { + Append( i, j ); + } + + /*! + * A synonym for Append( const_c_string, size_type ), provided for compatibility + * with PCL container classes. + */ + void Add( const_c_string t, size_type n ) + { + Append( t, n ); + } + + /*! + * A synonym for Append( const_c_string ), provided for compatibility with PCL + * container classes. + */ + void Add( const_c_string t ) + { + Append( t ); + } + + /*! + * A synonym for Append( char_type, size_type ), provided for compatibility with PCL + * container classes. + */ + void Add( char_type c, size_type n = 1 ) + { + Append( c, n ); + } + + /*! + * Appends a copy of the specified character \a c to this string. Returns a + * reference to this object. + */ + GenericString& operator +=( char_type c ) + { + Append( c ); + return *this; + } + + /*! + * Inserts a copy of the specified string \a s at the beginning of this + * string. + */ + template + void Prepend( const GenericString& s ) + { + Insert( 0, s ); + } + + /*! + * Inserts a copy of a string \a s at the beginning of this string. Returns + * a reference to this object. + */ + template + GenericString& operator -=( const GenericString& s ) + { + Prepend( s ); + return *this; + } + + /*! + * Inserts a copy of the character sequence defined by the range [i,j) at + * the beginning of this string. + * + * If \a i is greater than or equal to \a j, calling this member function + * has no effect. + */ + void Prepend( const_iterator i, const_iterator j ) + { + Insert( 0, i, j ); + } + + /*! + * Inserts a copy of the first \a n characters of a character array \a t at + * the beginning of this string. + */ + void Prepend( const_c_string t, size_type n ) + { + Insert( 0, t, n ); + } + + /*! + * Inserts a copy of the null-terminated character sequence \a t at the + * beginning of this string. + */ + void Prepend( const_c_string t ) + { + Insert( 0, t ); + } + + /*! + * Inserts a copy of the null-terminated sequence \a t at the beginning of + * this string. Returns a reference to this object. + */ + GenericString& operator -=( const_c_string t ) + { + Prepend( t ); + return *this; + } + + /*! + * Inserts \a n copies of a character \a c at the beginning of this string. + */ + void Prepend( char_type c, size_type n = 1 ) + { + Insert( 0, c, n ); + } + + /*! + * Inserts a copy of the specified character \a c at the beginning of this + * string. Returns a reference to this object. + */ + GenericString& operator -=( char_type c ) + { + Prepend( c ); + return *this; + } + + /*! + * Replaces a segment of \a n contiguous characters, starting at the \a i-th + * character in this string, with a copy of a string \a s. + */ + template + void Replace( size_type i, size_type n, const GenericString& s ) + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n != len ) + { + size_type ns = s.Length(); + if ( ns > 0 ) + { + if ( n < ns ) + UninitializedGrow( i, ns-n ); + else if ( ns < n ) + Delete( i, n-ns ); + else + EnsureUnique(); + + R::Copy( m_data->string+i, s.m_data->string, ns ); + } + else + Delete( i, n ); + } + else + Assign( s ); + } + } + } + + /*! + * Replaces a segment of at most \a n contiguous characters, starting at the + * \a i-th character in this string, with a copy of a null-terminated + * sequence \a t. + * + * If \a t is a pointer to the contents of this string (or, equivalently, an + * iterator on this string), this function invokes undefined behavior. + */ + void Replace( size_type i, size_type n, const_c_string t ) + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n != len ) + { + size_type nt = R::Length( t ); + if ( nt > 0 ) + { + if ( n < nt ) + UninitializedGrow( i, nt-n ); + else if ( nt < n ) + Delete( i, n-nt ); + else + EnsureUnique(); + + R::Copy( m_data->string+i, t, nt ); + } + else + Delete( i, n ); + } + else + Assign( t ); + } + } + } + + /*! + * Replaces a segment of at most \a n contiguous characters, starting at the + * \a i-th character in this string, with \a nc copies of a character \a c. + */ + void Replace( size_type i, size_type n, char_type c, size_type nc = 1 ) + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n != len ) + { + if ( nc > 0 ) + { + if ( n < nc ) + UninitializedGrow( i, nc-n ); + else if ( nc < n ) + Delete( i, n-nc ); + else + EnsureUnique(); + + R::Fill( m_data->string+i, c, nc ); + } + else + Delete( i, n ); + } + else + Assign( c, nc ); + } + } + } + + /*! + * Replaces all occurrences of a character \a c1 with \a c2 in a segment of + * \a n contiguous characters starting at the \a i-th character in this + * string. + */ + void ReplaceChar( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) + { + ReplaceChar( c1, c2, i, n, true/*case*/ ); + } + + /*! + * Replaces all occurrences of a character \a c1 with \a c2 in a segment of + * \a n contiguous characters starting at the \a i-th character in this + * string. + * + * This member function performs case-insensitive character comparisons. + */ + void ReplaceCharIC( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) + { + ReplaceChar( c1, c2, i, n, false/*case*/ ); + } + + /*! + * Replaces all occurrences of a string \a s1 with \a s2 in a segment of + * contiguous characters starting at the \a i-th character, and spanning to + * the end of this string. + */ + template + void ReplaceString( const GenericString& s1, + const GenericString& s2, size_type i = 0 ) + { + ReplaceString( s1.m_data->string, s1.Length(), s2.m_data->string, s2.Length(), i, true/*case*/ ); + } + + /*! + * Replaces all occurrences of a null-terminated string \a t1 with \a t2 in + * a segment of contiguous characters starting at the \a i-th character, and + * spanning to the end of this string. + */ + void ReplaceString( const_c_string t1, const_c_string t2, size_type i = 0 ) + { + ReplaceString( t1, R::Length( t1 ), t2, R::Length( t2 ), i, true/*case*/ ); + } + + /*! + * Replaces all occurrences of a string \a s1 with \a s2 in a segment of + * contiguous characters starting at the \a i-th character, and spanning to + * the end of this string. + * + * This member function performs case-insensitive string comparisons. + */ + template + void ReplaceStringIC( const GenericString& s1, + const GenericString& s2, size_type i = 0 ) + { + ReplaceString( s1.m_data->string, s1.Length(), s2.m_data->string, s2.Length(), i, false/*case*/ ); + } + + /*! + * Replaces all occurrences of a null-terminated string \a t1 with \a t2 in + * a segment of contiguous characters starting at the \a i-th character, and + * spanning to the end of this string. + * + * This member function performs case-insensitive string comparisons. + */ + void ReplaceStringIC( const_c_string t1, const_c_string t2, size_type i = 0 ) + { + ReplaceString( t1, R::Length( t1 ), t2, R::Length( t2 ), i, false/*case*/ ); + } + + /*! + * Deletes a contiguous segment of at most \a n characters starting at the + * \a i-th character in this string. + */ + void Delete( size_type i, size_type n = 1 ) + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n < len ) + { + size_type newLen = len-n; + if ( !IsUnique() || m_data->ShouldReallocate( newLen ) ) + { + Data* newData = Data::New( newLen ); + if ( i > 0 ) + R::Copy( newData->string, m_data->string, i ); + if ( i < newLen ) + R::Copy( newData->string+i, m_data->string+i+n, newLen-i ); + DetachFromData(); + m_data = newData; + } + else + { + if ( i < newLen ) + R::CopyOverlapped( m_data->string+i, m_data->string+i+n, newLen-i ); + m_data->SetLength( newLen ); + } + } + else + Clear(); + } + } + } + + /*! + * Deletes a segment of contiguous characters starting from the \a i-th + * character and spanning to the end of this string. + */ + void DeleteRight( size_type i ) + { + Delete( i, maxPos ); + } + + /*! + * Deletes the initial segment of at most \a i contiguous characters in this + * string. + */ + void DeleteLeft( size_type i ) + { + Delete( 0, i ); + } + + /*! + * Deletes all occurrences of the \a c character in a segment of contiguous + * characters starting from the \a i-th character and spanning to the end of + * this string. + */ + void DeleteChar( char_type c, size_type i = 0 ) + { + ReplaceString( &c, 1, nullptr, 0, i, true/*case*/ ); + } + + /*! + * Deletes all occurrences of the \a c character in a segment of contiguous + * characters starting from the \a i-th character and spanning to the end of + * this string. + * + * This member function performs case-insensitive character comparisons. + */ + void DeleteCharIC( char_type c, size_type i = 0 ) + { + ReplaceString( &c, 1, nullptr, 0, i, false/*case*/ ); + } + + /*! + * Deletes all occurrences of a string \a s in a segment of contiguous + * characters starting from the \a i-th character and spanning to the end of + * this string. + */ + template + void DeleteString( const GenericString& s, size_type i = 0 ) + { + ReplaceString( s.m_data->string, s.Length(), nullptr, 0, i, true/*case*/ ); + } + + /*! + * Deletes all occurrences of a null-terminated string \a s in a segment of + * contiguous characters starting from the \a i-th character and spanning to + * the end of this string. + */ + void DeleteString( const_c_string t, size_type i = 0 ) + { + ReplaceString( t, R::Length( t ), nullptr, 0, i, true/*case*/ ); + } + + /*! + * Deletes all occurrences of a string \a s in a segment of contiguous + * characters starting from the \a i-th character and spanning to the end of + * this string. + * + * This member function performs case-insensitive string comparisons. + */ + template + void DeleteStringIC( const GenericString& s, size_type i = 0 ) + { + ReplaceString( s.m_data->string, s.Length(), nullptr, 0, i, false/*case*/ ); + } + + /*! + * Deletes all occurrences of a null-terminated string \a s in a segment of + * contiguous characters starting from the \a i-th character and spanning to + * the end of this string. + * + * This member function performs case-insensitive string comparisons. + */ + void DeleteStringIC( const_c_string t, size_type i = 0 ) + { + ReplaceString( t, R::Length( t ), nullptr, 0, i, false/*case*/ ); + } + + /*! + * Removes all characters in this string, yielding an empty string. + * + * If this string is empty, then calling this member function has no effect. + * + * If this string uniquely references its string data, it is destroyed and + * deallocated; otherwise its reference counter is decremented. Then a new, + * empty string data structure is created and uniquely referenced. + */ + void Clear() + { + if ( !IsEmpty() ) + if ( IsUnique() ) + m_data->Deallocate(); + else + { + Data* newData = Data::New(); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns a string with a copy of at most \a n contiguous characters + * starting at the \a i-th character in this string. + */ + GenericString Substring( size_type i, size_type n = maxPos ) const + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n > 0 ) + { + if ( n < len ) + { + GenericString t; + t.m_data->Allocate( n ); + R::Copy( t.m_data->string, m_data->string+i, n ); + return t; + } + return *this; + } + } + return GenericString(); + } + + /*! + * Returns a string with a copy of the at most \a n contiguous initial + * characters of this string. + */ + GenericString Left( size_type n ) const + { + size_type len = Length(); + n = pcl::Min( n, len ); + if ( n > 0 ) + { + if ( n < len ) + { + GenericString t; + t.m_data->Allocate( n ); + R::Copy( t.m_data->string, m_data->string, n ); + return t; + } + return *this; + } + return GenericString(); + } + + /*! + * Returns a string with a copy of the at most \a n contiguous ending + * characters of this string. + */ + GenericString Right( size_type n ) const + { + size_type len = Length(); + n = pcl::Min( n, len ); + if ( n > 0 ) + { + if ( n < len ) + { + GenericString t; + t.m_data->Allocate( n ); + R::Copy( t.m_data->string, m_data->string+len-n, n ); + return t; + } + return *this; + } + return GenericString(); + } + + /*! + * Returns the suffix of this string starting at index \a i. Calling this + * member function is equivalent to: + * + * \code Right( Length()-i ) \endcode + */ + GenericString Suffix( size_type i ) const + { + return Substring( i ); + } + + /*! + * Returns the prefix of this string ending at index \a i. Calling this + * member function is equivalent to: + * + * \code Left( i-1 ) \endcode + */ + GenericString Prefix( size_type i ) const + { + return Left( (i > 0) ? i-1 : 0 ); + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a StringList. + * + * \param s The token separator string. + * + * \param trim True to \e trim the extracted tokens. If this parameter is + * true, existing leading and trailing whitespace characters + * will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type Break( C& list, const GenericString& s, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + size_type len = Length(); + if ( i < len ) + { + size_type n = s.Length(); + if ( n > 0 ) + for ( SearchEngine S( s.m_data->string, n, true/*case*/ ); ; ) + { + size_type j = S( m_data->string, i, len ); + + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + n; + } + } + return count; + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a + * StringList. + * + * \param s The token separator null-terminated string. + * + * \param trim True to \e trim the extracted tokens. If this parameter + * is true, existing leading and trailing whitespace + * characters will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type Break( C& list, const_c_string s, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + size_type len = Length(); + if ( i < len ) + { + size_type n = R::Length( s ); + if ( n > 0 ) + for ( SearchEngine S( s, n, true/*case*/ ); ; ) + { + size_type j = S( m_data->string, i, len ); + + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + n; + } + } + return count; + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a StringList. + * + * \param c The token separator character. Tokens will be separated by + * sequences of one or more instances of this character. + * + * \param trim True to \e trim the extracted tokens. If this parameter is + * true, existing leading and trailing whitespace characters + * will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type Break( C& list, char_type c, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + size_type len = Length(); + if ( i < len ) + { + for ( ;; ) + { + size_type j = i; + for ( const_iterator p = m_data->string + i; j < len; ++j, ++p ) + if ( *p == c ) + break; + + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + 1; + } + } + return count; + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a StringList. + * + * \param ca An array of token separator characters. Tokens will be + * separated by instances of any character included in this + * array. The template argument S must have type conversion + * semantics to the character type of this string class + * (char_type). If this array is empty, calling this function + * has no effect and zero is returned. + * + * \param trim True to \e trim the extracted tokens. If this parameter is + * true, existing leading and trailing whitespace characters + * will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type Break( C& list, const Array& ca, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + if ( !ca.IsEmpty() ) + { + size_type len = Length(); + if ( i < len ) + { + for ( ;; ) + { + size_type j = i; + for ( const_iterator p = m_data->string + i; j < len; ++j, ++p ) + for ( auto c : ca ) + if ( *p == char_type( c ) ) + goto __Break_1; +__Break_1: + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + 1; + } + } + } + return count; + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string by + * performing case-insensitive comparisons with a token separation string. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a StringList. + * + * \param s The token separator string. This function performs + * case-insensitive string comparisons to locate instances of + * this string. + * + * \param trim True to \e trim the extracted tokens. If this parameter is + * true, existing leading and trailing whitespace characters + * will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type BreakIC( C& list, const GenericString& s, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + size_type len = Length(); + if ( i < len ) + { + size_type n = s.Length(); + if ( n > 0 ) + { + for ( SearchEngine S( s.m_data->string, n, false/*case*/ ); ; ) + { + size_type j = S( m_data->string, i, len ); + + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + n; + } + } + } + return count; + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string by + * performing case-insensitive comparisons with a null-terminated token + * separation string. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a + * StringList. + * + * \param s The token separator null-terminated string. This + * function performs case-insensitive string comparisons + * to locate instances of this string. + * + * \param trim True to \e trim the extracted tokens. If this parameter + * is true, existing leading and trailing whitespace + * characters will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type BreakIC( C& list, const_c_string s, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + size_type len = Length(); + if ( i < len ) + { + size_type n = R::Length( s ); + if ( n > 0 ) + { + for ( SearchEngine S( s, n, false/*case*/ ); ; ) + { + size_type j = S( m_data->string, i, len ); + + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + n; + } + } + } + return count; + } + + /*! + * Gets a sequence of \e tokens (substrings) extracted from this string by + * performing case-insensitive comparisons with a token separator character. + * + * \param[out] list The list of extracted tokens. Must be a reference to a + * container, such as Array or List, or a derived class. + * Typically, this parameter is a reference to a StringList. + * + * \param c The token separator character. Tokens will be separated by + * sequences of one or more instances of this character. This + * function performs case-insensitive character comparisons + * to locate instances of this character. + * + * \param trim True to \e trim the extracted tokens. If this parameter is + * true, existing leading and trailing whitespace characters + * will be removed from each extracted token. + * + * \param i Starting character index. + * + * Returns the number of tokens extracted and added to the list. + */ + template + size_type BreakIC( C& list, char_type c, bool trim = false, size_type i = 0 ) const + { + size_type count = 0; + size_type len = Length(); + if ( i < len ) + { + c = R::ToCaseFolded( c ); + for ( ;; ) + { + size_type j = i; + for ( const_iterator p = m_data->string + i; j < len; ++j, ++p ) + if ( R::ToCaseFolded( *p ) == c ) + break; + + GenericString t; + if ( i < j ) + { + const_iterator l = m_data->string + i; + size_type m = j - i; + if ( trim ) + { + const_iterator r = l + m; + l = R::SearchTrimLeft( l, r ); + m = R::SearchTrimRight( l, r ) - l; + } + if ( m > 0 ) + { + t.m_data->Allocate( m ); + R::Copy( t.m_data->string, l, m ); + } + } + list.Add( t ); + ++count; + + if ( j == len ) + break; + + i = j + 1; + } + } + return count; + } + + /*! + * Returns the first character in this string, or a null character + * (R::Null()) if this string is empty. + */ + char_type FirstChar() const noexcept + { + return (m_data->string != nullptr) ? *m_data->string : R::Null(); + } + + /*! + * Returns the last character in this string, or a null character + * (R::Null()) if this string is empty. + */ + char_type LastChar() const noexcept + { + return (m_data->string < m_data->end) ? *(m_data->end-1) : R::Null(); + } + + /*! + * Returns true iff this string begins with the specified substring \a s. + */ + template + bool StartsWith( const GenericString& s ) const noexcept + { + if ( s.IsEmpty() || Length() < s.Length() ) + return false; + for ( const_iterator p = m_data->string, q = s.m_data->string; q < s.m_data->end; ++p, ++q ) + if ( *p != *q ) + return false; + return true; + } + + /*! + * Returns true iff this string begins with the specified null-terminated + * sequence \a t. + */ + bool StartsWith( const_c_string t ) const noexcept + { + size_type n = R::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->string, e = p+n; p < e; ++p, ++t ) + if ( *p != *t ) + return false; + return true; + } + + /*! + * Returns true iff this string begins with the specified character \a c. + */ + bool StartsWith( char_type c ) const noexcept + { + return m_data->string < m_data->end && *m_data->string == c; + } + + /*! + * Returns true iff this string begins with the specified substring \a s, + * performing case-insensitive character comparisons. + */ + template + bool StartsWithIC( const GenericString& s ) const noexcept + { + if ( s.IsEmpty() || Length() < s.Length() ) + return false; + for ( const_iterator p = m_data->string, q = s.m_data->string; q < s.m_data->end; ++p, ++q ) + if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *q ) ) + return false; + return true; + } + + /*! + * Returns true iff this string begins with the specified null-terminated + * sequence \a t, performing case-insensitive character comparisons. + */ + bool StartsWithIC( const_c_string t ) const noexcept + { + size_type n = R::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->string, e = p+n; p < e; ++p, ++t ) + if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *t ) ) + return false; + return true; + } + + /*! + * Returns true iff this string begins with the specified character \a c, + * performing a case-insensitive character comparison. + */ + bool StartsWithIC( char_type c ) const noexcept + { + return m_data->string < m_data->end && R::ToCaseFolded( *m_data->string ) == R::ToCaseFolded( c ); + } + + /*! + * Returns true iff this string ends with the specified substring \a s. + */ + template + bool EndsWith( const GenericString& s ) const noexcept + { + size_type n = s.Length(); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->end-n, q = s.m_data->string; p < m_data->end; ++p, ++q ) + if ( *p != *q ) + return false; + return true; + } + + /*! + * Returns true iff this string ends with the specified null-terminated + * string \a t. + */ + bool EndsWith( const_c_string t ) const noexcept + { + size_type n = R::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) + if ( *p != *t ) + return false; + return true; + } + + /*! + * Returns true iff this string ends with the specified character \a c. + */ + bool EndsWith( char_type c ) const noexcept + { + return m_data->string < m_data->end && *(m_data->end-1) == c; + } + + /*! + * Returns true iff this string ends with the specified substring \a s, + * performing case-insensitive character comparisons. + */ + template + bool EndsWithIC( const GenericString& s ) const noexcept + { + size_type n = s.Length(); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->end-n, q = s.m_data->string; p < m_data->end; ++p, ++q ) + if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *q ) ) + return false; + return true; + } + + /*! + * Returns true iff this string ends with the specified null-terminated + * string \a t, performing case-insensitive character comparisons. + */ + bool EndsWithIC( const_c_string t ) const noexcept + { + size_type n = R::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) + if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *t ) ) + return false; + return true; + } + + /*! + * Returns true iff this string ends with the specified character \a c, + * performing a case-insensitive character comparison. + */ + bool EndsWithIC( char_type c ) const noexcept + { + return m_data->string < m_data->end && R::ToCaseFolded( *(m_data->end-1) ) == R::ToCaseFolded( c ); + } + + /*! + * Returns the starting index \a k of the first occurrence of a substring + * \a s in this string, such that \a k >= \a i. Returns notFound if such + * occurrence does not exist. + */ + template + size_type FindFirst( const GenericString& s, size_type i = 0 ) const noexcept + { + size_type len = Length(); + i = SearchEngine( s.m_data->string, s.Length(), true/*case*/ )( m_data->string, i, len ); + return (i < len) ? i : notFound; + } + + /*! + * Returns the starting index \a k of the first occurrence of a + * null-terminated substring \a t in this string, such that \a k >= \a i. + * Returns notFound if such occurrence does not exist. + */ + size_type FindFirst( const_c_string t, size_type i = 0 ) const noexcept + { + size_type len = Length(); + i = SearchEngine( t, R::Length( t ), true/*case*/ )( m_data->string, i, len ); + return (i < len) ? i : notFound; + } + + /*! + * Returns the index \a k of the first occurrence of a character \a c in + * this string, such that \a k >= \a i. Returns notFound if such occurrence + * does not exist. + */ + size_type FindFirst( char_type c, size_type i = 0 ) const noexcept + { + for ( const_iterator p = m_data->string+i; p < m_data->end; ++p ) + if ( *p == c ) + return p - m_data->string; + return notFound; + } + + /*! + * Returns the starting index \a k of the first occurrence of a substring + * \a s in this string, such that \a k >= \a i. Returns notFound if such + * occurrence does not exist. + * + * This member function performs case-insensitive string comparisons to find + * an instance of the substring \a s. + */ + template + size_type FindFirstIC( const GenericString& s, size_type i = 0 ) const noexcept + { + size_type len = Length(); + i = SearchEngine( s.m_data->string, s.Length(), false/*case*/ )( m_data->string, i, len ); + return (i < len) ? i : notFound; + } + + /*! + * Returns the starting index \a k of the first occurrence of a + * null-terminated substring \a s in this string, such that \a k >= \a i. + * Returns notFound if such occurrence does not exist. + * + * This member function performs case-insensitive string comparisons to find + * an instance of the substring \a s. + */ + size_type FindFirstIC( const_c_string t, size_type i = 0 ) const noexcept + { + size_type len = Length(); + i = SearchEngine( t, R::Length( t ), false/*case*/ )( m_data->string, i, len ); + return (i < len) ? i : notFound; + } + + /*! + * Returns the index \a k of the first occurrence of a character \a c in + * this string, such that \a k >= \a i. Returns notFound if such occurrence + * does not exist. + * + * This member function performs case-insensitive character comparisons to + * find an instance of the character \a c. + */ + size_type FindFirstIC( char_type c, size_type i = 0 ) const noexcept + { + c = R::ToCaseFolded( c ); + for ( const_iterator p = m_data->string+i; p < m_data->end; ++p ) + if ( R::ToCaseFolded( *p ) == c ) + return p - m_data->string; + return notFound; + } + + /*! + * A synonym for FindFirst( const GenericString&, size_type ). + */ + template + size_type Find( const GenericString& s, size_type i = 0 ) const noexcept + { + return FindFirst( s, i ); + } + + /*! + * A synonym for FindFirst( const_c_string, size_type ). + */ + size_type Find( const_c_string t, size_type i = 0 ) const noexcept + { + return FindFirst( t, i ); + } + + /*! + * A synonym for FindFirst( char_type, size_type ). + */ + size_type Find( char_type c, size_type i = 0 ) const noexcept + { + return FindFirst( c, i ); + } + + /*! + * A synonym for FindFirstIC( const GenericString&, size_type ). + */ + template + size_type FindIC( const GenericString& s, size_type i = 0 ) const noexcept + { + return FindFirstIC( s, i ); + } + + /*! + * A synonym for FindFirstIC( const_c_string, size_type ). + */ + size_type FindIC( const_c_string t, size_type i = 0 ) const noexcept + { + return FindFirstIC( t, i ); + } + + /*! + * A synonym for FindFirstIC( char_type, size_type ). + */ + size_type FindIC( char_type c, size_type i = 0 ) const noexcept + { + return FindFirstIC( c, i ); + } + + /*! + * Returns the starting index \a k of the last occurrence of a substring + * \a s in this string, such that: + * + * \a k <= \a r - \a n, + * + * where \a n is the length of the substring \a s. Returns notFound if such + * occurrence does not exist. + */ + template + size_type FindLast( const GenericString& s, size_type r = maxPos ) const noexcept + { + r = pcl::Min( r, Length() ); + size_type i = SearchEngine( s.m_data->string, s.Length(), true/*case*/, true/*last*/ )( m_data->string, 0, r ); + return (i < r) ? i : notFound; + } + + /*! + * Returns the starting index \a k of the last occurrence of a + * null-terminated substring \a t in this string, such that: + * + * 0 <= \a k <= \a r - \a n, + * + * where \a n is the length of the substring \a t. Returns notFound if such + * occurrence does not exist. + */ + size_type FindLast( const_c_string t, size_type r = maxPos ) const noexcept + { + r = pcl::Min( r, Length() ); + size_type i = SearchEngine( t, R::Length( t ), true/*case*/, true/*last*/ )( m_data->string, 0, r ); + return (i < r) ? i : notFound; + } + + /*! + * Returns the index \a k of the last occurrence of a character \a c in this + * string, such that \a k < \a r. Returns notFound if such occurrence does + * not exist. + */ + size_type FindLast( char_type c, size_type r = maxPos ) const noexcept + { + r = pcl::Min( r, Length() ); + for ( const_iterator p = m_data->string+r; r > 0; --r ) + if ( *--p == c ) + return r - 1; + return notFound; + } + + /*! + * Returns the starting index \a k of the last occurrence of a substring + * \a s in this string, such that: + * + * \a k <= \a r - \a n, + * + * where \a n is the length of the substring \a s. Returns notFound if such + * occurrence does not exist. + * + * This member function performs case-insensitive string comparisons to + * find an instance of the specified substring \a s. + */ + template + size_type FindLastIC( const GenericString& s, size_type r = maxPos ) const noexcept + { + r = pcl::Min( r, Length() ); + size_type i = SearchEngine( s.m_data->string, s.Length(), false/*case*/, true/*last*/ )( m_data->string, 0, r ); + return (i < r) ? i : notFound; + } + + /*! + * Returns the starting index \a k of the last occurrence of a + * null-terminated substring \a t in this string, such that: + * + * 0 <= \a k <= \a r - \a n, + * + * where \a n is the length of the substring \a t. Returns notFound if such + * occurrence does not exist. + * + * This member function performs case-insensitive string comparisons to + * find an instance of the specified substring \a t. + */ + size_type FindLastIC( const_c_string t, size_type r = maxPos ) const noexcept + { + r = pcl::Min( r, Length() ); + size_type i = SearchEngine( t, R::Length( t ), false/*case*/, true/*last*/ )( m_data->string, 0, r ); + return (i < r) ? i : notFound; + } + + /*! + * Returns the index \a k of the last occurrence of a character \a c in this + * string, such that \a k < \a r. Returns notFound if such occurrence does + * not exist. + * + * This member function performs case-insensitive character comparisons to + * find an instance of the specified character \a c. + */ + size_type FindLastIC( char_type c, size_type r = maxPos ) const noexcept + { + c = R::ToCaseFolded( c ); + r = pcl::Min( r, Length() ); + for ( const_iterator p = m_data->string+r; r > 0; --r ) + if ( R::ToCaseFolded( *--p ) == c ) + return r - 1; + return notFound; + } + + /*! + * Returns true iff this string contains a substring \a s. + */ + template + bool Contains( const GenericString& s ) const noexcept + { + return Find( s ) != notFound; + } + + /*! + * Returns true iff this string contains a null-terminated substring \a t. + */ + bool Contains( const_c_string t ) const noexcept + { + return Find( t ) != notFound; + } + + /*! + * Returns true iff this string contains a character \a c. + */ + bool Contains( char_type c ) const noexcept + { + return Find( c ) != notFound; + } + + /*! + * Returns true iff this string contains a substring \a s. + * + * This member function performs case-insensitive string comparisons to + * find an instance of the specified substring \a s. + */ + template + bool ContainsIC( const GenericString& s ) const noexcept + { + return FindIC( s ) != notFound; + } + + /*! + * Returns true iff this string contains a null-terminated substring \a t. + * + * This member function performs case-insensitive string comparisons to + * find an instance of the specified substring \a t. + */ + bool ContainsIC( const_c_string t ) const noexcept + { + return FindIC( t ) != notFound; + } + + /*! + * Returns true iff this string contains a character \a c. + * + * This member function performs case-insensitive character comparisons to + * find an instance of the specified character \a c. + */ + bool ContainsIC( char_type c ) const noexcept + { + return FindIC( c ) != notFound; + } + + /*! + * Removes all leading and trailing trimable characters. + * + * Trimable characters are determined by the traits class R. A character + * \a c is trimable if R::IsTrimable( c ) is true. Generally, the set of + * trimable characters corresponds to the set of white space characters. + * + * \sa Trimmed(); + */ + void Trim() + { + const_iterator l = R::SearchTrimLeft( m_data->string, m_data->end ); + const_iterator r = R::SearchTrimRight( l, m_data->end ); + if ( m_data->string < l || r < m_data->end ) + Trim( l, r - l ); + } + + /*! + * Removes all leading trimable characters. + * + * Trimable characters are determined by the traits class R. A character + * \a c is trimable if R::IsTrimable( c ) is true. Generally, the set of + * trimable characters corresponds to the set of white space characters. + * + * \sa TrimmedLeft(); + */ + void TrimLeft() + { + const_iterator l = R::SearchTrimLeft( m_data->string, m_data->end ); + if ( m_data->string < l ) + Trim( l, m_data->end - l ); + } + + /*! + * Removes all trailing trimable characters. + * + * Trimable characters are determined by the traits class R. A character + * \a c is trimable if R::IsTrimable( c ) is true. Generally, the set of + * trimable characters corresponds to the set of white space characters. + * + * \sa TrimmedRight(); + */ + void TrimRight() + { + const_iterator r = R::SearchTrimRight( m_data->string, m_data->end ); + if ( r < m_data->end ) + Trim( m_data->string, r - m_data->string ); + } + + /*! + * Returns a duplicate of this string with all leading and trailing + * trimable characters removed. + * \sa Trim() + */ + GenericString Trimmed() const + { + GenericString s( *this ); + s.Trim(); + return s; + } + + /*! + * Returns a duplicate of this string with all leading trimable + * characters removed. + * \sa TrimLeft() + */ + GenericString TrimmedLeft() const + { + GenericString s( *this ); + s.TrimLeft(); + return s; + } + + /*! + * Returns a duplicate of this string with all trailing trimable + * characters removed. + * \sa TrimRight() + */ + GenericString TrimmedRight() const + { + GenericString s( *this ); + s.TrimRight(); + return s; + } + + /*! + * Ensures that this string is enclosed by a leading and a trailing instance + * of the specified character \a c. If this string is already enclosed by + * \a c, this function does nothing. + * \sa Enclosed() + */ + void EnsureEnclosed( char_type c ) + { + int encloseLeft = 1; + int encloseRight = 1; + size_type len = Length(); + if ( len > 0 ) + { + if ( *m_data->string == c ) + encloseLeft = 0; + if ( *(m_data->end-1) == c ) + if ( len > 1 ) + encloseRight = 0; + else + encloseLeft = 0; + } + size_type n = len + encloseLeft + encloseRight; + if ( n > len ) + { + if ( !IsUnique() || m_data->ShouldReallocate( n ) ) + { + Data* newData = Data::New( n ); + R::Copy( newData->string + encloseLeft, m_data->string, len ); + DetachFromData(); + m_data = newData; + } + else + { + m_data->SetLength( n ); + R::CopyOverlapped( m_data->string + encloseLeft, m_data->string, len ); + } + + if ( encloseLeft ) + *m_data->string = c; + if ( encloseRight ) + *(m_data->end-1) = c; + } + } + + /*! + * Returns a duplicate of this string enclosed by the specified character. + * If this string is already enclosed by \a c, this function returns an + * unmodified copy. + * \sa EnsureEnclosed() + */ + GenericString Enclosed( char_type c ) const + { + GenericString s( *this ); + s.EnsureEnclosed( c ); + return s; + } + + /*! + * Ensures that this string is enclosed by a leading and a trailing instance + * of the single quote character ('). If this string is already single + * quoted, this function does nothing. + * \sa SingleQuoted() + */ + void EnsureSingleQuoted() + { + EnsureEnclosed( R::SingleQuote() ); + } + + /*! + * Returns a duplicate of this string enclosed by single quote characters + * ('). If this string is already single quoted, this function returns an + * unmodified copy. + * \sa EnsureSingleQuoted() + */ + GenericString SingleQuoted() const + { + GenericString s( *this ); + s.EnsureSingleQuoted(); + return s; + } + + /*! + * Ensures that this string is enclosed by a leading and a trailing instance + * of the double quote character ("). If this string is already double + * quoted, this function does nothing. + * \sa DoubleQuoted() + */ + void EnsureDoubleQuoted() + { + EnsureEnclosed( R::DoubleQuote() ); + } + + /*! + * Returns a duplicate of this string enclosed by double quote characters + * ("). If this string is already double quoted, this function returns an + * unmodified copy. + * \sa EnsureDoubleQuoted() + */ + GenericString DoubleQuoted() const + { + GenericString s( *this ); + s.EnsureDoubleQuoted(); + return s; + } + + /*! + * Unquotes this string. + * + * If the string starts and ends with single quote characters, the result is + * the same string with the quotes removed and its length decremented by + * two. The same happens if the string starts and ends with double quote + * characters. + * + * If the string does not start and end with the same quote character, this + * function has no effect. + * + * \sa Unquoted() + */ + void Unquote() + { + size_type len = Length(); + if ( len > 1 ) + if ( *m_data->string == R::SingleQuote() && *(m_data->end-1) == R::SingleQuote() || + *m_data->string == R::DoubleQuote() && *(m_data->end-1) == R::DoubleQuote() ) + if ( IsUnique() ) + { + R::CopyOverlapped( m_data->string, m_data->string+1, len-2 ); + m_data->SetLength( len-2 ); + } + else + { + Data* newData = Data::New( len-2 ); + R::Copy( newData->string, m_data->string+1, len-2 ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns an unquoted duplicate of this string. + * \sa Unquote() + */ + GenericString Unquoted() const + { + GenericString s( *this ); + s.Unquote(); + return s; + } + + /*! + * Pads this string to the right, using the specified \a fill character, up + * to the specified \a width. + * + * If the current length \e n of this string is less than the specified + * \a width, \a width - \e n copies of the \a fill character will be + * appended to the string. If the current length is greater than or equal to + * \a width, this function has no effect. + * + * \sa JustifyRight(), JustifyCenter(), LeftJustified() + */ + void JustifyLeft( size_type width, char_type fill = R::Blank() ) + { + size_type len = Length(); + if ( len < width ) + Append( fill, width-len ); + } + + /*! + * Pads this string to the left, using the specified \a fill character, up + * to the specified \a width. + * + * If the current length \e n of this string is less than the specified + * \a width, \a width - \e n copies of the \a fill character will be + * prepended to the string. If the current length is greater than or equal to + * \a width, this function has no effect. + * + * \sa JustifyLeft(), JustifyCenter(), RightJustified() + */ + void JustifyRight( size_type width, char_type fill = R::Blank() ) + { + size_type len = Length(); + if ( len < width ) + Prepend( fill, width-len ); + } + + /*! + * Pads this string equally to the left and right, using the specified + * \a fill character, up to the specified \a width. + * + * If the current length \e n of this string is less than the specified + * \a width, let \e m = \a width - \e n, and let \e m2 = \e m/2. Then \e m2 + * copies of the \a fill character will be prepended to the string, and + * \e m - \e m2 \a fill characters will be appended. If the current length + * is greater than or equal to \a width, this function has no effect. + * + * \sa JustifyLeft(), JustifyRight(), CenterJustified() + */ + void JustifyCenter( size_type width, char_type fill = R::Blank() ) + { + size_type len = Length(); + if ( len < width ) + { + size_type n = width-len; + size_type n2 = n >> 1; + Prepend( fill, n2 ); + Append( fill, n-n2 ); + } + } + + /*! + * Returns a duplicate of this string padded to the right, using the + * specified \a fill character, up to the specified \a width. + * + * \sa JustifyLeft(), RightJustified(), CenterJustified() + */ + GenericString LeftJustified( size_type width, char_type fill = R::Blank() ) const + { + GenericString s( *this ); + s.JustifyLeft( width, fill ); + return s; + } + + /*! + * Returns a duplicate of this string padded to the left, using the + * specified \a fill character, up to the specified \a width. + * + * \sa JustifyRight(), LeftJustified(), CenterJustified() + */ + GenericString RightJustified( size_type width, char_type fill = R::Blank() ) const + { + GenericString s( *this ); + s.JustifyRight( width, fill ); + return s; + } + + /*! + * Returns a duplicate of this string padded equally to the left and right, + * using the specified \a fill character, up to the specified \a width. + * + * \sa JustifyCenter(), LeftJustified(), RightJustified() + */ + GenericString CenterJustified( size_type width, char_type fill = R::Blank() ) const + { + GenericString s( *this ); + s.JustifyCenter( width, fill ); + return s; + } + + /*! + * Compares numeric character values between two strings. + * + * \param s A string to which this string will be compared. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Performs a character-to-character comparison of numeric character values + * between this string and the specified string \a s, and returns an integer + * that indicates the comparison result: + * + * \li 0 if both strings are equal. + * \li +1 if this string postcedes the specified string \a s. + * \li -1 if this string precedes the specified string \a s. + * + * This function ignores the current platform locale. It considers Unicode + * code points exclusively. For case-insensitive comparisons, a standard + * Unicode case folding transformation is applied to each character pair. + */ + template + int CompareCodePoints( const GenericString& s, bool caseSensitive = true ) const noexcept + { + return R::CompareCodePoints( m_data->string, Length(), s.m_data->string, s.Length(), caseSensitive ); + } + + /*! + * Compares numeric character values a string and a null-terminated string. + * + * \param t The starting address of a null-terminated string + * to which this string will be compared. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Performs a character-to-character comparison of numeric character values + * between this string and the specified null-terminated string \a t, and + * returns an integer that indicates the comparison result: + * + * \li 0 if both strings are equal. + * \li +1 if this string postcedes the specified string \a t. + * \li -1 if this string precedes the specified string \a t. + * + * This function ignores the current platform locale. It considers Unicode + * code points exclusively. For case-insensitive comparisons, a standard + * Unicode case folding transformation is applied to each character pair. + */ + int CompareCodePoints( const_c_string t, bool caseSensitive = true ) const noexcept + { + return R::CompareCodePoints( m_data->string, Length(), t, R::Length( t ), caseSensitive ); + } + + /*! + * Compares numeric character values a string and a null-terminated string. + * + * \param c A single character to which this string will be + * compared. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value of this parameter + * is true. + * + * Performs a comparison between this string and the specified character + * \a c, and returns an integer that indicates the comparison result: + * + * \li 0 if this string is equal to \a c. + * \li +1 if this string postcedes the character \a c. + * \li -1 if this string precedes the character \a c. + * + * The performed comparison is equivalent to a comparison of this string + * with a fictitious string of length one, whose only character was equal to + * the specified character \a c. + * + * This function ignores the current platform locale. It considers Unicode + * code points exclusively. For case-insensitive comparisons, a standard + * Unicode case folding transformation is applied to each character pair. + */ + int CompareCodePoints( char_type c, bool caseSensitive = true ) const noexcept + { + return R::CompareCodePoints( m_data->string, Length(), &c, 1, caseSensitive ); + } + + /*! + * Lexicographical comparison between two strings. + * + * \param s A string to which this string will be compared. + * + * \param caseSensitive When true, a case-sensitive comparison is performed; + * otherwise the comparison does not distinguish + * between lowercase and uppercase characters (as + * defined by the selected locale). The default value + * of this parameter is true. + * + * \param localeAware When true, a locale-dependent comparison is done + * which takes into account the currently selected user + * locale (language and variants). When false, a + * locale-invariant comparison is carried out by + * comparing character code points (which is faster). + * The default value of this parameter is true. + * + * Performs a character-to-character comparison between this string and the + * specified string \a s, and returns an integer that indicates the + * comparison result: + * + * \li 0 if both strings are equal. + * \li +1 if this string postcedes the specified string \a s. + * \li -1 if this string precedes the specified string \a s. + */ + template + int Compare( const GenericString& s, + bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return R::Compare( m_data->string, Length(), s.m_data->string, s.Length(), caseSensitive, localeAware ); + } + + /*! + * Lexicographical comparison to a null-terminated string. + * + * \param t The starting address of a null-terminated string to + * which this string will be compared. + * + * \param caseSensitive When true, a case-sensitive comparison is performed; + * otherwise the comparison does not distinguish + * between lowercase and uppercase characters (as + * defined by the selected locale). The default value + * of this parameter is true. + * + * \param localeAware When true, a locale-dependent comparison is done + * which takes into account the currently selected user + * locale (language and variants). When false, a + * locale-invariant comparison is carried out by + * comparing character code points (which is faster). + * The default value of this parameter is true. + * + * Performs a character-to-character comparison between this string and the + * specified null-terminated string \a t, and returns an integer that + * indicates the comparison result: + * + * \li 0 if both strings are equal. + * \li +1 if this string postcedes the specified string \a t. + * \li -1 if this string precedes the specified string \a t. + */ + int Compare( const_c_string t, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return R::Compare( m_data->string, Length(), t, R::Length( t ), caseSensitive, localeAware ); + } + + /*! + * Lexicographical comparison to a single character. + * + * \param c A character to which this string will be compared. + * + * \param caseSensitive When true, a case-sensitive comparison is performed; + * otherwise the comparison does not distinguish + * between lowercase and uppercase characters (as + * defined by the selected locale). The default value + * of this parameter is true. + * + * \param localeAware When true, a locale-dependent comparison is done + * which takes into account the currently selected user + * locale (language and variants). When false, a + * locale-invariant comparison is carried out by + * comparing character code points (which is faster). + * The default value of this parameter is true. + * + * Performs a comparison between this string and the specified character + * \a c, and returns an integer that indicates the comparison result: + * + * \li 0 if this string is equal to \a c. + * \li +1 if this string postcedes the character \a c. + * \li -1 if this string precedes the character \a c. + * + * The performed comparison is equivalent to a comparison of this string + * with a fictitious string of length one, whose only character was equal to + * the specified character \a c. + */ + int Compare( char_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return R::Compare( m_data->string, Length(), &c, 1, caseSensitive, localeAware ); + } + + /*! + * Case-insensitive lexicographical comparison between two strings. + * + * \param s A string to which this string will be compared. + * + * \param localeAware When true, a locale-dependent comparison is done + * which takes into account the currently selected user + * locale (language and variants). When false, a + * locale-invariant comparison is carried out by + * comparing character code points (which is faster). + * The default value of this parameter is true. + * + * Performs a character-to-character, case-insensitive comparison between + * this string and the specified string \a s, and returns an integer that + * indicates the comparison result: + * + * \li 0 if both strings are equal. + * \li +1 if this string postcedes the specified string \a s. + * \li -1 if this string precedes the specified string \a s. + */ + template + int CompareIC( const GenericString& s, bool localeAware = true ) const noexcept + { + return R::Compare( m_data->string, Length(), s.m_data->string, s.Length(), false/*caseSensitive*/, localeAware ); + } + + /*! + * Case-insensitive lexicographical comparison to a null-terminated string. + * + * \param t The starting address of a null-terminated string to + * which this string will be compared. + * + * \param localeAware When true, a locale-dependent comparison is done + * which takes into account the currently selected user + * locale (language and variants). When false, a + * locale-invariant comparison is carried out by + * comparing character code points (which is faster). + * The default value of this parameter is true. + * + * Performs a character-to-character, case-insensitive comparison between + * this string and the specified null-terminated string \a t, and returns an + * integer that indicates the comparison result: + * + * \li 0 if both strings are equal. + * \li +1 if this string postcedes the specified string \a s. + * \li -1 if this string precedes the specified string \a s. + */ + int CompareIC( const_c_string t, bool localeAware = true ) const noexcept + { + return R::Compare( m_data->string, Length(), t, R::Length( t ), false/*caseSensitive*/, localeAware ); + } + + /*! + * Case-insensitive lexicographical comparison to a single character. + * + * \param c A character to which this string will be compared. + * + * \param localeAware When true, a locale-dependent comparison is done + * which takes into account the currently selected user + * locale (language and variants). When false, a + * locale-invariant comparison is carried out by + * comparing character code points (which is faster). + * The default value of this parameter is true. + * + * Performs a case-insensitive comparison between this string and the + * specified character \a c, and returns an integer that indicates the + * comparison result: + * + * \li 0 if this string is equal to \a c. + * \li +1 if this string postcedes the character \a c. + * \li -1 if this string precedes the character \a c. + * + * The performed comparison is equivalent to a case-insensitive comparison + * of this string with a fictitious string of length one, whose only + * character was equal to \a c. + */ + int CompareIC( char_type c, bool localeAware = true ) const noexcept + { + return R::Compare( m_data->string, Length(), &c, 1, false/*caseSensitive*/, localeAware ); + } + + /*! + * Wildcard string matching. + * + * \param pattern The pattern string. May contain multiple instances + * of the wildcard characters '*' and '?'. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value is true. + * + * Returns true iff this string matches the specified \a pattern. If either + * this string or the pattern is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + template + bool WildMatch( const GenericString& pattern, bool caseSensitive = true ) const noexcept + { + return R::WildMatch( m_data->string, Length(), pattern.m_data->string, pattern.Length(), caseSensitive ); + } + + /*! + * Wildcard string matching (case-insensitive). + * + * \param pattern The pattern string. May contain multiple instances + * of the wildcard characters '*' and '?'. + * + * This function performs case-insensitive comparisons between string and + * non-wild pattern characters. + * + * Returns true iff this string matches the specified \a pattern. If either + * this string or the pattern is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + template + bool WildMatchIC( const GenericString& pattern ) const noexcept + { + return R::WildMatch( m_data->string, Length(), pattern.m_data->string, pattern.Length(), false/*caseSensitive*/ ); + } + + /*! + * Wildcard string matching with a null-terminated pattern. + * + * \param pattern The pattern string. May contain multiple instances + * of the wildcard characters '*' and '?'. + * + * \param caseSensitive When true, a case-sensitive comparison is + * performed; otherwise the comparison does not + * distinguish between lowercase and uppercase + * characters. The default value is true. + * + * Returns true iff this string matches the specified \a pattern. If either + * this string or the pattern is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + bool WildMatch( const_c_string pattern, bool caseSensitive = true ) const noexcept + { + return R::WildMatch( m_data->string, Length(), pattern, R::Length( pattern ), caseSensitive ); + } + + /*! + * Wildcard string matching with a null-terminated pattern + * (case-insensitive). + * + * \param pattern The pattern string. May contain multiple instances + * of the wildcard characters '*' and '?'. + * + * This function performs case-insensitive comparisons between string and + * non-wild pattern characters. + * + * Returns true iff this string matches the specified \a pattern. If either + * this string or the pattern is empty, this function always returns false + * conventionally, even if the pattern is a single asterisk '*'. + */ + bool WildMatchIC( const_c_string pattern ) const noexcept + { + return R::WildMatch( m_data->string, Length(), pattern, R::Length( pattern ), false/*caseSensitive*/ ); + } + + /*! + * Returns true iff this string contains one or more wildcard characters + * (asterisk '*' or question mark '?'). + */ + bool HasWildcards() const noexcept + { + for ( iterator i = m_data->string; i < m_data->end; ++i ) + if ( R::IsWildcard( *i ) ) + return true; + return false; + } + + /*! + * Replaces all characters in this string with their \e case \e folded + * counterparts. + */ + void ToCaseFolded() + { + size_type len = Length(); + if ( len > 0 ) + { + EnsureUnique(); + R::ToCaseFolded( m_data->string, len ); + } + } + + /*! + * Replaces all \e uppercase characters in this string with their + * \e lowercase counterparts. + */ + void ToLowercase() + { + size_type len = Length(); + if ( len > 0 ) + { + EnsureUnique(); + R::ToLowercase( m_data->string, len ); + } + } + + /*! + * Replaces all \e lowercase characters in this string with their + * \e uppercase counterparts. + */ + void ToUppercase() + { + size_type len = Length(); + if ( len > 0 ) + { + EnsureUnique(); + R::ToUppercase( m_data->string, len ); + } + } + + /*! + * Returns a duplicate of this string with all characters replaced with + * their case folded counterparts. + */ + GenericString CaseFolded() const + { + GenericString s( *this ); + s.ToCaseFolded(); + return s; + } + + /*! + * Returns a duplicate of this string with all uppercase characters replaced + * with their lowercase counterparts. + */ + GenericString Lowercase() const + { + GenericString s( *this ); + s.ToLowercase(); + return s; + } + + /*! + * Returns a duplicate of this string with all lowercase characters replaced + * with their uppercase counterparts. + */ + GenericString Uppercase() const + { + GenericString s( *this ); + s.ToUppercase(); + return s; + } + + /*! + * Transposes the characters in this string, so that the first character + * becomes the last and the last becomes the first, the second becomes the + * next-to-last, and so on. + */ + void Reverse() + { + if ( !IsEmpty() ) + { + EnsureUnique(); + for ( iterator i = m_data->string, j = m_data->end; i < --j; ++i ) + pcl::Swap( *i, *j ); + } + } + + /*! + * Returns a duplicate of this string with its characters in reverse order. + */ + GenericString Reversed() const + { + GenericString s( *this ); + s.Reverse(); + return s; + } + + /*! + * Sorts the characters of this string in ascending order. + */ + void Sort() + { + if ( !IsEmpty() ) + { + EnsureUnique(); + pcl::Sort( m_data->string, m_data->end ); + } + } + + /*! + * Returns a duplicate of this string with its characters sorted in + * ascending order. + */ + GenericString Sorted() const + { + GenericString s( *this ); + s.Sort(); + return s; + } + + /*! + * Sorts the characters of this string in ascending order. Ordering is + * defined such that for any pair a, b of characters, the specified binary + * predicate p( a, b ) is true if a precedes b. + */ + template + void Sort( BP p ) + { + if ( !IsEmpty() ) + { + EnsureUnique(); + pcl::Sort( m_data->string, m_data->end, p ); + } + } + + /*! + * Returns a duplicate of this string with its characters sorted in + * ascending order with the specified binary predicate \a p. + */ + template + GenericString Sorted( BP p ) const + { + GenericString s( *this ); + s.Sort( p ); + return s; + } + + /*! + * Returns true iff this string can be interpreted as a numeric literal: + * + * \li The string is not empty. + * + * \li It is not exclusively composed of trimable characters. + * + * \li Its first non-trimable character is either a sign character, a + * decimal digit, or a decimal separator. + * + * \note This member function does \e not guarantee that this string + * contains a \e valid numeric literal. It only checks for the \e role of + * this string as a token in the context of a syntactic analysis. + */ + bool IsNumeral() const noexcept + { + if ( IsEmpty() ) + return false; + char_type c = *R::SearchTrimLeft( m_data->string, m_data->end ); + return R::IsDigit( c ) || R::IsSign( c ) || R::IsDecimalSeparator( c ); + } + + /*! + * Returns true iff this string can be interpreted as a symbol identifier: + * + * \li The string is not empty. + * + * \li It is not exclusively composed of trimable characters. + * + * \li Its first non-trimable character is either an alphabetic character or + * an underscore character. + * + * \note This member function does \e not guarantee that this string + * contains a \e valid symbol identifier. It only checks for the \e role of + * this string as a token in the context of a syntactic analysis. + */ + bool IsSymbol() const noexcept + { + if ( IsEmpty() ) + return false; + char_type c = *R::SearchTrimLeft( m_data->string, m_data->end ); + return R::IsSymbolDigit( c ); + } + + /*! + * Returns true only if this string contains a valid identifier: + * + * \li It is not an empty string. + * + * \li Its first character is either an alphabetic character or an + * underscore character. + * + * \li Its second and successive characters, if they exist, are all of them + * either alphabetic characters, decimal digits, or underscores. + * + * If this string is not a valid identifier, the \a pos variable will be set + * equal to the index of the first offending character (the first character + * that violates the above conditions). + */ + bool IsValidIdentifier( distance_type& pos ) const noexcept + { + if ( IsEmpty() ) + { + pos = 0; + return false; + } + const_iterator i = m_data->string; + if ( R::IsStartingSymbolDigit( *i ) ) + for ( ;; ) + { + if ( ++i == m_data->end ) + return true; + if ( !R::IsSymbolDigit( *i ) ) + break; + } + pos = i - m_data->string; + return false; + } + + /*! + * Returns true only if this string contains a valid identifier: + * + * \li It is not an empty string. + * + * \li Its first character is either an alphabetic character or an + * underscore character. + * + * \li Its second and successive characters, if they exist, are all of them + * either alphabetic characters, decimal digits, or underscores. + */ + bool IsValidIdentifier() const noexcept + { + if ( !IsEmpty() ) + if ( R::IsStartingSymbolDigit( *m_data->string ) ) + { + for ( const_iterator i = m_data->string; ++i < m_data->end; ) + if ( !R::IsSymbolDigit( *i ) ) + return false; + return true; + } + return false; + } + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this string. + * + * This function calls pcl::Hash64() for the internal string buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const noexcept + { + return pcl::Hash64( m_data->string, Size(), seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this string. + * + * This function calls pcl::Hash32() for the internal string buffer. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const noexcept + { + return pcl::Hash32( m_data->string, Size(), seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this string. This + * function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const noexcept + { + return Hash64( seed ); + } + + /*! + * If the internal free list of string data structures is available, this + * function destroys it and returns the number of deleted structures. + * Otherwise the function has no effect and returns zero. + * + * \note This function is \e not thread-safe. + */ + static size_type DeleteFreeList() + { + return Data::DeleteFreeList(); + } + + // ------------------------------------------------------------------------- + +protected: + + /*! + * \internal + * Dereferences string data and disposes it if it becomes garbage. + */ + void DetachFromData() + { + if ( !m_data->Detach() ) + Data::Dispose( m_data ); + } + + /*! + * \internal + * Internal string reallocation routine. + * + * Reallocates if necessary, ignoring current string contents. Reallocation + * may happen due either to insufficient available space, or (in a + * comparatively lazy fashion) to excessive unused space. + * + * Irrespective of reallocation, this function always updates internal data + * pointers to reflect the specified length in characters. + */ + void MaybeReallocate( size_type len ) + { + if ( IsUnique() ) + { + if ( m_data->ShouldReallocate( len ) ) + { + m_data->Deallocate(); + m_data->Allocate( len ); + } + else + m_data->SetLength( len ); + } + else + { + Data* newData = Data::New( len ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * \internal + * Internal string reallocation routine. + * + * Causes this string to grow by \a n uninitialized characters at the + * specified index \a i. The index \a i is updated as a side effect to + * ensure that 0 <= \a i <= Length() before reallocation. + */ + void UninitializedGrow( size_type& i, size_type n ) + { + size_type len = Length(); + size_type newLen = len+n; + if ( newLen > len ) + { + if ( i > len ) + i = len; + if ( IsUnique() ) + { + if ( size_type( m_data->capacity - m_data->string ) < newLen+1 ) + { + iterator old = m_data->string; + m_data->Allocate( newLen ); + if ( old != nullptr ) + { + if ( i > 0 ) + R::Copy( m_data->string, old, i ); + if ( i < len ) + R::Copy( m_data->string+i+n, old+i, len-i ); + m_data->alloc.Deallocate( old ); + } + } + else + { + if ( i < len ) + R::CopyOverlapped( m_data->string+i+n, m_data->string+i, len-i ); + m_data->SetLength( newLen ); + } + } + else + { + Data* newData = Data::New( newLen ); + if ( i > 0 ) + R::Copy( newData->string, m_data->string, i ); + if ( i < len ) + R::Copy( newData->string+i+n, m_data->string+i, len-i ); + DetachFromData(); + m_data = newData; + } + } + } + + /*! + * \internal + * String trimming primitive. + */ + void Trim( const_iterator left, size_type len ) + { + if ( len > 0 ) + { + if ( IsUnique() ) + { + if ( m_data->ShouldReallocate( len ) ) + { + iterator old = m_data->string; + m_data->Allocate( len ); + R::Copy( m_data->string, left, len ); + if ( old != nullptr ) + m_data->alloc.Deallocate( old ); + } + else + { + if ( left != m_data->string ) // trim left + R::CopyOverlapped( m_data->string, left, len ); + m_data->SetLength( len ); // trim right + } + } + else + { + Data* newData = Data::New( len ); + R::Copy( newData->string, left, len ); + DetachFromData(); + m_data = newData; + } + } + else + Clear(); + } + + /*! + * \internal + * Character replacement primitive. + */ + void ReplaceChar( char_type c1, char_type c2, size_type i, size_type n, bool caseSensitive ) + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( caseSensitive ) + { + for ( iterator p = m_data->string + i, p1 = p + n; p < p1; ++p ) + if ( *p == c1 ) + { + EnsureUnique(); + *p = c2; + for ( ; ++p < p1; ) + if ( *p == c1 ) + *p = c2; + break; + } + } + else + { + c1 = R::ToCaseFolded( c1 ); + for ( iterator p = m_data->string + i, p1 = p + n; p < p1; ++p ) + if ( R::ToCaseFolded( *p ) == c1 ) + { + EnsureUnique(); + *p = c2; + for ( ; ++p < p1; ) + if ( R::ToCaseFolded( *p ) == c1 ) + *p = c2; + break; + } + } + } + } + } + + /*! + * \internal + * String replacement primitive. + */ + void ReplaceString( const_iterator t1, size_type n1, const_iterator t2, size_type n2, size_type i, bool caseSensitive ) + { + if ( n1 > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + SearchEngine S( t1, n1, caseSensitive ); + if ( n1 == n2 ) + { + EnsureUnique(); + for ( size_type p = i; (p = S( m_data->string, p, len )) < len; p += n1 ) + R::Copy( m_data->string + p, t2, n2 ); + } + else + { + Array P; + for ( size_type p = i; (p = S( m_data->string, p, len )) < len; p += n1 ) + P.Add( p ); + if ( !P.IsEmpty() ) + { + size_type newLen = len; + if ( n1 < n2 ) + newLen += P.Length()*(n2 - n1); + else + newLen -= P.Length()*(n1 - n2); + + if ( newLen > 0 ) + { + Data* newData = Data::New( newLen ); + size_type targetIndex = 0; + size_type sourceIndex = 0; + for ( size_type p : P ) + { + size_type n = p - sourceIndex; + if ( n > 0 ) + R::Copy( newData->string+targetIndex, m_data->string+sourceIndex, n ); + R::Copy( newData->string+targetIndex+n, t2, n2 ); + targetIndex += n + n2; + sourceIndex = p + n1; + } + if ( sourceIndex < len ) + R::Copy( newData->string+targetIndex, m_data->string+sourceIndex, len-sourceIndex ); + DetachFromData(); + m_data = newData; + } + else + Clear(); + } + } + } + } + } + + /*! + * \internal + * \class pcl::GenericString::SearchEngine + * \brief Substring search primitive algorithm + * + * Implements the Boyer-Moore substring search algorithm (mismatched + * character heuristic). + * + * \b References + * + * \li Robert Sedgewick, Kevin Wayne (2011), Algorithms, 4th Edition, + * Addison-Wesley Professional, pp 770-773. + * + * \li Robert S. Boyer and J. Strother Moore (1977), A fast string + * searching algorithm, Communcations of the ACM Vol. 20 No. 10, + * pp 762-772. + */ + class PCL_CLASS SearchEngine + { + public: + + /*! + * Constructs a substring search engine for the specified \a pattern, + * pattern length in characters, and case sensitivity. + * + * Setting the \a useBoyerMoore parameter to \c false forces use of a + * brute-force search routine in all cases (useful for testing purposes + * and unique searches on very short strings). Otherwise a Boyer-Moore + * substring search algorithm will be used except for patterns of less + * than 4 characters. + */ + SearchEngine( const_iterator pattern, size_type patternLength, + bool caseSensitive = true, bool searchLast = false, bool useBoyerMoore = true ) + : m_pattern( pattern ) + , m_patternLength( int( patternLength ) ) + , m_caseSensitive( caseSensitive ) + , m_searchLast( searchLast ) + , m_useBoyerMoore( useBoyerMoore && m_patternLength > 3 ) + { + if ( m_useBoyerMoore ) + InitSkipList(); + } + + /*! + * Performs a substring search in the subset of contiguous characters of + * the specified string \a text defined by the range + * [\a startIndex,\a endIndex). The search pattern, search direction and + * case sensitivity are defined in the class constructor. + * + * Returns the character index where the first exact match has been + * found, or \a endIndex if no match was found. + * + * We implement the mismatched character heuristic version of + * the Boyer-Moore algorithm. + */ + size_type operator()( const_iterator text, size_type startIndex, size_type endIndex ) const noexcept + { + if ( endIndex <= startIndex + || m_patternLength <= 0 + || endIndex-startIndex < size_type( m_patternLength ) + || text == nullptr + || m_pattern == nullptr ) + return endIndex; + + if ( m_caseSensitive ) + { + if ( m_useBoyerMoore ) + { + if ( m_searchLast ) + { + for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) + { + int skip = 0; + const_iterator t = text + r - i; + const_iterator p = m_pattern; + for ( int j = m_patternLength; --j >= 0; ) + { + char_type c = *t++; + if ( c != *p++ ) + { + skip = j - m_skipList[uint8( c )]; + if ( skip < 1 ) + skip = 1; + break; + } + } + if ( skip == 0 ) + return r - i; + i += skip; + } + } + else + { + for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) + { + int skip = 0; + const_iterator t = text + i + m_patternLength; + const_iterator p = m_pattern + m_patternLength; + for ( int j = m_patternLength; --j >= 0; ) + { + char_type c = *--t; + if ( c != *--p ) + { + // ### N.B.: Could do better with a precomputed pattern mismatch table. + skip = j - m_skipList[uint8( c )]; + if ( skip < 1 ) + skip = 1; + break; + } + } + if ( skip == 0 ) + return i; + i += skip; + } + } + } + else + { + // Use a brute force search for very small patterns. + if ( m_searchLast ) + { + for ( size_type i = endIndex-m_patternLength; ; --i ) + { + const_iterator t = text + i; + const_iterator p = m_pattern; + for ( int j = m_patternLength; ; ++t, ++p ) + { + if ( *t != *p ) + break; + if ( --j == 0 ) + return i; + } + if ( i == startIndex ) + break; + } + } + else + { + for ( size_type i = startIndex, r = endIndex-m_patternLength; ; ++i ) + { + const_iterator t = text + i; + const_iterator p = m_pattern; + for ( int j = m_patternLength; ; ++t, ++p ) + { + if ( *t != *p ) + break; + if ( --j == 0 ) + return i; + } + if ( i == r ) + break; + } + } + } + } + else + { + if ( m_useBoyerMoore ) + { + if ( m_searchLast ) + { + for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) + { + int skip = 0; + const_iterator t = text + r - i; + const_iterator p = m_pattern; + for ( int j = m_patternLength; --j >= 0; ) + { + char_type c = R::ToCaseFolded( *t++ ); + if ( c != R::ToCaseFolded( *p++ ) ) + { + skip = j - m_skipList[uint8( c )]; + if ( skip < 1 ) + skip = 1; + break; + } + } + if ( skip == 0 ) + return r - i; + i += skip; + } + } + else + { + for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) + { + int skip = 0; + const_iterator t = text + i + m_patternLength; + const_iterator p = m_pattern + m_patternLength; + for ( int j = m_patternLength; --j >= 0; ) + { + char_type c = R::ToCaseFolded( *--t ); + if ( c != R::ToCaseFolded( *--p ) ) + { + // ### N.B.: Could do better with a precomputed pattern mismatch table. + skip = j - m_skipList[uint8( c )]; + if ( skip < 1 ) + skip = 1; + break; + } + } + if ( skip == 0 ) + return i; + i += skip; + } + } + } + else + { + // Use a brute force search for very small patterns. + if ( m_searchLast ) + { + for ( size_type i = endIndex-m_patternLength; ; --i ) + { + const_iterator t = text + i; + const_iterator p = m_pattern; + for ( int j = m_patternLength; ; ++t, ++p ) + { + if ( R::ToCaseFolded( *t ) != R::ToCaseFolded( *p ) ) + break; + if ( --j == 0 ) + return i; + } + if ( i == startIndex ) + break; + } + } + else + { + for ( size_type i = startIndex, r = endIndex-m_patternLength; ; ++i ) + { + const_iterator t = text + i; + const_iterator p = m_pattern; + for ( int j = m_patternLength; ; ++t, ++p ) + { + if ( R::ToCaseFolded( *t ) != R::ToCaseFolded( *p ) ) + break; + if ( --j == 0 ) + return i; + } + if ( i == r ) + break; + } + } + } + } + return endIndex; + } + + private: + + int m_skipList[ 256 ]; + const_iterator m_pattern; + int m_patternLength; + bool m_caseSensitive : 1; + bool m_searchLast : 1; + bool m_useBoyerMoore : 1; + + void InitSkipList() noexcept + { + ::memset( m_skipList, 0xff, sizeof( m_skipList ) ); // fill with -1 + if ( m_searchLast ) + { + const_iterator p = m_pattern + m_patternLength; + if ( m_caseSensitive ) + for ( int i = 0; i < m_patternLength; ++i ) + m_skipList[uint8( *--p )] = i; + else + for ( int i = 0; i < m_patternLength; ++i ) + m_skipList[uint8( R::ToCaseFolded( *--p ) )] = i; + } + else + { + const_iterator p = m_pattern; + if ( m_caseSensitive ) + for ( int i = 0; i < m_patternLength; ++i ) + m_skipList[uint8( *p++ )] = i; + else + for ( int i = 0; i < m_patternLength; ++i ) + m_skipList[uint8( R::ToCaseFolded( *p++ ) )] = i; + } + } + }; + + // ------------------------------------------------------------------------- + + /*! + * \internal + * \class pcl::GenericString::Data + * \brief Reference-counted string data structure + */ + class PCL_CLASS Data : public ReferenceCounter + { + private: + +#ifndef __PCL_NO_STRING_FREE_LIST + static Data* freeList; //!< Singly-linked list of free string data structures. + static AtomicInt freeLock; //!< Access synchronization for the free list. +#endif + + public: + + iterator string = nullptr; //!< Beginning of the null-terminated string + iterator end = nullptr; //!< End of the string + iterator capacity = nullptr; //!< End of the allocated block or link in free list + allocator alloc; //!< The allocator object + + /*! + * Constructs an empty string data structure. + */ + Data() = default; + + /*! + * Constructs a string of \a len characters. + */ + Data( size_type len ) + { + Allocate( len ); + } + + /*! + * Constructs a string of \a len characters and space allocated for a + * maximum of \a total characters (plus terminating null). + */ + Data( size_type len, size_type total ) + { + Allocate( len, total ); + } + + /*! + * Destroys a string data structure. + */ + ~Data() + { + Deallocate(); + } + + /*! + * Allocates space to store at least \a total characters plus a + * terminating null character, and updates internal pointers to define a + * string of \a len characters. + * + * If \a total < \a len this routine allocates strictly the space + * required to store \a len + 1 characters. Otherwise the allocated block + * will have an optimized length, generally greater than the number + * \a len + 1 of storable characters. + */ + void Allocate( size_type len, size_type total ) + { + total = (len <= total) ? alloc.PagedLength( total+1 ) : len+1; // +1 is room for a null terminating character + string = alloc.Allocate( total ); + capacity = string + total; + SetLength( len ); + } + + /*! + * Allocates space to store at least \a len characters plus a terminating + * null character. This function is a shortcut for Allocate( len, len ). + */ + void Allocate( size_type len ) + { + Allocate( len, len ); + } + + /*! + * Allocates space to store exactly \a total characters plus a + * terminating null character, and updates internal pointers to define a + * string of \a len <= \a total characters. + * + * This routine allocates strictly the space required to store + * \a total + 1 characters without length optimization. + */ + void Reserve( size_type len, size_type total ) + { + PCL_PRECONDITION( len <= total ) + string = alloc.Allocate( total+1 ); + capacity = string + total+1; + SetLength( pcl::Min( len, total ) ); + } + + /*! + * Deallocates string data, yielding an empty structure. + */ + void Deallocate() + { + PCL_CHECK( (string == nullptr) ? end == nullptr : string < end ) + if ( string != nullptr ) + { + alloc.Deallocate( string ); + Reset(); + } + } + + /*! + * Returns true iff a reallocation of string data should happen in order + * to change the string's length to \a len characters. + */ + bool ShouldReallocate( size_type len ) const noexcept + { + size_type m = capacity - string; + return m <= len || alloc.ReallocatedLength( m, len+1 ) < (m >> 1); + } + + /*! + * Sets the length of the string. Arranges internal pointers and writes a + * null string terminating character. + */ + void SetLength( size_type len ) noexcept + { + *(end = (string + len)) = R::Null(); + } + + /*! + * Sets all string pointers to \c nullptr. + */ + void Reset() noexcept + { + string = end = capacity = nullptr; + } + + /*! + * Returns a pointer to a free string data structure, or \c nullptr if + * none is available. The returned structure must be initialized. + * + * This function is thread-safe. + */ +#ifndef __PCL_NO_STRING_FREE_LIST + static Data* NextFree() noexcept + { + if ( freeLock.TestAndSet( 0, 1 ) ) + { + Data* data = freeList; + if ( data != nullptr ) + freeList = reinterpret_cast( data->string ); + freeLock.Store( 0 ); + return data; + } + return nullptr; + } +#endif // !__PCL_NO_STRING_FREE_LIST + + /*! + * Returns a free empty string data structure. Retrieves an existing data + * structure from the internal free list if available, or creates a new + * one otherwise. + * + * This function is thread-safe. + */ + static Data* New() + { +#ifndef __PCL_NO_STRING_FREE_LIST + Data* data = NextFree(); + if ( data != nullptr ) + { + data->string = nullptr; + return data; + } +#endif // !__PCL_NO_STRING_FREE_LIST + return new Data; + } + + /*! + * Returns a free string data structure of the specified length in + * characters. Retrieves an existing data structure from the internal + * free list if available, or creates a new one otherwise. + * + * This function is thread-safe. + */ + static Data* New( size_type len ) + { +#ifndef __PCL_NO_STRING_FREE_LIST + Data* data = NextFree(); + if ( data != nullptr ) + { + data->Allocate( len ); // ### FIXME: If allocation fails, data is a leak. + return data; + } +#endif // !__PCL_NO_STRING_FREE_LIST + return new Data( len ); + } + + /*! + * Returns a free string data structure with the specified length and + * total available space. Retrieves an existing data structure from the + * internal free list if available, or creates a new one otherwise. + * + * This function is thread-safe. + */ + static Data* New( size_type len, size_type total ) + { +#ifndef __PCL_NO_STRING_FREE_LIST + Data* data = NextFree(); + if ( data != nullptr ) + { + data->Allocate( len, total ); // ### FIXME: If allocation fails, data is a leak. + return data; + } +#endif // !__PCL_NO_STRING_FREE_LIST + return new Data( len, total ); + } + + /*! + * Deallocates and disposes a string data structure. If the internal free + * list is available, the deallocated structure is added to the list for + * subsequent reuse. Otherwise the structure is destroyed. + * + * This function is thread-safe. + */ + static void Dispose( Data* data ) + { + PCL_PRECONDITION( data != nullptr ) + PCL_CHECK( data->RefCount() == 0 ) +#ifndef __PCL_NO_STRING_FREE_LIST + if ( freeLock.TestAndSet( 0, 1 ) ) + { + data->Attach(); + data->Deallocate(); + data->string = reinterpret_cast( freeList ); + freeList = data; + freeLock.Store( 0 ); + } + else +#endif // !__PCL_NO_STRING_FREE_LIST + delete data; + } + + /*! + * If the internal free list is available, this function destroys it and + * returns the number of deleted string data structures. Otherwise the + * function has no effect and returns zero. + * + * \note This function is \e not thread-safe. + */ + static size_type DeleteFreeList() + { + size_type count = 0; +#ifndef __PCL_NO_STRING_FREE_LIST + while ( freeList != nullptr ) + { + Data* data = freeList; + freeList = reinterpret_cast( data->string ); + data->string = nullptr; + delete data; + ++count; + } +#endif // !__PCL_NO_STRING_FREE_LIST + return count; + } + }; + + /* + * The reference-counted string data. + */ + Data* m_data = nullptr; +}; + +#ifndef __PCL_NO_STRING_FREE_LIST + +template +typename GenericString::Data* GenericString::Data::freeList = nullptr; + +template +AtomicInt GenericString::Data::freeLock; + +#endif // !__PCL_NO_STRING_FREE_LIST + +/*! + * Exchanges two strings. + */ +template inline +void Swap( GenericString& s1, GenericString& s2 ) noexcept +{ + s1.Swap( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup genericstring_relational_ops GenericString Relational Operators + */ + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff two strings \a s1 and \a s2 are equal. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator ==( const GenericString& s1, const GenericString& s2 ) noexcept +{ + return s1.CompareCodePoints( s2 ) == 0; +} + +/*! + * Returns true iff a string \a s1 is less than a string \a s2. This function + * performs a character-to-character, locale-unaware comparison of numeric + * character values. See GenericString<>::CompareCodePoints() for more + * information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <( const GenericString& s1, const GenericString& s2 ) noexcept +{ + return s1.CompareCodePoints( s2 ) < 0; +} + +/*! + * Returns true iff a string \a s1 is less than or equal to a string \a s2. + * This function performs a character-to-character, locale-unaware comparison + * of numeric character values. See GenericString<>::CompareCodePoints() for + * more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <=( const GenericString& s1, const GenericString& s2 ) noexcept +{ + return s1.CompareCodePoints( s2 ) <= 0; +} + +/*! + * Returns true iff a string \a s1 is greater than a string \a s2. This + * function performs a character-to-character, locale-unaware comparison of + * numeric character values. See GenericString<>::CompareCodePoints() for more + * information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >( const GenericString& s1, const GenericString& s2 ) noexcept +{ + return s1.CompareCodePoints( s2 ) > 0; +} + +/*! + * Returns true iff a string \a s1 is greater than or equal to a string \a s2. + * This function performs a character-to-character, locale-unaware comparison + * of numeric character values. See GenericString<>::CompareCodePoints() for + * more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >=( const GenericString& s1, const GenericString& s2 ) noexcept +{ + return s1.CompareCodePoints( s2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff a string \a s1 is equal to a null-terminated string \a t2. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator ==( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) == 0; +} + +/*! + * Returns true iff a string \a s1 is less than a null-terminated string \a t2. + * This function performs a character-to-character, locale-unaware comparison + * of numeric character values. See GenericString<>::CompareCodePoints() for + * more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) < 0; +} + +/*! + * Returns true iff a string \a s1 is less than or equal to a null-terminated + * string \a t2. This function performs a character-to-character, + * locale-unaware comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <=( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) <= 0; +} + +/*! + * Returns true iff a string \a s1 is greater than a null-terminated string + * \a t2. This function performs a character-to-character, locale-unaware + * comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) > 0; +} + +/*! + * Returns true iff a string \a s1 is greater than or equal to a + * null-terminated string \a t2. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >=( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff a null-terminated string \a t1 is equal to a string \a s2. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator ==( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) == 0; +} + +/*! + * Returns true iff a null-terminated string \a t1 is less than a string \a s2. + * This function performs a character-to-character, locale-unaware comparison + * of numeric character values. See GenericString<>::CompareCodePoints() for + * more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) > 0; +} + +/*! + * Returns true iff a null-terminated string \a t1 is less than or equal to a + * string \a s2. This function performs a character-to-character, + * locale-unaware comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <=( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) >= 0; +} + +/*! + * Returns true iff a null-terminated string \a t1 is greater than a string + * \a s2. This function performs a character-to-character, locale-unaware + * comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) < 0; +} + +/*! + * Returns true iff a null-terminated string \a t1 is greater than or equal to + * a string \a s2. This function performs a character-to-character, + * locale-unaware comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >=( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff a string \a s1 is equal to a character \a c2. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator ==( const GenericString& s1, typename GenericString::char_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) == 0; +} + +/*! + * Returns true iff a string \a s1 is less than a character \a c2. This + * function performs a character-to-character, locale-unaware comparison of + * numeric character values. See GenericString<>::CompareCodePoints() for more + * information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <( const GenericString& s1, typename GenericString::char_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) < 0; +} + +/*! + * Returns true iff a string \a s1 is less than or equal to a character \a c2. + * This function performs a character-to-character, locale-unaware comparison + * of numeric character values. See GenericString<>::CompareCodePoints() for + * more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <=( const GenericString& s1, typename GenericString::char_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) <= 0; +} + +/*! + * Returns true iff a string \a s1 is greater than a character \a c2. This + * function performs a character-to-character, locale-unaware comparison of + * numeric character values. See GenericString<>::CompareCodePoints() for more + * information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >( const GenericString& s1, typename GenericString::char_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) > 0; +} + +/*! + * Returns true iff a string \a s1 is greater than or equal to a character + * \a c2. This function performs a character-to-character, locale-unaware + * comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >=( const GenericString& s1, typename GenericString::char_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff a character \a c1 is equal to a string \a s2. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator ==( typename GenericString::char_type c1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) == 0; +} + +/*! + * Returns true iff a character \a c1 is less than a string \a s2. This + * function performs a character-to-character, locale-unaware comparison of + * numeric character values. See GenericString<>::CompareCodePoints() for more + * information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <( typename GenericString::char_type c1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) > 0; +} + +/*! + * Returns true iff a character \a c1 is less than or equal to a string \a s2. + * This function performs a character-to-character, locale-unaware comparison + * of numeric character values. See GenericString<>::CompareCodePoints() for + * more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator <=( typename GenericString::char_type c1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) >= 0; +} + +/*! + * Returns true iff a character \a c1 is greater than a string \a s2. This + * function performs a character-to-character, locale-unaware comparison of + * numeric character values. See GenericString<>::CompareCodePoints() for more + * information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >( typename GenericString::char_type c1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) < 0; +} + +/*! + * Returns true iff a character \a c1 is greater than or equal to a string + * \a s2. This function performs a character-to-character, locale-unaware + * comparison of numeric character values. See + * GenericString<>::CompareCodePoints() for more information. + * \ingroup genericstring_relational_ops + */ +template inline +bool operator >=( typename GenericString::char_type c1, const GenericString& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class IsoString + * \brief Eight-bit string (ISO/IEC-8859-1 or UTF-8 string) + * + * %IsoString derives from a template instantiation of GenericString for the + * \c char type. On the PixInsight platform, %IsoString represents a dynamic + * ISO/IEC-8859-1 string, an 8-bit Unicode Transformation Format (UTF-8) + * string, or even a sequence of ASCII (or Latin-1) characters, depending on + * the context and type of transformations applied. + * + * \sa String + */ +class PCL_CLASS IsoString : public GenericString +{ +public: + + /*! + * Base class of %IsoString. + */ + typedef GenericString + string_base; + + /*! + * Represents a character pertaining to an %IsoString object. + */ + typedef string_base::char_type char_type; + + /*! + * The character traits class used by this template instantiation. + */ + typedef string_base::char_traits char_traits; + + /*! + * The block allocator used by this template instantiation. + */ + typedef string_base::block_allocator block_allocator; + + /*! + * The allocator class used by this template instantiation. + */ + typedef string_base::allocator allocator; + + /*! + * Null-terminated sequence of 8-bit characters. + */ + typedef string_base::c_string c_string; + + /*! + * Immutable null-terminated sequence of 8-bit characters. + */ + typedef string_base::const_c_string const_c_string; + + /*! + * %IsoString iterator. + */ + typedef string_base::iterator iterator; + + /*! + * Immutable %IsoString iterator. + */ + typedef string_base::const_iterator const_iterator; + + /*! + * Reverse %IsoString iterator. + */ + typedef string_base::reverse_iterator reverse_iterator; + + /*! + * Immutable reverse %IsoString iterator. + */ + typedef string_base::const_reverse_iterator const_reverse_iterator; + + /*! + * Represents a Unicode (UTF-16) string. + * \note This type must be defined as the same template instantiation used + * for the String class. + */ + typedef GenericString + ustring_base; + + /*! + * Represents a Unicode (UTF-16) character. + */ + typedef ustring_base::char_type uchar_type; + + /*! + * Unicode (UTF-16) character traits class. + */ + typedef ustring_base::char_traits uchar_traits; + + /*! + * Null-terminated sequence of UTF-16 characters. + */ + typedef ustring_base::c_string c_ustring; + + /*! + * Immutable null-terminated sequence of UTF-16 characters. + */ + typedef ustring_base::const_c_string const_c_ustring; + + /*! + * Unicode (UTF-16) string iterator. + */ + typedef ustring_base::iterator uchar_iterator; + + /*! + * Immutable Unicode (UTF-16) string iterator. + */ + typedef ustring_base::const_iterator const_uchar_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty %IsoString object. + */ + IsoString() = default; + + /*! + * Constructs an %IsoString object as a shallow copy of the specified + * \c string_base string \a s (copy constructor from the base class). + */ + IsoString( const string_base& s ) + : string_base( s ) + { + } + + /*! + * Copy constructor. + */ + IsoString( const IsoString& ) = default; + + /*! + * Constructs an %IsoString object by transferring data from the specified + * \c string_base string \a s (move constructor from the base class). + */ + IsoString( string_base&& s ) + : string_base( std::move( s ) ) + { + } + + /*! + * Move constructor. + */ + IsoString( IsoString&& ) = default; + + /*! + * Constructs an %IsoString as a copy of the specified Unicode string \a s, + * transformed to ISO/IEC-8859-1. Characters in the Unicode string that + * cannot be converted to ISO/IEC-8859-1 (that is, code points greater than + * 0x100) will have undefined values in the 8-bit string. Undefined values + * are represented with question mark characters (?). + */ + explicit + IsoString( const ustring_base& s ) + { + (void)operator =( s ); + } + + /*! + * Constructs an %IsoString as a copy of a null-terminated string \a t. + */ + IsoString( const_c_string t ) + : string_base( t ) + { + } + + /*! + * Constructs an %IsoString with the \a n first characters of the + * null-terminated string \a t, starting from its \a i-th character. + */ + IsoString( const_c_string t, size_type i, size_type n ) + : string_base( t, i, n ) + { + } + + /*! + * Constructs an %IsoString with \a n copies of a character \a c. + */ + IsoString( char_type c, size_type n = 1 ) + : string_base( c, n ) + { + } + + /*! + * Constructs an %IsoString with a copy of the character sequence defined by + * the range [i,j). + */ + IsoString( const_iterator i, const_iterator j ) + : string_base( i, j ) + { + } + + /*! + * Constructs an %IsoString with a copy of the character sequence stored in + * the specified initializer list \a l. + * + * This constructor is equivalent to: + * + * \code IsoString( l.begin(), l.end() ) \endcode + */ + IsoString( std::initializer_list l ) + : IsoString( l.begin(), l.end() ) + { + } + + /*! + * Constructs an %IsoString as a copy of the null-terminated Unicode + * (UTF-16) string \a t, transformed to ISO/IEC-8859-1. + * + * If the specified Unicode string \a t contains characters that cannot be + * converted to ISO/IEC-8859-1 characters, the corresponding characters in + * this string will have undefined values. For conversions from UTF-16 to + * UTF-8, see String::ToUTF8() and String::UTF16ToUTF8(). + */ + explicit + IsoString( const_c_ustring t ) + { + (void)operator =( t ); + } + + /*! + * Constructs an %IsoString with the \a n first characters of the + * null-terminated Unicode (UTF-16) string \a t, starting from its \a i-th + * character, transformed to ISO/IEC-8859-1. + * + * If the specified Unicode string \a t contains characters that cannot be + * converted to ISO/IEC-8859-1 characters, the corresponding characters in + * this string will have undefined values. For conversions from UTF-16 to + * UTF-8, see String::ToUTF8() and String::UTF16ToUTF8(). + */ + IsoString( const_c_ustring t, size_type i, size_type n ); + + /*! + * Constructs an %IsoString with a copy of the bytes stored in the specified + * ByteArray object. + * + * Source unsigned 8-bit integers will be reinterpreted as signed 8-bit + * characters. + */ + explicit + IsoString( const ByteArray& B ) + : IsoString( const_iterator( B.Begin() ), const_iterator( B.End() ) ) + { + } + + /*! + * Constructs an %IsoString as a literal representation of a \c bool value. + */ + explicit + IsoString( bool x ) + : string_base( x ? "true" : "false" ) + { + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c signed \c short value. + */ + explicit + IsoString( short x ) + { + (void)Format( "%hd", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of an + * \c unsigned \c short value. + */ + explicit + IsoString( unsigned short x ) + { + (void)Format( "%hu", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c signed \c int value. + */ + explicit + IsoString( int x ) + { + (void)Format( "%i", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of an + * \c unsigned \c int value. + */ + explicit + IsoString( unsigned int x ) + { + (void)Format( "%u", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c signed \c long value. + */ + explicit + IsoString( long x ) + { + (void)Format( "%ld", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of an + * \c unsigned \c long value. + */ + explicit + IsoString( unsigned long x ) + { + (void)Format( "%lu", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c signed \c long \c long value. + */ + explicit + IsoString( long long x ) + { + (void)Format( "%lli", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of an + * \c unsigned \c long \c long value. + */ + explicit + IsoString( unsigned long long x ) + { + (void)Format( "%llu", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c float value. + */ + explicit + IsoString( float x ) + { + (void)Format( "%.7g", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c double value. + */ + explicit + IsoString( double x ) + { + (void)Format( "%.16g", x ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c long \c double value. + */ + explicit + IsoString( long double x ) + { +#ifdef _MSC_VER + (void)Format( "%.16Lg", x ); +#else + (void)Format( "%.18Lg", x ); +#endif + } + +#ifndef __PCL_NO_STRING_COMPLEX + + /*! + * Constructs an %IsoString as a literal representation of an + * \c fcomplex value. + */ + explicit + IsoString( Complex& x ) + { + (void)Format( "{%.7g,%.7g}", x.Real(), x.Imag() ); + } + + /*! + * Constructs an %IsoString as a literal representation of a + * \c dcomplex value. + */ + explicit + IsoString( Complex& x ) + { + (void)Format( "{%.16g,%.16g}", x.Real(), x.Imag() ); + } + + /*! + * Constructs an %IsoString as a literal representation of an + * \c lcomplex value. + */ + explicit + IsoString( Complex& x ) + { +#ifdef _MSC_VER + (void)Format( "{%.16Lg,%.16Lg}", x.Real(), x.Imag() ); +#else + (void)Format( "{%.18Lg,%.18Lg}", x.Real(), x.Imag() ); +#endif + } + +#endif // !__PCL_NO_STRING_COMPLEX + +#ifdef __PCL_QT_INTERFACE + + explicit + IsoString( const QString& qs ) + : string_base( qs.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHARPTR_FROM_QSTRING( qs ) ) ) + { + } + + explicit + IsoString( const QByteArray& qb ) + : string_base( qb.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) ) ) + { + } + + explicit + IsoString( const QDate& qd ) + : string_base( iterator( PCL_GET_CHARPTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ) ) + { + } + + explicit + IsoString( const QDateTime& qdt ) + : string_base( iterator( PCL_GET_CHARPTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ) ) + { + } + +#endif + + // ------------------------------------------------------------------------- + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + IsoString& operator =( const IsoString& s ) + { + Assign( s ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + IsoString& operator =( IsoString&& s ) + { + Transfer( s ); + return *this; + } + + /*! + * Assigns a shallow copy of the \c string_base string \a s to this string. + * Returns a reference to this object. + */ + IsoString& operator =( const string_base& s ) + { + Assign( s ); + return *this; + } + + /*! + * Transfers the data from the \c string_base string \a s to this string + * (move assignment from base class). Returns a reference to this object. + */ + IsoString& operator =( string_base&& s ) + { + Transfer( s ); + return *this; + } + + /*! + * Assigns a copy of the Unicode string \a s (UTF-16) to this string, after + * converting source UTF-16 characters to ISO/IEC-8859-1 characters. Returns + * a reference to this object. + * + * If the specified UTF-16 string contains characters that cannot be + * converted to ISO/IEC-8859-1, the corresponding characters in this string + * will have undefined values. For conversions from UTF-16 to UTF-8, see + * String::ToUTF8() and String::UTF16ToUTF8(). + */ + IsoString& operator =( const ustring_base& s ) + { + return operator =( s.Begin() ); + } + + /*! + * Assigns a copy of the null-terminated string \a t to this string. Returns + * a reference to this object. + */ + IsoString& operator =( const_c_string t ) + { + Assign( t ); + return *this; + } + + /*! + * Assigns a single copy of a character \a c to this string. Returns a + * reference to this object. + */ + IsoString& operator =( char_type c ) + { + Assign( c, 1 ); + return *this; + } + + /*! + * Assigns a copy of the null-terminated Unicode string \a s (UTF-16) to + * this string, after converting source UTF-16 characters to ISO/IEC-8859-1 + * characters. Returns a reference to this object. + * + * If the specified UTF-16 string contains characters that cannot be + * converted to ISO/IEC-8859-1, the corresponding characters in this string + * will have undefined values. For conversions from UTF-16 to UTF-8, see + * String::ToUTF8() and String::UTF16ToUTF8(). + */ + IsoString& operator =( const_c_ustring t ); + +#ifdef __PCL_QT_INTERFACE + + IsoString& operator =( const QString& qs ) + { + if ( qs.isEmpty() ) + Clear(); + else + Assign( PCL_GET_CHARPTR_FROM_QSTRING( qs ) ); + return *this; + } + + IsoString& operator =( const QByteArray& qb ) + { + if ( qb.isEmpty() ) + Clear(); + else + Assign( PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) ); + return *this; + } + + IsoString& operator =( const QDate& qd ) + { + Assign( PCL_GET_CHARPTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ); + return *this; + } + + IsoString& operator =( const QDateTime& qdt ) + { + Assign( PCL_GET_CHARPTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ); + return *this; + } + +#endif + + // ------------------------------------------------------------------------- + + IsoString SetToLength( size_type n ) const + { + return string_base::SetToLength( n ); + } + + IsoString ResizedToNullTerminated() const + { + return string_base::ResizedToNullTerminated(); + } + + IsoString Squeezed() const + { + return string_base::Squeezed(); + } + + // ------------------------------------------------------------------------- + + IsoString Substring( size_type i, size_type n = maxPos ) const + { + return string_base::Substring( i, n ); + } + + IsoString Left( size_type n ) const + { + return string_base::Left( n ); + } + + IsoString Right( size_type n ) const + { + return string_base::Right( n ); + } + + IsoString Suffix( size_type i ) const + { + return string_base::Suffix( i ); + } + + IsoString Prefix( size_type i ) const + { + return string_base::Prefix( i ); + } + + // ------------------------------------------------------------------------- + + IsoString Trimmed() const + { + return string_base::Trimmed(); + } + + IsoString TrimmedLeft() const + { + return string_base::TrimmedLeft(); + } + + IsoString TrimmedRight() const + { + return string_base::TrimmedRight(); + } + + // ------------------------------------------------------------------------- + + IsoString LeftJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const + { + return string_base::LeftJustified( width, fill ); + } + + IsoString RightJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const + { + return string_base::RightJustified( width, fill ); + } + + IsoString CenterJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const + { + return string_base::CenterJustified( width, fill ); + } + + // ------------------------------------------------------------------------- + + IsoString Enclosed( char_type c ) const + { + return string_base::Enclosed( c ); + } + + IsoString SingleQuoted() const + { + return string_base::SingleQuoted(); + } + + IsoString DoubleQuoted() const + { + return string_base::DoubleQuoted(); + } + + IsoString Unquoted() const + { + return string_base::Unquoted(); + } + + // ------------------------------------------------------------------------- + + IsoString CaseFolded() const + { + return string_base::CaseFolded(); + } + + IsoString Lowercase() const + { + return string_base::Lowercase(); + } + + IsoString Uppercase() const + { + return string_base::Uppercase(); + } + + // ------------------------------------------------------------------------- + + IsoString Reversed() const + { + return string_base::Reversed(); + } + + IsoString Sorted() const + { + return string_base::Sorted(); + } + + template + IsoString Sorted( BP p ) const + { + return string_base::Sorted( p ); + } + + // ------------------------------------------------------------------------- + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * character. Returns a reference to this string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + IsoString& ToSeparated( const C& c, char_type separator ) + { + Clear(); + return c.ToSeparated( *this, separator ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * character, and built using an \a append binary function. Returns a + * reference to this string. + * + * The binary function must be of the form: + * + * \code void append( IsoString& s, char c ); \endcode + * + * where \a c is being appended to \a s. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + IsoString& ToSeparated( const C& c, char_type separator, AF append ) + { + Clear(); + return c.ToSeparated( *this, separator, append ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator string. + * Returns a reference to this string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + IsoString& ToSeparated( const C& c, const IsoString& separator ) + { + Clear(); + return c.ToSeparated( *this, separator ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator string, + * and built using an \a append binary function. Returns a reference to this + * string. + * + * The binary function must be of the form: + * + * \code void append( IsoString& s1, const IsoString& s2 ); \endcode + * + * where \a s2 is being appended to \a s1. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + IsoString& ToSeparated( const C& c, const IsoString& separator, AF append ) + { + Clear(); + return c.ToSeparated( *this, separator, append ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * null-terminated string. Returns a reference to this string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + IsoString& ToSeparated( const C& c, const_c_string separator ) + { + return ToSeparated( c, IsoString( separator ) ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * null-terminated string, and built using an \a append binary function. + * Returns a reference to this string. + * + * The binary function must be of the form: + * + * \code void append( IsoString& s1, const char* s2 ); \endcode + * + * where \a s2 is being appended to \a s1. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + IsoString& ToSeparated( const C& c, const_c_string separator, AF append ) + { + return ToSeparated( c, IsoString( separator ), append ); + } + + /*! + * Replaces the contents of this string with a sequence of comma-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, ',' ); \endcode + */ + template + IsoString& ToCommaSeparated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::Comma() ); + } + + /*! + * Replaces the contents of this string with a sequence of colon-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, ':' ); \endcode + */ + template + IsoString& ToColonSeparated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::Colon() ); + } + + /*! + * Replaces the contents of this string with a sequence of space-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, ' ' ); \endcode + */ + template + IsoString& ToSpaceSeparated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::Blank() ); + } + + /*! + * Replaces the contents of this string with a sequence of + * tabulator-separated tokens extracted from a container \a c. Returns a + * reference to this string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, '\t' ); \endcode + */ + template + IsoString& ToTabSeparated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::Tab() ); + } + + /*! + * Replaces the contents of this string with a sequence of new line + * separated tokens extracted from a container \a c. Returns a reference to + * this string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, '\n' ); \endcode + */ + template + IsoString& ToNewLineSeparated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::LF() ); + } + + /*! + * Replaces the contents of this string with a sequence of null-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, '\0' ); \endcode + */ + template + IsoString& ToNullSeparated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::Null() ); + } + + /*! + * Replaces the contents of this string with a hyphenated sequence of tokens + * extracted from a container \a c. Returns a reference to this string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, '-' ); \endcode + */ + template + IsoString& ToHyphenated( const C& c ) + { + return ToSeparated( c, IsoCharTraits::Hyphen() ); + } + + // ------------------------------------------------------------------------- + + /*! + * Replaces all occurrences of HTML special characters in this string with + * valid HTML entities. Returns a reference to this string. + * + * The following replacements are performed: + * + * '&' (ampersand) becomes "\&" \n + * '"' (double quote) becomes "\"" \n + * "'" (single quote) becomes "\'" \n + * '<' (less than) becomes "\<" \n + * '>' (greater than) becomes "\>" + * + * \sa EncodedHTMLSpecialChars(), ToDecodedHTMLSpecialChars() + */ + IsoString& ToEncodedHTMLSpecialChars(); + + /*! + * Returns a duplicate of this string with all occurrences of HTML special + * characters replaced with valid HTML entities. + * + * \sa ToEncodedHTMLSpecialChars(), DecodedHTMLSpecialChars() + */ + IsoString EncodedHTMLSpecialChars() const + { + return IsoString( *this ).ToEncodedHTMLSpecialChars(); + } + + /*! + * Replaces all occurrences of special HTML entities in this string with + * their corresponding plain text character equivalents. Returns a reference + * to this string. + * + * The following replacements are performed: + * + * "\&" (ampersand) becomes '&' \n + * "\"" (double quote) becomes '"' \n + * "\'" (single quote) becomes "'" \n + * "\'" (apostrophe) becomes "'" \n + * "\<" (less than) becomes '<' \n + * "\>" (greater than) becomes '>' + * + * \sa DecodedHTMLSpecialChars(), ToEncodedHTMLSpecialChars() + */ + IsoString& ToDecodedHTMLSpecialChars(); + + /*! + * Returns a duplicate of this string with all occurrences of special HTML + * entities replaced with their corresponding plain text character + * equivalents. + * + * \sa ToDecodedHTMLSpecialChars(), EncodedHTMLSpecialChars() + */ + IsoString DecodedHTMLSpecialChars() const + { + return IsoString( *this ).ToDecodedHTMLSpecialChars(); + } + + /*! + * Returns a URL-encoded string that represents a binary \a data block of + * the specified \a length in bytes. + * + * In a URL-encoded string, all characters that are not a-z, A-Z, 0-9, '-', + * '.', '_' or '~' are replaced with their percent-encoded representation + * %NN, where NN is a zero-padded, two-digit uppercase hexadecimal number. + * See RFC 3986 (http://tools.ietf.org/html/rfc3986). + * + * \sa ToURLEncoded( const C& ), ToURLEncoded() + */ + static IsoString ToURLEncoded( const void* data, size_type length ); + + /*! + * Returns a URL-encoded string for a container \a c, whose contents are + * treated as raw binary data. The objects stored in the container + * are considered as a sequence of bytes, irrespective of their actual data + * types or the classes they are instances of. + * + * The type C represents an array of contiguous objects, and must provide + * PCL container semantics: the Begin() and Length() standard container + * functions are required. + * + * \sa ToURLEncoded( const void*, size_type ) + */ + template + static IsoString ToURLEncoded( const C& c ) + { + return ToURLEncoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); + } + + /*! + * Replaces all characters that are not a-z, A-Z, 0-9, '-', '.', '_' or '~' + * with their percent-encoded representation %NN, where NN is a zero-padded, + * two-digit uppercase hexadecimal number. Returns a reference to this + * string. See RFC 3986 / URI Generic Syntax, for more information on URL + * encodings. + * + * \sa URLEncoded(), ToURLDecoded() + */ + IsoString& ToURLEncoded(); + + /*! + * Returns a URL-encoded duplicate of this string. See ToURLEncoded() for + * detailed information. + * + * \sa ToURLEncoded(), URLDecoded() + */ + IsoString URLEncoded() const + { + return IsoString( *this ).ToURLEncoded(); + } + + /*! + * Decodes a URL-encoded string stored as a raw \a data vector of the + * specified \a length in bytes. Returns the decoded binary raw data as a + * ByteArray object. + * + * This function replaces all percent-encoded character representations in + * the specified \a data vector with their actual characters in the output + * array. + * + * \sa FromURLEncoded(), ToURLEncoded( const void*, size_type ) + */ + static ByteArray FromURLEncoded( const void* data, size_type length ); + + /*! + * Decodes a URL-encoded generic string represented as a container \a c. + * Returns the decoded binary raw data as a ByteArray object. + * + * \sa FromURLEncoded( const void*, size_type ), + * ToURLEncoded( const void*, size_type ) + */ + template + static ByteArray FromURLEncoded( const C& c ) + { + return FromURLEncoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); + } + + /*! + * Decodes this URL-encoded string, and returns the decoded binary raw data + * as a ByteArray object. + * + * This function replaces all percent-encoded character representations in + * this string with their actual characters in the output array. + * + * If this string is empty, this function returns an empty %ByteArray. + * + * \sa FromURLEncoded( const void*, size_type ), ToURLEncoded() + */ + ByteArray FromURLEncoded() const + { + return FromURLEncoded( Begin(), Length() ); + } + + /*! + * Decodes a URL-encoded string stored as a raw \a data vector of the + * specified \a length in bytes. Returns the decoded data stored as an 8-bit + * string. + * + * This function replaces all percent-encoded character representations in + * the specified \a data vector with their actual characters in the output + * string. + * + * \sa ToURLDecoded(), URLDecoded() + */ + static IsoString ToURLDecoded( const void* data, size_type length ); + + /*! + * Decodes a URL-encoded generic string represented as a container \a c. + * Returns the decoded data stored as an 8-bit string. + * + * \sa ToURLDecoded( const void*, size_type ), ToURLDecoded(), URLDecoded() + */ + template + static IsoString ToURLDecoded( const C& c ) + { + return ToURLDecoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); + } + + /*! + * Replaces all percent-encoded representations of characters with their + * actual characters. Returns a reference to this string. + * + * This is the reverse transformation to URL encoding. See ToURLEncoded() + * for more information. + * + * \sa URLDecoded(), ToURLEncoded(), FromURLEncoded() + */ + IsoString& ToURLDecoded(); + + /*! + * Returns a URL-decoded duplicate of this string. See ToURLDecoded() for + * detailed information. + * + * \sa ToURLDecoded(), URLEncoded() + */ + IsoString URLDecoded() const + { + return IsoString( *this ).ToURLDecoded(); + } + + // ------------------------------------------------------------------------- + +#ifdef __PCL_QT_INTERFACE + + operator QString() const + { + return QString( c_str() ); + } + + operator QByteArray() const + { + return QByteArray( c_str() ); + } + + operator QDate() const + { + return QDate::fromString( c_str(), PCL_QDATE_FMT_STR ); + } + + operator QDateTime() const + { + return QDateTime::fromString( c_str(), PCL_QDATETIME_FMT_STR ); + } + +#endif + + /*! + * Replaces the contents of this string with a formatted representation of a + * variable-length set of values. Returns a reference to this string. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + IsoString& Format( const_c_string fmt, ... ) + { + va_list paramList; + va_start( paramList, fmt ); + + (void)VFormat( fmt, paramList ); + + va_end( paramList ); + return *this; + } + + /*! + * Appends a formatted representation of a variable-length set of values to + * the current contents of this string. Returns a reference to this string. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + IsoString& AppendFormat( const_c_string fmt, ... ) + { + va_list paramList; + va_start( paramList, fmt ); + + (void)AppendVFormat( fmt, paramList ); + + va_end( paramList ); + return *this; + } + + /*! + * Replaces the contents of this string with a formatted representation of a + * variable-length set of values, specified as a \c va_list standard + * parameter list. Returns the number of characters generated. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + int VFormat( const_c_string fmt, va_list paramList ); + + /*! + * Appends a formatted representation of a variable-length set of values, + * specified as a \c va_list standard parameter list, to the current + * contents of this string. Returns the number of characters appended. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + int AppendVFormat( const_c_string fmt, va_list paramList ); + + // ------------------------------------------------------------------------- + + /*! + * Returns a UTF-16 string with a converted copy of this %IsoString object. + * + * This function assumes that this %IsoString object contains only valid + * ISO/IEC-8859-1 characters. To perform UTF-8 to UTF-16 conversions, see + * UTF8ToUTF16() and MBSToWCS(). + * + * \sa UTF8ToUTF16(), MBSToWCS() + */ + ustring_base ToString() const + { + ustring_base s; + s.SetLength( Length() ); + uchar_iterator p = s.Begin(); + for ( const_iterator i = m_data->string; i < m_data->end; ++p, ++i ) + *p = uchar_type( *i ); + return s; + } + + /*! + * Returns a UTF-16 string with a representation of a subset of \a n + * contiguous UTF-8 characters from this %IsoString object, starting at the + * \a i-th character. + * + * \sa ToString(), MBSToWCS() + */ + ustring_base UTF8ToUTF16( size_type i = 0, size_type n = maxPos ) const; // implemented inline after String + + /*! + * Returns a copy of this multibyte string converted to a UTF-16 + * string. This conversion is dependent on the current locale. + * + * In the event of conversion error (if there are invalid multibyte + * characters in the source string) this routine returns an empty string. + * + * This member function is a convenience wrapper for the mbstowcs() routine + * of the standard C runtime library. Note that on platforms where the size + * of wchar_t is four bytes (e.g. Linux) this routine performs an additional + * conversion from UTF-32 to UTF-16. On platforms where the size of wchar_t + * is two bytes (e.g. Windows), the conversion is direct. + * + * \sa UTF8ToUTF16(), ToString() + */ + ustring_base MBSToWCS() const; + +#ifdef __PCL_QT_INTERFACE + + QString ToQString() const + { + return operator QString(); + } + + QByteArray ToQByteArray() const + { + return operator QByteArray(); + } + + QDate ToQDate() const + { + return operator QDate(); + } + + QDateTime ToQDateTime() const + { + return operator QDateTime(); + } + +#endif + + /*! + * Evaluates this string as a Boolean literal, and returns the result as a + * \c bool value. + * + * Returns \c true if this string is equal to "1", "true", "TRUE" or "T". + * Returns \c false if this string is equal to "0", "false", "FALSE" or "F". + * Otherwise this function throws a ParseError exception. + * + * \sa TryToBool() + */ + bool ToBool() const; + + /*! + * Attempts to evaluate this string as a Boolean literal. + * + * If this string can legally be converted to a Boolean value, this function + * returns \c true and stores the evaluation result in the \a value + * variable. A string can only be converted to Boolean type if it is equal + * to either "1", "true", "TRUE", "T", "0", "false", "FALSE" or "F". + * + * If this string cannot be converted to a Boolean value, this function + * returns \c false and does not change the \a value variable. This function + * does not throw any exception. + * + * \sa ToBool() + */ + bool TryToBool( bool& value ) const noexcept; + + /*! + * Evaluates this string as a floating point numeric literal, and returns + * the result as a \c float value. + * + * For information about the legal syntax of a floating point literal, see + * the documentation for the ToDouble() member function. + * + * If this string doesn't contain a valid floating point literal, or if the + * range of \c float is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToFloat() + */ + float ToFloat() const; + + /*! + * Attempts to evaluate this string as a floating point numeric literal. + * + * If this string can legally be converted to a floating point number, this + * function returns \c true and stores the evaluation result in the \a value + * variable. For information about the legal syntax of a floating point + * literal, see the documentation for the ToDouble() member function. + * + * If this string cannot be converted to a floating point number, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \sa ToFloat() + */ + bool TryToFloat( float& value ) const noexcept; + + /*! + * Evaluates this string as a floating point literal, and returns the result + * as a \c double value. + * + * The source string is expected to have the following format (informal + * format specification): + * + * [+|-][\][.[\]][\[+|-]\] + * + * where \ and \ are optional sequences of + * decimal digits from 0 to 9, \ is an exponent specifier + * (the letter 'e' (or 'E')), and \ is a sequence of decimal + * digits specifying a power of ten that multiplies the preceding numeric + * constant. At least a one-digit integer part, or a one-digit decimal part, + * is mandatory. FORTRAN exponent specifiers ('d' and 'f' (or 'D' and 'F')) + * are also recognized by this implementation. + * + * If this string doesn't contain a valid floating point literal, or if the + * range of \c double is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToDouble() + */ + double ToDouble() const; + + /*! + * Attempts to evaluate this string as a floating point numeric literal. + * + * If this string can legally be converted to a floating point number, this + * function returns \c true and stores the evaluation result in the \a value + * variable. For information about the legal syntax of a floating point + * literal, see the documentation for the ToDouble() member function. + * + * If this string cannot be converted to a floating point number, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \sa ToDouble() + */ + bool TryToDouble( double& value ) const noexcept; + + /*! + * Evaluates this string as an integer literal, and returns the result as a + * \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code long n = s.ToInt( 0 ); \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string doesn't contain a valid integer literal, or if the range + * of \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToInt() + */ + long ToInt() const + { + return ToInt( 0 ); + } + + /*! + * Attempts to evaluate this string as an integer numeric literal. + * + * If this string can legally be converted to an integer number, this + * function returns \c true and stores the evaluation result in the \a value + * variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * int v; + * if ( s.TryToInt( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an integer number, this function + * returns \c false and does not change the \a value variable. This function + * does not throw any exception. + * + * \sa ToInt() + */ + bool TryToInt( int& value ) const noexcept + { + return TryToInt( value, 0 ); + } + + /*! + * Evaluates this string as an integer literal in the specified \a base, and + * returns the result as a \c long value. + * + * If \a base is 0, the source string is expected to represent either a + * decimal constant, an octal constant, or a hexadecimal constant, any of + * which optionally preceded by a sign character (+ or -). A decimal + * constant begins with a non-zero digit, and consists of a sequence of + * decimal digits from '0' to '9'. An octal begins with the prefix '0', + * optionally followed by a sequence of the digits 0 to 7 only. A + * hexadecimal constant begins with the prefix '0x' or '0X', which must be + * followed by a sequence of decimal digits and letters from 'a' (or 'A') + * to 'f' (or 'F'), whose corresponding decimal values are from 10 to 15, + * respectively. + * + * Other legal values of \a base, from 2 to 36, specify the expected base of + * the integer constant represented by the source string. Decimal digits and + * letters from 'a' (or 'A') to 'z' (or 'Z') are used to represent all + * possible digits in the specified base, as necessary. + * + * If this string doesn't contain a valid integer literal in the specified + * \a base, if an illegal \a base is specified, or if the range of \c long + * is exceeded, this member function throws a ParseError exception. + * + * \sa TryToInt( int&, int ) const + */ + long ToInt( int base ) const; + + /*! + * Attempts to evaluate this string as an integer numeric literal in the + * specified \a base. + * + * If this string can legally be converted to an integer number in the + * specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an integer number in the specified + * \a base, this function returns \c false and does not change the \a value + * variable. This function does not throw any exception. + * + * \sa ToInt( int ) const + */ + bool TryToInt( int& value, int base ) const noexcept; + + /*! + * Evaluates this string as an unsigned integer literal, and returns the + * result as an \c unsigned \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code unsigned long n = s.ToUInt( 0 ); \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string doesn't contain a valid unsigned integer literal, or if + * the range of \c unsigned \c long is exceeded, this member function throws + * a ParseError exception. + * + * \sa TryToUInt() + */ + unsigned long ToUInt() const + { + return ToUInt( 0 ); + } + + /*! + * Attempts to evaluate this string as an unsigned integer literal. + * + * If this string can legally be converted to an unsigned integer number, + * this function returns \c true and stores the evaluation result in the + * \a value variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * unsigned v; + * if ( s.TryToUInt( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an integer number, this function + * returns \c false and does not change the \a value variable. This function + * does not throw any exception. + * + * \sa ToUInt() + */ + bool TryToUInt( unsigned& value ) const noexcept + { + return TryToUInt( value, 0 ); + } + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as an \c unsigned \c long value. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). The only exception + * is that for this member function, only a + sign is legal preceding the + * numeric constant represented by the source string. + * + * If this string doesn't contain a valid integer literal in the specified + * \a base, if an illegal \a base is specified, or if the range of + * \c unsigned \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToUInt( unsigned&, int ) const + */ + unsigned long ToUInt( int base ) const; + + /*! + * Attempts to evaluate this string as an unsigned integer literal in the + * specified \a base. + * + * If this string can legally be converted to an unsigned integer number in + * the specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * See the documentation under ToUInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an unsigned integer number in the + * specified \a base, this function returns \c false and does not change the + * \a value variable. This function does not throw any exception. + * + * \sa ToUInt( int ) const + */ + bool TryToUInt( unsigned& value, int base ) const noexcept; + + /*! + * Evaluates this string as an integer literal, and returns the result as a + * \c long \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code long long n = s.ToInt64( 0 ); \endcode + * + * If this string doesn't contain a valid integer literal, or if the range + * of \c long \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToInt64() + */ + long long ToInt64() const + { + return ToInt64( 0 ); + } + + /*! + * Attempts to evaluate this string as a 64-bit integer numeric literal in + * the specified \a base. + * + * If this string can legally be converted to a 64-bit integer number in the + * specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * long long v; + * if ( s.TryToInt64( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to a 64-bit integer number, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \sa ToInt64() + */ + bool TryToInt64( long long& value ) const noexcept + { + return TryToInt64( value, 0 ); + } + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as a \c long \c long value. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string doesn't contain a valid integer literal in the specified + * \a base, if an illegal \a base is specified, or if the range of + * \c long \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToInt64( long long&, int ) const + */ + long long ToInt64( int base ) const; + + /*! + * Attempts to evaluate this string as a 64-bit integer numeric literal in + * the specified \a base. + * + * If this string can legally be converted to a 64-bit integer number in the + * specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string cannot be converted to a 64-bit integer number in the + * specified \a base, this function returns \c false and does not change the + * \a value variable. This function does not throw any exception. + * + * \sa ToInt64( int ) const + */ + bool TryToInt64( long long& value, int base ) const noexcept; + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as an \c unsigned \c long \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code unsigned long long n = s.ToUInt64( 0 ); \endcode + * + * If this string doesn't contain a valid unsigned integer literal, or if + * the range of \c unsigned \c long \c long is exceeded, this member + * function throws a ParseError exception. + * + * \sa TryToUInt64() + */ + unsigned long long ToUInt64() const + { + return ToUInt64( 0 ); + } + + /*! + * Attempts to evaluate this string as a 64-bit unsigned integer numeric + * literal in the specified \a base. + * + * If this string can legally be converted to a 64-bit unsigned integer + * number in the specified \a base, this function returns \c true and stores + * the evaluation result in the \a value variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * unsigned long long v; + * if ( s.TryToUInt64( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to a 64-bit unsigned integer number, + * this function returns \c false and does not change the \a value variable. + * This function does not throw any exception. + * + * \sa ToUInt64() + */ + bool TryToUInt64( unsigned long long& value ) const noexcept + { + return TryToUInt64( value, 0 ); + } + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as an \c unsigned \c long \c long value. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string doesn't contain a valid unsigned integer literal in the + * specified \a base, if an illegal \a base is specified, or if the range of + * \c unsigned \c long \c long is exceeded, this member function throws a + * ParseError exception. + * + * \sa TryToUInt64( unsigned long long&, int ) const + */ + unsigned long long ToUInt64( int base ) const; + + /*! + * Attempts to evaluate this string as an unsigned 64-bit integer numeric + * literal in the specified \a base. + * + * If this string can legally be converted to an unsigned 64-bit integer + * number in the specified \a base, this function returns \c true and stores + * the evaluation result in the \a value variable. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string cannot be converted to an unsigned 64-bit integer number + * in the specified \a base, this function returns \c false and does not + * change the \a value variable. This function does not throw any exception. + * + * \sa ToUInt64( int ) const + */ + bool TryToUInt64( unsigned long long& value, int base ) const noexcept; + + /*! + * Evaluates this string as a sexagesimal numeric literal representation, + * and returns the result as a \c double value. + * + * The source string is expected to have the following format: + * + * [+|-]\[\\[\\]][.[\]] + * + * where \, \, \ and \ are sequences of + * decimal digits from 0 to 9, and \ is any sequence of characters + * specified as the \a separator argument. The default separator is the + * colon character, ':'. + * + * The result is equal to: + * + * \ * (\ + \/60 + \/3600) + * + * where omitted optional components are taken as zero, and \ is -1 + * iff a minus sign '-' leads the representation, or +1 otherwise. + * + * If this string doesn't contain a valid sexagesimal numeric literal, or if + * the range of \c double is exceeded, this member function throws a + * ParseError exception. + * + * \ingroup sexagesimal_conversion + * \sa TrySexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() + */ + double SexagesimalToDouble( const IsoString& separator = ':' ) const + { + int sign, s1, s2; double s3; + ParseSexagesimal( sign, s1, s2, s3, separator ); + return sign*(s1 + (s2 + s3/60)/60); + } + + double SexagesimalToDouble( char separator ) const + { + return SexagesimalToDouble( IsoString( separator ) ); + } + + double SexagesimalToDouble( const ustring_base& separator ) const + { + return SexagesimalToDouble( IsoString( separator ) ); + } + + /*! + * Evaluates this string as a sexagesimal numeric literal representation + * with the specified set of \a separators, and returns the result as a + * \c double value. + * + * This function is identical to SexagesimalToDouble( const IsoString& ), + * but a set of separator characters is specified as a dynamic array. Any + * occurrence of a character contained by \a separators will be valid as a + * token separator. + * + * \ingroup sexagesimal_conversion + * \sa TrySexagesimalToDouble( double&, const Array<>& ) + */ + double SexagesimalToDouble( const Array& separators ) const + { + int sign, s1, s2; double s3; + ParseSexagesimal( sign, s1, s2, s3, separators ); + return sign*(s1 + (s2 + s3/60)/60); + } + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal with + * the specified \a separator. + * + * If this string can legally be evaluated as a sexagesimal literal and + * converted to a floating point number, this function stores the evaluation + * result in the specified \a value variable and returns \c true. For + * information about the legal syntax of a sexagesimal literal, see the + * documentation for SexagesimalToDouble(). + * + * If this string cannot be evaluated as a sexagesimal literal, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \ingroup sexagesimal_conversion + * \sa SexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() + */ + bool TrySexagesimalToDouble( double& value, const IsoString& separator = ':' ) const noexcept + { + int sign, s1, s2; double s3; + if ( TryParseSexagesimal( sign, s1, s2, s3, separator ) ) + { + value = sign*(s1 + (s2 + s3/60)/60); + return true; + } + return false; + } + + bool TrySexagesimalToDouble( double& value, char separator ) const noexcept + { + return TrySexagesimalToDouble( value, IsoString( separator ) ); + } + + bool TrySexagesimalToDouble( double& value, const ustring_base& separator ) const noexcept + { + return TrySexagesimalToDouble( value, IsoString( separator ) ); + } + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal with + * the specified set of \a separators. + * + * This function is identical to + * TrySexagesimalToDouble( double&, const IsoString& ), but a set of + * separator characters is specified as a dynamic array. Any occurrence of a + * character contained by \a separators will be valid as a token separator. + * + * \ingroup sexagesimal_conversion + * \sa SexagesimalToDouble( const Array<>& ) + */ + bool TrySexagesimalToDouble( double& value, const Array& separators ) const noexcept + { + int sign, s1, s2; double s3; + if ( TryParseSexagesimal( sign, s1, s2, s3, separators ) ) + { + value = sign*(s1 + (s2 + s3/60)/60); + return true; + } + return false; + } + + /*! + * Evaluates this string as a sexagesimal numeric literal representation, + * using the specified \a separator, and stores the resulting components in + * the specified \a sign, \a s1, \a s2 and \a s3 variables. + * + * The output value of \a sign is either -1 or +1, respectively for negative + * and positive values. + * + * For information about the legal syntax of a sexagesimal literal, see the + * documentation for SexagesimalToDouble(). + * + * This function stores \e canonical minutes and seconds components, + * irrespective of the actual component values represented by this string. + * The output sexagesimal component values are such that: + * + * 0 ≤ \a s1 \n + * 0 ≤ \a s2 < 60 \n + * 0 ≤ \a s3 < 60 \n + * + * If this string doesn't contain a valid sexagesimal numeric literal, or if + * the range of \c double is exceeded, this member function throws a + * ParseError exception. + * + * \ingroup sexagesimal_conversion + * \sa TryParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() + */ + void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const IsoString& separator = ':' ) const; + + void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, char separator ) const + { + ParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); + } + + void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const ustring_base& separator ) const + { + ParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); + } + + /*! + * Evaluates this string as a sexagesimal numeric literal representation, + * using the specified set of \a separators, and stores the resulting + * components in the specified \a sign, \a s1, \a s2 and \a s3 variables. + * + * This function is identical to + * ParseSexagesimal( int&, int&, int&, double&, const IsoString& ), but a + * set of separator characters is specified as a dynamic array. Any + * occurrence of a character contained by \a separators will be valid as a + * token separator. + * + * \ingroup sexagesimal_conversion + * \sa TryParseSexagesimal( int&, int&, int&, double&, const Array<>& ) + */ + void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const; + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal + * representation, using the specified \a separator. If successful, stores + * the resulting components in the specified \a sign, \a s1, \a s2 and \a s3 + * variables, and returns \c true. For more information on syntax and + * output values and ranges, see the documentation for ParseSexagesimal(). + * + * If this string cannot be evaluated as a sexagesimal literal, this + * function returns \c false and does not change any of the \a sign, \a s1, + * \a s2 and \a s3 variables. This function does not throw any exception. + * + * \ingroup sexagesimal_conversion + * \sa ParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() + */ + bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const IsoString& separator = ':' ) const noexcept; + + bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, char separator ) const noexcept + { + return TryParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); + } + + bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const ustring_base& separator ) const noexcept + { + return TryParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); + } + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal + * representation, using the specified set of \a separators. + * + * This function is identical to + * TryParseSexagesimal( int&, int&, int&, double&, const IsoString& ), but a + * set of separator characters is specified as a dynamic array. Any + * occurrence of a character contained by \a separators will be valid as a + * token separator. + * + * \ingroup sexagesimal_conversion + * \sa ParseSexagesimal( int&, int&, int&, double&, const Array<>& ) + */ + bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const noexcept; + + /*! + * Returns a sexagesimal ASCII representation of the specified components + * \a sign, \a s1, \a s2 and \a s3, generated with the specified conversion + * \a options. + * + * The generated representation will correspond to a negative value iff + * \a sign < 0, positive otherwise. + * + * The generated representation is of the form: + * + * [+|-]\[\\[\\]][.[\]] + * + * where the second and third sexagesimal components are canonicalized: + * + * 0 ≤ \ < 60 + * 0 ≤ \ < 60 + * + * irrespective of the original \a s2 and \a s3 argument values. + * + * \ingroup sexagesimal_conversion + * \sa SexagesimalToDouble(), SexagesimalConversionOptions, + * AngleConversionOptions, LongitudeConversionOptions, RAConversionOptions, + * LatitudeConversionOptions, DecConversionOptions + */ + static IsoString ToSexagesimal( int sign, double s1, double s2, double s3, + const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ); + + /*! + * Returns a sexagesimal ASCII representation of the specified decimal value + * \a d, generated with the specified conversion \a options. + * + * Calling this member function is equivalent to: + * + * \code ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); \endcode + * + * \ingroup sexagesimal_conversion + */ + static IsoString ToSexagesimal( double d, const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ) + { + return ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); + } + + /*! + * Evaluates this string as a date and time specification in ISO 8601 + * extended format, and stores the resulting components in the specified + * variables. + * + * \param year On output, the year of the date. + * + * \param month On output, the month of the date in the range [1,12]. + * + * \param day On output, the day of the date in the range [1,31]. + * + * \param dayf On output, the day fraction corresponding to the time + * specification, in the range [0,1). + * + * \param tz On output, the time zone offset in hours, in the range + * [-12,+12]. + * + * In ISO 8601 extended representations, decimal fractions must be divided + * from integer parts exclusively by the full stop or dot character ('.', + * ASCII code point 46(10) = 2E(16)). + * + * \sa TryParseISO8601DateTime(), TimePoint::FromString() + */ + void ParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const; + + /*! + * Attempts to evaluate this string as a date and time specification in ISO + * 8601 extended format. If successful, stores the resulting components in + * the specified \a year, \a month, \a day and \a dayf and \a tz variables, + * and returns \c true. For more information on syntax and + * output values and ranges, see the ParseISO8601DateTime(). + * + * If this string cannot be evaluated as a valid date and time in ISO 8601 + * format, this function returns \c false and does not change any of the + * passed variables. This function does not throw any exception. + * + * \sa ParseISO8601DateTime(), TimePoint::TryFromString() + */ + bool TryParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const noexcept; + + /*! + * Returns an ASCII representation of a date and time in ISO 8601 extended + * format. + * + * \param year The year of the date. + * + * \param month The month of the date in the range [1,12]. + * + * \param day The day of the date in the range [1,31]. + * + * \param dayf The day fraction corresponding to the time specification, + * in the range [0,1). + * + * \param tz The time zone offset in hours, in the range [-12,+12]. The + * default value is zero, to be interpreted as UTC. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 format. + * + * \sa CurrentUTCISO8601DateTime(), CurrentLocalISO8601DateTime(), + * ParseISO8601DateTime(), ISO8601ConversionOptions, + * TimePoint::ToIsoString() + */ + static IsoString ToISO8601DateTime( int year, int month, int day, double dayf, double tz = 0, + const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); + + /*! + * Returns an ASCII representation of the current UTC date and time in ISO + * 8601 extended format. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 format. + * + * \sa CurrentLocalISO8601DateTime(), ToISO8601DateTime(), + * ISO8601ConversionOptions, TimePoint::Now() + */ + static IsoString CurrentUTCISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); + + /*! + * Returns an ASCII representation of the current local date and time in ISO + * 8601 extended format. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 format. + * + * \sa CurrentUTCISO8601DateTime(), ToISO8601DateTime(), + * ISO8601ConversionOptions + */ + static IsoString CurrentLocalISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); + + /*! + * Returns an hex-encoded string for a binary \a data block of the specified + * \a length in bytes. The hex-encoded string is composed of hexadecimal + * digits: 0-9 and a-f, and its length is twice that of the input length. + * + * \sa ToHex( const C& ), ToBase64(), ToByteArray() + */ + static IsoString ToHex( const void* data, size_type length ); + + /*! + * Returns an hex-encoded string for a container \a c, whose contents are + * treated as raw binary data. The objects stored in the container + * are considered as a sequence of bytes, irrespective of their actual data + * types or the classes they are instances of. + * + * The type C represents an array of contiguous objects, and must provide + * PCL container semantics: the Begin() and Length() standard container + * functions are required. + * + * \sa ToHex( const void*, size_type ) + */ + template + static IsoString ToHex( const C& c ) + { + return ToHex( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); + } + + /*! + * Returns a Base64-encoded string for a binary \a data block of the + * specified \a length in bytes. + * + * Base64 is a MIME content transfer encoding of binary data translated into + * a base 64 representation composed of printable characters. See RFC 1421 + * (http://tools.ietf.org/html/rfc1421). + * + * \sa ToBase64( const C& ), ToHex(), ToByteArray() + */ + static IsoString ToBase64( const void* data, size_type length ); + + /*! + * Returns a Base64-encoded string for a container \a c, whose contents are + * treated as raw binary data. The objects stored in the container + * are considered as a sequence of bytes, irrespective of their actual data + * types or the classes they are instances of. + * + * The type C represents an array of contiguous objects, and must provide + * PCL container semantics: the Begin() and Length() standard container + * functions are required. + * + * \sa ToBase64( const void*, size_type ), ToByteArray() + */ + template + static IsoString ToBase64( const C& c ) + { + return ToBase64( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); + } + + /*! + * Returns a ByteArray object that stores a copy of this string. In the + * returned array, source 8-bit characters have been reinterpreted as + * unsigned 8-bit integers. + * + * \sa ToBase64(), ToHex() + */ + ByteArray ToByteArray() const + { + return ByteArray( Begin(), End() ); + } + + /*! + * Decodes an hex-encoded string, and returns the decoded binary raw data + * stored in a ByteArray object. + * + * This function expects this string to be hex-encoded; if it isn't, or if + * it contains invalid hexadecimal digits, a ParseError exception will be + * thrown. + * + * If this string is empty, this function returns an empty %ByteArray. + * + * \sa ToHex(), FromBase64() + */ + ByteArray FromHex() const; + + /*! + * Decodes a Base64-encoded string, and returns the decoded binary raw data + * stored in a ByteArray object. + * + * This function expects this string to be Base64-encoded; if it isn't, or + * if it contains an invalid Base64 representation, a ParseError exception + * will be thrown. + * + * If this string is empty, this function returns an empty %ByteArray. + * + * \sa ToBase64(), FromHex() + */ + ByteArray FromBase64() const; + + /*! + * Generates a string of \a n random 8-bit code points, with character types + * and ranges as prescribed by the specified \a options. + * + * \sa RandomizationOption + */ + static IsoString Random( size_type n, RandomizationOptions options = RandomizationOption::Default ); + + /*! + * Generates a universally unique identifier (UUID) in canonical form. + * + * The canonical UUID has 36 characters with the following format: + * + * xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + * + * where 'x' represents a lowercase hexadecimal digit, '4' is the UUID + * version indicator (version 4 = truly random UUID), and 'y' is one of '8', + * '9', 'a', or 'b'. + */ + static IsoString UUID(); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup isostring_concatenation_ops IsoString Concatenation Operators + */ + +/*! + * Returns a string with the concatenation of two strings \a s1 and \a s2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( const IsoString::string_base& s1, const IsoString::string_base& s2 ) +{ + IsoString s( s1 ); + s.Append( s2 ); + return s; +} + +/*! + * Returns a string with the concatenation of two strings \a s1 (rvalue + * reference) and \a s2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::string_base&& s1, const IsoString::string_base& s2 ) +{ + s1.Append( s2 ); + return IsoString( std::move( s1 ) ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 (rvalue + * reference) and \a s2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString&& s1, const IsoString::string_base& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 and \a s2 + * (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( const IsoString::string_base& s1, IsoString::string_base&& s2 ) +{ + s2.Prepend( s1 ); + return IsoString( std::move( s2 ) ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 and \a s2 + * (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( const IsoString::string_base& s1, IsoString&& s2 ) +{ + s2.Prepend( s1 ); + return std::move( s2 ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 (rvalue + * reference) and \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::string_base&& s1, IsoString::string_base&& s2 ) +{ + s1.Append( s2 ); + return IsoString( std::move( s1 ) ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 (rvalue + * reference) and \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString&& s1, IsoString::string_base&& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 (rvalue + * reference) and \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::string_base&& s1, IsoString&& s2 ) +{ + s1.Append( s2 ); + return IsoString( std::move( s1 ) ); +} + +/*! + * Returns a string with the concatenation of two strings \a s1 (rvalue + * reference) and \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString&& s1, IsoString&& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a string with the concatenation of a string \a s1 and a + * null-terminated string \a t2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( const IsoString::string_base& s1, IsoString::const_c_string t2 ) +{ + IsoString s = s1; + s.Append( t2 ); + return s; +} + +/*! + * Returns a string with the concatenation of a string \a s1 (rvalue reference) + * and a null-terminated string \a t2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::string_base&& s1, IsoString::const_c_string t2 ) +{ + s1.Append( t2 ); + return IsoString( std::move( s1 ) ); +} + +/*! + * Returns a string with the concatenation of a string \a s1 (rvalue reference) + * and a null-terminated string \a t2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString&& s1, IsoString::const_c_string t2 ) +{ + s1.Append( t2 ); + return std::move( s1 ); +} + +/*! + * Returns a string with the concatenation of a null-terminated string \a t1 + * and a string \a s2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::const_c_string t1, const IsoString::string_base& s2 ) +{ + IsoString s = s2; + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a string with the concatenation of a null-terminated string \a t1 + * and a string \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::const_c_string t1, IsoString::string_base&& s2 ) +{ + s2.Prepend( t1 ); + return IsoString( std::move( s2 ) ); +} + +/*! + * Returns a string with the concatenation of a null-terminated string \a t1 + * and a string \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::const_c_string t1, IsoString&& s2 ) +{ + s2.Prepend( t1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a string with the concatenation of a string \a s1 and a single + * character \a c2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( const IsoString::string_base& s1, IsoString::char_type c2 ) +{ + IsoString s = s1; + s.Append( c2 ); + return s; +} + +/*! + * Returns a string with the concatenation of a string \a s1 (rvalue reference) + * and a single character \a c2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::string_base&& s1, IsoString::char_type c2 ) +{ + s1.Append( c2 ); + return IsoString( std::move( s1 ) ); +} + +/*! + * Returns a string with the concatenation of a string \a s1 (rvalue reference) + * and a single character \a c2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString&& s1, IsoString::char_type c2 ) +{ + s1.Append( c2 ); + return std::move( s1 ); +} + +/*! + * Returns a string with the concatenation of a single character \a c1 and a + * string \a s2. + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::char_type c1, const IsoString::string_base& s2 ) +{ + IsoString s = s2; + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a string with the concatenation of a single character \a c1 and a + * string \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::char_type c1, IsoString::string_base&& s2 ) +{ + s2.Prepend( c1 ); + return IsoString( std::move( s2 ) ); +} + +/*! + * Returns a string with the concatenation of a single character \a c1 and a + * string \a s2 (rvalue reference). + * \ingroup isostring_concatenation_ops + */ +inline IsoString operator +( IsoString::char_type c1, IsoString&& s2 ) +{ + s2.Prepend( c1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Appends a string \a s2 to a string \a s1. Returns a reference to the + * left-hand operand string \a s1 + * \ingroup isostring_concatenation_ops + */ +inline IsoString& operator <<( IsoString& s1, const IsoString::string_base& s2 ) +{ + s1.Append( s2 ); + return s1; +} + +/*! + * Appends a string \a s2 to a string \a s1. Returns a reference to the + * left-hand operand string \a s1 + * \ingroup isostring_concatenation_ops + */ +inline IsoString& operator <<( IsoString&& s1, const IsoString::string_base& s2 ) +{ + s1.Append( s2 ); + return s1; +} + +/*! + * Appends a null-terminated string \a t2 to a string \a s1. Returns a + * reference to the left-hand operand string \a s1 + * \ingroup isostring_concatenation_ops + */ +inline IsoString& operator <<( IsoString& s1, IsoString::const_c_string t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a null-terminated string \a t2 to a string \a s1. Returns a + * reference to the left-hand operand string \a s1 + * \ingroup isostring_concatenation_ops + */ +inline IsoString& operator <<( IsoString&& s1, IsoString::const_c_string t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a single character \a c2 to a string \a s1. Returns a reference to + * the left-hand operand string \a s1 + * \ingroup isostring_concatenation_ops + */ +inline IsoString& operator <<( IsoString& s1, IsoString::char_type c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a single character \a c2 to a string \a s1. Returns a reference to + * the left-hand operand string \a s1 + * \ingroup isostring_concatenation_ops + */ +inline IsoString& operator <<( IsoString&& s1, IsoString::char_type c2 ) +{ + s1.Append( c2 ); + return s1; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_STRING_OSTREAM + +inline std::ostream& operator <<( std::ostream& o, const IsoString& s ) +{ + return o << s.c_str(); +} + +#endif + +// ---------------------------------------------------------------------------- + +/*! + * \class String + * \brief Unicode (UTF-16) string + * + * %String derives from an instantiation of GenericString for \c char16_type. + * It represents a dynamic string of characters in 16-bit Unicode + * Transformation Format (UTF-16) on the PixInsight platform. + * + * \sa IsoString + */ +class PCL_CLASS String : public GenericString +{ +public: + + /*! + * Base class of %String. + */ + typedef GenericString + string_base; + + /*! + * Represents a character pertaining to a %String object. + */ + typedef string_base::char_type char_type; + + /*! + * The character traits class used by this template instantiation. + */ + typedef string_base::char_traits char_traits; + + /*! + * The block allocator used by this template instantiation. + */ + typedef string_base::block_allocator block_allocator; + + /*! + * The allocator class used by this template instantiation. + */ + typedef string_base::allocator allocator; + + /*! + * Null-terminated sequence of UTF-16 characters. + */ + typedef string_base::c_string c_string; + + /*! + * Immutable null-terminated sequence of UTF-16 characters. + */ + typedef string_base::const_c_string const_c_string; + + /* + * Null-terminated UTF-16 string - C++11 compatibility. + */ + typedef char16_t* c16_string; + + /* + * Immutable null-terminated UTF-16 string - C++11 compatibility. + */ + typedef const char16_t* const_c16_string; + + /*! + * %String iterator. + */ + typedef string_base::iterator iterator; + + /*! + * Immutable %String iterator. + */ + typedef string_base::const_iterator const_iterator; + + /*! + * Reverse %String iterator. + */ + typedef string_base::reverse_iterator reverse_iterator; + + /*! + * Immutable reverse %String iterator. + */ + typedef string_base::const_reverse_iterator const_reverse_iterator; + + /*! + * Represents an 8-bit string. Depending on the context, this type + * represents a sequence of ISO/IEC-8859-1, ASCII, or UTF-8 code points. + * + * \note This type must be defined as the same template instantiation used + * for the IsoString class. + */ + typedef GenericString + string8_base; + + /*! + * Represents an 8-bit character (ISO/IEC-8859-1, ASCII or UTF-8). + */ + typedef string8_base::char_type char8_type; + + /*! + * 8-bit character traits class. + */ + typedef string8_base::char_traits char8_traits; + + /*! + * Null-terminated sequence of 8-bit characters. + */ + typedef string8_base::c_string c_string8; + + /*! + * Immutable null-terminated sequence of 8-bit characters. + */ + typedef string8_base::const_c_string const_c_string8; + + /*! + * 8-bit string iterator. + */ + typedef string8_base::iterator char8_iterator; + + /*! + * Immutable 8-bit string iterator. + */ + typedef string8_base::const_iterator const_char8_iterator; + + // ------------------------------------------------------------------------- + + /*! + * Constructs an empty %String object. + */ + String() = default; + + /*! + * Constructs a %String object as a copy of the specified \c string_base + * string \a s (copy constructor from the base class). + */ + String( const string_base& s ) + : string_base( s ) + { + } + + /*! + * Copy constructor. + */ + String( const String& ) = default; + + /*! + * Constructs a %String object by transferring data from the specified + * \c string_base string \a s (move constructor from the base class). + */ + String( string_base&& s ) + : string_base( std::move( s ) ) + { + } + + /*! + * Move constructor. + */ + String( String&& ) = default; + + /*! + * Constructs a %String as a transformed copy of the specified 8-bit, + * ISO/IEC-8859-1 string \a s. + */ + String( const string8_base& s ) + { + Assign( s ); + } + + /*! + * Constructs a %String as a copy of a null-terminated string \a t. + */ + String( const_iterator t ) + : string_base( t ) + { + } + + /*! + * Constructs a %String with the \a n first characters of the + * null-terminated string \a t, starting from its \a i-th character. + */ + String( const_iterator t, size_type i, size_type n ) + : string_base( t, i, n ) + { + } + + /*! + * Constructs a %String with \a n copies of a UTF-16 character \a c. + */ + String( char_type c, size_type n ) + : string_base( c, n ) + { + } + + /*! + * Constructs a %String with a copy of the character sequence defined by + * the range [i,j). + */ + String( const_iterator i, const_iterator j ) + : string_base( i, j ) + { + } + + /*! + * Constructs a %String with a copy of the character sequence stored in the + * specified initializer list \a l. + * + * This constructor is equivalent to: + * + * \code String( l.begin(), l.end() ) \endcode + */ + String( std::initializer_list l ) + : String( l.begin(), l.end() ) + { + } + + /*! + * Constructs a %String as a copy of a null-terminated string \a t of + * \c char16_t characters. + */ + String( const char16_t* t ) + : string_base( reinterpret_cast( t ) ) + { + } + + /*! + * Constructs a %String with the \a n first characters of the + * null-terminated string \a t of \c char16_t characters, starting from its + * \a i-th character. + */ + String( const char16_t* t, size_type i, size_type n ) + : string_base( reinterpret_cast( t ), i, n ) + { + } + + /*! + * Constructs a %String with \a n copies of a \c char16_t character \a c. + */ + String( char16_t c, size_type n ) + : string_base( char_type( c ), n ) + { + } + + /*! + * Constructs a %String as a copy of a null-terminated string \a t of + * \c wchar_t characters. + */ + String( const wchar_t* t ) + { + Assign( t ); + } + + /*! + * Constructs a %String with the \a n first characters of the + * null-terminated string \a t of \c wchar_t characters, starting from its + * \a i-th character. + */ + String( const wchar_t* t, size_type i, size_type n ) + { + Assign( t, i, n ); + } + + /*! + * Constructs a %String with \a n copies of a \c wchar_t character \a c. + */ + String( wchar_t c, size_type n ) + : string_base( char_type( c ), n ) + { + } + + /*! + * Constructs a %String as a transformed copy of the null-terminated 8-bit, + * ISO/IEC-8859-1 string \a t. + */ + String( const_c_string8 t ) + { + Assign( t ); + } + + /*! + * Constructs a %String with the \a n first characters of the + * null-terminated, 8-bit ISO/IEC-8859-1 string \a t, starting from its + * \a i-th character. + */ + String( const_c_string8 t, size_type i, size_type n ) + { + Assign( t, i, n ); + } + + /*! + * Constructs a %String with the sequence of 8-bit characters in the range + * [i,j) of 8-bit string iterators. + */ + String( const_char8_iterator i, const_char8_iterator j ) + { + Assign( i, j ); + } + + /*! + * Constructs a %String with a copy of the 8-bit ISO/IEC-8859-1 character + * sequence stored in the specified initializer list \a l. + * + * This constructor is equivalent to: + * + * \code String( l.begin(), l.end() ) \endcode + */ + String( std::initializer_list l ) + : String( l.begin(), l.end() ) + { + } + + /*! + * Constructs a %String object with \a n copies of an ISO/IEC-8859-1 + * character \a c. + */ + String( char8_type c, size_type n = 1 ) + : string_base( char_type( c ), n ) + { + } + + /*! + * Constructs a %String as a literal representation of a \c bool value. + */ + explicit + String( bool x ) + { + Assign( x ? "true" : "false" ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c signed \c short value. + */ + explicit + String( short x ) + { + (void)Format( L"%hd", x ); + } + + /*! + * Constructs a %String as a literal representation of an + * \c unsigned \c short value. + */ + explicit + String( unsigned short x ) + { + (void)Format( L"%hu", x ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c signed \c int value. + */ + explicit + String( int x ) + { + (void)Format( L"%i", x ); + } + + /*! + * Constructs a %String as a literal representation of an + * \c unsigned \c int value. + */ + explicit + String( unsigned int x ) + { + (void)Format( L"%u", x ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c signed \c long value. + */ + explicit + String( long x ) + { + (void)Format( L"%ld", x ); + } + + /*! + * Constructs a %String as a literal representation of an + * \c unsigned \c long value. + */ + explicit + String( unsigned long x ) + { + (void)Format( L"%lu", x ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c signed \c long \c long value. + */ + explicit + String( long long x ) + { + (void)Format( L"%lli", x ); + } + + /*! + * Constructs a %String as a literal representation of an + * \c unsigned \c long \c long value. + */ + explicit + String( unsigned long long x ) + { + (void)Format( L"%llu", x ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c float value. + */ + explicit + String( float x ) + { + (void)Format( L"%.7g", x ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c double value. + */ + explicit + String( double x ) + { + (void)Format( L"%.16g", x ); + } + + /*! + * Constructs a %String as a literal representation of a + * \c long \c double value. + */ + explicit + String( long double x ) + { +#ifdef _MSC_VER + (void)Format( L"%.16Lg", x ); +#else + (void)Format( L"%.18Lg", x ); +#endif + } + +#ifndef __PCL_NO_STRING_COMPLEX + + /*! + * Constructs a %String as a literal representation of an \c fcomplex value. + */ + explicit + String( Complex& x ) + { + (void)Format( L"{%.7g,%.7g}", x.Real(), x.Imag() ); + } + + /*! + * Constructs a %String as a literal representation of a \c dcomplex value. + */ + explicit + String( Complex& x ) + { + (void)Format( L"{%.16g,%.16g}", x.Real(), x.Imag() ); + } + + /*! + * Constructs a %String as a literal representation of an \c lcomplex value. + */ + explicit + String( Complex& x ) + { +#ifdef _MSC_VER + (void)Format( L"{%.16Lg,%.16Lg}", x.Real(), x.Imag() ); +#else + (void)Format( L"{%.18Lg,%.18Lg}", x.Real(), x.Imag() ); +#endif + } + +#endif // !__PCL_NO_STRING_COMPLEX + +#ifdef __PCL_QT_INTERFACE + + explicit + String( const QString& qs ) + : string_base( qs.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ) ) + { + } + + explicit + String( const QDate& qd ) + : string_base( iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ) ) + { + } + + explicit + String( const QDateTime& qdt ) + : string_base( iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ) ) + { + } + +#endif + + // ------------------------------------------------------------------------- + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + String& operator =( const String& s ) + { + string_base::Assign( s ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + String& operator =( String&& s ) + { + string_base::Transfer( s ); + return *this; + } + + /*! + * Assigns a shallow copy of the \c string_base string \a s to this string. + * Returns a reference to this object. + */ + String& operator =( const string_base& s ) + { + string_base::Assign( s ); + return *this; + } + + /*! + * Transfers the data from the \c string_base string \a s to this string + * (move assignment from base class). Returns a reference to this object. + */ + String& operator =( string_base&& s ) + { + string_base::Transfer( s ); + return *this; + } + + /*! + * Assigns a copy of the 8-bit ISO/IEC-8859-1 string \a s to this string. + * Returns a reference to this object. + */ + String& operator =( const string8_base& s ) + { + Assign( s ); + return *this; + } + + /*! + * Assigns a copy of the null-terminated string \a t to this string. Returns + * a reference to this object. + */ + String& operator =( const_iterator t ) + { + string_base::Assign( t ); + return *this; + } + + /*! + * Assigns a single copy of a character \a c to this string. Returns a + * reference to this object. + */ + String& operator =( char_type c ) + { + string_base::Assign( c ); + return *this; + } + + /*! + * Assigns a copy of the null-terminated string \a t of \c char16_t to this + * string. Returns a reference to this object. + */ + String& operator =( const char16_t* t ) + { + string_base::Assign( reinterpret_cast( t ) ); + return *this; + } + + /*! + * Assigns a single copy of a \c char16_t character \a c to this string. + * Returns a reference to this object. + */ + String& operator =( char16_t c ) + { + string_base::Assign( char_type( c ) ); + return *this; + } + + /*! + * Assigns a copy of the null-terminated string \a t of \c wchar_t to this + * string. Returns a reference to this object. + */ + String& operator =( const wchar_t* t ) + { + Assign( t ); + return *this; + } + + /*! + * Assigns a single copy of a \c wchar_t character \a c to this string. + * Returns a reference to this object. + */ + String& operator =( wchar_t c ) + { + Assign( c ); + return *this; + } + + /*! + * Assigns a copy of the null-terminated 8-bit ISO/IEC-8859-1 string \a t to + * this string. Returns a reference to this object. + */ + String& operator =( const_c_string8 t ) + { + Assign( t ); + return *this; + } + + /*! + * Assigns a single copy of an ISO/IEC-8859-1 character \a c to this string. + * Returns a reference to this object. + */ + String& operator =( char8_type c ) + { + Assign( c ); + return *this; + } + +#ifdef __PCL_QT_INTERFACE + + String& operator =( const QString& qs ) + { + if ( qs.isEmpty() ) + Clear(); + else + string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ); + return *this; + } + + String& operator =( const QDate& qd ) + { + string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ); + return *this; + } + + String& operator =( const QDateTime& qdt ) + { + string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ); + return *this; + } + +#endif + + // ------------------------------------------------------------------------- + + /*! + * Assigns a string \a s to this string. + */ + void Assign( const String& s ) + { + string_base::Assign( s ); + } + + /*! + * Assigns a contiguous segment of \a n characters of a string \a s, + * starting from its \a i-th character, to this string. + */ + void Assign( const String& s, size_type i, size_type n ) + { + string_base::Assign( s, i, n ); + } + + /*! + * Assigns a null-terminated string \a t to this string. + */ + void Assign( const_iterator t ) + { + string_base::Assign( t ); + } + + /*! + * Assigns a sequence of characters defined by the range [i,j) to this + * string. + */ + void Assign( const_iterator i, const_iterator j ) + { + string_base::Assign( i, j ); + } + + /*! + * Assigns a sequence of characters defined by the specified initializer + * list \a l to this string. This function is equivalent to: + * + * \code Assign( l.begin(), l.end() ) \endcode + */ + void Assign( std::initializer_list l ) + { + Assign( l.begin(), l.end() ); + } + + /*! + * Assigns a contiguous segment of at most \a n characters of a + * null-terminated sequence \a t, starting from its \a i-th character, to + * this string. + */ + void Assign( const_iterator t, size_type i, size_type n ) + { + string_base::Assign( t, i, n ); + } + + /*! + * Assigns \a n copies of a character \a c to this string. + */ + void Assign( char_type c, size_type n = 1 ) + { + string_base::Assign( c, n ); + } + + /*! + * Assigns a null-terminated string \a t of \c char16_t to this string. + */ + void Assign( const char16_t* t ) + { + string_base::Assign( reinterpret_cast( t ) ); + } + + /*! + * Assigns a contiguous segment of \a n characters of a null-terminated + * string \a t of \c char16_t, starting from its \a i-th character, to this + * string. + */ + void Assign( const char16_t* t, size_type i, size_type n ) + { + string_base::Assign( reinterpret_cast( t ), i, n ); + } + + /*! + * Assigns \a n copies of a \c char16_t character \a c to this string. + */ + void Assign( char16_t c, size_type n = 1 ) + { + string_base::Assign( char_type( c ), n ); + } + + /*! + * Assigns a null-terminated string \a t of \c wchar_t to this string. + */ + void Assign( const wchar_t* t ); + + /*! + * Assigns a contiguous segment of \a n characters of a null-terminated + * string \a t of \c wchar_t, starting from its \a i-th character, to this + * string. + */ + void Assign( const wchar_t* t, size_type i, size_type n ); + + /*! + * Assigns \a n copies of a \c wchar_t character \a c to this string. + */ + void Assign( wchar_t c, size_type n = 1 ) + { + string_base::Assign( char_type( c ), n ); + } + + /*! + * Assigns a copy of the 8-bit ISO/IEC-8859-1 string \a s to this string. + */ + void Assign( const string8_base& s ) + { + size_type n = s.Length(); + if ( n > 0 ) + { + MaybeReallocate( n ); + const_char8_iterator t = s.Begin(); + PCL_IVDEP + for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) + *i = char_type( uint8( *t ) ); + } + else + Clear(); + } + + /*! + * Assigns a null-terminated 8-bit ISO/IEC-8859-1 string \a t to this + * object. + */ + void Assign( const_c_string8 t ) + { + size_type n = char8_traits::Length( t ); + if ( n > 0 ) + { + MaybeReallocate( n ); + PCL_IVDEP + for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) + *i = char_type( uint8( *t ) ); + } + else + Clear(); + } + + /*! + * Assigns a contiguous segment of \a n characters of a null-terminated + * 8-bit ISO/IEC-8859-1 string \a t, starting from its \a i-th character, to + * this string. + */ + void Assign( const_c_string8 t, size_type i, size_type n ) + { + size_type len = char8_traits::Length( t ); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + MaybeReallocate( n ); + t += i; + PCL_IVDEP + for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) + *i = char_type( uint8( *t ) ); + } + else + Clear(); + } + + /*! + * Assigns a contiguous sequence of 8-bit ISO/IEC-8859-1 characters in the + * range [i,j) to this string, replacing its previous contents. + */ + void Assign( const_char8_iterator p, const_char8_iterator q ) + { + if ( p < q ) + { + MaybeReallocate( q - p ); + PCL_IVDEP + for ( iterator i = m_data->string; i < m_data->end; ++i, ++p ) + *i = char_type( uint8( *p ) ); + } + else + Clear(); + } + + /*! + * Assigns a sequence of 8-bit ISO/IEC-8859-1 characters defined by the + * specified initializer list \a l to this string. This function is + * equivalent to: + * + * \code Assign( l.begin(), l.end() ) \endcode + */ + void Assign( std::initializer_list l ) + { + Assign( l.begin(), l.end() ); + } + + /*! + * Assigns \a n copies of an ISO/IEC-8859-1 character \a c to this string. + */ + void Assign( char8_type c, size_type n = 1 ) + { + string_base::Assign( char_type( c ), n ); + } + + // ------------------------------------------------------------------------- + + void Insert( size_type i, const String& s ) + { + string_base::Insert( i, s ); + } + + void Insert( size_type i, const_iterator p, const_iterator q ) + { + string_base::Insert( i, p, q ); + } + + void Insert( size_type i, const_iterator t ) + { + string_base::Insert( i, t ); + } + + void Insert( size_type i, const_iterator t, size_type n ) + { + string_base::Insert( i, t, n ); + } + + void Insert( size_type i, char_type c, size_type n = 1 ) + { + string_base::Insert( i, c, n ); + } + + void Insert( size_type i, const char16_t* t ) + { + string_base::Insert( i, reinterpret_cast( t ) ); + } + + void Insert( size_type i, char16_t c, size_type n = 1 ) + { + string_base::Insert( i, String( c, n ) ); + } + + void Insert( size_type i, const wchar_t* t ) + { +#ifdef __PCL_WINDOWS + string_base::Insert( i, reinterpret_cast( t ) ); +#else + string_base::Insert( i, String( t ) ); +#endif + } + + void Insert( size_type i, wchar_t c, size_type n = 1 ) + { + string_base::Insert( i, String( c, n ) ); + } + + void Insert( size_type i, const string8_base& s, size_type n ) + { + n = pcl::Min( n, s.Length() ); + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + const_char8_iterator t = s.Begin(); + PCL_IVDEP + for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) + *p = char_type( uint8( *t ) ); + } + } + + void Insert( size_type i, const string8_base& s ) + { + size_type n = s.Length(); + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + const_char8_iterator t = s.Begin(); + PCL_IVDEP + for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) + *p = char_type( uint8( *t ) ); + } + } + + void Insert( size_type i, const_c_string8 t ) + { + size_type n = char8_traits::Length( t ); + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + PCL_IVDEP + for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) + *p = char_type( uint8( *t ) ); + } + } + + void Insert( size_type i, const_c_string8 t, size_type n ) + { + n = pcl::Min( n, char8_traits::Length( t ) ); + if ( n > 0 ) + { + UninitializedGrow( i, n ); // -> 0 <= i <= len + PCL_IVDEP + for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) + *p = char_type( uint8( *t ) ); + } + } + + void Insert( size_type i, const_char8_iterator p, const_char8_iterator q ) + { + if ( p < q ) + { + size_type n = q - p; + UninitializedGrow( i, n ); // -> 0 <= i <= len + PCL_IVDEP + for ( iterator r = m_data->string+i, s = r+n; r < s; ++r, ++p ) + *r = char_type( uint8( *p ) ); + } + } + + void Insert( size_type i, char8_type c, size_type n = 1 ) + { + string_base::Insert( i, char_type( c ), n ); + } + + // ------------------------------------------------------------------------- + + void Append( const String& s ) + { + string_base::Append( s ); + } + + String& operator +=( const String& s ) + { + Append( s ); + return *this; + } + + void Append( const_iterator i, const_iterator j ) + { + string_base::Append( i, j ); + } + + void Append( const_iterator t ) + { + string_base::Append( t ); + } + + String& operator +=( const_iterator t ) + { + Append( t ); + return *this; + } + + void Append( const_iterator t, size_type n ) + { + string_base::Append( t, n ); + } + + void Append( char_type c, size_type n = 1 ) + { + string_base::Append( c, n ); + } + + String& operator +=( char_type c ) + { + Append( c ); + return *this; + } + + void Append( const char16_t* t ) + { + string_base::Append( reinterpret_cast( t ) ); + } + + String& operator +=( const char16_t* t ) + { + Append( t ); + return *this; + } + + void Append( char16_t c, size_type n = 1 ) + { + string_base::Append( char_type( c ), n ); + } + + String& operator +=( char16_t c ) + { + Append( c ); + return *this; + } + + void Append( const wchar_t* t ) + { +#ifdef __PCL_WINDOWS + string_base::Append( reinterpret_cast( t ) ); +#else + string_base::Append( String( t ) ); +#endif + } + + String& operator +=( const wchar_t* t ) + { + Append( t ); + return *this; + } + + void Append( wchar_t c, size_type n = 1 ) + { + string_base::Append( char_type( c ), n ); + } + + String& operator +=( wchar_t c ) + { + Append( c ); + return *this; + } + + void Append( const string8_base& s ) + { + Insert( maxPos, s ); + } + + String& operator +=( const string8_base& s ) + { + Append( s ); + return *this; + } + + void Append( const string8_base& s, size_type n ) + { + Insert( maxPos, s, n ); + } + + void Append( const_c_string8 t ) + { + Insert( maxPos, t ); + } + + String& operator +=( const_c_string8 t ) + { + Append( t ); + return *this; + } + + void Append( const_c_string8 t, size_type n ) + { + Insert( maxPos, t, n ); + } + + void Append( const_char8_iterator p, const_char8_iterator q ) + { + Insert( maxPos, p, q ); + } + + void Append( char8_type c, size_type n = 1 ) + { + string_base::Append( char_type( c ), n ); + } + + String& operator +=( char8_type c ) + { + Append( c ); + return *this; + } + + void Add( const String& s ) + { + Append( s ); + } + + void Add( const_iterator i, const_iterator j ) + { + Append( i, j ); + } + + void Add( const_iterator t ) + { + Append( t ); + } + + void Add( const_iterator t, size_type n ) + { + Append( t, n ); + } + + void Add( char_type c, size_type n = 1 ) + { + Append( c, n ); + } + + void Add( const char16_t* t ) + { + Append( t ); + } + + void Add( char16_t c, size_type n = 1 ) + { + Append( c, n ); + } + + void Add( const wchar_t* t ) + { + Append( t ); + } + + void Add( wchar_t c, size_type n = 1 ) + { + Append( c, n ); + } + + void Add( const string8_base& s ) + { + Append( s ); + } + + void Add( const string8_base& s, size_type n ) + { + Append( s, n ); + } + + void Add( const_c_string8 t ) + { + Append( t ); + } + + void Add( const_c_string8 t, size_type n ) + { + Append( t, n ); + } + + void Add( const_char8_iterator p, const_char8_iterator q ) + { + Append( p, q ); + } + + void Add( char8_type c, size_type n = 1 ) + { + Append( c, n ); + } + + // ------------------------------------------------------------------------- + + void Prepend( const String& s ) + { + string_base::Prepend( s ); + } + + String& operator -=( const String& s ) + { + Prepend( s ); + return *this; + } + + void Prepend( const_iterator i, const_iterator j ) + { + string_base::Prepend( i, j ); + } + + void Prepend( const_iterator t ) + { + string_base::Prepend( t ); + } + + String& operator -=( const_iterator t ) + { + Prepend( t ); + return *this; + } + + void Prepend( const_iterator t, size_type n ) + { + string_base::Prepend( t, n ); + } + + void Prepend( char_type c, size_type n = 1 ) + { + string_base::Prepend( c, n ); + } + + String& operator -=( char_type c ) + { + Prepend( c ); + return *this; + } + + void Prepend( const char16_t* t ) + { + string_base::Prepend( reinterpret_cast( t ) ); + } + + String& operator -=( const char16_t* t ) + { + Prepend( t ); + return *this; + } + + void Prepend( char16_t c, size_type n = 1 ) + { + string_base::Prepend( char_type( c ), n ); + } + + String& operator -=( char16_t c ) + { + Prepend( c ); + return *this; + } + + void Prepend( const wchar_t* t ) + { +#ifdef __PCL_WINDOWS + string_base::Prepend( reinterpret_cast( t ) ); +#else + string_base::Prepend( String( t ) ); +#endif + } + + String& operator -=( const wchar_t* t ) + { + Prepend( t ); + return *this; + } + + void Prepend( wchar_t c, size_type n = 1 ) + { + string_base::Prepend( char_type( c ), n ); + } + + String& operator -=( wchar_t c ) + { + Prepend( c ); + return *this; + } + + void Prepend( const string8_base& s ) + { + Insert( 0, s ); + } + + String& operator -=( const string8_base& s ) + { + Prepend( s ); + return *this; + } + + void Prepend( const string8_base& s, size_type n ) + { + Insert( 0, s, n ); + } + + void Prepend( const_c_string8 t ) + { + Insert( 0, t ); + } + + String& operator -=( const_c_string8 t ) + { + Prepend( t ); + return *this; + } + + void Prepend( const_c_string8 t, size_type n ) + { + Insert( 0, t, n ); + } + + void Prepend( const_char8_iterator p, const_char8_iterator q ) + { + Insert( 0, p, q ); + } + + void Prepend( char8_type c, size_type n = 1 ) + { + string_base::Prepend( String( c, n ) ); + } + + String& operator -=( char8_type c ) + { + Prepend( c ); + return *this; + } + + // ------------------------------------------------------------------------- + + void Replace( size_type i, size_type n, const String& s ) + { + string_base::Replace( i, n, s ); + } + + void Replace( size_type i, size_type n, const_iterator t ) + { + string_base::Replace( i, n, t ); + } + + void Replace( size_type i, size_type n, char_type c, size_type nc = 1 ) + { + string_base::Replace( i, n, c, nc ); + } + + void Replace( size_type i, size_type n, const char16_t* t ) + { + string_base::Replace( i, n, reinterpret_cast( t ) ); + } + + void Replace( size_type i, size_type n, char16_t c, size_type nc = 1 ) + { + string_base::Replace( i, n, char_type( c ), nc ); + } + + void Replace( size_type i, size_type n, const wchar_t* t ) + { +#ifdef __PCL_WINDOWS + string_base::Replace( i, n, reinterpret_cast( t ) ); +#else + string_base::Replace( i, n, String( t ) ); +#endif + } + + void Replace( size_type i, size_type n, wchar_t c, size_type nc = 1 ) + { + string_base::Replace( i, n, char_type( c ), nc ); + } + + void Replace( size_type i, size_type n, const_c_string8 t ) + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + if ( n == len ) + Assign( t ); + else + { + size_type nt = char8_traits::Length( t ); + if ( nt > 0 ) + { + if ( n < nt ) + UninitializedGrow( i, nt-n ); + else if ( nt < n ) + Delete( i, n-nt ); + else + EnsureUnique(); + + PCL_IVDEP + for ( iterator p = m_data->string+i, q = p+nt; p < q; ++p, ++t ) + *p = char_type( *t ); + } + else + Delete( i, n ); + } + } + } + } + + void Replace( size_type i, size_type n, char8_type c, size_type nc = 1 ) + { + string_base::Replace( i, n, char_type( c ), nc ); + } + + // ------------------------------------------------------------------------- + + void ReplaceChar( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceChar( c1, c2, i, n ); + } + + void ReplaceCharIC( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceCharIC( c1, c2, i, n ); + } + + void ReplaceChar( char16_t c1, char16_t c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n ); + } + + void ReplaceCharIC( char16_t c1, char16_t c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n ); + } + + void ReplaceChar( wchar_t c1, wchar_t c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n ); + } + + void ReplaceCharIC( wchar_t c1, wchar_t c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n ); + } + + void ReplaceChar( char8_type c1, char8_type c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n ); + } + + void ReplaceCharIC( char8_type c1, char8_type c2, size_type i = 0, size_type n = maxPos ) + { + string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n ); + } + + // ------------------------------------------------------------------------- + + void ReplaceString( const String& s1, const String& s2, size_type i = 0 ) + { + string_base::ReplaceString( s1, s2, i ); + } + + void ReplaceStringIC( const String& s1, const String& s2, size_type i = 0 ) + { + string_base::ReplaceStringIC( s1, s2, i ); + } + + void ReplaceString( const_iterator t1, const_iterator t2, size_type i = 0 ) + { + string_base::ReplaceString( t1, t2, i ); + } + + void ReplaceStringIC( const_iterator t1, const_iterator t2, size_type i = 0 ) + { + string_base::ReplaceStringIC( t1, t2, i ); + } + + void ReplaceString( const char16_t* t1, const char16_t* t2, size_type i = 0 ) + { + string_base::ReplaceString( reinterpret_cast( t1 ), + reinterpret_cast( t2 ), i ); + } + + void ReplaceStringIC( const char16_t* t1, const char16_t* t2, size_type i = 0 ) + { + string_base::ReplaceStringIC( reinterpret_cast( t1 ), + reinterpret_cast( t2 ), i ); + } + + void ReplaceString( const wchar_t* t1, const wchar_t* t2, size_type i = 0 ) + { +#ifdef __PCL_WINDOWS + string_base::ReplaceString( reinterpret_cast( t1 ), + reinterpret_cast( t2 ), i ); +#else + string_base::ReplaceString( String( t1 ), String( t2 ), i ); +#endif + } + + void ReplaceStringIC( const wchar_t* t1, const wchar_t* t2, size_type i = 0 ) + { +#ifdef __PCL_WINDOWS + string_base::ReplaceStringIC( reinterpret_cast( t1 ), + reinterpret_cast( t2 ), i ); +#else + string_base::ReplaceStringIC( String( t1 ), String( t2 ), i ); +#endif + } + + void ReplaceString( const_c_string8 t1, const_c_string8 t2, size_type i = 0 ) + { + string_base::ReplaceString( String( t1 ), String( t2 ), i ); + } + + void ReplaceStringIC( const_c_string8 t1, const_c_string8 t2, size_type i = 0 ) + { + string_base::ReplaceStringIC( String( t1 ), String( t2 ), i ); + } + + // ------------------------------------------------------------------------- + + void DeleteChar( char_type c, size_type i = 0 ) + { + string_base::DeleteChar( c, i ); + } + + void DeleteCharIC( char_type c, size_type i = 0 ) + { + string_base::DeleteCharIC( c, i ); + } + + void DeleteChar( char16_t c, size_type i = 0 ) + { + string_base::DeleteChar( char_type( c ), i ); + } + + void DeleteCharIC( char16_t c, size_type i = 0 ) + { + string_base::DeleteCharIC( char_type( c ), i ); + } + + void DeleteChar( wchar_t c, size_type i = 0 ) + { + string_base::DeleteChar( char_type( c ), i ); + } + + void DeleteCharIC( wchar_t c, size_type i = 0 ) + { + string_base::DeleteCharIC( char_type( c ), i ); + } + + void DeleteChar( char8_type c, size_type i = 0 ) + { + string_base::DeleteChar( char_type( c ), i ); + } + + void DeleteCharIC( char8_type c, size_type i = 0 ) + { + string_base::DeleteCharIC( char_type( c ), i ); + } + + // ------------------------------------------------------------------------- + + void DeleteString( const String& s, size_type i = 0 ) + { + string_base::DeleteString( s, i ); + } + + void DeleteStringIC( const String& s, size_type i = 0 ) + { + string_base::DeleteStringIC( s, i ); + } + + void DeleteString( const_iterator t, size_type i = 0 ) + { + string_base::DeleteString( t, i ); + } + + void DeleteStringIC( const_iterator t, size_type i = 0 ) + { + string_base::DeleteStringIC( t, i ); + } + + void DeleteString( const char16_t* t, size_type i = 0 ) + { + string_base::DeleteString( reinterpret_cast( t ), i ); + } + + void DeleteStringIC( const char16_t* t, size_type i = 0 ) + { + string_base::DeleteStringIC( reinterpret_cast( t ), i ); + } + + void DeleteString( const wchar_t* t, size_type i = 0 ) + { +#ifdef __PCL_WINDOWS + string_base::DeleteString( reinterpret_cast( t ), i ); +#else + string_base::DeleteString( String( t ), i ); +#endif + } + + void DeleteStringIC( const wchar_t* t, size_type i = 0 ) + { +#ifdef __PCL_WINDOWS + string_base::DeleteStringIC( reinterpret_cast( t ), i ); +#else + string_base::DeleteStringIC( String( t ), i ); +#endif + } + + void DeleteString( const_c_string8 t, size_type i = 0 ) + { + string_base::DeleteString( String( t ), i ); + } + + void DeleteStringIC( const_c_string8 t, size_type i = 0 ) + { + string_base::DeleteStringIC( String( t ), i ); + } + + // ------------------------------------------------------------------------- + + bool StartsWith( const String& s ) const noexcept + { + return string_base::StartsWith( s ); + } + + bool StartsWith( const_iterator t ) const noexcept + { + return string_base::StartsWith( t ); + } + + bool StartsWith( char_type c ) const noexcept + { + return string_base::StartsWith( c ); + } + + bool StartsWithIC( const String& s ) const noexcept + { + return string_base::StartsWithIC( s ); + } + + bool StartsWithIC( const_iterator t ) const noexcept + { + return string_base::StartsWithIC( t ); + } + + bool StartsWithIC( char_type c ) const noexcept + { + return string_base::StartsWithIC( c ); + } + + bool StartsWith( const char16_t* t ) const noexcept + { + return string_base::StartsWith( reinterpret_cast( t ) ); + } + + bool StartsWith( char16_t c ) const noexcept + { + return string_base::StartsWith( char_type( c ) ); + } + + bool StartsWithIC( const char16_t* t ) const noexcept + { + return string_base::StartsWithIC( reinterpret_cast( t ) ); + } + + bool StartsWithIC( char16_t c ) const noexcept + { + return string_base::StartsWithIC( char_type( c ) ); + } + + bool StartsWith( const wchar_t* t ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::StartsWith( reinterpret_cast( t ) ); +#else + return string_base::StartsWith( String( t ) ); +#endif + } + + bool StartsWith( wchar_t c ) const noexcept + { + return string_base::StartsWith( char_type( c ) ); + } + + bool StartsWithIC( const wchar_t* t ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::StartsWithIC( reinterpret_cast( t ) ); +#else + return string_base::StartsWithIC( String( t ) ); +#endif + } + + bool StartsWithIC( wchar_t c ) const noexcept + { + return string_base::StartsWithIC( char_type( c ) ); + } + + bool StartsWith( const_c_string8 t ) const noexcept + { + size_type n = char8_traits::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->string, q = p+n; p < q; ++p, ++t ) + if ( *p != char_type( *t ) ) + return false; + return true; + } + + bool StartsWith( char8_type c ) const noexcept + { + return string_base::StartsWith( char_type( c ) ); + } + + bool StartsWithIC( const_c_string8 t ) const noexcept + { + size_type n = char8_traits::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->string, q = p+n; p < q; ++p, ++t ) + if ( char_traits::ToCaseFolded( *p ) != char_type( char8_traits::ToCaseFolded( *t ) ) ) + return false; + return true; + } + + bool StartsWithIC( char8_type c ) const noexcept + { + return string_base::StartsWithIC( char_type( c ) ); + } + + // ------------------------------------------------------------------------- + + bool EndsWith( const String& s ) const noexcept + { + return string_base::EndsWith( s ); + } + + bool EndsWith( const_iterator t ) const noexcept + { + return string_base::EndsWith( t ); + } + + bool EndsWith( char_type c ) const noexcept + { + return string_base::EndsWith( c ); + } + + bool EndsWithIC( const String& s ) const noexcept + { + return string_base::EndsWithIC( s ); + } + + bool EndsWithIC( const_iterator t ) const noexcept + { + return string_base::EndsWithIC( t ); + } + + bool EndsWithIC( char_type c ) const noexcept + { + return string_base::EndsWithIC( c ); + } + + bool EndsWith( const char16_t* t ) const noexcept + { + return string_base::EndsWith( reinterpret_cast( t ) ); + } + + bool EndsWith( char16_t c ) const noexcept + { + return string_base::EndsWith( char_type( c ) ); + } + + bool EndsWithIC( const char16_t* t ) const noexcept + { + return string_base::EndsWithIC( reinterpret_cast( t ) ); + } + + bool EndsWithIC( char16_t c ) const noexcept + { + return string_base::EndsWithIC( char_type( c ) ); + } + + bool EndsWith( const wchar_t* t ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::EndsWith( reinterpret_cast( t ) ); +#else + return string_base::EndsWith( String( t ) ); +#endif + } + + bool EndsWith( wchar_t c ) const noexcept + { + return string_base::EndsWith( char_type( c ) ); + } + + bool EndsWithIC( const wchar_t* t ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::EndsWithIC( reinterpret_cast( t ) ); +#else + return string_base::EndsWithIC( String( t ) ); +#endif + } + + bool EndsWithIC( wchar_t c ) const noexcept + { + return string_base::EndsWithIC( char_type( c ) ); + } + + bool EndsWith( const_c_string8 t ) const noexcept + { + size_type n = char8_traits::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) + if ( *p != char_type( *t ) ) + return false; + return true; + } + + bool EndsWith( char8_type c ) const noexcept + { + return string_base::EndsWith( char_type( c ) ); + } + + bool EndsWithIC( const_c_string8 t ) const noexcept + { + size_type n = char8_traits::Length( t ); + if ( n == 0 || Length() < n ) + return false; + for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) + if ( char_traits::ToCaseFolded( *p ) != char_type( char8_traits::ToCaseFolded( *t ) ) ) + return false; + return true; + } + + bool EndsWithIC( char8_type c ) const noexcept + { + return string_base::EndsWithIC( char_type( c ) ); + } + + // ------------------------------------------------------------------------- + + size_type FindFirst( const String& s, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( s, i ); + } + + size_type FindFirst( const_iterator t, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( t, i ); + } + + size_type FindFirst( char_type c, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( c, i ); + } + + size_type FindFirstIC( const String& s, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( s, i ); + } + + size_type FindFirstIC( const_iterator t, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( t, i ); + } + + size_type FindFirstIC( char_type c, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( c, i ); + } + + size_type FindFirst( const char16_t* t, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( reinterpret_cast( t ), i ); + } + + size_type FindFirst( char16_t c, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( char_type( c ), i ); + } + + size_type FindFirstIC( const char16_t* t, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( reinterpret_cast( t ), i ); + } + + size_type FindFirstIC( char16_t c, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( char_type( c ), i ); + } + + size_type FindFirst( const wchar_t* t, size_type i = 0 ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::FindFirst( reinterpret_cast( t ), i ); +#else + return string_base::FindFirst( String( t ), i ); +#endif + } + + size_type FindFirst( wchar_t c, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( char_type( c ), i ); + } + + size_type FindFirstIC( const wchar_t* t, size_type i = 0 ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::FindFirstIC( reinterpret_cast( t ), i ); +#else + return string_base::FindFirstIC( String( t ), i ); +#endif + } + + size_type FindFirstIC( wchar_t c, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( char_type( c ), i ); + } + + size_type FindFirst( const_c_string8 t, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( String( t ), i ); + } + + size_type FindFirst( char8_type c, size_type i = 0 ) const noexcept + { + return string_base::FindFirst( char_type( c ), i ); + } + + size_type FindFirstIC( const_c_string8 t, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( String( t ), i ); + } + + size_type FindFirstIC( char8_type c, size_type i = 0 ) const noexcept + { + return string_base::FindFirstIC( char_type( c ), i ); + } + + // + + size_type Find( const String& s, size_type i = 0 ) const noexcept + { + return FindFirst( s, i ); + } + + size_type Find( const_iterator t, size_type i = 0 ) const noexcept + { + return FindFirst( t, i ); + } + + size_type Find( char_type c, size_type i = 0 ) const noexcept + { + return FindFirst( c, i ); + } + + size_type Find( const char16_t* t, size_type i = 0 ) const noexcept + { + return FindFirst( t, i ); + } + + size_type Find( char16_t c, size_type i = 0 ) const noexcept + { + return FindFirst( c, i ); + } + + size_type Find( const wchar_t* t, size_type i = 0 ) const noexcept + { + return FindFirst( t, i ); + } + + size_type Find( wchar_t c, size_type i = 0 ) const noexcept + { + return FindFirst( c, i ); + } + + size_type Find( const_c_string8 t, size_type i = 0 ) const noexcept + { + return FindFirst( t, i ); + } + + size_type Find( char8_type c, size_type i = 0 ) const noexcept + { + return FindFirst( c, i ); + } + + size_type FindIC( const String& s, size_type i = 0 ) const noexcept + { + return FindFirstIC( s, i ); + } + + size_type FindIC( const_iterator t, size_type i = 0 ) const noexcept + { + return FindFirstIC( t, i ); + } + + size_type FindIC( char_type c, size_type i = 0 ) const noexcept + { + return FindFirstIC( c, i ); + } + + size_type FindIC( const char16_t* t, size_type i = 0 ) const noexcept + { + return FindFirstIC( t, i ); + } + + size_type FindIC( char16_t c, size_type i = 0 ) const noexcept + { + return FindFirstIC( c, i ); + } + + size_type FindIC( const wchar_t* t, size_type i = 0 ) const noexcept + { + return FindFirstIC( t, i ); + } + + size_type FindIC( wchar_t c, size_type i = 0 ) const noexcept + { + return FindFirstIC( c, i ); + } + + size_type FindIC( const_c_string8 t, size_type i = 0 ) const noexcept + { + return FindFirstIC( t, i ); + } + + size_type FindIC( char8_type c, size_type i = 0 ) const noexcept + { + return FindFirstIC( c, i ); + } + + // ------------------------------------------------------------------------- + + size_type FindLast( const String& s, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( s, r ); + } + + size_type FindLast( const_iterator t, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( t, r ); + } + + size_type FindLast( char_type c, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( c, r ); + } + + size_type FindLastIC( const String& s, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( s, r ); + } + + size_type FindLastIC( const_iterator t, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( t, r ); + } + + size_type FindLastIC( char_type c, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( c, r ); + } + + size_type FindLast( const char16_t* t, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( reinterpret_cast( t ), r ); + } + + size_type FindLast( char16_t c, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( char_type( c ), r ); + } + + size_type FindLastIC( const char16_t* t, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( reinterpret_cast( t ), r ); + } + + size_type FindLastIC( char16_t c, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( char_type( c ), r ); + } + + size_type FindLast( const wchar_t* t, size_type r = maxPos ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::FindLast( reinterpret_cast( t ), r ); +#else + return string_base::FindLast( String( t ), r ); +#endif + } + + size_type FindLast( wchar_t c, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( char_type( c ), r ); + } + + size_type FindLastIC( const wchar_t* t, size_type r = maxPos ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::FindLastIC( reinterpret_cast( t ), r ); +#else + return string_base::FindLastIC( String( t ), r ); +#endif + } + + size_type FindLastIC( wchar_t c, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( char_type( c ), r ); + } + + size_type FindLast( const_c_string8 t, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( String( t ), r ); + } + + size_type FindLast( char8_type c, size_type r = maxPos ) const noexcept + { + return string_base::FindLast( char_type( c ), r ); + } + + size_type FindLastIC( const_c_string8 t, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( String( t ), r ); + } + + size_type FindLastIC( char8_type c, size_type r = maxPos ) const noexcept + { + return string_base::FindLastIC( char_type( c ), r ); + } + + // ------------------------------------------------------------------------- + + bool Contains( const String& s ) const noexcept + { + return string_base::Contains( s ); + } + + bool Contains( const_iterator t ) const noexcept + { + return string_base::Contains( t ); + } + + bool Contains( char_type c ) const noexcept + { + return string_base::Contains( c ); + } + + bool ContainsIC( const String& s ) const noexcept + { + return string_base::ContainsIC( s ); + } + + bool ContainsIC( const_iterator t ) const noexcept + { + return string_base::ContainsIC( t ); + } + + bool ContainsIC( char_type c ) const noexcept + { + return string_base::ContainsIC( c ); + } + + bool Contains( const char16_t* t ) const noexcept + { + return string_base::Contains( reinterpret_cast( t ) ); + } + + bool Contains( char16_t c ) const noexcept + { + return string_base::Contains( char_type( c ) ); + } + + bool ContainsIC( const char16_t* t ) const noexcept + { + return string_base::ContainsIC( reinterpret_cast( t ) ); + } + + bool ContainsIC( char16_t c ) const noexcept + { + return string_base::ContainsIC( char_type( c ) ); + } + + bool Contains( const wchar_t* t ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::Contains( reinterpret_cast( t ) ); +#else + return string_base::Contains( String( t ) ); +#endif + } + + bool Contains( wchar_t c ) const noexcept + { + return string_base::Contains( char_type( c ) ); + } + + bool ContainsIC( const wchar_t* t ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::ContainsIC( reinterpret_cast( t ) ); +#else + return string_base::ContainsIC( String( t ) ); +#endif + } + + bool ContainsIC( wchar_t c ) const noexcept + { + return string_base::ContainsIC( char_type( c ) ); + } + + bool Contains( const_c_string8 t ) const noexcept + { + return string_base::Contains( String( t ) ); + } + + bool Contains( char8_type c ) const noexcept + { + return string_base::Contains( char_type( c ) ); + } + + bool ContainsIC( const_c_string8 t ) const noexcept + { + return string_base::ContainsIC( String( t ) ); + } + + bool ContainsIC( char8_type c ) const noexcept + { + return string_base::ContainsIC( char_type( c ) ); + } + + // ------------------------------------------------------------------------- + + int CompareCodePoints( const String& s, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( s, caseSensitive ); + } + + int CompareCodePoints( const_iterator t, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( t, caseSensitive ); + } + + int CompareCodePoints( char_type c, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( c, caseSensitive ); + } + + int CompareCodePoints( const char16_t* t, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( reinterpret_cast( t ), caseSensitive ); + } + + int CompareCodePoints( char16_t c, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( char_type( c ), caseSensitive ); + } + + int CompareCodePoints( const wchar_t* t, bool caseSensitive = true ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::CompareCodePoints( reinterpret_cast( t ), caseSensitive ); +#else + return string_base::CompareCodePoints( String( t ), caseSensitive ); +#endif + } + + int CompareCodePoints( wchar_t c, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( char_type( c ), caseSensitive ); + } + + int CompareCodePoints( const_c_string8 t, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( String( t ), caseSensitive ); + } + + int CompareCodePoints( char8_type c, bool caseSensitive = true ) const noexcept + { + return string_base::CompareCodePoints( char_type( c ), caseSensitive ); + } + + // ------------------------------------------------------------------------- + + int Compare( const String& s, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( s, caseSensitive, localeAware ); + } + + int Compare( const_iterator t, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( t, caseSensitive, localeAware ); + } + + int Compare( char_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( c, caseSensitive, localeAware ); + } + + int CompareIC( const String& s, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( s, localeAware ); + } + + int CompareIC( const_iterator t, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( t, localeAware ); + } + + int CompareIC( char_type c, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( c, localeAware ); + } + + int Compare( const char16_t* t, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( reinterpret_cast( t ), caseSensitive, localeAware ); + } + + int Compare( char16_t c, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( char_type( c ), caseSensitive, localeAware ); + } + + int CompareIC( const char16_t* t, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( reinterpret_cast( t ), localeAware ); + } + + int CompareIC( char16_t c, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( char_type( c ), localeAware ); + } + + int Compare( const wchar_t* t, bool caseSensitive = true, bool localeAware = true ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::Compare( reinterpret_cast( t ), caseSensitive, localeAware ); +#else + return string_base::Compare( String( t ), caseSensitive, localeAware ); +#endif + } + + int Compare( wchar_t c, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( char_type( c ), caseSensitive, localeAware ); + } + + int CompareIC( const wchar_t* t, bool localeAware = true ) const noexcept + { +#ifdef __PCL_WINDOWS + return string_base::CompareIC( reinterpret_cast( t ), localeAware ); +#else + return string_base::CompareIC( String( t ), localeAware ); +#endif + } + + int CompareIC( wchar_t c, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( char_type( c ), localeAware ); + } + + int Compare( const_c_string8 t, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( String( t ), caseSensitive, localeAware ); + } + + int Compare( char8_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept + { + return string_base::Compare( char_type( c ), caseSensitive, localeAware ); + } + + int CompareIC( const_c_string8 t, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( String( t ), localeAware ); + } + + int CompareIC( char8_type c, bool localeAware = true ) const noexcept + { + return string_base::CompareIC( char_type( c ), localeAware ); + } + + // ------------------------------------------------------------------------- + + bool WildMatch( const String& pattern, bool caseSensitive = true ) const noexcept + { + return string_base::WildMatch( pattern, caseSensitive ); + } + + bool WildMatchIC( const String& pattern ) const noexcept + { + return string_base::WildMatchIC( pattern ); + } + + bool WildMatch( const_iterator pattern, bool caseSensitive = true ) const noexcept + { + return string_base::WildMatch( pattern, caseSensitive ); + } + + bool WildMatchIC( const_iterator pattern ) const noexcept + { + return string_base::WildMatchIC( pattern ); + } + + bool WildMatch( const string8_base& pattern, bool caseSensitive = true ) const noexcept + { + return char_traits::WildMatch( m_data->string, Length(), pattern.Begin(), pattern.Length(), caseSensitive ); + } + + bool WildMatchIC( const string8_base& pattern ) const noexcept + { + return char_traits::WildMatch( m_data->string, Length(), pattern.Begin(), pattern.Length(), false/*caseSensitive*/ ); + } + + bool WildMatch( const_c_string8 pattern, bool caseSensitive = true ) const noexcept + { + return char_traits::WildMatch( m_data->string, Length(), pattern, char8_traits::Length( pattern ), caseSensitive ); + } + + bool WildMatchIC( const_c_string8 pattern ) const noexcept + { + return char_traits::WildMatch( m_data->string, Length(), pattern, char8_traits::Length( pattern ), false/*caseSensitive*/ ); + } + + // ------------------------------------------------------------------------- + + String SetToLength( size_type n ) const + { + return string_base::SetToLength( n ); + } + + String ResizedToNullTerminated() const + { + return string_base::ResizedToNullTerminated(); + } + + String Squeezed() const + { + return string_base::Squeezed(); + } + + // ------------------------------------------------------------------------- + + String Substring( size_type i, size_type n = maxPos ) const + { + return string_base::Substring( i, n ); + } + + String Left( size_type n ) const + { + return string_base::Left( n ); + } + + String Right( size_type n ) const + { + return string_base::Right( n ); + } + + String Suffix( size_type i ) const + { + return string_base::Suffix( i ); + } + + String Prefix( size_type i ) const + { + return string_base::Prefix( i ); + } + + // ------------------------------------------------------------------------- + + template + size_type Break( C& list, const String& s, bool trim = false, size_type i = 0 ) const + { + return string_base::Break( list, s, trim, i ); + } + + template + size_type Break( C& list, const string8_base& s, bool trim = false, size_type i = 0 ) const + { + return string_base::Break( list, String( s ), trim, i ); + } + + template + size_type Break( C& list, const_c_string8 s, bool trim = false, size_type i = 0 ) const + { + return string_base::Break( list, String( s ), trim, i ); + } + + template + size_type Break( C& list, char_type c, bool trim = false, size_type i = 0 ) const + { + return string_base::Break( list, c, trim, i ); + } + + template + size_type Break( C& list, char8_type c, bool trim = false, size_type i = 0 ) const + { + return string_base::Break( list, char_type( c ), trim, i ); + } + + template + size_type Break( C& list, const Array& ca, bool trim = false, size_type i = 0 ) const + { + return string_base::Break( list, ca, trim, i ); + } + + // ------------------------------------------------------------------------- + + template + size_type BreakIC( C& list, const String& s, bool trim = false, size_type i = 0 ) const + { + return string_base::BreakIC( list, s, trim, i ); + } + + template + size_type BreakIC( C& list, const string8_base& s, bool trim = false, size_type i = 0 ) const + { + return string_base::BreakIC( list, String( s ), trim, i ); + } + + template + size_type BreakIC( C& list, const_c_string8 s, bool trim = false, size_type i = 0 ) const + { + return string_base::BreakIC( list, String( s ), trim, i ); + } + + template + size_type BreakIC( C& list, char_type c, bool trim = false, size_type i = 0 ) const + { + return string_base::BreakIC( list, c, trim, i ); + } + + template + size_type BreakIC( C& list, char8_type c, bool trim = false, size_type i = 0 ) const + { + return string_base::BreakIC( list, char_type( c ), trim, i ); + } + + // ------------------------------------------------------------------------- + + String Trimmed() const + { + return string_base::Trimmed(); + } + + String TrimmedLeft() const + { + return string_base::TrimmedLeft(); + } + + String TrimmedRight() const + { + return string_base::TrimmedRight(); + } + + // ------------------------------------------------------------------------- + + String LeftJustified( size_type width, char_type fill = CharTraits::Blank() ) const + { + return string_base::LeftJustified( width, fill ); + } + + String RightJustified( size_type width, char_type fill = CharTraits::Blank() ) const + { + return string_base::RightJustified( width, fill ); + } + + String CenterJustified( size_type width, char_type fill = CharTraits::Blank() ) const + { + return string_base::CenterJustified( width, fill ); + } + + // ------------------------------------------------------------------------- + + String Enclosed( char_type c ) const + { + return string_base::Enclosed( c ); + } + + String SingleQuoted() const + { + return string_base::SingleQuoted(); + } + + String DoubleQuoted() const + { + return string_base::DoubleQuoted(); + } + + String Unquoted() const + { + return string_base::Unquoted(); + } + + // ------------------------------------------------------------------------- + + String CaseFolded() const + { + return string_base::CaseFolded(); + } + + String Lowercase() const + { + return string_base::Lowercase(); + } + + String Uppercase() const + { + return string_base::Uppercase(); + } + + // ------------------------------------------------------------------------- + + String Reversed() const + { + return string_base::Reversed(); + } + + String Sorted() const + { + return string_base::Sorted(); + } + + template + String Sorted( BP p ) const + { + return string_base::Sorted( p ); + } + + // ------------------------------------------------------------------------- + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * character. Returns a reference to this string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, char_type separator ) + { + Clear(); + return c.ToSeparated( *this, separator ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * character, and built using an \a append binary function. Returns a + * reference to this string. + * + * The binary function must be of the form: + * + * \code void append( String& s, char16_type c ); \endcode + * + * where \a c is being appended to \a s. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, char_type separator, AF append ) + { + Clear(); + return c.ToSeparated( *this, separator, append ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator string. + * Returns a reference to this string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, const String& separator ) + { + Clear(); + return c.ToSeparated( *this, separator ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator string, + * and built using an \a append binary function. Returns a reference to this + * string. + * + * The binary function must be of the form: + * + * \code void append( String& s1, const String& s2 ); \endcode + * + * where \a s2 is being appended to \a s1. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, const String& separator, AF append ) + { + Clear(); + return c.ToSeparated( *this, separator, append ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * null-terminated string. Returns a reference to this string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, const_c_string separator ) + { + return ToSeparated( c, String( separator ) ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * null-terminated string, and built using an \a append binary function. + * Returns a reference to this string. + * + * The binary function must be of the form: + * + * \code void append( String& s1, const char16_type* s2 ); \endcode + * + * where \a s2 is being appended to \a s1. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, const_c_string separator, AF append ) + { + return ToSeparated( c, String( separator ), append ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * null-terminated 8-bit string (const char*). Returns a reference to this + * string. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, const_c_string8 separator ) + { + return ToSeparated( c, String( separator ) ); + } + + /*! + * Replaces the contents of this string with a sequence of tokens extracted + * from a container \a c, separated with the specified \a separator + * null-terminated 8-bit string (const char*), and built using an \a append + * binary function. Returns a reference to this string. + * + * The binary function must be of the form: + * + * \code void append( String& s1, const char* s2 ); \endcode + * + * where \a s2 is being appended to \a s1. + * + * The container type C must have separated list generation semantics. All + * iterable PCL containers such as Array, Vector, etc. provide the necessary + * ToSeparated member functions. + */ + template + String& ToSeparated( const C& c, const_c_string8 separator, AF append ) + { + return ToSeparated( c, String( separator ), append ); + } + + /*! + * Replaces the contents of this string with a sequence of comma-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( ',' ) ); \endcode + */ + template + String& ToCommaSeparated( const C& c ) + { + return ToSeparated( c, CharTraits::Comma() ); + } + + /*! + * Replaces the contents of this string with a sequence of colon-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( ':' ) ); \endcode + */ + template + String& ToColonSeparated( const C& c ) + { + return ToSeparated( c, CharTraits::Colon() ); + } + + /*! + * Replaces the contents of this string with a sequence of space-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( ' ' ) ); \endcode + */ + template + String& ToSpaceSeparated( const C& c ) + { + return ToSeparated( c, CharTraits::Blank() ); + } + + /*! + * Replaces the contents of this string with a sequence of + * tabulator-separated tokens extracted from a container \a c. Returns a + * reference to this string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( '\t' ) ); \endcode + */ + template + String& ToTabSeparated( const C& c ) + { + return ToSeparated( c, CharTraits::Tab() ); + } + + /*! + * Replaces the contents of this string with a sequence of new line + * separated tokens extracted from a container \a c. Returns a reference to + * this string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( '\n' ) ); \endcode + */ + template + String& ToNewLineSeparated( const C& c ) + { + return ToSeparated( c, CharTraits::LF() ); + } + + /*! + * Replaces the contents of this string with a sequence of null-separated + * tokens extracted from a container \a c. Returns a reference to this + * string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( '\0' ) ); \endcode + */ + template + String& ToNullSeparated( const C& c ) + { + return ToSeparated( c, CharTraits::Null() ); + } + + /*! + * Replaces the contents of this string with a hyphenated sequence of tokens + * extracted from a container \a c. Returns a reference to this string. + * + * This member function is equivalent to: + * + * \code ToSeparated( c, char16_type( '-' ) ); \endcode + */ + template + String& ToHyphenated( const C& c ) + { + return ToSeparated( c, CharTraits::Hyphen() ); + } + + // ------------------------------------------------------------------------- + + /*! + * Replaces all occurrences of HTML special characters in this string with + * valid HTML entities. Returns a reference to this string. + * + * The following replacements are performed: + * + * '&' (ampersand) becomes "\&" \n + * '"' (double quote) becomes "\"" \n + * "'" (single quote) becomes "\'" \n + * '<' (less than) becomes "\<" \n + * '>' (greater than) becomes "\>" + * + * \sa EncodedHTMLSpecialChars(), ToDecodedHTMLSpecialChars() + */ + String& ToEncodedHTMLSpecialChars(); + + /*! + * Returns a duplicate of this string with all occurrences of HTML special + * characters replaced with valid HTML entities. + * + * \sa ToEncodedHTMLSpecialChars(), DecodedHTMLSpecialChars() + */ + String EncodedHTMLSpecialChars() const + { + return String( *this ).ToEncodedHTMLSpecialChars(); + } + + /*! + * Replaces all occurrences of special HTML entities in this string with + * their corresponding plain text character equivalents. Returns a reference + * to this string. + * + * The following replacements are performed: + * + * "\&" (ampersand) becomes '&' \n + * "\"" (double quote) becomes '"' \n + * "\'" (single quote) becomes "'" \n + * "\'" (apostrophe) becomes "'" \n + * "\<" (less than) becomes '<' \n + * "\>" (greater than) becomes '>' + * + * \sa DecodedHTMLSpecialChars(), ToEncodedHTMLSpecialChars() + */ + String& ToDecodedHTMLSpecialChars(); + + /*! + * Returns a duplicate of this string with all occurrences of special HTML + * entities replaced with their corresponding plain text character + * equivalents. + * + * \sa ToDecodedHTMLSpecialChars(), EncodedHTMLSpecialChars() + */ + String DecodedHTMLSpecialChars() const + { + return String( *this ).ToDecodedHTMLSpecialChars(); + } + + // ------------------------------------------------------------------------- + +#ifdef __PCL_QT_INTERFACE + + operator QString() const + { + return PCL_GET_QSTRING_FROM_CHAR16PTR( c_str() ); + } + + operator QDate() const + { + return QDate::fromString( operator QString(), PCL_QDATE_FMT_STR ); + } + + operator QDateTime() const + { + return QDateTime::fromString( operator QString(), PCL_QDATETIME_FMT_STR ); + } + +#endif + + /*! + * Replaces the contents of this string with a formatted representation of a + * variable-length set of values. Returns a reference to this string. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + String& Format( const_c_string8 fmt, ... ) + { + va_list paramList; + va_start( paramList, fmt ); + + (void)VFormat( fmt, paramList ); + + va_end( paramList ); + return *this; + } + + /*! + * Appends a formatted representation of a variable-length set of values to + * the current contents of this string. Returns a reference to this string. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + String& AppendFormat( const_c_string8 fmt, ... ) + { + va_list paramList; + va_start( paramList, fmt ); + + (void)AppendVFormat( fmt, paramList ); + + va_end( paramList ); + return *this; + } + + /*! + * Replaces the contents of this string with a formatted representation of a + * variable-length set of values, specified as a \c va_list standard + * parameter list. Returns the number of characters generated. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + int VFormat( const_c_string8 fmt, va_list paramList ) + { + IsoString s; + int count = s.VFormat( fmt, paramList ); + Assign( s ); + return count; + } + + /*! + * Appends a formatted representation of a variable-length set of values, + * specified as a \c va_list standard parameter list, to the current + * contents of this string. Returns the number of characters appended. + * + * The \a fmt null-terminated string is a standard printf format + * string. It follows the same rules as its counterpart parameter in + * the standard printf( const char* fmt, ... ) C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + int AppendVFormat( const_c_string8 fmt, va_list paramList ) + { + IsoString s; + int count = s.VFormat( fmt, paramList ); + Append( s ); + return count; + } + + /*! + * Replaces the contents of this string with a formatted representation of a + * variable-length set of values. Returns a reference to this string. + * + * The \a fmt null-terminated string is a standard printf format + * string of \c wchar_t characters. It follows the same rules as its + * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) + * C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + String& Format( const wchar_t* fmt, ... ) + { + va_list paramList; + va_start( paramList, fmt ); + + (void)VFormat( fmt, paramList ); + + va_end( paramList ); + return *this; + } + + /*! + * Appends a formatted representation of a variable-length set of values to + * the current contents of this string. Returns a reference to this string. + * + * The \a fmt null-terminated string is a standard printf format + * string of \c wchar_t characters. It follows the same rules as its + * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) + * C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + String& AppendFormat( const wchar_t* fmt, ... ) + { + va_list paramList; + va_start( paramList, fmt ); + + (void)AppendVFormat( fmt, paramList ); + + va_end( paramList ); + return *this; + } + + /*! + * Replaces the contents of this string with a formatted representation of a + * variable-length set of values, specified as a \c va_list standard + * parameter list. Returns the number of characters generated. + * + * The \a fmt null-terminated string is a standard printf format + * string of \c wchar_t characters. It follows the same rules as its + * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) + * C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + int VFormat( const wchar_t* fmt, va_list paramList ); + + /*! + * Appends a formatted representation of a variable-length set of values, + * specified as a \c va_list standard parameter list, to the current + * contents of this string. Returns the number of characters appended. + * + * The \a fmt null-terminated string is a standard printf format + * string of \c wchar_t characters. It follows the same rules as its + * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) + * C runtime function. + * + * The required space to store the resulting formatted output is calculated + * and allocated transparently. + */ + int AppendVFormat( const wchar_t* fmt, va_list paramList ); + + // ------------------------------------------------------------------------- + + /*! + * Conversion of a UTF-8 substring to a UTF-16 string. + * + * Converts a contiguous sequence of \a n characters starting at the \a i-th + * position of the specified null-terminated UTF-8 \a string. Returns the + * resulting UTF-16 string. + * + * \sa UTF16ToUTF8(), UTF16ToUTF32(), UTF32ToUTF16() + */ + static String UTF8ToUTF16( const_c_string8 string, size_type i = 0, size_type n = maxPos ); + + /*! + * Conversion of a UTF-16 substring to a UTF-8 string. + * + * Converts a contiguous sequence of \a n characters starting at the \a i-th + * position of the specified null-terminated UTF-16 \a string. Returns the + * resulting UTF-8 string. + * + * \sa UTF8ToUTF16(), UTF16ToUTF32(), UTF32ToUTF16() + */ + static IsoString UTF16ToUTF8( const_c_string string, size_type i = 0, size_type n = maxPos ); + + /*! + * Conversion of a UTF-16 substring to a UTF-32 string. + * + * Converts a contiguous sequence of \a n characters starting at the \a i-th + * position of the specified null-terminated UTF-16 \a string. Returns the + * resulting UTF-32 string as a dynamic array. + * + * \sa UTF8ToUTF16(), UTF16ToUTF8(), UTF32ToUTF16() + */ + static Array UTF16ToUTF32( const_c_string string, size_type i = 0, size_type n = maxPos ); + + /*! + * Conversion of a UTF-32 substring to a UTF-16 string. + * + * Converts a contiguous sequence of \a n characters starting at the \a i-th + * position of the specified null-terminated UTF-32 \a string. Returns the + * resulting UTF-16 string. + * + * \sa UTF8ToUTF16(), UTF16ToUTF8(), UTF16ToUTF32() + */ + static String UTF32ToUTF16( const uint32* string, size_type i = 0, size_type n = maxPos ); + + // ------------------------------------------------------------------------- + + /*! + * Returns an 8-bit, ISO/IEC-8859-1 string with a converted copy of this + * %String object. Characters in this string that cannot be converted to + * ISO-8859-1 (that is, characters with code points greater than 0x100) will + * have undefined values in the returned string. Undefined values are + * represented with question mark characters (?). + * + * \sa ToUTF8(), ToMBS(), ToUTF32(), To7BitASCII() + */ + IsoString ToIsoString() const; + + /*! + * Returns a 7-bit ASCII string with a converted copy of this %String + * object. Characters in this string that cannot be converted to the 7-bit + * ASCII set (that is, characters with code points greater than 0x80) will + * have undefined values in the returned string. Undefined values are + * represented with question mark characters (?). + * + * \sa ToIsoString(), ToUTF8(), ToMBS(), ToUTF32() + */ + IsoString To7BitASCII() const; + + /*! + * Returns an 8-bit string with a UTF-8 representation of a subset of \a n + * contiguous UTF-16 characters from this %String object, starting at the + * \a i-th character. + * + * \sa ToMBS(), ToLocal8Bit(), ToIsoString(), ToUTF32() + */ + IsoString ToUTF8( size_type i = 0, size_type n = maxPos ) const + { + return UTF16ToUTF8( Begin(), i, n ); + } + + /*! + * Returns a copy of this Unicode string converted to a multibyte + * string. This conversion is dependent on the current locale. + * + * In the event of conversion error (if there are invalid wide characters in + * the source string) this routine returns an empty string. + * + * This member function is a convenience wrapper for the wcstombs() routine + * of the standard C runtime library. Note that on platforms where the size + * of wchar_t is four bytes (e.g. Linux) this routine performs an additional + * conversion from UTF-16 to UTF-32. On platforms where the size of wchar_t + * is two bytes (e.g. Windows), the conversion is direct. + * + * \sa ToUTF8(), ToLocal8Bit(), ToIsoString(), ToUTF32(); + */ + IsoString ToMBS() const; + + /*! + * Returns a copy of this Unicode string converted to an 8-bit + * locale-dependent string. On UNIX/Linux systems (FreeBSD, Linux, Mac OS X) + * this function is equivalent to ToUTF8(). On Windows, this function + * returns ToMBS(). + * + * \sa ToUTF8(), ToMBS(); + */ + IsoString ToLocal8Bit() const + { +#ifdef __PCL_WINDOWS + return ToMBS(); +#else + return ToUTF8(); +#endif + } + + /*! + * Returns a copy of a contiguous segment of \a n characters of this string, + * starting from its \a i-th character, as a dynamic array of \c wchar_t. A + * null terminating character (L'\\0' specifically) is always appended to + * the resulting array. + * + * Depending on the platform, the \c wchar_t type may be 16-bit wide + * (Windows) or 32-bit wide (UNIX/Linux). The char16_type used by %String is + * always a 16-bit character (UTF-16) on all supported platforms. + * + * This member function provides a platform-independent way to obtain the + * contents of a %String object as a standard null-terminated string of + * \c wchar_t characters. + * + * On platforms where wchar_t occupies four bytes (UNIX/Linux), this + * function assumes that this %String object contains no surrogates. For a + * generalized conversion from UTF-16 to UTF-32, see ToUTF32(). + * + * \sa ToUTF32(), ToUTF8(), ToMBS(), ToIsoString() + */ + Array ToWCharArray( size_type i = 0, size_type n = maxPos ) const + { + if ( n > 0 ) + { + size_type len = Length(); + if ( i < len ) + { + n = pcl::Min( n, len-i ); + Array a( n+1, wchar_t( 0 ) ); +#ifdef __PCL_WINDOWS + char_traits::Copy( reinterpret_cast( a.Begin() ), m_data->string+i, n ); +#else + Array::iterator w = a.Begin(); + for ( const_iterator s = m_data->string+i, e = s+n; s < e; ++w, ++s ) + *w = wchar_t( *s ); +#endif // __PCL_WINDOWS + return a; + } + } + + return Array( size_type( 1 ), wchar_t( 0 ) ); + } + + /*! + * Returns a dynamic array of 32-bit integers with a UTF-32 representation + * of a subset of \a n contiguous UTF-16 characters from this %String + * object, starting at the \a i-th character. A null terminating character + * (uint32( 0 ) specifically) is always appended to the resulting array. + * + * \sa ToWCharArray(), ToUTF8(), ToMBS(), ToIsoString() + */ + Array ToUTF32( size_type i = 0, size_type n = maxPos ) const + { + return UTF16ToUTF32( Begin(), i, n ); + } + +#ifdef __PCL_QT_INTERFACE + + QString ToQString() const + { + return operator QString(); + } + + QDate ToQDate() const + { + return operator QDate(); + } + + QDateTime ToQDateTime() const + { + return operator QDateTime(); + } + +#endif + + /*! + * Evaluates this string as a Boolean literal, and returns the result as a + * \c bool value. + * + * Returns \c true if this string is equal to "1", "true", "TRUE" or "T". + * Returns \c false if this string is equal to "0", "false", "FALSE" or "F". + * Otherwise this function throws a ParseError exception. + * + * \sa TryToBool() + */ + bool ToBool() const; + + /*! + * Attempts to evaluate this string as a Boolean literal. + * + * If this string can legally be converted to a Boolean value, this function + * returns \c true and stores the evaluation result in the \a value + * variable. A string can only be converted to Boolean type if it is equal + * to either "1", "true", "TRUE", "T", "0", "false", "FALSE" or "F". + * + * If this string cannot be converted to a Boolean value, this function + * returns \c false and does not change the \a value variable. This function + * does not throw any exception. + * + * \sa ToBool() + */ + bool TryToBool( bool& value ) const noexcept; + + /*! + * Evaluates this string as a floating point numeric literal, and returns + * the result as a \c float value. + * + * For information about the legal syntax of a floating point literal, see + * the documentation for the ToDouble() member function. + * + * If this string doesn't contain a valid floating point literal, or if the + * range of \c float is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToFloat() + */ + float ToFloat() const; + + /*! + * Attempts to evaluate this string as a floating point numeric literal. + * + * If this string can legally be converted to a floating point number, this + * function returns \c true and stores the evaluation result in the \a value + * variable. For information about the legal syntax of a floating point + * literal, see the documentation for the ToDouble() member function. + * + * If this string cannot be converted to a floating point number, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \sa ToFloat() + */ + bool TryToFloat( float& value ) const noexcept; + + /*! + * Evaluates this string as a floating point literal, and returns the result + * as a \c double value. + * + * The source string is expected to have the following format (informal + * format specification): + * + * [+|-][\][.[\]][\[+|-]\] + * + * where \ and \ are optional sequences of + * decimal digits from 0 to 9, \ is an exponent specifier + * (the letter 'e' (or 'E')), and \ is a sequence of decimal + * digits specifying a power of ten that multiplies the preceding numeric + * constant. At least a one-digit integer part, or a one-digit decimal part, + * is mandatory. FORTRAN exponent specifiers ('d' and 'f' (or 'D' and 'F')) + * are also recognized by this implementation. + * + * If this string doesn't contain a valid floating point literal, or if the + * range of \c double is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToDouble() + */ + double ToDouble() const; + + /*! + * Attempts to evaluate this string as a floating point numeric literal. + * + * If this string can legally be converted to a floating point number, this + * function returns \c true and stores the evaluation result in the \a value + * variable. For information about the legal syntax of a floating point + * literal, see the documentation for the ToDouble() member function. + * + * If this string cannot be converted to a floating point number, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \sa ToDouble() + */ + bool TryToDouble( double& value ) const noexcept; + + /*! + * Evaluates this string as an integer literal, and returns the result as a + * \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code long n = s.ToInt( 0 ); \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string doesn't contain a valid integer literal, or if the range + * of \c long is exceeded, this member function throws a ParseError exception. + * + * \sa TryToInt() + */ + long ToInt() const + { + return ToInt( 0 ); + } + + /*! + * Attempts to evaluate this string as an integer numeric literal. + * + * If this string can legally be converted to an integer number, this + * function returns \c true and stores the evaluation result in the \a value + * variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * int v; + * if ( s.TryToInt( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an integer number, this function + * returns \c false and does not change the \a value variable. This function + * does not throw any exception. + * + * \sa ToInt() + */ + bool TryToInt( int& value ) const noexcept + { + return TryToInt( value, 0 ); + } + + /*! + * Evaluates this string as an integer literal in the specified \a base, and + * returns the result as a \c long value. + * + * If \a base is 0, the source string is expected to represent either a + * decimal constant, an octal constant, or a hexadecimal constant, any of + * which optionally preceded by a sign character (+ or -). A decimal + * constant begins with a non-zero digit, and consists of a sequence of + * decimal digits from '0' to '9'. An octal begins with the prefix '0', + * optionally followed by a sequence of the digits 0 to 7 only. A + * hexadecimal constant begins with the prefix '0x' or '0X', which must be + * followed by a sequence of decimal digits and letters from 'a' (or 'A') + * to 'f' (or 'F'), whose corresponding decimal values are from 10 to 15, + * respectively. + * + * Other legal values of \a base, from 2 to 36, specify the expected base of + * the integer constant represented by the source string. Decimal digits and + * letters from 'a' (or 'A') to 'z' (or 'Z') are used to represent all + * possible digits in the specified base, as necessary. + * + * If this string doesn't contain a valid integer literal in the specified + * \a base, if an illegal \a base is specified, or if the range of \c long + * is exceeded, this member function throws a ParseError exception. + * + * \sa TryToInt( int&, int ) const + */ + long ToInt( int base ) const; + + /*! + * Attempts to evaluate this string as an integer numeric literal in the + * specified \a base. + * + * If this string can legally be converted to an integer number in the + * specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an integer number in the specified + * \a base, this function returns \c false and does not change the \a value + * variable. This function does not throw any exception. + * + * \sa ToInt( int ) const + */ + bool TryToInt( int& value, int base ) const noexcept; + + /*! + * Evaluates this string as an unsigned integer literal, and returns the + * result as an \c unsigned \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code unsigned long n = s.ToUInt( 0 ); \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string doesn't contain a valid unsigned integer literal, or if + * the range of \c unsigned \c long is exceeded, this member function throws + * a ParseError exception. + * + * \sa TryToUInt() + */ + unsigned long ToUInt() const + { + return ToUInt( 0 ); + } + + /*! + * Attempts to evaluate this string as an unsigned integer literal. + * + * If this string can legally be converted to an unsigned integer number, + * this function returns \c true and stores the evaluation result in the + * \a value variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * unsigned v; + * if ( s.TryToUInt( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an integer number, this function + * returns \c false and does not change the \a value variable. This function + * does not throw any exception. + * + * \sa ToUInt() + */ + bool TryToUInt( unsigned& value ) const noexcept + { + return TryToUInt( value, 0 ); + } + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as an \c unsigned \c long value. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). The only exception + * is that for this member function, only a + sign is legal preceding the + * numeric constant represented by the source string. + * + * If this string doesn't contain a valid integer literal in the specified + * \a base, if an illegal \a base is specified, or if the range of + * \c unsigned \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToUInt( unsigned&, int ) const + */ + unsigned long ToUInt( int base ) const; + + /*! + * Attempts to evaluate this string as an unsigned integer literal in the + * specified \a base. + * + * If this string can legally be converted to an unsigned integer number in + * the specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * See the documentation under ToUInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to an unsigned integer number in the + * specified \a base, this function returns \c false and does not change the + * \a value variable. This function does not throw any exception. + * + * \sa ToUInt( int ) const + */ + bool TryToUInt( unsigned& value, int base ) const noexcept; + + /*! + * Evaluates this string as an integer literal, and returns the result as a + * \c long \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code long long n = s.ToInt64( 0 ); \endcode + * + * If this string doesn't contain a valid integer literal, or if the range + * of \c long \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToInt64() + */ + long long ToInt64() const + { + return ToInt64( 0 ); + } + + /*! + * Attempts to evaluate this string as a 64-bit integer numeric literal in + * the specified \a base. + * + * If this string can legally be converted to a 64-bit integer number in the + * specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * long long v; + * if ( s.TryToInt64( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to a 64-bit integer number, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \sa ToInt64() + */ + bool TryToInt64( long long& value ) const noexcept + { + return TryToInt64( value, 0 ); + } + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as a \c long \c long value. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string doesn't contain a valid integer literal in the specified + * \a base, if an illegal \a base is specified, or if the range of + * \c long \c long is exceeded, this member function throws a ParseError + * exception. + * + * \sa TryToInt64( long long&, int ) const + */ + long long ToInt64( int base ) const; + + /*! + * Attempts to evaluate this string as a 64-bit integer numeric literal in + * the specified \a base. + * + * If this string can legally be converted to a 64-bit integer number in the + * specified \a base, this function returns \c true and stores the + * evaluation result in the \a value variable. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string cannot be converted to a 64-bit integer number in the + * specified \a base, this function returns \c false and does not change the + * \a value variable. This function does not throw any exception. + * + * \sa ToInt64( int ) const + */ + bool TryToInt64( long long& value, int base ) const noexcept; + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as an \c unsigned \c long \c long value. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code unsigned long long n = s.ToUInt64( 0 ); \endcode + * + * If this string doesn't contain a valid unsigned integer literal, or if + * the range of \c unsigned \c long \c long is exceeded, this member + * function throws a ParseError exception. + * + * \sa TryToUInt64() + */ + unsigned long long ToUInt64() const + { + return ToUInt64( 0 ); + } + + /*! + * Attempts to evaluate this string as a 64-bit unsigned integer numeric + * literal in the specified \a base. + * + * If this string can legally be converted to a 64-bit unsigned integer + * number in the specified \a base, this function returns \c true and stores + * the evaluation result in the \a value variable. + * + * Calling this member function for a string \c s is equivalent to: + * + * \code + * unsigned long long v; + * if ( s.TryToUInt64( v, 0 ) ) ... + * \endcode + * + * See the documentation under ToInt( int ) for information about automatic + * base conversions when \a base=0 is specified. + * + * If this string cannot be converted to a 64-bit unsigned integer number, + * this function returns \c false and does not change the \a value variable. + * This function does not throw any exception. + * + * \sa ToUInt64() + */ + bool TryToUInt64( unsigned long long& value ) const noexcept + { + return TryToUInt64( value, 0 ); + } + + /*! + * Evaluates this string as an unsigned integer literal in the specified + * \a base, and returns the result as an \c unsigned \c long \c long value. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string doesn't contain a valid unsigned integer literal in the + * specified \a base, if an illegal \a base is specified, or if the range of + * \c unsigned \c long \c long is exceeded, this member function throws a + * ParseError exception. + * + * \sa TryToUInt64( unsigned long long&, int ) const + */ + unsigned long long ToUInt64( int base ) const; + + /*! + * Attempts to evaluate this string as an unsigned 64-bit integer numeric + * literal in the specified \a base. + * + * If this string can legally be converted to an unsigned 64-bit integer + * number in the specified \a base, this function returns \c true and stores + * the evaluation result in the \a value variable. + * + * For information about possible values of \a base and how these are + * interpreted, see the documentation under ToInt( int ). + * + * If this string cannot be converted to an unsigned 64-bit integer number + * in the specified \a base, this function returns \c false and does not + * change the \a value variable. This function does not throw any exception. + * + * \sa ToUInt64( int ) const + */ + bool TryToUInt64( unsigned long long& value, int base ) const noexcept; + + /*! + * Evaluates this string as a sexagesimal numeric literal representation, + * and returns the result as a \c double value. + * + * The source string is expected to have the following format: + * + * [+|-]\[\\[\\]][.[\]] + * + * where \, \, \ and \ are sequences of + * decimal digits from 0 to 9, and \ is any sequence of characters + * specified as the \a separator argument. The default separator is the + * colon character, ':'. + * + * The result is equal to: + * + * \ * (\ + \/60 + \/3600) + * + * where omitted optional components are taken as zero, and \ is -1 + * iff a minus sign '-' leads the representation, or +1 otherwise. + * + * If this string doesn't contain a valid sexagesimal numeric literal, or if + * the range of \c double is exceeded, this member function throws a + * ParseError exception. + * + * \ingroup sexagesimal_conversion + * \sa TrySexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() + */ + double SexagesimalToDouble( const String& separator = ':' ) const + { + int sign, s1, s2; double s3; + ParseSexagesimal( sign, s1, s2, s3, separator ); + return sign*(s1 + (s2 + s3/60)/60); + } + + /*! + * Evaluates this string as a sexagesimal numeric literal representation + * with the specified set of \a separators, and returns the result as a + * \c double value. + * + * This function is identical to SexagesimalToDouble( const String& ), but a + * set of separator characters is specified as a dynamic array. Any + * occurrence of a character contained by \a separators will be valid as a + * token separator. + * + * \ingroup sexagesimal_conversion + * \sa TrySexagesimalToDouble( double&, const Array<>& ) + */ + double SexagesimalToDouble( const Array& separators ) const + { + int sign, s1, s2; double s3; + ParseSexagesimal( sign, s1, s2, s3, separators ); + return sign*(s1 + (s2 + s3/60)/60); + } + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal with + * the specified \a separator. + * + * If this string can legally be evaluated as a sexagesimal literal and + * converted to a floating point number, this function stores the evaluation + * result in the specified \a value variable and returns \c true. For + * information about the legal syntax of a sexagesimal literal, see the + * documentation for SexagesimalToDouble(). + * + * If this string cannot be evaluated as a sexagesimal literal, this + * function returns \c false and does not change the \a value variable. This + * function does not throw any exception. + * + * \ingroup sexagesimal_conversion + * \sa SexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() + */ + bool TrySexagesimalToDouble( double& value, const String& separator = ':' ) const noexcept + { + int sign, s1, s2; double s3; + if ( TryParseSexagesimal( sign, s1, s2, s3, separator ) ) + { + value = sign*(s1 + (s2 + s3/60)/60); + return true; + } + return false; + } + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal with + * the specified set of \a separators. + * + * This function is identical to + * TrySexagesimalToDouble( double&, const String& ), but a set of separator + * characters is specified as a dynamic array. Any occurrence of a character + * contained by \a separators will be valid as a token separator. + * + * \ingroup sexagesimal_conversion + * \sa SexagesimalToDouble( const Array<>& ) + */ + bool TrySexagesimalToDouble( double& value, const Array& separators ) const noexcept + { + int sign, s1, s2; double s3; + if ( TryParseSexagesimal( sign, s1, s2, s3, separators ) ) + { + value = sign*(s1 + (s2 + s3/60)/60); + return true; + } + return false; + } + + /*! + * Evaluates this string as a sexagesimal numeric literal representation, + * using the specified \a separator, and stores the resulting components in + * the specified \a sign, \a s1, \a s2 and \a s3 variables. + * + * The output value of \a sign is either -1 or +1, respectively for negative + * and positive values. + * + * For information about the legal syntax of a sexagesimal literal, see the + * documentation for SexagesimalToDouble(). + * + * This function stores \e canonical minutes and seconds components, + * irrespective of the actual component values represented by this string. + * The output sexagesimal component values are such that: + * + * 0 ≤ \a s1 \n + * 0 ≤ \a s2 < 60 \n + * 0 ≤ \a s3 < 60 \n + * + * If this string doesn't contain a valid sexagesimal numeric literal, or if + * the range of \c double is exceeded, this member function throws a + * ParseError exception. + * + * \ingroup sexagesimal_conversion + * \sa TryParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() + */ + void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const String& separator = ':' ) const; + + /*! + * Evaluates this string as a sexagesimal numeric literal representation, + * using the specified set of \a separators, and stores the resulting + * components in the specified \a sign, \a s1, \a s2 and \a s3 variables. + * + * This function is identical to + * ParseSexagesimal( int&, int&, int&, double&, const String& ), but a set + * of separator characters is specified as a dynamic array. Any occurrence + * of a character contained by \a separators will be valid as a token + * separator. + * + * \ingroup sexagesimal_conversion + * \sa TryParseSexagesimal( int&, int&, int&, double&, const Array<>& ) + */ + void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const; + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal + * representation, using the specified \a separator. If successful, stores + * the resulting components in the specified \a sign, \a s1, \a s2 and \a s3 + * variables, and returns \c true. For more information on syntax and + * output values and ranges, see the documentation for ParseSexagesimal(). + * + * If this string cannot be evaluated as a sexagesimal literal, this + * function returns \c false and does not change any of the \a sign, \a s1, + * \a s2 and \a s3 variables. This function does not throw any exception. + * + * \ingroup sexagesimal_conversion + * \sa ParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() + */ + bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const String& separator = ':' ) const noexcept; + + /*! + * Attempts to evaluate this string as a sexagesimal numeric literal + * representation, using the specified set of \a separators. + * + * This function is identical to + * TryParseSexagesimal( int&, int&, int&, double&, const String& ), but a + * set of separator characters is specified as a dynamic array. Any + * occurrence of a character contained by \a separators will be valid as a + * token separator. + * + * \ingroup sexagesimal_conversion + * \sa ParseSexagesimal( int&, int&, int&, double&, const Array<>& ) + */ + bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const noexcept; + + /*! + * Returns a sexagesimal ASCII representation of the specified components + * \a sign, \a s1, \a s2 and \a s3, generated with the specified conversion + * \a options. + * + * The generated representation will correspond to a negative value iff + * \a sign < 0, positive otherwise. + * + * The generated representation is of the form: + * + * [+|-]\[\\[\\]][.[\]] + * + * where the second and third sexagesimal components are canonicalized: + * + * 0 ≤ \ < 60 + * 0 ≤ \ < 60 + * + * irrespective of the original \a s2 and \a s3 argument values. + * + * \ingroup sexagesimal_conversion + * \sa SexagesimalToDouble(), SexagesimalConversionOptions, + * AngleConversionOptions, LongitudeConversionOptions, RAConversionOptions, + * LatitudeConversionOptions, DecConversionOptions + */ + static String ToSexagesimal( int sign, double s1, double s2, double s3, + const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ); + + /*! + * Returns a sexagesimal ASCII representation of the specified decimal value + * \a d, generated with the specified conversion \a options. + * + * Calling this member function is equivalent to: + * + * \code ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); \endcode + * + * \ingroup sexagesimal_conversion + */ + static String ToSexagesimal( double d, const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ) + { + return ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); + } + + /*! + * Evaluates this string as a date and time specification in ISO 8601 + * extended format, and stores the resulting components in the specified + * variables. + * + * \param year On output, the year of the date. + * + * \param month On output, the month of the date in the range [1,12]. + * + * \param day On output, the day of the date in the range [1,31]. + * + * \param dayf On output, the day fraction corresponding to the time + * specification, in the range [0,1). + * + * \param tz On output, the time zone offset in hours, in the range + * [-12,+12]. + * + * In ISO 8601 extended representations, decimal fractions must be divided + * from integer parts exclusively by the full stop or dot character ('.', + * ASCII code point 46(10) = 2E(16)). + * + * \sa TryParseISO8601DateTime(), TimePoint::FromString() + */ + void ParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const; + + /*! + * Attempts to evaluate this string as a date and time specification in ISO + * 8601 extended format. If successful, stores the resulting components in + * the specified \a year, \a month, \a day and \a dayf and \a tz variables, + * and returns \c true. For more information on syntax and + * output values and ranges, see the ParseISO8601DateTime(). + * + * If this string cannot be evaluated as a valid date and time in ISO 8601 + * format, this function returns \c false and does not change any of the + * passed variables. This function does not throw any exception. + * + * \sa ParseISO8601DateTime(), TimePoint::TryFromString() + */ + bool TryParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const noexcept; + + /*! + * Returns a string representation of a date and time in ISO 8601 extended + * format. + * + * \param year The year of the date. + * + * \param month The month of the date in the range [1,12]. + * + * \param day The day of the date in the range [1,31]. + * + * \param dayf The day fraction corresponding to the time specification, + * in the range [0,1). + * + * \param tz The time zone offset in hours, in the range [-12,+12]. The + * default value is zero, to be interpreted as UTC. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 format. + * + * \sa CurrentUTCISO8601DateTime(), CurrentLocalISO8601DateTime(), + * ParseISO8601DateTime(), ISO8601ConversionOptions, + * TimePoint::ToString() + */ + static String ToISO8601DateTime( int year, int month, int day, double dayf, double tz = 0, + const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); + + /*! + * Returns an ASCII representation of the current UTC date and time in ISO + * 8601 extended format. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 format. + * + * \sa CurrentLocalISO8601DateTime(), ToISO8601DateTime(), + * ISO8601ConversionOptions, TimePoint::Now() + */ + static String CurrentUTCISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); + + /*! + * Returns an ASCII representation of the current local date and time in ISO + * 8601 extended format. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 format. + * + * \sa CurrentUTCISO8601DateTime(), ToISO8601DateTime(), + * ISO8601ConversionOptions + */ + static String CurrentLocalISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); + + /*! + * Generates a string of \a n random 16-bit code points, with character + * types and ranges as prescribed by the specified \a options. + * + * \sa RandomizationOption + */ + static String Random( size_type n, RandomizationOptions options = RandomizationOption::Default ); + + /*! + * Generates a universally unique identifier (UUID) in canonical form. + * + * The canonical UUID has 36 characters with the following format: + * + * xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + * + * where 'x' represents a lowercase hexadecimal digit, '4' is the UUID + * version indicator (version 4 = truly random UUID), and 'y' is one of '8', + * '9', 'a', or 'b'. + */ + static String UUID(); +}; + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +inline IsoString::IsoString( const_c_ustring t, size_type p, size_type n ) +{ + size_type len = uchar_traits::Length( t ); + if ( p < len ) + { + m_data->Allocate( n = pcl::Min( n, len-p ) ); + t += p; + for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) + *i = char_type( uint8( *t ) ); + } +} + +inline IsoString& IsoString::operator =( const_c_ustring t ) +{ + size_type len = uchar_traits::Length( t ); + if ( len > 0 ) + { + MaybeReallocate( len ); + for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) + *i = char_type( uint8( *t ) ); + } + else + Clear(); + + return *this; +} + +inline IsoString::ustring_base IsoString::UTF8ToUTF16( size_type i, size_type n ) const +{ + return String::UTF8ToUTF16( Begin(), i, n ); +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup string_concatenation_ops String Concatenation Operators + */ + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * and \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, const String::string_base& s2 ) +{ + String s = s1; + s.Append( s2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * (rvalue reference) and \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, const String::string_base& s2 ) +{ + s1.Append( s2 ); + return String( std::move( s1 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * (rvalue reference) and \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, const String::string_base& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * and \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, String::string_base&& s2 ) +{ + s2.Prepend( s1 ); + return String( std::move( s2 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * and \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, String&& s2 ) +{ + s2.Prepend( s1 ); + return std::move( s2 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * (rvalue reference) and \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, String::string_base&& s2 ) +{ + s1.Append( s2 ); + return String( std::move( s1 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * (rvalue reference) and \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, String::string_base&& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * (rvalue reference) and \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, String&& s2 ) +{ + s1.Append( s2 ); + return String( std::move( s1 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 + * (rvalue reference) and \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, String&& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a null-terminated UTF-16 string \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, String::const_iterator t2 ) +{ + String s = s1; + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated UTF-16 string \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, String::const_iterator t2 ) +{ + s1.Append( t2 ); + return String( std::move( s1 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated UTF-16 string \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, String::const_iterator t2 ) +{ + s1.Append( t2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated UTF-16 + * string \a t1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::const_iterator t1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated UTF-16 + * string \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::const_iterator t1, String::string_base&& s2 ) +{ + s2.Prepend( t1 ); + return String( std::move( s2 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated UTF-16 + * string \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::const_iterator t1, String&& s2 ) +{ + s2.Prepend( t1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a single UTF-16 character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, String::char_type c2 ) +{ + String s = s1; + s.Append( c2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single UTF-16 character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, String::char_type c2 ) +{ + s1.Append( c2 ); + return String( std::move( s1 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single UTF-16 character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, String::char_type c2 ) +{ + s1.Append( c2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a single UTF-16 character + * \a c1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::char_type c1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a single UTF-16 character + * \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::char_type c1, String::string_base&& s2 ) +{ + s2.Prepend( c1 ); + return String( std::move( s2 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a single UTF-16 character + * \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::char_type c1, String&& s2 ) +{ + s2.Prepend( c1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a null-terminated string of \c char16_t \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, const char16_t* t2 ) +{ + String s = s1; + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated string of \c char16_t \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, const char16_t* t2 ) +{ + String s = std::move( s1 ); + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated string of \c char16_t \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, const char16_t* t2 ) +{ + s1.Append( t2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated string + * of \c char16_t \a t1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const char16_t* t1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated string + * of \c char16_t \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const char16_t* t1, String::string_base&& s2 ) +{ + String s = std::move( s2 ); + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated string + * of \c char16_t \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const char16_t* t1, String&& s2 ) +{ + s2.Prepend( t1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a single \c char16_t character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, char16_t c2 ) +{ + String s = s1; + s.Append( c2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single \c char16_t character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, char16_t c2 ) +{ + String s = std::move( s1 ); + s.Append( c2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single \c char16_t character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, char16_t c2 ) +{ + s1.Append( c2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a single \c char16_t + * character \a c1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( char16_t c1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a single \c char16_t + * character \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( char16_t c1, String::string_base&& s2 ) +{ + String s = std::move( s2 ); + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a single \c char16_t + * character \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( char16_t c1, String&& s2 ) +{ + s2.Prepend( c1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a null-terminated string of \c wchar_t \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, const wchar_t* t2 ) +{ + String s = s1; + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated string of \c wchar_t \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, const wchar_t* t2 ) +{ + String s = std::move( s1 ); + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated string of \c wchar_t \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, const wchar_t* t2 ) +{ + s1.Append( t2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated string + * of \c wchar_t \a t1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const wchar_t* t1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated string + * of \c wchar_t \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const wchar_t* t1, String::string_base&& s2 ) +{ + String s = std::move( s2 ); + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated string + * of \c wchar_t \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const wchar_t* t1, String&& s2 ) +{ + s2.Prepend( t1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a single \c wchar_t character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, wchar_t c2 ) +{ + String s = s1; + s.Append( c2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single \c wchar_t character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, wchar_t c2 ) +{ + String s = std::move( s1 ); + s.Append( c2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single \c wchar_t character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, wchar_t c2 ) +{ + s1.Append( c2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a single \c wchar_t + * character \a c1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( wchar_t c1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a single \c wchar_t + * character \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( wchar_t c1, String::string_base&& s2 ) +{ + String s = std::move( s2 ); + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a single \c wchar_t + * character \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( wchar_t c1, String&& s2 ) +{ + s2.Prepend( c1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * an 8-bit string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, const String::string8_base& s2 ) +{ + String s = s1; + s.Append( s2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and an 8-bit string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, const String::string8_base& s2 ) +{ + String s = std::move( s1 ); + s.Append( s2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and an 8-bit string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, const String::string8_base& s2 ) +{ + s1.Append( s2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of an 8-bit string \a s1 and + * a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string8_base& s1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( s1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of an 8-bit string \a s1 and + * a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string8_base& s1, String::string_base&& s2 ) +{ + String s = std::move( s2 ); + s.Prepend( s1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of an 8-bit string \a s1 and + * a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string8_base& s1, String&& s2 ) +{ + s2.Prepend( s1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a null-terminated 8-bit string \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, String::const_c_string8 t2 ) +{ + String s = s1; + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated 8-bit string \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, String::const_c_string8 t2 ) +{ + String s = std::move( s1 ); + s.Append( t2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a null-terminated 8-bit string \a t2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, String::const_c_string8 t2 ) +{ + s1.Append( t2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated 8-bit + * string \a t1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::const_c_string8 t1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated 8-bit + * string \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::const_c_string8 t1, String::string_base&& s2 ) +{ + String s = std::move( s2 ); + s.Prepend( t1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a null-terminated 8-bit + * string \a t1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::const_c_string8 t1, String&& s2 ) +{ + s2.Prepend( t1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and + * a single 8-bit character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( const String::string_base& s1, String::char8_type c2 ) +{ + String s = s1; + s.Append( c2 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single 8-bit character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::string_base&& s1, String::char8_type c2 ) +{ + s1.Append( String::char_type( c2 ) ); + return String( std::move( s1 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 + * (rvalue reference) and a single 8-bit character \a c2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String&& s1, String::char8_type c2 ) +{ + s1.Append( c2 ); + return std::move( s1 ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a single 8-bit character + * \a c1 and a UTF-16 string \a s2. + * \ingroup string_concatenation_ops + */ +inline String operator +( String::char8_type c1, const String::string_base& s2 ) +{ + String s = s2; + s.Prepend( c1 ); + return s; +} + +/*! + * Returns a UTF-16 string with the concatenation of a single 8-bit character + * \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::char8_type c1, String::string_base&& s2 ) +{ + s2.Prepend( String::char_type( c1 ) ); + return String( std::move( s2 ) ); +} + +/*! + * Returns a UTF-16 string with the concatenation of a single 8-bit character + * \a c1 and a UTF-16 string \a s2 (rvalue reference). + * \ingroup string_concatenation_ops + */ +inline String operator +( String::char8_type c1, String&& s2 ) +{ + s2.Prepend( c1 ); + return std::move( s2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Appends a UTF-16 string \a s2 to a UTF-16 string \a s1. Returns a reference + * to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, const String::string_base& s2 ) +{ + s1.Append( s2 ); + return s1; +} + +/*! + * Appends a UTF-16 string \a s2 to a UTF-16 string \a s1. Returns a reference + * to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, const String::string_base& s2 ) +{ + s1.Append( s2 ); + return s1; +} + +/*! + * Appends a null-terminated UTF-16 string \a t2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, String::const_iterator& t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a null-terminated UTF-16 string \a t2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, String::const_iterator& t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a single UTF-16 character \a c2 to a UTF-16 string \a s1. Returns a + * reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, String::char_type c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a single UTF-16 character \a c2 to a UTF-16 string \a s1. Returns a + * reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, String::char_type c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a null-terminated string \a t2 of \c char16_t to a UTF-16 string + * \a s1. Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, const char16_t* t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a null-terminated string \a t2 of \c char16_t to a UTF-16 string + * \a s1. Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, const char16_t* t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a single \c char16_t character \a c2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, char16_t c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a single \c char16_t character \a c2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, char16_t c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a null-terminated string \a t2 of \c wchar_t to a UTF-16 string + * \a s1. Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, const wchar_t* t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a null-terminated string \a t2 of \c wchar_t to a UTF-16 string + * \a s1. Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, const wchar_t* t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a single \c wchar_t character \a c2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, wchar_t c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a single \c wchar_t character \a c2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, wchar_t c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends an 8-bit string \a s2 to a UTF-16 string \a s1. Returns a reference + * to the left-hand operand Unicode string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, const String::string8_base& s2 ) +{ + s1.Append( s2 ); + return s1; +} + +/*! + * Appends an 8-bit string \a s2 to a UTF-16 string \a s1. Returns a reference + * to the left-hand operand Unicode string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, const String::string8_base& s2 ) +{ + s1.Append( s2 ); + return s1; +} + +/*! + * Appends a null-terminated 8-bit string \a t2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand Unicode string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, String::const_c_string8 t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a null-terminated 8-bit string \a t2 to a UTF-16 string \a s1. + * Returns a reference to the left-hand operand Unicode string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, String::const_c_string8 t2 ) +{ + s1.Append( t2 ); + return s1; +} + +/*! + * Appends a single 8-bit character \a c2 to a UTF-16 string \a s1. Returns a + * reference to the left-hand operand Unicode string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String& s1, String::char8_type c2 ) +{ + s1.Append( c2 ); + return s1; +} + +/*! + * Appends a single 8-bit character \a c2 to a UTF-16 string \a s1. Returns a + * reference to the left-hand operand Unicode string \a s1. + * \ingroup string_concatenation_ops + */ +inline String& operator <<( String&& s1, String::char8_type c2 ) +{ + s1.Append( c2 ); + return s1; +} + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup string_relational_ops String Relational Operators + */ + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const String& s1, const char16_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const String& s1, const char16_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) < 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const String& s1, const char16_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) <= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const String& s1, const char16_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) > 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const String& s1, const char16_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const char16_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const char16_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) > 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const char16_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) >= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const char16_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) < 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const char16_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const String& s1, char16_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const String& s1, char16_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) < 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const String& s1, char16_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) <= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const String& s1, char16_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) > 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const String& s1, char16_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( char16_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( char16_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) > 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( char16_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) >= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( char16_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) < 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( char16_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const String& s1, const wchar_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const String& s1, const wchar_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) < 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const String& s1, const wchar_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) <= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const String& s1, const wchar_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) > 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const String& s1, const wchar_t* t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const wchar_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const wchar_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) > 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const wchar_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) >= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const wchar_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) < 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const wchar_t* t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const String& s1, wchar_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const String& s1, wchar_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) < 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const String& s1, wchar_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) <= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const String& s1, wchar_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) > 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const String& s1, wchar_t c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( wchar_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( wchar_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) > 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( wchar_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) >= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( wchar_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) < 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( wchar_t c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const String& s1, String::const_c_string8 t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const String& s1, String::const_c_string8 t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) < 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const String& s1, String::const_c_string8 t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) <= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const String& s1, String::const_c_string8 t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) > 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const String& s1, String::const_c_string8 t2 ) noexcept +{ + return s1.CompareCodePoints( t2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( String::const_c_string8 t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( String::const_c_string8 t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) > 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( String::const_c_string8 t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) >= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( String::const_c_string8 t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) < 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( String::const_c_string8 t1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( t1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( const String& s1, String::char8_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( const String& s1, String::char8_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) < 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( const String& s1, String::char8_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) <= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( const String& s1, String::char8_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) > 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( const String& s1, String::char8_type c2 ) noexcept +{ + return s1.CompareCodePoints( c2 ) >= 0; +} + +// ---------------------------------------------------------------------------- + +/*! + * Equality operator. + * \ingroup string_relational_ops + */ +inline bool operator ==( String::char8_type c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) == 0; +} + +/*! + * Less than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <( String::char8_type c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) > 0; +} + +/*! + * Less than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator <=( String::char8_type c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) >= 0; +} + +/*! + * Greater than operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >( String::char8_type c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) < 0; +} + +/*! + * Greater than or equal operator. This function performs a + * character-to-character, locale-unaware comparison of numeric character + * values. See GenericString<>::CompareCodePoints() for more information. + * \ingroup string_relational_ops + */ +inline bool operator >=( String::char8_type c1, const String& s2 ) noexcept +{ + return s2.CompareCodePoints( c1 ) <= 0; +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_STRING_OSTREAM + +inline std::wostream& operator <<( std::wostream& o, const String& s ) +{ +#ifdef __PCL_WINDOWS + return o << reinterpret_cast( s.c_str() ); +#else + Array w = s.ToWCharArray(); + return o << w.Begin(); +#endif +} + +inline std::ostream& operator <<( std::ostream& o, const String& s ) +{ + return o << s.ToUTF8(); +} + +#endif // __PCL_NO_STRING_OSTREAM + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_String_h + +// ---------------------------------------------------------------------------- +// EOF pcl/String.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StringList.h b/3rdparty/include/pcl/StringList.h new file mode 100644 index 0000000..93b68e2 --- /dev/null +++ b/3rdparty/include/pcl/StringList.h @@ -0,0 +1,152 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StringList.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_StringList_h +#define __PCL_StringList_h + +/// \file pcl/StringList.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup string_lists String List Classes + */ + +/*! + * \class pcl::StringList + * \ingroup string_lists + * \brief Dynamic list of Unicode (UTF-16) strings. + * + * %StringList is a template instantiation of Array for the String class. + */ +typedef Array StringList; + +/*! + * \class pcl::SortedStringList + * \ingroup string_lists + * \brief Dynamic sorted list of Unicode (UTF-16) strings. + * + * %SortedStringList is a template instantiation of SortedArray for String. + */ +typedef SortedArray SortedStringList; + +/*! + * \class pcl::IsoStringList + * \ingroup string_lists + * \brief Dynamic list of 8-bit strings. + * + * %IsoStringList is a template instantiation of Array for IsoString. + */ +typedef Array IsoStringList; + +/*! + * \class pcl::SortedIsoStringList + * \ingroup string_lists + * \brief Dynamic sorted list of 8-bit strings. + * + * %SortedIsoStringList is a template instantiation of SortedArray for the + * IsoString class. + */ +typedef SortedArray SortedIsoStringList; + +/*! + * \defgroup key_value_string_lists Key-Value String List Classes + */ + +/*! + * \class pcl::StringKeyValueList + * \ingroup string_lists + * \ingroup key_value_string_lists + * \brief Dynamic list of key-value associations implemented as Unicode (UTF-16) strings. + */ +typedef Array StringKeyValueList; + +/*! + * \class pcl::SortedStringKeyValueList + * \ingroup string_lists + * \ingroup key_value_string_lists + * \brief Dynamic sorted list of key-value associations implemented as Unicode (UTF-16) strings. + */ +typedef SortedArray SortedStringKeyValueList; + +/*! + * \class pcl::IsoStringKeyValueList + * \ingroup string_lists + * \ingroup key_value_string_lists + * \brief Dynamic list of key-value associations implemented as 8-bit strings. + */ +typedef Array IsoStringKeyValueList; + +/*! + * \class pcl::SortedIsoStringKeyValueList + * \ingroup string_lists + * \ingroup key_value_string_lists + * \brief Dynamic sorted list of key-value associations implemented as 8-bit strings. + */ +typedef SortedArray SortedIsoStringKeyValueList; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_StringList_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StringList.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/StructuringElement.h b/3rdparty/include/pcl/StructuringElement.h new file mode 100644 index 0000000..b9ed2f9 --- /dev/null +++ b/3rdparty/include/pcl/StructuringElement.h @@ -0,0 +1,956 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/StructuringElement.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_StructuringElement_h +#define __PCL_StructuringElement_h + +/// \file pcl/StructuringElement.h + +#include +#include + +#include +#include +#include +#include // Reverse() +#include // BitmapStructure +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class StructuringElement + * \brief Abstract base class of all PCL structuring elements. + * + * %StructuringElement defines a square multiway structure that can be used, + * along with a MorphologicalOperator, to build a MorphologicalTransformation. + * + * A structure is a square matrix of Boolean elements. When an element is true + * we say that that element \e exists. Nonexistent (false) structure elements + * are ignored when a morphological operator is applied to an image. + * + * A structuring element works for morphological transformations in a + * similar way to a kernel filter for spatial convolutions: the + * structure is placed centered on a pixel of the image being processed, and + * only those neighbor pixels falling behind existing structure elements are + * taken into account to compute the result of a morphological operator. When + * this operation is repeated for each pixel in an image, it implements a + * morphological transformation. + * + * %StructuringElement holds a multiway structure. Each way is + * actually a separate structure, so a multiway structure actually groups a + * set of structures with the same dimensions. When a multiway structure is + * used to apply a morphological operator, the operator is first applied + * through each way in the structure, and the result is the same operator + * applied to the partial results. + * + * This class is thread-safe. This means that multiple execution threads can + * access the same %StructuringElement instance concurrently to perform + * morphological transformations. + * + * \sa MorphologicalOperator, MorphologicalTransformation + */ +class PCL_CLASS StructuringElement +{ +public: + + /*! + * Represents an element of a structure existence mask. + */ + typedef uint32 existence_mask_element; + + /*! + * Represents a structure existence mask. + */ + typedef GenericVector existence_mask; + + /*! + * Represents a set of structure existence masks. + */ + typedef GenericVector existence_mask_set; + + /*! + * A vector type used to store the number of existing structure elements. + */ + typedef GenericVector existence_mask_count; + + /*! + * Constructs a default \e box %StructuringElement object of the specified + * \a size in pixels and number of ways \a n. + */ + StructuringElement( int size = 3, int n = 1 ) + : m_size( Max( 3, size|1 ) ) + , m_mask( Max( 1, n ) ) + , m_count( 0, Max( 1, n ) ) + { + PCL_PRECONDITION( size >= 3 ) + PCL_PRECONDITION( (size & 1) != 0 ) + PCL_PRECONDITION( n >= 1 ) + for ( int k = 0; k < NumberOfWays(); ++k ) + m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() ); + } + + /*! + * Copy constructor. + */ + StructuringElement( const StructuringElement& x ) + : m_size( x.m_size ) + , m_mask( x.NumberOfWays() ) + , m_count( 0, x.NumberOfWays() ) + { + for ( int k = 0; k < NumberOfWays(); ++k ) + m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() ); + } + + /*! + * Destroys a %StructuringElement object. + */ + virtual ~StructuringElement() + { + } + + /*! + * Returns a pointer to a dynamically allocated duplicate of this + * structuring element. + */ + virtual StructuringElement* Clone() const = 0; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + StructuringElement& operator =( const StructuringElement& x ) + { + if ( &x != this ) + { + volatile AutoLock lock( m_mutex ); + m_size = x.m_size; + m_mask = existence_mask_set( x.NumberOfWays() ); + m_count = existence_mask_count( 0, x.NumberOfWays() ); + m_reflected = false; + m_initialized = 0; + for ( int k = 0; k < NumberOfWays(); ++k ) + m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() ); + } + return *this; + } + + /*! + * Returns the number of ways in this structure. + */ + int NumberOfWays() const + { + return int( m_mask.Length() ); + } + + /*! + * Returns the size of this structure in pixels. + */ + int Size() const + { + return m_size; + } + + /*! + * Returns the total number of structure elements, or Size()*Size(). Note + * that this includes both existing and nonexistent structure elements. + */ + int NumberOfElements() const + { + return m_size*m_size; + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * The default implementation of this member function returns true if all + * elements in the k-th way are reported as existing elements by the + * ElementExists() member function. + * + * \note This is a performance-critical routine. When possible, derived + * classes should reimplement it in more efficient ways (for example, a + * circular structure is never a box structure). + */ + virtual bool IsBox( int k ) const + { + PCL_PRECONDITION( k >= 0 && k < NumberOfWays() ) + Initialize(); + return m_count[k] == NumberOfElements(); + } + + /*! + * Returns true iff a given element exists in this structure. + * + * \param i column position (X-coordinate) of the requested structure + * element. Must be 0 <= i < n, where n is the structure size. + * + * \param j row position (Y-coordinate) of the requested structure + * element. Must be 0 <= j < n, where n is the structure size. + * + * \param k Way index. Must be 0 <= k < m, where m is the number of ways + * defined in this structure. + */ + virtual bool ElementExists( int i, int j, int k ) const + { + PCL_PRECONDITION( i >= 0 && i < m_size ) + PCL_PRECONDITION( j >= 0 && j < m_size ) + PCL_PRECONDITION( k >= 0 && k < NumberOfWays() ) + return true; + } + + /*! + * Gets the subset of pixel sample values that correspond to existing + * elements in a way of this structure. + * + * \param[out] h1 %Vector of samples from the input \a h array that + * correspond to existing structure elements. + * + * \param[out] nh1 The number of existing elements in the k-th way of + * this structure. This is also the number of samples + * stored in the \a h1 vector. + * + * \param h Input array of samples. Must be the starting address of a + * square matrix of \a n samples stored in row order, where \a n + * is the number of elements in this structure (equal to + * NumberOfElements()). + * + * \param k Way index. Must be 0 <= k < m, where m is the number of ways + * defined in this structure. + * + * \note This function is thread-safe. + */ + template + void PeekElements( T* h1, int& nh1, const T* h, int k ) const + { + PCL_PRECONDITION( h1 != 0 ) + PCL_PRECONDITION( h != 0 ) + PCL_PRECONDITION( k >= 0 && k < NumberOfWays() ) + Initialize(); + nh1 = 0; + for ( existence_mask::const_iterator m = m_mask[k].Begin(), m1 = m_mask[k].End(); m < m1; ++m, ++h ) + if ( *m ) + { + *h1++ = *h; + ++nh1; + } + } + + /*! + * Reflects this structure. + * + * Structure reflection is equivalent to a 180 degrees rotation of the + * underlying structure mask for each way. This member function is called + * internally by MorphologicalTransformation to apply dilation operators. + */ + void Reflect() + { + Initialize(); + for ( existence_mask_set::iterator i = m_mask.Begin(); i != m_mask.End(); ++i ) + pcl::Reverse( i->Begin(), i->End() ); + m_reflected = !m_reflected; + } + + /*! + * Returns true iff this structure has been reflected. Note that after an + * even number of successive reflections (which is a no-op) this member + * function will return false. + */ + bool IsReflected() const + { + return m_reflected; + } + + /*! + * Initializes the internal existence tables. + * + * A structure is a square matrix of Boolean elements. When an element is + * true we say that that element \e exists. Nonexistent (false) structure + * elements are ignored when a morphological operator is applied to + * transform an image. + * + * StructuringElement (and derived classes) uses a set of precomputed + * existence tables that greatly improves performance of + * morphological transformations, especially for complex structures. Calling + * this member function forces the immediate calculation of existence + * tables, if they haven't already been calculated previously. If the + * existence tables already exist, this function does nothing. + * + * You normally should not need to call this member function directly, as + * existence tables are automatically calculated when required. + * + * \note This is a thread-safe routine. It can be safely called from + * multiple running threads. + */ + void Initialize() const + { + if ( !m_initialized ) + { + volatile AutoLock lock( m_mutex ); + if ( m_initialized.Load() == 0 ) + { + int N = NumberOfWays(); + for ( int k = 0; k < N; ++k ) + { + m_count[k] = 0; // redundant, but doesn't hurt + existence_mask::iterator m = m_mask[k].Begin(); + for ( int i = 0; i < m_size; ++i ) + for ( int j = 0; j < m_size; ++j, ++m ) + if ( ElementExists( i, j, k ) ) + { + *m = 1; + ++m_count[k]; + } + else + *m = 0; + } + + m_initialized.Store( 1 ); + } + } + } + +private: + + /* + * Structure size. + */ + int m_size; + + /* + * Element existence masks (one mask per way). + * An element exists iff its corresponding mask element is nonzero. + */ + mutable existence_mask_set m_mask; + + /* + * Number of existing elements for each way. + */ + mutable existence_mask_count m_count; + + /* + * Flag true when the structure has been reflected. + */ + bool m_reflected = false; + + /* + * Flag true when existence masks have been calculated. + */ + mutable AtomicInt m_initialized; + + /* + * Thread synchronization. + */ + mutable Mutex m_mutex; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BoxStructure + * \brief Standard box (square) structure. + * + * A block structure defines all of its elements. For example, a box + * structure of size 5 is: + * + *
+ * x x x x x
+ * x x x x x
+ * x x x x x
+ * x x x x x
+ * x x x x x
+ * 
+ * + * where existing elements are marked as 'x'. + * + * \sa CircularStructure, OrthogonalStructure, DiagonalStructure, StarStructure + */ +class PCL_CLASS BoxStructure : public StructuringElement +{ +public: + + /*! + * Constructs a standard block structure of the specified \a size. + */ + BoxStructure( int size ) + : StructuringElement( size, 1 ) + { + } + + /*! + * Copy constructor. + */ + BoxStructure( const BoxStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new BoxStructure( *this ); + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * As reimplemented by %BoxStructure, this member function always + * returns true. + */ + bool IsBox( int k ) const override + { + PCL_PRECONDITION( k == 0 ) + return true; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class CircularStructure + * \brief Standard circular structure. + * + * The standard circular structure of size 7 is defined as follows: + * + *
+ * · · x x x · ·
+ * · x x x x x ·
+ * x x x x x x x
+ * x x x x x x x
+ * x x x x x x x
+ * · x x x x x ·
+ * · · x x x · ·
+ * 
+ * + * where existing elements are marked as 'x' and nonexisting elements are + * denoted as '·'. + * + * Circular structures can help in preserving small structures, especially + * rounded ones, like stars. + * + * \sa ThreeWayStructure, OrthogonalStructure, DiagonalStructure, StarStructure + */ +class PCL_CLASS CircularStructure : public StructuringElement +{ +public: + + /*! + * Constructs a standard circular structure of the specified \a diameter. + */ + CircularStructure( int diameter ) + : StructuringElement( diameter, 1 ) + { + } + + /*! + * Copy constructor. + */ + CircularStructure( const CircularStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new CircularStructure( *this ); + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * As reimplemented by %CircularStructure, this member function always + * returns false. + */ + bool IsBox( int k ) const override + { + PCL_PRECONDITION( k == 0 ) + return false; + } + + /*! + */ + bool ElementExists( int i, int j, int k ) const override + { + PCL_PRECONDITION( i >= 0 && i < Size() ) + PCL_PRECONDITION( j >= 0 && j < Size() ) + PCL_PRECONDITION( k == 0 ) + float n2 = 0.5F*Size(); + float di = i+0.5F - n2; + float dj = j+0.5F - n2; + return di*di + dj*dj <= n2*n2; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class OrthogonalStructure + * \brief Standard orthogonal structure. + * + * An orthogonal structure of size 5 is defined as follows: + * + *
+ * · · x · ·
+ * · · x · ·
+ * x x x x x
+ * · · x · ·
+ * · · x · ·
+ * 
+ * + * where existing elements are marked as 'x' and nonexisting elements are + * denoted as '·'. + * + * \sa ThreeWayStructure, CircularStructure, DiagonalStructure, StarStructure + */ +class PCL_CLASS OrthogonalStructure : public StructuringElement +{ +public: + + /*! + * Constructs an orthogonal structure of the specified \a size. + */ + OrthogonalStructure( int size ) + : StructuringElement( size, 1 ) + { + } + + /*! + * Copy constructor. + */ + OrthogonalStructure( const OrthogonalStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new OrthogonalStructure( *this ); + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * As reimplemented by %OrthogonalStructure, this member function always + * returns false. + */ + bool IsBox( int k ) const override + { + PCL_PRECONDITION( k == 0 ) + return false; + } + + /*! + */ + bool ElementExists( int i, int j, int k ) const override + { + PCL_PRECONDITION( i >= 0 && i < Size() ) + PCL_PRECONDITION( j >= 0 && j < Size() ) + PCL_PRECONDITION( k == 0 ) + int n2 = Size() >> 1; + return i == n2 || j == n2; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class DiagonalStructure + * \brief Standard diagonal structure. + * + * A diagonal structure of size 5 is defined as follows: + * + *
+ * x · · · x
+ * · x · x ·
+ * · · x · ·
+ * · x · x ·
+ * x · · · x
+ * 
+ * + * where existing elements are marked as 'x' and nonexisting elements are + * denoted as '·'. + * + * \sa ThreeWayStructure, CircularStructure, OrthogonalStructure, StarStructure + */ +class PCL_CLASS DiagonalStructure : public StructuringElement +{ +public: + + /*! + * Constructs a diagonal structure of the specified \a size. + */ + DiagonalStructure( int size ) + : StructuringElement( size, 1 ) + { + } + + /*! + * Copy constructor. + */ + DiagonalStructure( const DiagonalStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new DiagonalStructure( *this ); + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * As reimplemented by %DiagonalStructure, this member function always + * returns false. + */ + bool IsBox( int k ) const override + { + PCL_PRECONDITION( k == 0 ) + return false; + } + + /*! + */ + bool ElementExists( int i, int j, int k ) const override + { + PCL_PRECONDITION( i >= 0 && i < Size() ) + PCL_PRECONDITION( j >= 0 && j < Size() ) + PCL_PRECONDITION( k == 0 ) + return j == i || j == Size()-i-1; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class StarStructure + * \brief Standard star structure. + * + * A star structure of size 7 is defined as follows: + * + *
+ * · · · x · · ·
+ * · x · x · x ·
+ * · · x x x · ·
+ * x x x x x x x
+ * · · x x x · ·
+ * · x · x · x ·
+ * · · · x · · ·
+ * 
+ * + * where existing elements are marked as 'x' and nonexisting elements are + * denoted as '·'. + * + * \sa ThreeWayStructure, CircularStructure, OrthogonalStructure, + * DiagonalStructure + */ +class PCL_CLASS StarStructure : public StructuringElement +{ +public: + + /*! + * Constructs a star structure of the specified \a size. + */ + StarStructure( int size ) + : StructuringElement( size, 1 ) + { + } + + /*! + * Copy constructor. + */ + StarStructure( const StarStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new StarStructure( *this ); + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * As reimplemented by %StarStructure, this member function always + * returns false. + */ + bool IsBox( int k ) const override + { + PCL_PRECONDITION( k == 0 ) + return false; + } + + /*! + */ + bool ElementExists( int i, int j, int k ) const override + { + PCL_PRECONDITION( i >= 0 && i < Size() ) + PCL_PRECONDITION( j >= 0 && j < Size() ) + PCL_PRECONDITION( k == 0 ) + int n2 = Size() >> 1; + if ( i == n2 || j == n2 ) + return true; + if ( j == i || j == Size()-i-1 ) + { + float n2 = 0.5F*Size(); + float di = i+0.5F - n2; + float dj = j+0.5F - n2; + return di*di + dj*dj <= n2*n2; + } + return false; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ThreeWayStructure + * \brief Standard three-way structure. + * + * The standard three-way structure of size 5 is defined as follows: + * + *
+ *   Way #0       Way #1       Way #2
+ *
+ * · · x · ·    x · · · x    · · · · ·
+ * · · x · ·    · x · x ·    · · · · ·
+ * x x · x x    · · · · ·    · · x · ·
+ * · · x · ·    · x · x ·    · · · · ·
+ * · · x · ·    x · · · x    · · · · ·
+ * 
+ * + * where existing elements are marked as 'x' and nonexisting elements are + * denoted as '·'. + * + * The standard three-way structure leads to ranking operations where data + * from different spatial directions are ranked separately. When used to apply + * morphological operators, standard three-way structures can preserve edges + * better than box structures, especially when applied recursively. + * + * \sa CircularStructure, OrthogonalStructure, DiagonalStructure, StarStructure + */ +class PCL_CLASS ThreeWayStructure : public StructuringElement +{ +public: + + /*! + * Constructs a standard three-way structure of the specified \a size. + */ + ThreeWayStructure( int size ) + : StructuringElement( size, 3 ) + { + } + + /*! + * Copy constructor. + */ + ThreeWayStructure( const ThreeWayStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new ThreeWayStructure( *this ); + } + + /*! + * Returns true iff this is a box structure. All elements in a box + * structure are existing elements. + * + * As reimplemented by %ThreeWayStructure, this member function always + * returns false. + */ + bool IsBox( int k ) const override + { + PCL_PRECONDITION( k >= 0 && k < 3 ) + return false; + } + + /*! + */ + bool ElementExists( int i, int j, int k ) const override + { + PCL_PRECONDITION( i >= 0 && i < Size() ) + PCL_PRECONDITION( j >= 0 && j < Size() ) + PCL_PRECONDITION( k >= 0 && k < 3 ) + int n2 = Size() >> 1; + switch ( k ) + { + default: + case 0: // central element + return i == n2 && j == n2; + case 1: // horizontal and vertical elements + return i == n2 || j == n2; + case 2: // diagonal elements + return (j == i || j == Size()-i-1) && i != n2; + } + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class BitmapStructure + * \brief A structuring element where static strings are used to define custom + * existence matrices. + * + * %BitmapStructure allows you to build a structuring element using character + * strings to define the existence of structure elements. Each string defines a + * structure way, where 'x' characters correspond to existing structure + * elements. For example, the following array of static strings: + * + *
+ * const char* B[] = { "--x--"
+ *                     "-xxx-"
+ *                     "xxxxx"
+ *                     "-xxx-"
+ *                     "--x--",
+ *                     //
+ *                     "-xxx-"
+ *                     "xxxxx"
+ *                     "xxxxx"
+ *                     "xxxxx"
+ *                     "-xxx-" };
+ * 
+ * + * would define a 5x5 structure with two ways. 'x' characters define existing + * elements; other character values ('-' in this case) are interpreted as + * nonexistent elements. The corresponding %BitmapStructure object would be + * constructed as follows: + * + * BitmapStructure S( B, 5, 2 ); + * + * This class is a convenient, straightforward approach to defining multi-way + * custom structuring elements that can be used directly with the + * MorphologicalTransformation class. + */ +class PCL_CLASS BitmapStructure : public StructuringElement +{ +public: + + /*! + * Represents a structure bitmap. Each bitmap defines the existence matrix + * for a \e way of the structuring element. + */ + typedef IsoString bitmap; + + /*! + * Represents a set of bitmaps used to define the structure ways in a + * %BitmapStructure object. + */ + typedef IsoStringList bitmap_set; + + /*! + * Constructs a %BitmapStructure object of the specified \a size and \a n + * number of ways. + * + * \param bitmaps An array of null-terminated strings representing the + * set of ways in this structuring element. There must be + * \a n contiguous null-terminated strings of length + * \a size*size characters at the address specified by + * this argument. In these strings, 'x' characters + * correspond to existing structure elements; other + * character values will be interpreted as nonexistent + * structure elements. + * + * \param size Size of this structure. Must be an odd integer >= 3. + * + * \param n Number of ways in this structure. Must be >= 1. + */ + BitmapStructure( const char** bitmaps, int size, int n = 1 ) + : StructuringElement( size, n ) + { + PCL_PRECONDITION( bitmaps != nullptr ) + PCL_PRECONDITION( *bitmaps != '\0' ) + for ( int i = 0; i < NumberOfWays(); ++i ) + m_bitmaps.Add( bitmap( bitmaps[i] ) ); + } + + /*! + * Copy constructor. + */ + BitmapStructure( const BitmapStructure& ) = default; + + /*! + */ + StructuringElement* Clone() const override + { + return new BitmapStructure( *this ); + } + + /*! + */ + bool ElementExists( int i, int j, int k ) const override + { + PCL_PRECONDITION( i >= 0 && i < Size() ) + PCL_PRECONDITION( j >= 0 && j < Size() ) + PCL_PRECONDITION( k >= 0 && k < NumberOfWays() ) + return m_bitmaps[k][i + j*Size()] == 'x'; + } + +protected: + + bitmap_set m_bitmaps; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_StructuringElement_h + +// ---------------------------------------------------------------------------- +// EOF pcl/StructuringElement.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SurfacePolynomial.h b/3rdparty/include/pcl/SurfacePolynomial.h new file mode 100644 index 0000000..07b5079 --- /dev/null +++ b/3rdparty/include/pcl/SurfacePolynomial.h @@ -0,0 +1,546 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SurfacePolynomial.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_SurfacePolynomial_h +#define __PCL_SurfacePolynomial_h + +/// \file pcl/SurfacePolynomial.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class SurfacePolynomial + * \brief Two-dimensional interpolating/approximating surface polynomial. + * + * %SurfacePolynomial implements interpolating surface polynomials for + * arbitrarily distributed input nodes in two dimensions. + * + * Compared to surface splines (also known as thin plates), surface + * polynomials are much more rigid, that is, much less adaptable to local + * function variations. This can be a desirable property in some scenarios. An + * important drawback of polynomials is that they are prone to oscillations, + * especially for relatively high interpolation orders greater than three. An + * important advantage is that they are fast even for very large data sets. + * + * \sa SurfaceSpline + */ +template +class PCL_CLASS SurfacePolynomial +{ +public: + + /*! + * Represents a vector of coordinates, function values or polynomial + * coefficients. + */ + typedef GenericVector vector_type; + + /*! + * The numeric type used to represent coordinates, function values and + * polynomial coefficients. + */ + typedef typename vector_type::scalar scalar; + + /*! + * Default constructor. Constructs an empty, two-dimensional interpolating + * surface polynomial of third degree. + */ + SurfacePolynomial() = default; + + /*! + * Copy constructor. + */ + SurfacePolynomial( const SurfacePolynomial& ) = default; + + /*! + * Move constructor. + */ + SurfacePolynomial( SurfacePolynomial&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~SurfacePolynomial() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SurfacePolynomial& operator =( const SurfacePolynomial& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SurfacePolynomial& operator =( SurfacePolynomial&& ) = default; + + /*! + * Returns true iff this surface polynomial is valid. A valid surface + * polynomial has been initialized with a sufficient number of nodes. + */ + bool IsValid() const + { + return !m_polynomial.IsEmpty(); + } + + /*! + * Returns the degree of this surface polynomial. + */ + int Degree() const + { + return m_degree; + } + + /*! + * Sets the degree of this surface polynomial. + * + * \param degree Polynomial degree. Must be ≥ 1. + * + * Calling this member function implicitly resets this %SurfacePolynomial + * object and destroys all internal working structures. + * + * High-degree polynomials, especially for degrees higher than three, tend + * to oscillate and may generate artifacts in the interpolated surface. + * + * The default degree is 3. Recommended values are 2, 3 and 4. + */ + void SetDegree( int degree ) + { + PCL_PRECONDITION( degree >= 1 ) + Clear(); + m_degree = pcl::Max( 1, degree ); + } + + /*! + * Generation of a two-dimensional surface polynomial. + * + * \param x X node coordinates. + * + * \param y Y node coordinates. + * + * \param z Node values. + * + * \param n Number of nodes. Must be ≥ 3 + * (3 nodes * 2 coordinates = six degrees of freedom). + * + * The input nodes can be arbitrarily distributed, and they don't need to + * follow any specific order. However, all nodes must be distinct with + * respect to the machine epsilon for the floating point type T. + */ + void Initialize( const T* x, const T* y, const T* z, int n ) + { + PCL_PRECONDITION( x != nullptr && y != nullptr && z != nullptr ) + PCL_PRECONDITION( n > 2 ) + + if ( n < 3 ) + throw Error( "At least three input nodes are required in SurfacePolynomial::Initialize()" ); + + Clear(); + + // Find mean coordinate values + m_x0 = m_y0 = 0; + for ( int i = 0; i < n; ++i ) + { + m_x0 += x[i]; + m_y0 += y[i]; + } + m_x0 /= n; + m_y0 /= n; + + // Find radius of unit circle + m_r0 = 0; + for ( int i = 0; i < n; ++i ) + { + double dx = m_x0 - x[i]; + double dy = m_y0 - y[i]; + double r = Sqrt( dx*dx + dy*dy ); + if ( r > m_r0 ) + m_r0 = r; + } + if ( 1 + m_r0 == 1 ) + throw Error( "SurfacePolynomial::Initialize(): Empty or insignificant interpolation space" ); + + m_r0 = 1/m_r0; + + const int size = (m_degree + 1)*(m_degree + 2) >> 1; + + DMatrix M( 0.0, size, size ); + DVector R( 0.0, size ); + { + // Transform coordinates to unit circle + DVector X( n ), Y( n ); + for ( int i = 0; i < n; ++i ) + { + X[i] = m_r0*(x[i] - m_x0); + Y[i] = m_r0*(y[i] - m_y0); + } + + GenericVector Z( n ); + for ( int k = 0; k < n; ++k ) + { + Z[k] = DVector( size ); + for ( int i = 0, l = 0; i <= m_degree; ++i ) + for ( int j = 0; j <= m_degree-i; ++j, ++l ) + Z[k][l] = PowI( X[k], i ) * PowI( Y[k], j ); + } + + int n2 = n*n; + for ( int i = 0; i < size; ++i ) + { + for ( int j = 0; j < size; ++j ) + { + for ( int k = 0; k < n; ++k ) + M[i][j] += Z[k][i] * Z[k][j]; + M[i][j] /= n2; + } + + for ( int k = 0; k < n; ++k ) + R[i] += z[k] * Z[k][i]; + R[i] /= n2; + } + } + + for ( int i = 0; i < size; ++i ) + { + double pMi = M[i][i]; + if ( M[i][i] != 0 ) + { + for ( int j = i; j < size; ++j ) + M[i][j] /= pMi; + R[i] /= pMi; + } + + for ( int k = 1; i+k < size; ++k ) + { + double pMk = M[i+k][i]; + if ( M[i+k][i] != 0 ) + { + for ( int j = i; j < size; ++j ) + { + M[i+k][j] /= pMk; + M[i+k][j] -= M[i][j]; + } + R[i+k] /= pMk; + R[i+k] -= R[i]; + } + } + } + + m_polynomial = vector_type( size ); + for ( int i = size; --i >= 0; ) + { + m_polynomial[i] = scalar( R[i] ); + for ( int j = i; --j >= 0; ) + R[j] -= M[j][i]*R[i]; + } + } + + /*! + * Two-dimensional surface polynomial interpolation. Returns an interpolated + * value at the specified \a x and \a y coordinates. + */ + T operator ()( double x, double y ) const + { + PCL_PRECONDITION( !m_polynomial.IsEmpty() ) + + double dx = m_r0*(x - m_x0); + double dy = m_r0*(y - m_y0); + double z = 0; + double px = 1; + for ( int i = 0, l = 0; ; px *= dx ) + { + double py = 1; + for ( int j = 0; j <= m_degree-i; py *= dy, ++j, ++l ) + z += m_polynomial[l]*px*py; + if ( ++i > m_degree ) + break; + } + return T( z ); + } + + /*! + * Resets this surface polynomial interpolation, deallocating all internal + * working structures. + */ + void Clear() + { + m_polynomial.Clear(); + } + +protected: + + double m_r0 = 1; // scaling factor for normalization of node coordinates + double m_x0 = 0; // zero offset for normalization of X node coordinates + double m_y0 = 0; // zero offset for normalization of Y node coordinates + int m_degree = 3; // polynomial degree > 0 + vector_type m_polynomial; // coefficients of the 2-D surface polynomial +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PointSurfacePolynomial + * \brief Vector polynomial interpolation/approximation in two dimensions + * + * The template parameter P represents an interpolation point in two + * dimensions. The type P must implement P::x and P::y data members accessible + * from the current %PointSurfacePolynomial template specialization. These + * members must provide the values of the horizontal and vertical coordinates, + * respectively, of an interpolation point. In addition, the scalar types of + * the P::x and P::y point members must support conversion to double semantics. + */ +template +class PCL_CLASS PointSurfacePolynomial +{ +public: + + /*! + * Represents an interpolation point in two dimensions. + */ + typedef P point; + + /*! + * Represents a sequence of interpolation points. + */ + typedef Array point_list; + + /*! + * Represents a coordinate interpolating/approximating surface. + */ + typedef SurfacePolynomial surface; + + /*! + * Default constructor. Yields an empty instance that cannot be used without + * initialization. + */ + PointSurfacePolynomial() = default; + + /*! + * Copy constructor. + */ + PointSurfacePolynomial( const PointSurfacePolynomial& ) = default; + + /*! + * Move constructor. + */ + PointSurfacePolynomial( PointSurfacePolynomial&& ) = default; + + /*! + * Constructs a %PointSurfacePolynomial object initialized for the + * specified input data and interpolation parameters. + * + * See the corresponding Initialize() member function for a detailed + * description of parameters. + */ + PointSurfacePolynomial( const point_list& P1, const point_list& P2, int degree = 3 ) + { + Initialize( P1, P2, degree ); + } + + /*! + * Constructs a %PointSurfacePolynomial object initialized with prescribed + * point surface interpolations. + * + * See the corresponding Initialize() member function for a more detailed + * description of parameters and their required conditions. + */ + PointSurfacePolynomial( const surface& Sx, const surface& Sy ) + { + Initialize( Sx, Sy ); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PointSurfacePolynomial& operator =( const PointSurfacePolynomial& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PointSurfacePolynomial& operator =( PointSurfacePolynomial&& ) = default; + + /*! + * Initializes this %PointSurfacePolynomial object for the specified + * input data and interpolation parameters. + * + * \param P1 A sequence of distinct interpolation node points. + * + * \param P2 A sequence of interpolation values. For each point in + * \a P1, the coordinates of its counterpart point in + * \a P2 will be used as the interpolation node values in + * the X and Y directions. + * + * \param degree Polynomial degree. Must be ≥ 1. The default value is + * 3. See SurfacePolynomial::SetDegree() for a complete + * description of this parameter. + * + * The input nodes can be arbitrarily distributed and don't need to follow + * any specific order. However, all node points should be distinct with + * respect to the machine epsilon for the floating point type used to + * represent coordinates. + * + * See the SurfacePolynomial::Initialize() member function for a complete + * description of this initialization process. + */ + void Initialize( const point_list& P1, const point_list& P2, int degree = 3 ) + { + PCL_PRECONDITION( P1.Length() >= 3 ) + PCL_PRECONDITION( P1.Length() <= P2.Length() ) + PCL_PRECONDITION( degree > 0 ) + + m_Sx.Clear(); + m_Sy.Clear(); + + m_Sx.SetDegree( degree ); + m_Sy.SetDegree( degree ); + + if ( P1.Length() < 3 || P2.Length() < 3 ) + throw Error( "PointSurfacePolynomial::Initialize(): At least three input nodes must be specified." ); + + if ( P2.Length() < P1.Length() ) + throw Error( "PointSurfacePolynomial::Initialize(): Incompatible point array lengths." ); + + DVector X( int( P1.Length() ) ), + Y( int( P1.Length() ) ), + Zx( int( P1.Length() ) ), + Zy( int( P1.Length() ) ); + for ( int i = 0; i < X.Length(); ++i ) + { + X[i] = P1[i].x; + Y[i] = P1[i].y; + Zx[i] = P2[i].x; + Zy[i] = P2[i].y; + } + m_Sx.Initialize( X.Begin(), Y.Begin(), Zx.Begin(), X.Length() ); + m_Sy.Initialize( X.Begin(), Y.Begin(), Zy.Begin(), X.Length() ); + } + + /*! + * Deallocates internal structures, yielding an empty object that cannot be + * used before a new call to Initialize(). + */ + void Clear() + { + m_Sx.Clear(); + m_Sy.Clear(); + } + + /*! + * Returns true iff this is a valid, initialized object ready for + * interpolation. + */ + bool IsValid() const + { + return m_Sx.IsValid() && m_Sy.IsValid(); + } + + /*! + * Returns a reference to the internal object used for interpolation in the + * X plane direction. + */ + const surface& SurfaceX() const + { + return m_Sx; + } + + /*! + * Returns a reference to the internal object used for interpolation in the + * Y plane direction. + */ + const surface& SurfaceY() const + { + return m_Sy; + } + + /*! + * Returns an interpolated point at the specified coordinates. + */ + template + DPoint operator ()( T x, T y ) const + { + return DPoint( m_Sx( x, y ), m_Sy( x, y ) ); + } + + /*! + * Returns an interpolated point at the given \a p.x and \a p.y coordinates. + */ + template + DPoint operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + +private: + + /* + * The surface interpolations in the X and Y plane directions. + */ + surface m_Sx, m_Sy; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SurfacePolynomial_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SurfacePolynomial.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SurfaceSimplifier.h b/3rdparty/include/pcl/SurfaceSimplifier.h new file mode 100644 index 0000000..ab52875 --- /dev/null +++ b/3rdparty/include/pcl/SurfaceSimplifier.h @@ -0,0 +1,581 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SurfaceSimplifier.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_SurfaceSimplifier_h +#define __PCL_SurfaceSimplifier_h + +/// \file pcl/SurfaceSimplifier.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * Default tolerance for surface simplification. + * + * The tolerance parameter determines the maximum absolute deviation of + * function values from a plane allowed to simplify the subset of points within + * a subregion of the input point space. This parameter is specified in + * bivariate function values, i.e. in Z-axis units. + */ +#define __PCL_SURFACE_SIMPLIFIER_DEFAULT_TOLERANCE 0.01 + +/* + * Default state of the surface simplification outlier rejection feature. + * + * When enabled, a prescribed fraction of outlier points will be rejected on + * each subregion for estimation of local curvature. + */ +#define __PCL_SURFACE_SIMPLIFIER_DEFAULT_REJECTION_ENABLED true + +/* + * Default rejection fraction for surface simplification. + * + * This parameter specifies the maximum fraction of outliers allowed for + * simplification of a subset of points in a region of the input point space. + * Point rejection makes the surface simplification algorithm robust to outlier + * function values. + */ +#define __PCL_SURFACE_SIMPLIFIER_DEFAULT_REJECT_FRACTION 0.2F + +/* + * Whether to include subregion centroids in simplified point sets. + * + * When enabled, the centroid of each simplified subregion will also be + * included in the corresponding list of simplified points. This can improve + * the shape preservation behavior of the surface simplification algorithm, at + * the cost of a reduced amount of additional points. + */ +#define __PCL_SURFACE_SIMPLIFIER_DEFAULT_INCLUDE_CENTROIDS false + +// ---------------------------------------------------------------------------- + +/*! + * \class SurfaceSimplifier + * \brief Shape-preserving simplification of 2-D surfaces + * + * Given a finite set of three dimensional points representing sampled values + * of a real bivariate function of the form + * + * z = f(x,y), + * + * the shape-preserving surface simplification algorithm attempts to generate a + * reduced set of points with equivalent geometric properties to within a + * prescribed maximum error parameter. + * + * The implemented algorithm divides the input point space recursively on the + * XY plane into rectangular regions using custom quadtree structures. For each + * region, the algorithm finds the orientation of the dominant plane through + * principal component analysis. The deviation of function values from the + * dominant plane is evaluated for the points in the region, and if the region + * is considered flat to within a tolerance parameter, its points are replaced + * with a simplified (reduced) set of points that tends to preserve the local + * shape of the original function over the region. If the region is tagged as + * curve, it is further divided using a new quadtree recursion, until no + * additional simplification can be achieved. + * + * Surface simplification is an important auxiliary tool to improve the + * practical application of surface interpolation and approximation devices. + * These algorithms allow us to work with large-scale data sets by selecting a + * subset of essential data points, usually much smaller than the original set, + * adapted to solve a particular problem. Surface simplification is + * particularly useful for the application of computationally expensive + * approximation algorithms, such as surface splines or thin plates. A good + * example is computation of high accuracy astrometric solutions, where surface + * simplification allows us to use large sets of thousands of stars to generate + * thin plate models of local distortions. Since generation of thin plates has + * roughly O(N^3) time complexity, the efficient reduction of input point sets + * is crucial for this application. + */ +class PCL_CLASS SurfaceSimplifier +{ +private: + + /*! + * \struct SurfaceSimplifier::point + * \brief Working 3-D point structure for quadtree storage used by the + * recursive surface simplification algorithm. + * \internal + */ + struct point + { + typedef double component; + + component x, y, z; + + point() = default; + point( const point& ) = default; + + template + point( T a_x, T a_y, T a_z ) + : x( double( a_x ) ) + , y( double( a_y ) ) + , z( double( a_z ) ) + { + } + + template + point( T k ) + { + x = y = z = double( k ); + } + + component operator[]( int i ) const + { + return i ? y : x; + } + + point& operator +=( const point& p ) + { + x += p.x; y += p.y; z += p.z; + return *this; + } + + template + point& operator /=( T k ) + { + x /= k; y /= k; z /= k; + return *this; + } + + double SquaredDistanceTo( const point& p ) const + { + double dx = p.x - x, dy = p.y - y; + return dx*dx + dy*dy; + } + }; + + typedef QuadTree tree; + + typedef typename tree::rectangle rectangle; + + typedef typename tree::point_list point_list; + +public: + + /*! + * Constructs a new %SurfaceSimplifier object with default parameters: + * + * \li Tolerance = 0.01 in function value units (Z-axis values). + * \li Outlier rejection enabled + * \li Outlier rejection fraction = 0.2 + * \li Inclusion of centroid points disabled + */ + SurfaceSimplifier() = default; + + /*! + * Constructs a new %SurfaceSimplifier instance with the specified + * \a tolerance. + */ + SurfaceSimplifier( double tolerance ) + : m_tolerance( Abs( tolerance ) ) + { + PCL_PRECONDITION( tolerance >= 0 ) + } + + /*! + * Copy constructor. + */ + SurfaceSimplifier( const SurfaceSimplifier& ) = default; + + /*! + * Returns the current tolerance of this surface simplifier. + * + * See the SetTolerance() member function for a description of the + * tolerance parameter. + */ + double Tolerance() const + { + return m_tolerance; + } + + /*! + * Sets the \a tolerance of this surface simplifier. + * + * The tolerance parameter determines the maximum absolute deviation of + * function values from a plane allowed to simplify the subset of points + * within a subregion of the input point space. + * + * The value of this parameter is specified in bivariate function value + * units, i.e. in Z-axis units. Higher tolerances tend to allow for more + * simplification, and hence for shorter simplified point lists. However, an + * excessive tolerance value may degrade the accuracy of the simplified + * surface in terms of preservation of the original function's structure and + * shape. This parameter must be tailored carefully to the requirements of + * the function being simplified and the tasks where the simplified version + * is going to be applied. + */ + void SetTolerance( double tolerance ) + { + PCL_PRECONDITION( tolerance > 0 ) + m_tolerance = Abs( tolerance ); + } + + /*! + * Returns true iff outlier rejection is enabled for this object. + * + * See the EnableRejection() and RejectFraction() member functions for a + * description of outlier rejection in the surface simplification algorithm. + */ + bool IsRejectionEnabled() const + { + return m_enableRejection; + } + + /*! + * Enables outlier rejection for this surface simplifier. + * + * When enabled, a prescribed fraction of outlier points (see the + * RejectFraction() member function) will be rejected on each subregion for + * estimation of local curvature. An adequate amount of rejection is + * important to achieve a robust result, especially for simplification of + * noisy data where outliers may generate false curvatures that prevent + * efficient simplification. + */ + void EnableRejection( bool enabled = true ) + { + m_enableRejection = enabled; + } + + /*! + * Disables outlier rejection for this surface simplifier. See + * EnableRejection() for more information. + */ + void DisableRejection( bool disable = true ) + { + EnableRejection( !disable ); + } + + /*! + * Returns the fraction of outlier points rejected for estimation of local + * curvature. + * + * See the EnableRejection() and RejectFraction() member functions for a + * description of outlier rejection in the surface simplification algorithm. + */ + float RejectFraction() const + { + return m_rejectFraction; + } + + /*! + * Sets the fraction of outlier points rejected by this surface simplifier. + * + * This parameter defines a fraction of outlier points that will be rejected + * on each subregion of the point space being simplified, for estimation of + * local curvature. + * + * Rejecting an adequate fraction of points makes the surface simplification + * algorithm more immune to noise in the input data, including erroneous + * points that may deviate considerably from the true surface represented by + * the sampled function. The result is a more robust and accurate simplified + * surface. However, too high of a rejection fraction may remove significant + * data and lead to an inaccurate result. + * + * The specified \a rejectFraction value must be in the (0,1) range. The + * default value upon construction is 0.2, which is quite appropriate in + * most cases. + */ + void SetRejectFraction( float rejectFraction ) + { + PCL_PRECONDITION( rejectFraction > 0 && rejectFraction < 1 ) + m_rejectFraction = Range( rejectFraction, 0.0F, 1.0F ); + } + + /*! + * Returns true iff inclusion of centroid points is enabled for this object. + * + * See the EnableCentroidInclusion() member function for a description of + * the centroid inclusion feature of the surface simplification algorithm. + */ + bool IsCentroidInclusionEnabled() const + { + return m_includeCentroids; + } + + /*! + * Enables inclusion of centroid points for this surface simplifier. + * + * When a subregion of the input space is simplified, the surface + * simplification algorithm replaces the subset of points in the subregion + * with a simplified, reduced set. If this option is enabled, the average + * point of the subset, also known as \e centroid, is also included in the + * simplified point list. This usually improves the shape preservation + * behavior of the algorithm, at the cost of a small amount of additional + * points in the simplified point list. + */ + void EnableCentroidInclusion( bool enable = true ) + { + m_includeCentroids = enable; + } + + /*! + * Disables inclusion of centroid points for this surface simplifier. See + * EnableCentroidInclusion() for more information. + */ + void DisableCentroidInclusion( bool disable = true ) + { + EnableCentroidInclusion( !disable ); + } + + /*! + * Attempts to simplify a set of points given by its separate coordinates + * and function values. + * + * \param[out] xs The X coordinates of the simplified point set. + * + * \param[out] ys The Y coordinates of the simplified point set. + * + * \param[out] zs The function values for the simplified point set. + * + * \param x The X coordinates of the input point set. + * + * \param y The Y coordinates of the input point set. + * + * \param z The function values for the input point set. + * + * The template argument C must be a direct container of numeric scalars + * with random access semantics, such as Array or GenericVector. + * + * If the specified surface can be simplified with the current working + * parameters defined for this object, the output containers will have less + * elements (usually \e much less) than the input containers. Otherwise an + * exact copy of the input containers will be obtained in \a xs, \a ys and + * \a zs. This will happen also if the input containers have less than four + * coordinates, since a triangular facet cannot be simplified. + */ + template + void Simplify( C& xs, C& ys, C& zs, const C& x, const C& y, const C& z ) const + { + int n = int( Min( Min( x.Length(), y.Length() ), z.Length() ) ); + if ( n < 4 ) + { + xs = x; ys = y; zs = z; + return; + } + + point_list P; + for ( int i = 0; i < n; ++i ) + P << point( x[i], y[i], z[i] ); + + tree R( P, n ); + P = Simplify( R ); + if ( int( P.Length() ) >= n ) + { + xs = x; ys = y; zs = z; + return; + } + + R.Build( P, n ); + P = Simplify( R ); + + n = int( P.Length() ); + xs = C( n ); + ys = C( n ); + zs = C( n ); + for ( int i = 0; i < n; ++i ) + { + xs[i] = typename C::item_type( P[i].x ); + ys[i] = typename C::item_type( P[i].y ); + zs[i] = typename C::item_type( P[i].z ); + } + } + +private: + + double m_tolerance = __PCL_SURFACE_SIMPLIFIER_DEFAULT_TOLERANCE; + float m_rejectFraction = __PCL_SURFACE_SIMPLIFIER_DEFAULT_REJECT_FRACTION; + bool m_enableRejection = __PCL_SURFACE_SIMPLIFIER_DEFAULT_REJECTION_ENABLED; + bool m_includeCentroids = __PCL_SURFACE_SIMPLIFIER_DEFAULT_INCLUDE_CENTROIDS; + + /*! + * Recursive part of the shape-preserving surface simplification algorithm. + * Returns the simplified point list for the set of points stored in the + * local quadtree \a R. + * \internal + */ + point_list Simplify( tree& R ) const + { + point_list Q; + R.Traverse( + [&Q,this]( const rectangle& rect, point_list& points, void*& ) + { + int n = int( points.Length() ); + if ( n < 4 ) // cannot simplify triangles + { + Q << points; + return; + } + + /* + * Compute local centroid coordinates. + */ + point p0( 0 ); + for ( const point& p : points ) + p0 += p; + p0 /= n; + + /* + * Form the covariance matrix. + */ + double xx = 0, xy = 0, xz = 0, yy = 0, yz = 0, zz = 0; + for ( const point& p : points ) + { + double dx = p.x - p0.x; + double dy = p.y - p0.y; + double dz = p.z - p0.z; + xx += dx*dx; + xy += dx*dy; + xz += dx*dz; + yy += dy*dy; + yz += dy*dz; + zz += dz*dz; + } + int n1 = n - 1; + xx /= n1; + xy /= n1; + xz /= n1; + yy /= n1; + yz /= n1; + zz /= n1; + Matrix M( xx, xy, xz, + xy, yy, yz, + xz, yz, zz ); + + /* + * Test all local function values against the plane fitted at the + * centroid, with optional outlier rejection. The plane normal + * vector is the least eigenvector, from which we can form the + * plane equation: ax + by + cz = 0. + */ + ComputeEigenvectors( M ); + double a = M[0][0]; + double b = M[1][0]; + double c = M[2][0]; + int mr = m_enableRejection ? Max( 1, TruncInt( m_rejectFraction*n ) ) : 1; // max. number of outliers + int nr = 0; + point_list P = points; + for ( point& p : P ) + { + double z = p0.z - (a*(p.x - p0.x) + b*(p.y - p0.y))/c; + if ( Abs( p.z - z ) > m_tolerance ) + { + if ( ++nr == mr ) + { + /* + * If the current region deviates from the fitted plane + * more than allowed by the tolerance parameter after + * outlier rejection, try to simplify it further with a + * deeper quadtree subdivision. + */ + tree R( points, TruncInt( 0.75*n ) ); + Q << Simplify( R ); + return; + } + + // Winsorize outlier function values. + p.z = (p.z > z) ? z + m_tolerance : z - m_tolerance; + } + } + + /* + * If the current region is flat to within the tolerance parameter, + * take the convex hull as its simplified point set. This is what + * makes our simplification algorithm shape-preserving. + */ + if ( m_includeCentroids ) + { + // If one or more points have been rejected, calculate a new + // centroid function value from Winsorized z coordinates. + if ( nr > 0 ) + { + p0.z = 0; + for ( const point& p : P ) + p0.z += p.z; + p0.z /= n; + } + Q << p0; + } + Q << ConvexHull( P ); + } + ); + + return Q; + } + + /*! + * \internal + * Compute the eigenvectors of a 3x3 symmetric matrix. + */ + static void ComputeEigenvectors( Matrix& ); + + /*! + * \internal + * Compute the convex hull of a point set. + */ + static point_list ConvexHull( point_list& ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SurfaceSimplifier_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SurfaceSimplifier.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/SurfaceSpline.h b/3rdparty/include/pcl/SurfaceSpline.h new file mode 100644 index 0000000..e5eb2e5 --- /dev/null +++ b/3rdparty/include/pcl/SurfaceSpline.h @@ -0,0 +1,2011 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/SurfaceSpline.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_SurfaceSpline_h +#define __PCL_SurfaceSpline_h + +/// \file pcl/SurfaceSpline.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION +# include +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/* + * Default quadtree bucket capacity for recursive surface subspline generation. + */ +#define __PCL_RSSPLINE_DEFAULT_TREE_BUCKET_CAPACITY 64 + +/* + * Default maximum spline length for a non-recursive quadtree node in a + * recursive surface spline. + */ +#define __PCL_RSSPLINE_DEFAULT_SPLINE_MAX_LENGTH 1600 + +/* + * Whether to allow extrapolation outside the interpolation region for + * recursive surface splines. Extrapolation is disabled by default because + * recursively defined subsplines are slightly more prone to oscillation than + * normal surface splines. + */ +#define __PCL_RSSPLINE_DEFAULT_ALLOW_EXTRAPOLATION false + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::RadialBasisFunction + * \brief Implemented radial basis functions (RBFs) for surface spline + * interpolation. + * + * The symbols used in the following table are: + * + * phi(r) The radial basis function evaluated at a point (x,y) + * r Distance to center, r^2 = (x-xc)^2 + (y-yc)^2 + * (xc,yc) Center point + * eps Shape parameter + * + * + * + * + * + * + * + * + * + *
RadialBasisFunction::Unknown Unknown or unsupported function.
RadialBasisFunction::VariableOrder phi(r) = (r^2)^(m-1) * Ln( r^2 )
RadialBasisFunction::ThinPlateSpline phi(r) = r^2 * Ln( r )
RadialBasisFunction::Gaussian phi(r) = Exp( -(eps*r)^2 )
RadialBasisFunction::Multiquadric phi(r) = Sqrt( 1 + (eps*r)^2 )
RadialBasisFunction::InverseMultiquadric phi(r) = 1/Sqrt( 1 + (eps*r)^2 )
RadialBasisFunction::InverseQuadratic phi(r) = 1/( 1 + (eps*r)^2 )
+ */ +namespace RadialBasisFunction +{ + enum value_type + { + Unknown = -1, + VariableOrder = 0, // phi(r) = (r^2)^(m-1) * Ln( r^2 ) + ThinPlateSpline, // phi(r) = r^2 * Ln( r ) + Gaussian, // phi(r) = Exp( -(eps*r)^2 ) + Multiquadric, // phi(r) = Sqrt( 1 + (eps*r)^2 ) + InverseMultiquadric, // phi(r) = 1/Sqrt( 1 + (eps*r)^2 ) + InverseQuadratic, // phi(r) = 1/( 1 + (eps*r)^2 ) + __number_of_items__, + Default = ThinPlateSpline + }; + + inline static bool Validate( int rbf ) + { + return rbf >= 0 && rbf < __number_of_items__; + } +} + +// ---------------------------------------------------------------------------- + +/*! + * \class SurfaceSplineBase + * \brief Base class of two-dimensional surface splines. + */ +class PCL_CLASS SurfaceSplineBase +{ +public: + + /*! + * Represents a radial basis function (RBF) supported by this surface spline + * implementation. + */ + typedef RadialBasisFunction::value_type rbf_type; + +protected: + + /*! + * Default constructor. + */ + SurfaceSplineBase() = default; + + /*! + * Copy constructor. + */ + SurfaceSplineBase( const SurfaceSplineBase& ) = default; + + /*! + * Move constructor. + */ + SurfaceSplineBase( SurfaceSplineBase&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~SurfaceSplineBase() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SurfaceSplineBase& operator =( const SurfaceSplineBase& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SurfaceSplineBase& operator =( SurfaceSplineBase&& ) = default; + + /*! + * Surface spline generation, 32-bit floating point data. + */ + static void Generate( float* __restrict__ c, + rbf_type, double e2, bool polynomial, + const float* __restrict__ x, const float* __restrict__ y, const float* __restrict__ z, + int n, int m, float r, const float* __restrict__ w ); + + /*! + * Surface spline generation, 64-bit floating point data. + */ + static void Generate( double* __restrict__ c, + rbf_type, double e2, bool polynomial, + const double* __restrict__ x, const double* __restrict__ y, const double* __restrict__ z, + int n, int m, float r, const float* __restrict__ w ); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SurfaceSpline + * \brief Two-dimensional interpolating/approximating surface spline. + * + * %SurfaceSpline implements interpolating or smoothing surface splines for + * arbitrarily distributed input nodes in two dimensions using radial basis + * functions (RBFs). + * + * The most distinctive property of surface splines is their high adaptability + * to local variations, which makes them ideal to model complex two dimensional + * functions with high accuracy. These interpolation properties largely depend + * on the employed radial basis functions. The well-known thin plate + * spline function is the default RBF used by this implementation. A thin + * plate spline describes the minimal-energy bending of a thin sheet of metal + * passing through a set of interpolation points in three-dimensional space. + * This physical justification gives thin plate splines accuracy and + * adaptability properties that we have been applying successfully to many + * critical data modeling tasks, including very especially image registration + * and astrometric solutions with arbitrary distortion corrections. + * + * Other RBFs supported by this class include a variable order function that + * allows imposing the derivability order of the interpolation/approximation + * spline, as well as less globally dependent functions such as Gaussian and + * multiquadric RBFs. See the RadialBasisFunction namespace for the complete + * list of supported RBFs. + * + * An important advantage of our implementation is the possibility to control + * adaptability with approximating (or smoothing) surface splines, as opposed + * to interpolating splines, and the possibility to control adaptability both + * as a global property of the modeling device, or on a point-by-point basis. + * + * The main drawback of surface splines is that they are computationally + * expensive, especially for large data sets. Generation of surface splines + * usually requires solving dense linear systems, which involves the use of + * algorithms with O(N^3) complexity (such as the Bunch-Kaufman diagonal + * pivoting method). This limits the applicability of this implementation to + * data sets of no more than about 2000-3000 interpolation nodes using current + * hardware. See the RecursivePointSurfaceSpline class for a more efficient + * implementation to generate local subsplines based on quadtrees. + * + * For fast evaluation of surface splines in massive problems, see the + * GridInterpolation and PointGridInterpolation classes for highly efficient + * discretized implementations. + * + * \sa PointSurfaceSpline, RecursivePointSurfaceSpline, GridInterpolation, + * PointGridInterpolation, ShepardInterpolation, SurfacePolynomial + */ +template +class PCL_CLASS SurfaceSpline : private SurfaceSplineBase +{ +public: + + /*! + * The numeric type used to represent coordinates, function values and + * spline coefficients. + */ + typedef T scalar; + + /*! + * Represents a vector of coordinates, function values or spline + * coefficients. + */ + typedef GenericVector vector; + + /*! + * The numeric type used to represent the interpolation strength of a + * surface interpolation node. + */ + typedef float weight; + + /*! + * Represents a vector of interpolation node weights. + */ + typedef GenericVector weight_vector; + + /*! + * Represents a radial basis function (RBF) supported by this surface spline + * implementation. + */ + typedef SurfaceSplineBase::rbf_type rbf_type; + + /*! + * Default constructor. Constructs an empty, two-dimensional interpolating + * surface spline of second order. + */ + SurfaceSpline() = default; + + /*! + * Copy constructor. + */ + SurfaceSpline( const SurfaceSpline& ) = default; + + /*! + * Move constructor. + */ + SurfaceSpline( SurfaceSpline&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~SurfaceSpline() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SurfaceSpline& operator =( const SurfaceSpline& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SurfaceSpline& operator =( SurfaceSpline&& ) = default; + + /*! + * Returns true iff this surface spline is valid. A valid surface spline has + * been initialized with three or more interpolation nodes. + */ + bool IsValid() const + { + return m_x.Length() >= 3 && m_x.Length() == m_y.Length(); + } + + /*! + * Returns the number of nodes used by this surface spline interpolation. + */ + int Length() const + { + return m_x.Length(); + } + + /*! + * Returns a vector with the X node coordinates used to initialize this + * surface spline. If this object has not been initialized, this function + * returns an empty vector. + */ + vector X() const + { + vector x( m_x.Length() ); + if ( IsValid() ) + for ( int i = 0; i < m_x.Length(); ++i ) + x[i] = m_x0 + m_x[i]/m_r0; + return x; + } + + /*! + * Returns a vector with the Y node coordinates used to initialize this + * surface spline. If this object has not been initialized, this function + * returns an empty vector. + */ + vector Y() const + { + vector y( m_y.Length() ); + if ( IsValid() ) + for ( int i = 0; i < m_y.Length(); ++i ) + y[i] = m_y0 + m_y[i]/m_r0; + return y; + } + + /*! + * Returns the type of radial basis function (RBF) used by this surface + * spline. See the RadialBasisFunction namespace for the list of supported + * RBFs in the current implementation. + */ + rbf_type RBFType() const + { + return m_rbf; + } + + /*! + * Sets the radial basis function that will be used by this surface spline. + * + * Calling this member function implicitly resets this %SurfaceSpline object + * and destroys all internal working structures. If the specified RBF is not + * of a variable order type, the derivability order of this surface spline + * will be reset to second order. + */ + void SetRBFType( rbf_type rbf ) + { + Clear(); + m_rbf = rbf; + } + + /*! + * Returns the shape parameter applied to scale the radial basis function + * used by this surface spline. + * + * The shape parameter is only used by decreasing RBFs, i.e., it is not used + * by the variable order and thin plate spline RBFs, which are + * parameter-free. + */ + double ShapeParameter() const + { + return Sqrt( m_eps2 ); + } + + /*! + * Sets the shape parameter applied to scale the radial basis function used + * by this surface spline. + * + * If the specified value \a eps is zero, an optimal shape parameter value + * will be computed automatically during initialization of spline functions. + * See the Initialize() member function for more information. + * + * Calling this member function implicitly resets this %SurfaceSpline object + * and destroys all internal working structures. + * + * The shape parameter is only used by decreasing RBFs, i.e., it is not used + * by the variable order and thin plate spline RBFs, which are + * parameter-free. + */ + void SetShapeParameter( double eps ) + { + Clear(); + m_eps = Abs( eps ); + m_eps2 = m_eps*m_eps; + } + + /*! + * Returns the derivability order of this surface spline. + */ + int Order() const + { + return m_order; + } + + /*! + * Sets the derivability order of this surface spline. + * + * \param order Derivability order. Must be ≥ 2. + * + * Calling this member function implicitly resets this %SurfaceSpline object + * and destroys all internal working structures. + * + * Specifying a derivability order ≥ 2 is really useful for variable + * order radial basis functions (RadialBasisFunction::VariableOrder). Other + * RBFs are implicitly of second order, so when they are selected the order + * specified by calling this function will only change the polynomial part + * of the surface spline. + * + * Only when a variable order RBF is selected, the surface spline will be + * continuously differentiable up to the specified \a order after a + * subsequent initialization. If the order is too high, an ill-conditioned + * linear system may result even for a set of valid interpolation nodes. + * + * The default order is 2. Recommended values are 2 and 3. + */ + void SetOrder( int order ) + { + PCL_PRECONDITION( order > 1 ) + Clear(); + m_order = pcl::Max( 2, order ); + } + + /*! + * Returns true iff this surface spline adds a stabilizing first-degree + * polynomial to the RBF interpolation/approximation function. + * + * A polynomial part is always enabled by default. Disabling it can generate + * some stability issues, especially for data sets with highly varying node + * values. + */ + bool IsPolynomialEnabled() const + { + return m_havePolynomial; + } + + /*! + * Enables the use of a stabilizing first-degree polynomial added to the RBF + * interpolation/approximation function. + * + * Calling this member function implicitly resets this %SurfaceSpline object + * and destroys all internal working structures. + */ + void EnablePolynomial( bool enable = true ) + { + Clear(); + m_havePolynomial = enable; + } + + /*! + * Disables the use of a stabilizing first-degree polynomial added to the + * RBF interpolation/approximation function. + * + * Calling this member function implicitly resets this %SurfaceSpline object + * and destroys all internal working structures. + */ + void DisablePolynomial( bool disable = true ) + { + EnablePolynomial( !disable ); + } + + /*! + * Returns the smoothing factor of this surface spline. See + * SetSmoothing() for more information. + */ + float Smoothing() const + { + return m_smoothing; + } + + /*! + * Sets the smoothing factor of this surface spline. + * + * \param s Smoothing factor. Must be ≥ 0. + * + * For \a s = 0, an interpolating surface spline will be generated: all node + * values will be reproduced exactly at their respective coordinates. + * + * For \a s > 0, a smoothing (or approximating) surface spline will be + * generated: increasing \a s values will generate splines closer to the + * reference plane of the input node set. + * + * \note This parameter is only used for the thin plate spline and variable + * order spline radial basis functions. For other RBFs only interpolation + * surface splines can be generated with this implementation, and hence this + * parameter is always ignored. + */ + void SetSmoothing( float s ) + { + PCL_PRECONDITION( s >= 0 ) + Clear(); + m_smoothing = pcl::Max( 0.0F, s ); + } + + /*! + * Generation of a two-dimensional surface spline (thin plate). + * + * \param x X node coordinates. + * + * \param y Y node coordinates. + * + * \param z Node function values. + * + * \param n Number of nodes. Must be ≥ 3 + * (3 nodes * 2 coordinates = six degrees of freedom). + * + * \param w When the smoothing factor of this spline is > 0, this is a + * vector of positive weights > 0 corresponding to the + * specified input nodes. If this parameter is \c nullptr, + * unit weights are assumed for all input nodes. When the + * smoothing factor is zero (interpolating spline), this + * parameter is ignored. + * + * The input nodes can be arbitrarily distributed, and they don't need to + * follow any specific order. However, all nodes should be distinct with + * respect to the machine epsilon for the floating point type T. + * + * This initialization function includes a sanitization routine. If there + * are duplicate points in the specified set of input nodes, only the first + * occurrence of each duplicate will be kept to build the surface spline, + * and the rest of duplicate points will be ignored. Two points are + * considered equal if their coordinates don't differ more than the machine + * epsilon for the floating point type T. + * + * For an interpolating surface spline (when smoothness = 0), all node + * function values will be reproduced exactly at their respective + * coordinates. In this case the vector \a w of node weights will be + * ignored. + * + * For an approximating surface spline (smoothness > 0), if a vector \a w of + * node weights is specified, it will be used to assign a different + * interpolation \e strength to each interpolation node. In this case the + * vector \a w must have at least \a n values greater than zero. A node + * weight larger than one will reduce the smoothness of the interpolating + * surface at the corresponding node coordinates, or in other words, it will + * give more prominence to the corresponding data point. A node weight of + * one will apply the current surface smoothness at its node position. A + * node weight smaller than one will increase the interpolation smoothness. + * + * \note The smoothing factor and the \a w parameter are only used for the + * thin plate spline and variable order spline radial basis functions. For + * other RBFs only interpolation surface splines can be generated with this + * implementation, and hence the \a w parameter is always ignored. + */ + void Initialize( const scalar* x, const scalar* y, const scalar* z, int n, const weight* w = nullptr ) + { + PCL_PRECONDITION( x != nullptr && y != nullptr && z != nullptr ) + PCL_PRECONDITION( n > 2 ) + + if ( x == nullptr || y == nullptr || z == nullptr ) + throw Error( "SurfaceSpline::Initialize(): Null vector pointer(s)." ); + + if ( n < 3 ) + throw Error( "SurfaceSpline::Initialize(): At least three input nodes must be specified." ); + + Clear(); + + if ( m_smoothing <= 0 ) + w = nullptr; + + try + { + /* + * Find mean coordinates. + */ + m_x0 = m_y0 = 0; + for ( int i = 0; i < n; ++i ) + { + m_x0 += x[i]; + m_y0 += y[i]; + } + m_x0 /= n; + m_y0 /= n; + + /* + * Find radius of largest containing circle. + */ + m_r0 = 0; + for ( int i = 0; i < n; ++i ) + { + double dx = x[i] - m_x0; + double dy = y[i] - m_y0; + double r = Sqrt( dx*dx + dy*dy ); + if ( r > m_r0 ) + m_r0 = r; + } + if ( 1 + m_r0 == 1 ) + throw Error( "SurfaceSpline::Initialize(): Empty or insignificant interpolation space." ); + m_r0 = 1/m_r0; + + /* + * If requested, compute an optimal shape parameter. + */ + if ( m_eps == 0 ) + { + Array R2; + for ( int i = 0; i < n; ++i ) + for ( int j = i; ++j < n; ) + { + double dx = x[i] - x[j]; + double dy = y[i] - y[j]; + R2 << dx*dx + dy*dy; + } + m_eps2 = 1/(m_r0*4*Sqrt( Median( R2.Begin(), R2.End() ) )); + } + else + m_eps2 = m_r0*m_eps; + m_eps2 *= m_eps2; + + /* + * Build point list with normalized node coordinates. + */ + Array P; + for ( int i = 0; i < n; ++i ) + P << NodeData( m_r0*(x[i] - m_x0), + m_r0*(y[i] - m_y0), + z[i], + (w != nullptr && w[i] > 0) ? w[i] : 1.0F ); + + /* + * Find duplicate input nodes. Two nodes are considered equal if their + * (normalized) coordinates don't differ more than the machine epsilon + * for the floating point type T. + */ + P.Sort(); + Array remove; + for ( int i = 0, j = 1; j < n; ++i, ++j ) + if ( Abs( P[i].x - P[j].x ) <= std::numeric_limits::epsilon() ) + if ( Abs( P[i].y - P[j].y ) <= std::numeric_limits::epsilon() ) + remove << i; + + /* + * Build working vectors, excluding duplicate input nodes. + */ + int N = n - int( remove.Length() ); + if ( N < 3 ) + throw Error( "SurfaceSpline::Initialize(): Less than three input nodes left after sanitization." ); + m_x = vector( N ); + m_y = vector( N ); + vector fz( N ); + if ( w != nullptr ) + m_weights = weight_vector( N ); + int i = 0, k = 0; + for ( int j : remove ) + { + for ( ; i < j; ++i, ++k ) + { + m_x[k] = P[i].x; + m_y[k] = P[i].y; + fz[k] = P[i].z; + if ( w != nullptr ) + m_weights[k] = P[i].w; + } + ++i; + } + for ( ; i < n; ++i, ++k ) + { + m_x[k] = P[i].x; + m_y[k] = P[i].y; + fz[k] = P[i].z; + if ( w != nullptr ) + m_weights[k] = P[i].w; + } + + m_spline = vector( scalar( 0 ), N + (m_havePolynomial ? ((m_order*(m_order + 1)) >> 1) : 0) ); + + Generate( m_spline.Begin(), m_rbf, m_eps2, m_havePolynomial, + m_x.Begin(), m_y.Begin(), fz.Begin(), N, m_order, + m_smoothing, m_weights.Begin() ); + } + catch ( ... ) + { + Clear(); + throw; + } + } + + /*! + * Resets this surface spline interpolation, deallocating all internal + * working structures. + */ + void Clear() + { + m_x.Clear(); + m_y.Clear(); + m_weights.Clear(); + m_spline.Clear(); + } + + /*! + * Two-dimensional surface spline interpolation/approximation. Returns an + * approximated or interpolated function value at the specified \a x and + * \a y coordinates. + * + * Before calling this function, a valid surface spline must be generated by + * calling Initialize(). If called fon an uninitialized object, this member + * function invokes undefined behavior. + */ + scalar operator ()( double x, double y ) const + { + PCL_PRECONDITION( !m_x.IsEmpty() && !m_y.IsEmpty() ) + PCL_CHECK( m_order >= 2 ) + PCL_CHECK( !m_spline.IsEmpty() ) + + /* + * Normalized interpolation coordinates. + */ + x = m_r0*(x - m_x0); + y = m_r0*(y - m_y0); + + /* + * Add polynomial part of the surface spline. + */ + int n = m_x.Length(); + double z = 0; + if ( m_havePolynomial ) + { + z += m_spline[n]; + switch ( m_order ) + { + case 2: + z += m_spline[n+1]*x + m_spline[n+2]*y; + break; + case 3: + z += (m_spline[n+1] + m_spline[n+3]*x + m_spline[n+4]*y)*x + (m_spline[n+2] + m_spline[n+5]*y)*y; + break; + default: + for ( int i = 1, j = n+1, i1 = (m_order*(m_order + 1))>>1, ix = 0, iy = 0; i < i1; ++i, ++j ) + if ( ix == 0 ) + { + ix = iy + 1; + iy = 0; + z += m_spline[j] * PowI( x, ix ); + } + else + { + --ix; + ++iy; + z += m_spline[j] * PowI( x, ix ) * PowI( y, iy ); + } + break; + } + } + + /* + * Add radial basis functions. + */ + switch ( m_rbf ) + { + case RadialBasisFunction::VariableOrder: + for ( int i = 0; i < n; ++i ) + { + double dx = m_x[i] - x; + double dy = m_y[i] - y; + double r2 = dx*dx + dy*dy; + if ( r2 != 0 ) + { + double r2m1 = r2; + for ( int j = m_order; --j > 1; ) + r2m1 *= r2; + z += m_spline[i] * r2m1 * pcl::Ln( r2 ); + } + } + break; + case RadialBasisFunction::ThinPlateSpline: + for ( int i = 0; i < n; ++i ) + { + double dx = m_x[i] - x; + double dy = m_y[i] - y; + double r2 = dx*dx + dy*dy; + if ( r2 != 0 ) + z += m_spline[i] * r2 * pcl::Ln( Sqrt( r2 ) ); + } + break; + case RadialBasisFunction::Gaussian: + for ( int i = 0; i < n; ++i ) + { + double dx = m_x[i] - x; + double dy = m_y[i] - y; + z += m_spline[i] * pcl::Exp( -m_eps2 * (dx*dx + dy*dy) ); + } + break; + case RadialBasisFunction::Multiquadric: + for ( int i = 0; i < n; ++i ) + { + double dx = m_x[i] - x; + double dy = m_y[i] - y; + z += m_spline[i] * pcl::Sqrt( 1 + m_eps2 * (dx*dx + dy*dy) ); + } + break; + case RadialBasisFunction::InverseMultiquadric: + for ( int i = 0; i < n; ++i ) + { + double dx = m_x[i] - x; + double dy = m_y[i] - y; + z += m_spline[i] / pcl::Sqrt( 1 + m_eps2 * (dx*dx + dy*dy) ); + } + break; + case RadialBasisFunction::InverseQuadratic: + for ( int i = 0; i < n; ++i ) + { + double dx = m_x[i] - x; + double dy = m_y[i] - y; + z += m_spline[i] / (1 + m_eps2 * (dx*dx + dy*dy)); + } + break; + default: + break; + } + + return scalar( z ); + } + + /*! + * Returns an interpolated/approximated function value at the specified + * \a p.x and \a p.y point coordinates. See operator()( double, double ) for + * more information. + */ + template + scalar operator ()( const GenericPoint& p ) const + { + return operator ()( double( p.x ), double( p.y ) ); + } + +protected: + + rbf_type m_rbf = RadialBasisFunction::Default; + bool m_havePolynomial = true; // use 1st order polynomial for stabilization + double m_eps = 0; // shape parameter, 0 -> find optimal value automatically + double m_eps2 = 0; // squared shape parameter + vector m_x; // vector of normalized X node coordinates + vector m_y; // vector of normalized Y node coordinates + double m_r0 = 1; // scaling factor for normalization of node coordinates + double m_x0 = 0; // zero offset for normalization of X node coordinates + double m_y0 = 0; // zero offset for normalization of Y node coordinates + int m_order = 2; // derivative order >= 2 + float m_smoothing = 0; // <= 0 -> interpolating spline, > 0 -> smoothing factor of approximating spline + weight_vector m_weights; // optional node weights for approximating spline + vector m_spline; // coefficients of the 2-D surface spline, polynomial coeffs. at tail + + /*! + * \struct NodeData + * \brief Auxiliary structure for data sanitization. + * \internal + */ + struct NodeData + { + scalar x, y, z; + weight w; + + NodeData( scalar a_x, scalar a_y, scalar a_z, weight a_w ) + : x( a_x ), y( a_y ), z( a_z ), w( a_w ) + { + } + + bool operator ==( const NodeData& p ) const + { + return x == p.x && y == p.y; + } + + bool operator <( const NodeData& p ) const + { + return (x != p.x) ? x < p.x : y < p.y; + } + }; + + friend class DrizzleData; + friend class DrizzleDataDecoder; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PointSurfaceSpline + * \brief Vector surface spline interpolation/approximation in two dimensions + * + * The template parameter P represents an interpolation point in two + * dimensions. The type P must implement P::x and P::y data members accessible + * from the current %PointSurfaceSpline template specialization. These members + * must provide the values of the horizontal and vertical coordinates, + * respectively, of an interpolation point. In addition, the scalar types of + * the P::x and P::y point members must support conversion to double semantics. + * + * \sa SurfaceSpline, RecursivePointSurfaceSpline + */ +template +class PCL_CLASS PointSurfaceSpline +{ +public: + + /*! + * Represents an interpolation point in two dimensions. + */ + typedef P point; + + /*! + * Represents a sequence of interpolation points. + */ + typedef Array point_list; + + /*! + * Represents a coordinate interpolating/approximating surface spline. + */ + typedef SurfaceSpline spline; + + /*! + * Represents a radial basis function (RBF) supported by this point surface + * spline implementation. + */ + typedef spline::rbf_type rbf_type; + + /*! + * Default constructor. Yields an empty instance that cannot be used without + * initialization. + */ + PointSurfaceSpline() = default; + + /*! + * Copy constructor. + */ + PointSurfaceSpline( const PointSurfaceSpline& ) = default; + + /*! + * Move constructor. + */ + PointSurfaceSpline( PointSurfaceSpline&& ) = default; + + /*! + * Constructs a %PointSurfaceSpline object initialized for the specified + * input data and interpolation parameters. + * + * See the corresponding Initialize() member function for a detailed + * description of parameters. + */ + template + PointSurfaceSpline( const point_list& P1, const point_list& P2, + float smoothness = 0, int order = 2, + const weight_vector& W = weight_vector(), + rbf_type rbf = RadialBasisFunction::Default, + double eps = 0, + bool polynomial = true ) + { + Initialize( P1, P2, smoothness, W, order, rbf, eps, polynomial ); + } + + /*! + * Constructs a %PointSurfaceSpline object initialized with prescribed point + * surface splines. + * + * See the corresponding Initialize() member function for a more detailed + * description of parameters and their required conditions. + */ + PointSurfaceSpline( const spline& Sx, const spline& Sy ) + { + Initialize( Sx, Sy ); + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + PointSurfaceSpline& operator =( const PointSurfaceSpline& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + PointSurfaceSpline& operator =( PointSurfaceSpline&& ) = default; + + /*! + * Initializes this %PointSurfaceSpline object for the specified input data + * and interpolation parameters. + * + * \param P1 A sequence of distinct interpolation node points. + * + * \param P2 A sequence of interpolation values. For each point in + * \a P1, the coordinates of its counterpart point in + * \a P2 will be used as the interpolation node values in + * the X and Y directions. + * + * \param smoothness Smoothing factor. Must be ≥ 0. The default value is + * zero, that is, interpolating surface splines are + * generated by default. + * + * \param W Reference to a vector of positive node \e weights > 0, + * when the smoothing factor is > 1. For an interpolating + * spline this parameter will be ignored (see below). This + * argument must be a reference to a vector or array of + * \c float values. + * + * \param order Derivative order of continuity. Must be ≥ 2. The + * default value is 2. This parameter is only taken into + * account when the \a rbf parameter is + * RadialBasisFunction::VariableOrder. + * + * \param rbf The type of radial basis function (RBF) used for + * surface spline generation. The default is + * RadialBasisFunction::ThinPlateSpline in the current + * implementation. + * + * \param eps The shape parameter used for decreasing radial basis + * functions. Increasing RBFs, such as thin plate splines + * and variable order functions, are parameter-free and + * ignore this parameter. + * + * \param polynomial If true, surface spline generation will include a first + * order polynomial part for stabilization. If false, only + * radial basis functions will be used without a + * polynomial component. + * + * For \a smoothness <= 0, an interpolating spline will be generated: all + * node values will be reproduced exactly at their respective coordinates. + * In this case the \a W parameter will be ignored. + * + * For \a smoothness > 0, a smoothing (or approximating) spline will be + * generated: increasing \a smoothness values will generate splines closer + * to the reference plane of the input node set. If nonempty, the specified + * vector \a W of node weights will be used to assign a different + * interpolation \e strength to each interpolation node. In this case the + * vector \a W must have at least the same length as the shortest of the + * \a P1 and \a P2 vectors, and must contain values greater than zero. A + * node weight larger than one will reduce the smoothness of the + * interpolating surface at the corresponding node coordinates, or in other + * words, it will give more prominence to the corresponding data point. A + * node weight of one will apply the specified \a smoothness at its node + * position. Contrarily, a node weight smaller than one will increase the + * interpolation smoothness locally. + * + * When the variable order RBF is specified, the surface spline will be + * continuously differentiable up to the specified \a order. If this order + * is too high, an ill-conditioned linear system may result, especially for + * large data sets. The recommended values are 2, 3, 4 or 5, but order 2 is + * usually the most useful and safest option for most applications. + * Derivative orders greater than 3 may lead to numerically unstable + * interpolation devices, which should always be used with care. For the + * rest of RBFs the \a order parameter is ignored and second order functions + * are always used. + * + * \note The \a smoothness and \a W parameters are only used for the thin + * plate spline and variable order spline radial basis functions. For other + * RBFs only interpolation surface splines can be generated with this + * implementation, and hence these parameters are always ignored. + */ + template + void Initialize( const point_list& P1, const point_list& P2, + float smoothness = 0, const weight_vector& W = weight_vector(), int order = 2, + rbf_type rbf = RadialBasisFunction::Default, + double eps = 0, + bool polynomial = true ) + { + PCL_PRECONDITION( P1.Length() >= 3 ) + PCL_PRECONDITION( P1.Length() <= P2.Length() ) + PCL_PRECONDITION( order >= 2 ) + PCL_PRECONDITION( W.IsEmpty() || P1.Length() <= W.Length() ) + + Clear(); + + if ( P1.Length() < 3 || P2.Length() < 3 ) + throw Error( "PointSurfaceSpline::Initialize(): At least three input nodes must be specified." ); + + if ( P1.Length() > P2.Length() || + !W.IsEmpty() && P1.Length() > size_type( W.Length() ) ) + throw Error( "PointSurfaceSpline::Initialize(): Insufficient data." ); + + m_Sx.SetRBFType( rbf ); + m_Sx.SetOrder( order ); + m_Sx.SetShapeParameter( eps ); + m_Sx.EnablePolynomial( polynomial ); + m_Sx.SetSmoothing( smoothness ); + + m_Sy.SetRBFType( rbf ); + m_Sy.SetOrder( order ); + m_Sy.SetShapeParameter( eps ); + m_Sy.EnablePolynomial( polynomial ); + m_Sy.SetSmoothing( smoothness ); + + DVector X( int( P1.Length() ) ), + Y( int( P1.Length() ) ), + Zx( int( P1.Length() ) ), + Zy( int( P1.Length() ) ); + for ( int i = 0; i < X.Length(); ++i ) + { + X[i] = P1[i].x; + Y[i] = P1[i].y; + Zx[i] = P2[i].x; + Zy[i] = P2[i].y; + } + m_Sx.Initialize( X.Begin(), Y.Begin(), Zx.Begin(), X.Length(), W.Begin() ); + m_Sy.Initialize( X.Begin(), Y.Begin(), Zy.Begin(), X.Length(), W.Begin() ); + } + + /*! + * \internal + * Internal-use initialization routine. + */ + void Initialize( const DVector& X1, const DVector& Y1, const DVector& Z1, + const DVector& X2, const DVector& Y2, const DVector& Z2, + float smoothness = 0, + const FVector& W1 = FVector(), const FVector& W2 = FVector(), + int order = 2, + rbf_type rbf = RadialBasisFunction::Default, + double eps = 0, + bool polynomial = true ) + { + PCL_PRECONDITION( X1.Length() >= 3 ) + PCL_PRECONDITION( X2.Length() >= 3 ) + PCL_PRECONDITION( X1.Length() <= Y1.Length() ) + PCL_PRECONDITION( X1.Length() <= Z1.Length() ) + PCL_PRECONDITION( W1.IsEmpty() || X1.Length() <= W1.Length() ) + PCL_PRECONDITION( X2.Length() <= Y2.Length() ) + PCL_PRECONDITION( X2.Length() <= Z2.Length() ) + PCL_PRECONDITION( W2.IsEmpty() || X2.Length() <= W2.Length() ) + PCL_PRECONDITION( order >= 2 ) + + Clear(); + + if ( X1.Length() < 3 || X2.Length() < 3 ) + throw Error( "PointSurfaceSpline::Initialize(): At least three input nodes must be specified." ); + + if ( X1.Length() > Y1.Length() || + X1.Length() > Z1.Length() || + !W1.IsEmpty() && X1.Length() > W1.Length() || + X2.Length() > Y2.Length() || + X2.Length() > Z2.Length() || + !W2.IsEmpty() && X2.Length() > W2.Length() ) + throw Error( "PointSurfaceSpline::Initialize(): Insufficient data." ); + + m_Sx.SetRBFType( rbf ); + m_Sx.SetOrder( order ); + m_Sx.SetShapeParameter( eps ); + m_Sx.EnablePolynomial( polynomial ); + m_Sx.SetSmoothing( smoothness ); + m_Sx.Initialize( X1.Begin(), Y1.Begin(), Z1.Begin(), X1.Length(), W1.Begin() ); + + m_Sy.SetRBFType( rbf ); + m_Sy.SetOrder( order ); + m_Sy.SetShapeParameter( eps ); + m_Sy.EnablePolynomial( polynomial ); + m_Sy.SetSmoothing( smoothness ); + m_Sy.Initialize( X2.Begin(), Y2.Begin(), Z2.Begin(), X2.Length(), W2.Begin() ); + } + + /*! + * Initializes this %PointSurfaceSpline object with prescribed point surface + * splines. + * + * \param Sx 2-D point surface spline for interpolation of function values + * in the X direction. + * + * \param Sy 2-D point surface spline for interpolation of function values + * in the Y direction. + * + * Both surface splines must be valid. If one or both splines are invalid, + * calling this member function is equivalent to Clear(). + * + * After calling this member function successfuly, this object will store + * deep copies of the specified surface spline instances. + */ + void Initialize( const spline& Sx, const spline& Sy ) + { + Clear(); + if ( Sx.IsValid() && Sy.IsValid() ) + { + m_Sx = Sx; + m_Sy = Sy; + } + } + + /*! + * Returns an approximation to the inverse surface spline of this object. + * + * The returned object can be used to perform an inverse interpolation: + * Given an interpolation point P2, the returned spline will interpolate the + * corresponding node point P1. See Initialize() for more information on + * spline initialization. + * + * In general, the returned object can only provide an approximation to the + * inverse of the underlying coordinate transformation. In particular, if + * this object has been initialized as an approximating surface spline, its + * inverse spline will compute node point coordinates from approximate + * (smoothed) interpolated coordinates, instead of the original ones. + * + * If two or more interpolation points were identical when this object was + * initialized, calling this member function may lead to an ill-conditioned + * linear system. In such case, an Error exception will be thrown. + * + * If this object has not been initialized, this function returns an + * uninitialized %PointSurfaceSpline object. + */ + PointSurfaceSpline Inverse() const + { + PointSurfaceSpline inverse; + if ( IsValid() ) + { + DVector X = m_Sx.X(), + Y = m_Sx.Y(), + Zx( m_Sx.X().Length() ), + Zy( m_Sx.Y().Length() ); + for ( int i = 0; i < X.Length(); ++i ) + { + Zx[i] = m_Sx( X[i], Y[i] ); + Zy[i] = m_Sy( X[i], Y[i] ); + } + + inverse.m_Sx.SetRBFType( m_Sx.RBFType() ); + inverse.m_Sx.SetOrder( m_Sx.Order() ); + inverse.m_Sx.SetShapeParameter( m_Sx.ShapeParameter() ); + inverse.m_Sx.EnablePolynomial( m_Sx.IsPolynomialEnabled() ); + inverse.m_Sx.Initialize( Zx.Begin(), Zy.Begin(), X.Begin(), X.Length() ); + + inverse.m_Sy.SetRBFType( m_Sy.RBFType() ); + inverse.m_Sy.SetOrder( m_Sy.Order() ); + inverse.m_Sy.SetShapeParameter( m_Sy.ShapeParameter() ); + inverse.m_Sy.EnablePolynomial( m_Sy.IsPolynomialEnabled() ); + inverse.m_Sy.Initialize( Zx.Begin(), Zy.Begin(), Y.Begin(), X.Length() ); + } + return inverse; + } + + /*! + * Deallocates internal structures, yielding an empty spline that cannot be + * used before a new call to Initialize(). + */ + void Clear() + { + m_Sx.Clear(); + m_Sy.Clear(); + } + + /*! + * Returns true iff this is a valid, initialized object ready for + * interpolation. + */ + bool IsValid() const + { + return m_Sx.IsValid() && m_Sy.IsValid(); + } + + /*! + * Returns a reference to the internal surface spline object used for + * interpolation in the X plane direction. + */ + const spline& SplineX() const + { + return m_Sx; + } + + /*! + * Returns a reference to the internal surface spline object used for + * interpolation in the Y plane direction. + */ + const spline& SplineY() const + { + return m_Sy; + } + + /*! + * Returns an interpolated point at the specified coordinates. + */ + template + DPoint operator ()( T x, T y ) const + { + return DPoint( m_Sx( x, y ), m_Sy( x, y ) ); + } + + /*! + * Returns an interpolated point at the given \a p.x and \a p.y coordinates. + */ + template + DPoint operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + +private: + + /* + * The surface splines in the X and Y plane directions. + */ + spline m_Sx, m_Sy; + + friend class DrizzleData; + friend class DrizzleDataDecoder; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class RecursivePointSurfaceSpline + * \brief Vector surface spline interpolation/approximation in two dimensions + * with recursive subspline generation. + * + * This class is a functional replacement for PointSurfaceSpline. It splits the + * interpolation region recursively using quadtrees. At each quadtree leaf node + * a subspline is generated with a subset of the interpolation nodes, with + * additional data redundancy to ensure smoothness across subregion boundaries. + * + * This recursive scheme is appropriate for large-scale problems, where single + * thin plate splines can be impractical because their generation has O(n^3) + * time complexity. An instance of %RecursivePointSurfaceSpline can be built + * with an unlimited number of arbitrarily distributed interpolation points. + * + * \sa PointSurfaceSpline, SurfaceSpline + */ +template +class PCL_CLASS RecursivePointSurfaceSpline : public ParallelProcess +{ +public: + + /*! + * Represents a point surface spline. + */ + typedef PointSurfaceSpline

spline; + + /* + * Represents a recursive point surface spline. + */ + typedef RecursivePointSurfaceSpline

recursive_spline; + + /*! + * Represents an interpolation point in two dimensions. + */ + typedef typename spline::point point; + + /*! + * Represents a sequence of interpolation points. + */ + typedef typename spline::point_list point_list; + + /*! + * Default constructor. Yields an empty instance that cannot be used without + * initialization. + */ + RecursivePointSurfaceSpline() = default; + + /*! + * Copy constructor. Copy construction is disabled because this class uses + * internal data structures that cannot be copy-constructed. However, + * %RecursivePointSurfaceSpline implements move construction and move + * assignment. + */ + RecursivePointSurfaceSpline( const RecursivePointSurfaceSpline& ) = delete; + + /*! + * Copy assignment operator. Copy assignment is disabled because this class + * uses internal data structures that cannot be copy-assigned. However, + * %RecursivePointSurfaceSpline implements move assignment and move + * construction. + */ + RecursivePointSurfaceSpline& operator =( const RecursivePointSurfaceSpline& ) = delete; + + /*! + * Move constructor. + */ + RecursivePointSurfaceSpline( RecursivePointSurfaceSpline&& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + RecursivePointSurfaceSpline& operator =( RecursivePointSurfaceSpline&& ) = default; + + /*! + * Constructs a %RecursivePointSurfaceSpline object initialized for the + * specified input data and interpolation parameters. + * + * See the corresponding Initialize() member function for a detailed + * description of parameters. + */ + template + RecursivePointSurfaceSpline( const point_list& P1, const point_list& P2, + float smoothness = 0, + int order = 2, + const weight_vector& W = weight_vector(), + bool allowExtrapolation = __PCL_RSSPLINE_DEFAULT_ALLOW_EXTRAPOLATION, + int maxSplineLength = __PCL_RSSPLINE_DEFAULT_SPLINE_MAX_LENGTH, + int bucketCapacity = __PCL_RSSPLINE_DEFAULT_TREE_BUCKET_CAPACITY, + bool verbose = true ) + { + Initialize( P1, P2, smoothness, W, order, allowExtrapolation, maxSplineLength, bucketCapacity, verbose ); + } + + /*! + * Virtual destructor. + */ + virtual ~RecursivePointSurfaceSpline() + { + Clear(); + } + + /*! + * Initializes this %RecursivePointSurfaceSpline object for the specified + * input data and interpolation parameters. + * + * \param P1 A sequence of distinct interpolation node points. + * + * \param P2 A sequence of interpolation values. For each point in + * \a P1, the coordinates of its counterpart point in + * \a P2 will be used as the interpolation node values in + * the X and Y directions. + * + * \param smoothness Smoothing factor. Must be ≥ 0 (default = 0). + * + * \param W Reference to a vector of positive node \e weights > 0, + * when the smoothing factor is > 1. For an interpolating + * spline this parameter will be ignored (see below). This + * argument must be a reference to a vector or array of + * \c float values. + * + * \param order Derivative order. Must be ≥ 2 (default = 2). + * + * \param allowExtrapolation Whether to allow extrapolation on points + * exterior to the region defined by the specified set of + * interpolation node points \a P1. Extrapolation is not + * allowed by default because recursively generated + * subsplines are slightly more prone to oscillation than + * normal surface splines. + * + * \param maxSplineLength Maximum length of a point surface spline in a + * non-recursive %RecursivePointSurfaceSpline instance. + * The default value is 1600 points. Be aware that surface + * spline generation has O(n^3) time complexity (that's + * why this class exists after all), and the number of + * generated quadtree nodes grows exponentially with the + * total number of interpolation points. The default value + * is a reasonable compromise for balanced efficiency in + * most practical cases. + * + * \param bucketCapacity Bucket capacity for quadtree generation. The + * default value is 64 points. By decreasing this value + * the recursive surface spline initialization process + * will be faster, but the generated subsplines will be + * less accurate, leading to more border artifacts between + * contiguous quadtree node regions. + * + * \param verbose If true, this function will write information to the + * standard PixInsight console to provide some feedback to + * the user during the (potentially long) initialization + * process. If false, no feedback will be provided. + * + * For \a smoothness ≤ 0, interpolating subsplines will be generated: all + * node values will be reproduced exactly at their respective coordinates. + * In this case the \a W parameter will be ignored. + * + * For \a smoothness > 0, smoothing (or approximating) subsplines will be + * generated: increasing \a smoothness values will generate splines closer + * to the reference planes of their input node sets. If nonempty, the + * specified vector \a W of node weights will be used to assign a different + * interpolation strength to each interpolation node. In this case the + * vector \a W must have at least the same length as the shortest of the + * \a P1 and \a P2 vectors, and must contain values greater than zero. A + * node weight larger than one will reduce the smoothness of the + * interpolating surface at the corresponding node coordinates, or in other + * words, it will give more prominence to the corresponding data point. A + * node weight of one will apply the specified \a smoothness at its node + * position. Contrarily, a node weight smaller than one will increase the + * interpolation smoothness locally. + * + * The generated surface subsplines will be continuously differentiable up + * to the specified \a order. If this order is too high, ill-conditioned + * linear systems may result, especially for large data sets. The + * recommended values are 2, 3, 4 or 5, but order 2 is usually the most + * useful and safest option for most applications. Derivative orders greater + * than 3 may lead to numerically unstable interpolation devices, which + * should always be used with care. + */ + template + void Initialize( const point_list& P1, const point_list& P2, + float smoothness = 0, + const weight_vector& W = weight_vector(), + int order = 2, + bool allowExtrapolation = __PCL_RSSPLINE_DEFAULT_ALLOW_EXTRAPOLATION, + int maxSplineLength = __PCL_RSSPLINE_DEFAULT_SPLINE_MAX_LENGTH, + int bucketCapacity = __PCL_RSSPLINE_DEFAULT_TREE_BUCKET_CAPACITY, + bool verbose = true ) + { + PCL_PRECONDITION( P1.Length() >= 3 ) + PCL_PRECONDITION( P1.Length() <= P2.Length() ) + PCL_PRECONDITION( order >= 2 ) + PCL_PRECONDITION( W.IsEmpty() || P1.Length() <= W.Length() ) + + Clear(); + + if ( P1.Length() < 3 || P2.Length() < 3 ) + throw Error( "RecursivePointSurfaceSpline::Initialize(): At least three input nodes must be specified." ); + + bool weighted = smoothness > 0 && !W.IsEmpty(); + + if ( P1.Length() > P2.Length() || weighted && P1.Length() > size_type( W.Length() ) ) + throw Error( "RecursivePointSurfaceSpline::Initialize(): Insufficient data." ); + + m_extrapolate = allowExtrapolation; + + if ( P1.Length() <= size_type( maxSplineLength ) ) + { + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( "Building surface subsplines", 100 ); + } +#endif + for ( const auto& p : P1 ) + { + if ( p.x < m_rect.x0 ) + m_rect.x0 = p.x; + else if ( p.x > m_rect.x1 ) + m_rect.x1 = p.x; + if ( p.y < m_rect.y0 ) + m_rect.y0 = p.y; + else if ( p.y > m_rect.y1 ) + m_rect.y1 = p.y; + } + + m_spline.Initialize( P1, P2, smoothness, W, order, + (order == 2) ? RadialBasisFunction::ThinPlateSpline + : RadialBasisFunction::VariableOrder ); + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + if ( verbose ) + monitor.Complete(); +#endif + } + else + { + /* + * Find the total interpolation region. + */ + search_rectangle rect = search_coordinate( 0 ); + node_list data; + for ( size_type i = 0; i < P1.Length(); ++i ) + { + const point& p1 = P1[i]; + const point& p2 = P2[i]; + data << (weighted ? Node( p1, p2, W[i] ) : Node( p1, p2 )); + if ( p1.x < rect.x0 ) + rect.x0 = p1.x; + else if ( p1.x > rect.x1 ) + rect.x1 = p1.x; + if ( p1.y < rect.y0 ) + rect.y0 = p1.y; + else if ( p1.y > rect.y1 ) + rect.y1 = p1.y; + } + // Force a square interpolation region for optimal quadtree behavior. + if ( rect.Width() < rect.Height() ) + rect.InflateBy( (rect.Height() - rect.Width())/2, search_coordinate( 0 ) ); + else + rect.InflateBy( search_coordinate( 0 ), (rect.Width() - rect.Height())/2 ); + + /* + * Build the interpolation quadtree. + */ + m_tree.Build( rect, data, bucketCapacity ); + + /* + * Build subspline interpolation data. + */ + Array subsplineData; + m_tree.Traverse( + [&]( const search_rectangle& rect, const node_list& points, void*& D ) + { + /* + * Ensure redundancy for all subsplines by gathering a set of + * interpolation points in an extended rectangular region around + * each quadtree node. + */ + search_rectangle r = rect.InflatedBy( 1.5*Max( rect.Width(), rect.Height() ) ); + node_list N = m_tree.Search( r ); + + /* + * Sort the cloud of interpolation points by proximity to a + * circle centered at the argument of the minimum RBF value + * (approximately 0.61 in normalized coordinates). + */ + if ( N.Length() > size_type( maxSplineLength ) ) + { + point c = rect.Center(); + double d = 0.61 * (Max( r.Width(), r.Height() )/2 + Max( rect.Width(), rect.Height() )/4); + N.Sort( + [&]( const auto& a, const auto& b ) + { + return Abs( a.position.DistanceTo( c ) - d ) < Abs( b.position.DistanceTo( c ) - d ); + } ); + } + + /* + * Get the optimal subset of at most maxSplineLength redundant + * interpolation points for this quadtree node. + */ + point_list P1, P2; + Array PW; + for ( int j = 0, l = Min( int( N.Length() ), maxSplineLength ); j < l; ++j ) + { + P1 << N[j].position; + P2 << N[j].value; + if ( weighted ) + PW << N[j].weight; + } + + subsplineData << SubsplineData( P1, P2, PW, D ); + } ); + + /* + * Generate all subsplines. + */ + StatusMonitor monitor; +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + StandardStatus status; + if ( verbose ) + { + monitor.SetCallback( &status ); + monitor.Initialize( "Building recursive surface subsplines", subsplineData.Length() ); + } +#endif + Array L = Thread::OptimalThreadLoads( subsplineData.Length(), + 1/*overheadLimit*/, + m_parallel ? m_maxProcessors : 1 ); + AbstractImage::ThreadData threadData( monitor, subsplineData.Length() ); + ReferenceArray threads; + for ( int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) ) + threads.Add( new SubsplineGenerationThread( threadData, + subsplineData, + smoothness, + order, + allowExtrapolation, + maxSplineLength, + bucketCapacity, + n, + n + int( L[i] ) ) ); + AbstractImage::RunThreads( threads, threadData ); + threads.Destroy(); + } + } + + /*! + * Deallocates internal structures, yielding an empty object that cannot be + * used before a new call to Initialize(). + */ + void Clear() + { + m_tree.Traverse( + []( const search_rectangle&, node_list&, void*& D ) + { + delete reinterpret_cast( D ); + } ); + m_tree.Clear(); + m_spline.Clear(); + m_rect = search_coordinate( 0 ); + } + + /*! + * Returns true if this object splits the interpolation space recursively + * with subsplines. In such case this object contains a quadtree structure + * that will be searched for suitable point surface splines to interpolate + * function values. + * + * Returns false is this object performs no further recursion. In such case + * this object contains a point surface spline that will be used directly to + * interpolate function values. + */ + bool IsRecursive() const + { + return !m_tree.IsEmpty(); + } + + /*! + * Returns true iff this is a valid, initialized object ready for + * interpolation. + */ + bool IsValid() const + { + return IsRecursive() || m_spline.IsValid(); + } + + /*! + * Returns an interpolated point at the specified \a x, \a y coordinates. + * + * If extrapolation is disabled for this object and the specified + * coordinates fall outside the interpolation region defined upon + * initialization, a point at the origin (that is, with zero coordinates) is + * returned conventionally. Otherwise the nearest subspline will be used to + * extrapolate the returned value. + */ + template + DPoint operator ()( T x, T y ) const + { + if ( m_spline.IsValid() ) + { + if ( m_extrapolate || m_rect.IncludesFast( x, y ) ) + return m_spline( x, y ); + } + else + { + const typename tree::Node* node = m_tree.NodeAt( search_point( x, y ) ); + if ( node == nullptr ) + { + if ( !m_extrapolate ) + return 0.0; + + search_rectangle r0 = m_tree.Root()->rect; + if ( x <= r0.x0 ) + { + if ( y <= r0.y0 ) + node = m_tree.NodeAt( search_point( r0.x0 + SearchDelta, r0.y0 + SearchDelta ) ); + else if ( y >= r0.y1 ) + node = m_tree.NodeAt( search_point( r0.x0 + SearchDelta, r0.y1 - SearchDelta ) ); + else + node = m_tree.NodeAt( search_point( r0.x0 + SearchDelta, search_coordinate( y ) ) ); + } + else if ( x >= r0.x1 ) + { + if ( y <= r0.y0 ) + node = m_tree.NodeAt( search_point( r0.x1 - SearchDelta, r0.y0 + SearchDelta ) ); + else if ( y >= r0.y1 ) + node = m_tree.NodeAt( search_point( r0.x1 - SearchDelta, r0.y1 - SearchDelta ) ); + else + node = m_tree.NodeAt( search_point( r0.x1 - SearchDelta, search_coordinate( y ) ) ); + } + else if ( y <= r0.y0 ) + node = m_tree.NodeAt( search_point( search_coordinate( x ), r0.y0 + SearchDelta ) ); + else // y >= r0.y1 + node = m_tree.NodeAt( search_point( search_coordinate( x ), r0.y1 - SearchDelta ) ); + + if ( node == nullptr ) // ?! + return 0.0; + } + + if ( node->IsLeaf() ) + { + const typename tree::LeafNode* leaf = static_cast( node ); + if ( leaf->data == nullptr ) // ?! + return 0.0; + return reinterpret_cast( leaf->data )->operator()( x, y ); + } + + DPoint p = 0.0; + int n = 0; + if ( node->nw != nullptr ) + { + const typename tree::LeafNode* leaf; + if ( y <= node->nw->rect.y1 ) + leaf = m_tree.LeafNodeAt( search_point( node->nw->rect.x1 - SearchDelta, search_coordinate( y ) ) ); + else if ( x <= node->nw->rect.x1 ) + leaf = m_tree.LeafNodeAt( search_point( search_coordinate( x ), node->nw->rect.y1 - SearchDelta ) ); + else + leaf = m_tree.LeafNodeAt( search_point( node->nw->rect.x1 - SearchDelta, node->nw->rect.y1 - SearchDelta ) ); + + if ( leaf != nullptr ) + { + p += reinterpret_cast( leaf->data )->operator()( x, y ); + ++n; + } + } + if ( node->ne != nullptr ) + { + const typename tree::LeafNode* leaf; + if ( y <= node->ne->rect.y1 ) + leaf = m_tree.LeafNodeAt( search_point( node->ne->rect.x0 + SearchDelta, search_coordinate( y ) ) ); + else if ( x <= node->ne->rect.x0 ) + leaf = m_tree.LeafNodeAt( search_point( node->ne->rect.x0 + SearchDelta, node->ne->rect.y1 - SearchDelta ) ); + else + leaf = m_tree.LeafNodeAt( search_point( search_coordinate( x ), node->ne->rect.y1 - SearchDelta ) ); + + if ( leaf != nullptr ) + { + p += reinterpret_cast( leaf->data )->operator()( x, y ); + ++n; + } + } + if ( node->sw != nullptr ) + { + const typename tree::LeafNode* leaf; + if ( y >= node->sw->rect.y0 ) + leaf = m_tree.LeafNodeAt( search_point( node->sw->rect.x1 - SearchDelta, search_coordinate( y ) ) ); + else if ( x <= node->sw->rect.x1 ) + leaf = m_tree.LeafNodeAt( search_point( search_coordinate( x ), node->sw->rect.y0 + SearchDelta ) ); + else + leaf = m_tree.LeafNodeAt( search_point( node->sw->rect.x1 - SearchDelta, node->sw->rect.y0 + SearchDelta ) ); + + if ( leaf != nullptr ) + { + p += reinterpret_cast( leaf->data )->operator()( x, y ); + ++n; + } + } + if ( node->se != nullptr ) + { + const typename tree::LeafNode* leaf; + if ( y >= node->se->rect.y0 ) + leaf = m_tree.LeafNodeAt( search_point( node->se->rect.x0 + SearchDelta, search_coordinate( y ) ) ); + else if ( x <= node->se->rect.x0 ) + leaf = m_tree.LeafNodeAt( search_point( node->se->rect.x0 + SearchDelta, node->se->rect.y0 + SearchDelta ) ); + else + leaf = m_tree.LeafNodeAt( search_point( search_coordinate( x ), node->se->rect.y0 + SearchDelta ) ); + + if ( leaf != nullptr ) + { + p += reinterpret_cast( leaf->data )->operator()( x, y ); + ++n; + } + } + + if ( n > 0 ) + return p/double( n ); + } + + return 0.0; + } + + /*! + * Returns an interpolated point at the given \a p.x and \a p.y coordinates. + * + * If extrapolation is disabled for this object and the specified point + * lies outside the interpolation region defined upon initialization, a + * point at the origin (that is, with zero coordinates) is returned + * conventionally. Otherwise the nearest subspline will be used to + * extrapolate the returned value. + */ + template + DPoint operator ()( const GenericPoint& p ) const + { + return operator ()( p.x, p.y ); + } + +private: + + /* + * Interpolation data point, QuadTree-compatible. + */ + struct Node + { + typedef typename point::component component; + + point position, value; + float weight; + + Node( const point& p, const point& v ) + : position( p ) + , value( v ) + { + } + + Node( const point& p, const point& v, float w ) + : position( p ) + , value( v ) + , weight( w ) + { + } + + Node( const Node& ) = default; + + component& operator []( int i ) + { + return position[i]; + } + + component operator []( int i ) const + { + return position[i]; + } + }; + + typedef QuadTree tree; + typedef typename tree::point_list node_list; + typedef typename tree::rectangle search_rectangle; + typedef typename tree::coordinate search_coordinate; + typedef GenericPoint search_point; + + tree m_tree; // the tree of subsplines + spline m_spline; // final point spline if there is no further recursion + search_rectangle m_rect = search_coordinate( 0 ); // the interpolation region for this subspline + bool m_extrapolate = __PCL_RSSPLINE_DEFAULT_ALLOW_EXTRAPOLATION; + + static constexpr search_coordinate SearchDelta = + 2 * std::numeric_limits::epsilon(); + + /* + * Parallel subspline generation. + */ + struct SubsplineData + { + point_list P1, P2; + Array PW; + mutable void** nodeData; + + SubsplineData( const point_list& p1, const point_list& p2, const Array& pw, void*& nd ) + : P1( p1 ) + , P2( p2 ) + , PW( pw ) + , nodeData( &nd ) + { + } + }; + + class SubsplineGenerationThread : public Thread + { + public: + + SubsplineGenerationThread( const AbstractImage::ThreadData& data, + const Array& subsplineData, + float smoothness, + int order, + bool allowExtrapolation, + int maxSplineLength, + int bucketCapacity, + int startIndex, int endIndex ) + : m_data( data ) + , m_subsplineData( subsplineData ) + , m_smoothness( smoothness ) + , m_order( order ) + , m_allowExtrapolation( allowExtrapolation ) + , m_maxSplineLength( maxSplineLength ) + , m_bucketCapacity( bucketCapacity ) + , m_startIndex( startIndex ) + , m_endIndex( endIndex ) + { + } + + PCL_HOT_FUNCTION void Run() override + { + INIT_THREAD_MONITOR() + + for ( int i = m_startIndex; i < m_endIndex; ++i ) + { + const SubsplineData& d = m_subsplineData[i]; + AutoPointer s( + new recursive_spline( d.P1, d.P2, m_smoothness, m_order, d.PW, + m_allowExtrapolation, + m_maxSplineLength, + m_bucketCapacity, + false/*verbose*/ ) ); + *reinterpret_cast( d.nodeData ) = s.Release(); + + UPDATE_THREAD_MONITOR( 1 ) + } + + m_success = true; + } + + operator bool() const + { + return m_success; + } + + private: + + const AbstractImage::ThreadData& m_data; + const Array& m_subsplineData; + float m_smoothness; + int m_order; + bool m_allowExtrapolation; + int m_maxSplineLength; + int m_bucketCapacity; + int m_startIndex, m_endIndex; + bool m_success = false; + }; + + friend class DrizzleData; + friend class DrizzleDataDecoder; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_SurfaceSpline_h + +// ---------------------------------------------------------------------------- +// EOF pcl/SurfaceSpline.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/TabBox.h b/3rdparty/include/pcl/TabBox.h new file mode 100644 index 0000000..4ac0098 --- /dev/null +++ b/3rdparty/include/pcl/TabBox.h @@ -0,0 +1,391 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/TabBox.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_TabBox_h +#define __PCL_TabBox_h + +/// \file pcl/TabBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::TabPosition + * \brief Tab positions in TabBox controls. + * + * + * + * + *
TabPosition::Top Tabs are located at the top side of the TabBox control
TabPosition::Bottom Tabs are located at the bottom side of the TabBox control
+ */ +namespace TabPosition +{ + enum value_type + { + Top, // Tabs are located at the top side of the tab box control + Bottom // Tabs are located at the bottom side of the tab box control + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class TabBox + * \brief Client-side interface to a PixInsight %TabBox control. + * + * ### TODO: Write a detailed description for %TabBox. + */ +class PCL_CLASS TabBox : public Control +{ +public: + + /*! + * Represents a tab position. + */ + typedef TabPosition::value_type tab_position; + + /*! + * Constructs a %TabBox as a child control of \a parent. + */ + TabBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %TabBox control. + */ + virtual ~TabBox() + { + } + + /*! + * Returns the number of page controls in this %TabBox. + */ + int NumberOfPages() const; + + /*! + * Returns the zero-based index of the current page control in this %TabBox, + * or -1 if this %TabBox has no page controls. + */ + int CurrentPageIndex() const; + + /*! + * Selects the current page control by its zero-based \a index. + */ + void SetCurrentPageIndex( int index ); + + /*! + * A synonym for SetCurrentPageIndex( index ) + */ + void SelectPage( int index ) + { + SetCurrentPageIndex( index ); + } + + /*! + * Returns a reference to the current page control in this %TabBox, or + * Control::Null() if this %TabBox has no page controls. + */ + Control& CurrentPageControl() const; + + /*! + * Returns a reference to the page control at the specified zero-based + * \a index in this %TabBox, or Control::Null() if this %TabBox has no page + * controls, or if \a index is not valid. + */ + Control& PageControlByIndex( int index ) const; + + /*! + * Inserts a new page control in this %TabBox. + * + * \param index Zero-based index where the new page control will be + * inserted. If \a index is greater than or equal to the number + * of existing page controls, the new page will be appended to + * the list of existing page controls. If \a index is less than + * zero, the new page will be prepended to the list of existing + * page controls. + * + * \param page The page control to be inserted. + * + * \param label The text that will be shown on the new tab selector. + * + * \param icon The icon that will be shown on the new tab selector. + * + * \sa AddPage(), RemovePage() + */ + void InsertPage( int index, Control& page, const String& label, const Bitmap& icon = Bitmap::Null() ); + + /*! + * Appends a new page control to this %TabBox. + * + * This is a convenience member function, equivalent to + * InsertPage( NumberOfPages(), page, label, icon ) + * + * \a InsertPage, RemovePage() + */ + void AddPage( Control& page, const String& label, const Bitmap& icon = Bitmap::Null() ) + { + InsertPage( NumberOfPages(), page, label, icon ); + } + + /*! + * Removes the page control at the specified zero-based \a index. + * + * This member function does not delete the page control; it simply removes + * it from the list of page controls in this %TabBox. + * + * \sa InsertPage(), AddPage() + */ + void RemovePage( int idx ); + + /*! + * Returns the position of the tab selectors row in this %TabBox. + * + * \sa SetTabPosition() + */ + tab_position TabPosition() const; + + /*! + * Sets the position of the tab selectors row in this %TabBox. + * + * \sa TabPosition() + */ + void SetTabPosition( tab_position pos ); + + /*! + * Returns true iff the page control at the specified \a index is enabled. + * + * \sa EnablePage(), DisablePage() + */ + bool IsPageEnabled( int index ) const; + + /*! + * Enables or disables the page control at the specified \a index. + * + * \sa DisablePage(), IsPageEnabled() + */ + void EnablePage( int index, bool enable = true ); + + /*! + * Disables or enables the page control at the specified \a index. + * + * This is a convenience member function, equivalent to + * EnablePage( index, !disable ) + * + * \sa EnablePage(), IsPageEnabled() + */ + void DisablePage( int index, bool disable = true ) + { + EnablePage( index, !disable ); + } + + /*! # + */ + String PageLabel( int idx ) const; + + /*! # + */ + void SetPageLabel( int idx, const String& ); + + /*! # + */ + void ClearPageLabel( int idx ) + { + SetPageLabel( idx, String() ); + } + + /*! # + */ + Bitmap PageIcon( int idx ) const; + + /*! # + */ + void SetPageIcon( int idx, const Bitmap& ); + + /*! # + */ + void ClearPageIcon( int idx ) + { + SetPageIcon( idx, Bitmap::Null() ); + } + + /*! # + */ + String PageToolTip( int idx ) const; + + /*! # + */ + void SetPageToolTip( int idx, const String& ); + + /*! # + */ + void ClearPageToolTip( int idx ) + { + SetPageToolTip( idx, String() ); + } + + /*! # + */ + Control& LeftControl() const; + + /*! # + */ + Control& RightControl() const; + + /*! # + */ + void SetControls( Control& left, Control& right ); + + /*! # + */ + void SetLeftControl( Control& w ) + { + SetControls( w, RightControl() ); + } + + /*! # + */ + void SetRightControl( Control& w ) + { + SetControls( LeftControl(), w ); + } + + /*! # + */ + void ClearLeftControl() + { + SetLeftControl( Control::Null() ); + } + + /*! # + */ + void ClearRightControl() + { + SetRightControl( Control::Null() ); + } + + /*! # + */ + void ClearControls() + { + SetControls( Control::Null(), Control::Null() ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnPageSelected( TabBox& sender, int pageIndex ); + + /*! + * \defgroup tab_box_event_handlers TabBox Event Handlers + */ + + /*! + * Defines the prototype of a tab box page event handler. + * + * A tab box page event is generated when the user changes the current page + * in a tab box control. + * + * \param sender The control that sends a tab box page event. + * + * \param pageIndex The zero-based index of a tab box page. + * + * \ingroup tab_box_event_handlers + */ + typedef void (Control::*page_event_handler)( TabBox& sender, int pageIndex ); + + /*! + * Sets the tab box page selected event handler for this %TabBox control. + * + * \param handler The tab box page event handler. Must be a member + * function of the receiver object's class. + * + * \param receiver The control that will receive tab box page selected + * events from this %TabBox. + * + * \ingroup tab_box_event_handlers + */ + void OnPageSelected( page_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + page_event_handler onPageSelected = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class TabBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_TabBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/TabBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/TextAlign.h b/3rdparty/include/pcl/TextAlign.h new file mode 100644 index 0000000..2013ead --- /dev/null +++ b/3rdparty/include/pcl/TextAlign.h @@ -0,0 +1,112 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/TextAlign.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_TextAlign_h +#define __PCL_TextAlign_h + +/// \file pcl/TextAlign.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::TextAlign + * \brief Text alignment modes. + * + * + * + * + * + * + * + * + * + * + * + * + *
TextAlign::Unknown Unknown or unsupported alignment
TextAlign::Left Left alignment
TextAlign::Right Right alignment
TextAlign::HorzCenter Centered horizontally
TextAlign::Justify Left and right justified
TextAlign::Top Top alignment
TextAlign::Bottom Bottom alignment
TextAlign::VertCenter Centered vertically
TextAlign::Center Centered horizontally and vertically. Equal to HorzCenter|VertCenter.
TextAlign::Default Default alignment. Equal to Left|Top.
+ */ +namespace TextAlign +{ + enum mask_type + { + Unknown = 0x00, + Left = 0x01, + Right = 0x02, + HorzCenter = 0x04, + Justify = 0x08, + Top = 0x20, + Bottom = 0x40, + VertCenter = 0x80, + Center = HorzCenter|VertCenter, + Default = Left|Top + }; +} + +/*! + * A collection of text alignment mode flags. + */ +typedef Flags TextAlignmentFlags; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_TextAlign_h + +// ---------------------------------------------------------------------------- +// EOF pcl/TextAlign.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/TextBox.h b/3rdparty/include/pcl/TextBox.h new file mode 100644 index 0000000..1557c4c --- /dev/null +++ b/3rdparty/include/pcl/TextBox.h @@ -0,0 +1,316 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/TextBox.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_TextBox_h +#define __PCL_TextBox_h + +/// \file pcl/TextBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class TextBox + * \brief Client-side interface to a PixInsight %TextBox control. + * + * %TextBox is a multiline, plain text output control. A %TextBox control + * implements the entire text output functionality of a PixInsight console; + * refer to the Console class for full information about console output + * capabilities. + * + * \sa Console, CodeEditor + */ +class PCL_CLASS TextBox : public Frame +{ +public: + + /*! + * Constructs a %TextBox as a child control of \a parent with the specified + * initial \a text. + */ + TextBox( const String& text = String(), Control& parent = Control::Null() ); + + /*! + * Destroys a %TextBox control. + */ + virtual ~TextBox() + { + } + + /*! + * Returns the current text of this %TextBox control. + */ + String Text() const; + + /*! + * Sets the text of this %TextBox control. + */ + void SetText( const String& ); + + /*! + * Returns a string that can be used to write the specified \a text to a + * %TextBox control as plain text, that is without interpreting + * tags or character entities. + */ + template + static S PlainText( const S& text ) + { + return "" + text + ""; + } + + /*! + * Sets the plain text of this %TextBox control. + * + * This member function is equivalent to SetText( PlainText( text ) ). + */ + template + void SetPlainText( const S& text ) + { + SetText( PlainText( text ) ); + } + + /*! + * Clears (removes) the text in this %TextBox control. + */ + void Clear() + { + SetText( String() ); + } + + /*! + * Returns true iff this %TextBox control is in read-only state. + * + * \sa SetReadOnly(), SetReadWrite() + */ + bool IsReadOnly() const; + + /*! + * Enables or disables the read-only state of this %TextBox control. + * + * \sa SetReadWrite(), IsReadOnly() + */ + void SetReadOnly( bool ro = true ); + + /*! + * Disables or enables the read-only state of this %TextBox control. + * + * This is a convenience member function, equivalent to + * SetReadOnly( !rw ) + * + * \sa SetReadOnly(), IsReadOnly() + */ + void SetReadWrite( bool rw = true ) + { + SetReadOnly( !rw ); + } + + /*! + * Selects all the text in this %TextBox control. + * + * \sa Unselect(), GetSelection(), SetSelection() + */ + void SelectAll( bool = true ); + + /*! + * Clears the current text selection in this %TextBox. + * + * This member function does not delete the selected text; it only removes + * the selection. + * + * \sa SelectAll(), GetSelection(), SetSelection() + */ + void Unselect( bool unsel = true ) + { + SelectAll( !unsel ); + } + + /*! + * Gets the current text selection in this %TextBox control. + * + * \param selStart Index of the first selected character. + * \param selEnd Index of the last selected character plus one. + * + * When selStart < selEnd, there is a text selection in this %TextBox. Both + * indexes are zero-based. + * + * \sa SetSelection() + */ + void GetSelection( int& selStart, int& selEnd ) const; + + /*! + * Sets a new text selection in this %TextBox control. + * + * \param selStart Index of the first selected character. + * \param selEnd Index of the last selected character plus one. + * + * When selStart < selEnd, there is a text selection in this %TextBox. Both + * indexes are zero-based. + * + * \sa GetSelection() + */ + void SetSelection( int selStart, int selEnd ); + + /*! + * Returns true iff this %TextBox control has a valid selection. + */ + bool HasSelection() const + { + int s0, s1; + GetSelection( s0, s1 ); + return s0 != s1; + } + + /*! + * Returns the selected text in this %TextBox control, or an empty string if + * there is no selection. + * + * \sa GetSelection(), SetSelection(), SelectAll(), Unselect() + */ + String SelectedText() const; + + /*! # + */ + int CaretPosition() const; + + /*! # + */ + void SetCaretPosition( int ); + + /*! # + */ + void Home() + { + SetCaretPosition( 0 ); + } + + /*! # + */ + void End() + { + SetCaretPosition( int_max ); + } + + /*! # + */ + void Insert( const String& text ); + + /*! # + */ + void Delete(); + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnTextUpdated( TextBox& sender, const String& text ); + // void OnCaretPositionUpdated( TextBox& sender, int oldPos, int newPos ); + // void OnSelectionUpdated( TextBox& sender, int newStart, int newEnd ); + + /*! # + */ + typedef void (Control::*unicode_event_handler)( TextBox& sender, const String& ); + + /*! # + */ + typedef void (Control::*caret_event_handler)( TextBox& sender, int oldPos, int newPos ); + + /*! # + */ + typedef void (Control::*selection_event_handler)( TextBox& sender, int newStart, int newEnd ); + + /*! # + */ + void OnTextUpdated( unicode_event_handler, Control& ); + + /*! # + */ + void OnCaretPositionUpdated( caret_event_handler, Control& ); + + /*! # + */ + void OnSelectionUpdated( selection_event_handler, Control& ); + +private: + + struct EventHandlers + { + unicode_event_handler onTextUpdated = nullptr; + caret_event_handler onCaretPositionUpdated = nullptr; + selection_event_handler onSelectionUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class TextBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_TextBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/TextBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Thread.h b/3rdparty/include/pcl/Thread.h new file mode 100644 index 0000000..f4a3af3 --- /dev/null +++ b/3rdparty/include/pcl/Thread.h @@ -0,0 +1,753 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Thread.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_Thread_h +#define __PCL_Thread_h + +/// \file pcl/Thread.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup thread_support Thread Support Classes and Functions + */ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ThreadPriority + * \brief Thread scheduling priorities. + * + * + * + * + * + * + * + * + * + * + * + *
ThreadPriority::Inherit Inherit the caller's thread priority. This is the default value.
ThreadPriority::Idle Schedule when no other threads are busy.
ThreadPriority::Lowest Schedule more often than \e idle priority, but less than \e low priority.
ThreadPriority::Low Schedule more often than \e lowest priority, but less than \e normal priority.
ThreadPriority::Normal Standard thread priority.
ThreadPriority::High Schedule more often than \e normal priority, but less than \e highest priority.
ThreadPriority::Highest Schedule more often than \e high priority, but less than \e time-critical priority.
ThreadPriority::TimeCritical Schedule as often as possible, taking precedence over any other threads.
ThreadPriority::DefaultMax Default maximum priority. This is a platform-dependent, maximum thread priority recommended for processing modules.
+ * + * Note that not all platforms and operating systems handle thread scheduling + * priorities in the same way. In general, modules should use the default + * maximum thread priority by specifying ThreadPriority::DefaultMax instead of + * hard-coded priority values. Time-critical priority should be reserved for + * performance-critical, very brief and fast tasks exclusively, and should only + * be used when it is \e really necessary. This is particularly important on + * Windows platforms. + * + * \ingroup thread_support + */ +namespace ThreadPriority +{ + enum value_type + { + Inherit, // Inherit caller's thread priority. + Idle, // Schedule when no other threads are busy. + Lowest, + Low, + Normal, // Standard thread priority + High, + Highest, + TimeCritical, // Schedule as often as possible, taking precedence over any other threads. +#ifdef __PCL_WINDOWS + DefaultMax = Normal // On Windows, anything above Normal is the same as TimeCritical ... +#else + DefaultMax = Highest +#endif + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Thread + * \brief Client-side interface to a PixInsight thread. + * + * ### TODO: Write a detailed description for %Thread + * + * \ingroup thread_support + */ +class PCL_CLASS Thread : public UIObject +{ +public: + + /*! + * Represents a thread priority. + */ + typedef ThreadPriority::value_type priority; + + /*! + * Constructs a %Thread object. + */ + Thread(); + + /*! + * Destroys a %Thread object. + */ + virtual ~Thread() + { + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since threads are unique objects by nature, calling this member function + * has no effect. + */ + void EnsureUnique() override + { + // Threads are unique objects by definition. + } + + /*! + * Returns a reference to a null %Thread instance. + * + * A null %Thread does not correspond to an existing thread in the core + * PixInsight application. + */ + static Thread& Null(); + + /*! + * Starts thread execution with the specified scheduling \a priority and CPU + * affinity to the specified \a processor. + * + * After calling this member function, the PixInsight core application will + * create a new execution thread from which the Run() virtual member + * function will be invoked for this %Thread instance. + * + * By default, the calling thread's scheduling priority is inherited by + * newly created threads. In general, to maximize performance in a way well + * adapted to the running platform, ThreadPriority::DefaultMax should be + * specified as the value of the \a priority parameter. + * + * By default, threads have no specific CPU affinity. By specifying a valid + * \a processor index, a thread can be scheduled to run on a specific + * logical processor. When the specified \a processor is >= 0, the internal + * thread dispatcher will set the corresponding CPU affinity when this + * thread is executed, just before calling its Run() virtual member + * function. This is usually a more convenient way to control thread + * affinity than the SetAffinity() member function, because it allows + * setting CPU affinity before a thread starts execution. + * + * \note Currently, thread affinity can only be set on Linux and Windows + * platforms. On FreeBSD and Mac OS X, specifying a processor with this + * function has no effect. We hope to overcome this limitation in a future + * version of PCL. + * + * \note Since version 1.8.0 of the PixInsight core application, nested + * parallelism is fully supported. This means that multiple threads can be + * run by calling Thread::Start() from either the root thread or any running + * %Thread object. In versions prior to 1.8.0, a thread could only be run + * from the root thread. + */ + void Start( priority = ThreadPriority::Inherit, int processor = -1 ); + + /*! + * Returns a set of processor indices corresponding to this thread's + * \e CPU \e affinity. + * + * The affinity of a thread defines the set of logical processors on which + * the thread is eligible to run. %Thread affinity allows to improve + * execution speed by restricting each thread to run on a separate + * processor. This prevents the performance cost caused by the cache + * invalidation that occurs when a process ceases to execute on one + * processor and then restarts execution on a different one (e.g. the + * infamous ping-pong effect). + * + * If this thread is not running, this function returns the affinity of the + * calling thread. + * + * \note Currently, this function only works on Linux. On FreeBSD, Mac OS X + * and Windows platforms, this function always returns an empty array. We + * hope to overcome this limitation in a future version of PCL. + */ + Array Affinity() const; + + /*! + * Sets the affinity of this thread to the specified set of \a processors. + * + * Each element on the specified \a processors array is a zero-based index + * corresponding to an existing logical processor. The first processor has + * index zero and the last one has index n-1, where n is the total number of + * logical processors on the host machine. Logical processors include + * physical processors and processor cores, as well as logical processors on + * systems with hyper-threading technology. + * + * Returns true iff the operation was performed correctly. In general, this + * function returns false if this thread is not running, or if the specified + * set contains nonexistent processor indices. It can also return false if + * the calling process does not have the necessary privileges, altough this + * should not happen under normal conditions. + * + * \note The CPU affinity of the calling thread cannot be changed with this + * function. If this thread is not running, this function returns false and + * does nothing. + * + * \note Currently, thread affinity can only be set on Linux and Windows + * platforms. On FreeBSD and Mac OS X, calling this function has no effect. + * We hope to overcome this limitation in a future version of PCL. + */ + bool SetAffinity( const Array& processors ); + + /*! + * Sets the CPU affinity of this thread to the specified \a processor. + * + * The specified \a processor is a zero-based index corresponding to an + * existing logical processor. The first processor has index zero and the + * last one has index n-1, where n is the total number of logical processors + * on the host machine. Logical processors include physical processors and + * processor cores, as well as logical processors on systems with + * hyper-threading technology. + * + * Returns true iff the operation was performed correctly. In general, this + * function returns false if this thread is not running, or if the specified + * processor does not exist. It can also return false if the calling process + * does not have the necessary privileges, altough this should not happen + * under normal conditions. + * + * \note The CPU affinity of the calling thread cannot be changed with this + * function. If this thread is not running, this function returns false and + * does nothing. + * + * \note Currently, thread affinity can only be set on Linux and Windows + * platforms. On FreeBSD and Mac OS X, calling this function has no effect. + * We hope to overcome this limitation in a future version of PCL. + */ + bool SetAffinity( int processor ); + + /*! + * Forces immediate termination of thread execution. + * + * \warning Calling this function is dangerous because it causes the + * immediate termination of a running thread without giving it a chance to + * perform any cleanup. For example, open files will not be closed, locked + * objects will not be unlocked, and shared static variables may be left at + * invalid states, with unpredictable results. + * + * \warning Calling this member function is strongly discouraged - Use it + * at your own risk + */ + void Kill(); // ### Dangerous - Use at your own risk! ### + + /*! + * Returns true iff this thread is running. + */ + bool IsActive() const; + + /*! + * Returns this thread's priority. + */ + priority Priority() const; + + /*! + * Sets this thread's priority. + */ + void SetPriority( priority ); + + /*! + * Resets this thread's priority to the default value, which inherits the + * calling thread's priority. + */ + void ResetPriority() + { + SetPriority( ThreadPriority::Inherit ); + } + + /*! + * Suspends execution of the calling thread until this thread terminates + * execution. If this thread is not running, this function returns + * immediately. + * + * \warning If this thread does not return from its Run() member function, + * for example because this thread hangs or enters an infinite loop, the + * thread that calls this function will remain suspended forever (crashed). + */ + void Wait(); + + /*! + * Suspends execution of the calling thread until one of the following + * conditions is met: + * + * \li This thread terminates execution, or this thread is not running. + * \li The specified time interval \a ms in milliseconds has elapsed. + * + * This member function returns true if this thread has finished execution + * before the specified time \a ms in milliseconds has elapsed. It also + * returns true if this thread is not running. + * + * \note Unlike Wait(), this function cannot crash the calling thread if + * this thread is crashed, unless a huge amount of time is specified as the + * function argument. + */ + bool Wait( unsigned ms ); + + /*! + * Suspends execution of this thread during the specified time interval + * \a ms in milliseconds. + */ + void Sleep( unsigned ms ); + + /* + * Returns a reference to the current thread (the thread from which this + * member function is invoked), or Thread::Null() if the current thread is + * either (a) a thread not being controlled by the PixInsight API, or (b) a + * thread that has been created by another module. + static Thread& CurrentThread(); + */ + + /*! + * This member function returns true if and only if it is called from the + * root thread. The root thread is the thread where the graphical + * user interface is running on the PixInsight core application. + * + * \note Since version 1.8.0 of the PixInsight core application, nested + * parallelism is fully supported. This means that multiple threads can be + * run by calling Thread::Start() from either the root thread or any running + * %Thread object. In versions prior to 1.8.0, a thread could only be run + * from the root thread. + */ + static bool IsRootThread(); + + /*! + * Returns the total number of running %Thread objects. + * + * \note This function knows nothing about threads out of PCL control, so it + * will return zero if no %Thread instance is currently active, even if + * there are other native threads being executed. + */ + static int NumberOfRunningThreads(); + + /*! + * %Thread execution routine. + * + * This member function is invoked by the PixInsight core application upon + * execution start, just after calling the Start() member function. During + * execution of this routine, it is said that this is a running + * thread. + * + * Derived classes must reimplement this member function to provide specific + * thread functionality. + * + * \note There is no problem at all in calling this member function + * directly. This may be useful, for example, if the same code must be + * executed in a single thread (without calling Start()) and as + * multithreaded code. + */ + virtual void Run() + { + // Reimplement this function to provide your thread's functionality. + } + + /*! + * Returns the current status of this thread. The thread status is a 32-bit + * unsigned integer number that can be set for an active thread by calling + * its SetStatus() member function. + * + * %Thread status is primarily intended as an efficient mechanism to send + * custom messages to running threads, for thread synchronization or other + * control purposes. + * + * \note This member function is thread-safe. It can be safely called for a + * running thread. + * + * \note This member function blocks the caller's execution until the thread + * status can be retrieved. Hence, the operation performed by this function + * is expensive in terms of thread synchronization. For a non-blocking + * version of this function see the documentation for TryGetStatus(). + */ + uint32 Status() const; + + /*! + * Attempts to get the current status of this thread without blocking the + * caller's execution. + * + * Returns true iff the thread status could be retrieved and stored in the + * specified \a status variable. + * + * Returns false if the status couldn't be read. In this case the value of + * the \a status variable won't be changed. + * + * \note This member function is thread-safe. It can be safely called for a + * running thread. + * + * \note This is a non-blocking fast version of the Status() member + * function. It should be used when acquiring the thread's status is not + * strictly necessary to continue thread execution. + */ + bool TryGetStatus( uint32& status ) const; + + /*! + * Sets the current status of a running thread. See the documentation of + * Thread::Status() for more information. + * + * \note Calling this function for an inactive thread has no effect. The + * thread status can only be set for a running thread. + * + * \note If the high-order bit of \a status is set, an abort message will be + * sent to the running thread. See the Abort() member function for more + * information. + * + * \note This member function is thread-safe. It can be safely called for a + * running thread, even from other running threads. + */ + void SetStatus( uint32 status ); + + /*! + * Sends an abort message to a running thread. + * + * If the thread calls Module->ProcessEvents() after an abort message has + * been sent, or if it uses some of the standard status monitoring classes + * (such as StandardStatus for example), a ProcessAborted exception will be + * thrown automatically in the thread. The exception will be thrown in the + * (reimplemented) Thread::Run() member function, where it should be caught + * and used to terminate thread execution by returning from Run(). This + * mechanism can be used to synchronize and stop running threads in a + * controlled and thread-safe way. + * + * \note A thread abort message means that the high-order bit of a running + * thread's status has been set. This member function simply sets the thread + * status to 0x80000000. To effectively abort the thread, it should call + * Module->ProcessEvents(), as described above, and should stop its + * execution after catching a ProcessAborted exception. + * + * \note This member function is thread-safe. It can be safely called for a + * running thread, even from other running threads. + */ + void Abort() + { + SetStatus( 0x80000000 ); + } + + /*! + * Returns true iff this thread has been aborted. A thread has been aborted + * if it has received an abort message by a previous call to Abort(), or by + * setting the high-order bit of its thread status word. + * + * \note This member function is thread-safe. It can be safely called for a + * running thread. + * + * \note This function calls Status() to read the current thread's status. + * Consequently, it blocks the caller's execution and has the same + * performance problems. For a non-blocking alternative, see TryIsAborted(). + */ + bool IsAborted() const + { + return (Status() & 0x80000000) != 0; + } + + /*! + * Returns true iff this thread has been aborted, and the current thread's + * status could be retrieved without blocking the caller's execution. + * + * \note This member function is thread-safe. It can be safely called for a + * running thread. + * + * \note This is a non-blocking fast version of the IsAborted() member + * function. It should be used when acquiring the thread's status is not + * strictly necessary to continue thread execution. + */ + bool TryIsAborted() const + { + uint32 status; + return TryGetStatus( status ) && (status & 0x80000000) != 0; + } + + /*! + * Returns the console output text currently accumulated in this thread. + * + * When a %Thread object is running (that is, when its IsActive() member + * function returns true), no operation on the graphical user interface is + * permitted from the thread. This includes console text output. + * + * When a running thread writes text to the console, for example by calling + * Console::Write() or Console::WriteLn(), the text is not sent to the + * console (which in fact would raise an Error exception), but it is instead + * appended to the thread's console output text. The accumulated + * output text can be sent to the console once the thread has finished + * execution, or it can be retrieved by calling this member function. + */ + String ConsoleOutputText() const; + + /*! + * Returns true iff this thread has any accumulated console output text that + * still has not been flushed or cleared. + * + * For information on thread console output, refer to the documentation for + * the ConsoleOutputText() member function. + */ + bool HasConsoleOutputText() const + { + return !ConsoleOutputText().IsEmpty(); + } + + /*! + * Erases the accumulated console output text in this thread. + * + * For information on thread console output, refer to the documentation for + * the ConsoleOutputText() member function. + */ + void ClearConsoleOutputText(); + + /*! + * Sends any accumulated console output text in this thread to the console. + * + * After writing the accumulated text to the console, this member function + * clears it, so that repeated calls to this function will have no effect. + * + * For information on thread console output, refer to the documentation for + * the ConsoleOutputText() member function. + * + * \note This member function must only be called from the root thread. + * Calling it from a running %Thread object has no effect. + */ + void FlushConsoleOutputText(); + + /*! + * Returns the maximum number of threads that can be used concurrently to + * process a set of items. + * + * \param count Number of processing units. A processing unit can + * be a single pixel, a row of pixels, or any suitable item, + * according to the task being performed by the caller. + * + * \param overheadLimit %Thread overhead limit in processing units. The + * function returns a maximum number of threads such that no + * thread would have to process less processing units than this + * value. The default overhead limit is one processing unit. + * + * This function takes into account the number of existing processors in + * the system, as well as the maximum number of processors currently allowed + * for external processes by the core application, and the number of threads + * currently active. The following global variables are taken into account + * (see the PixInsightSettings class for more information about global + * variables on the PixInsight platform): + * + * + * + * + * + * + * + * + * + * + *
Process/EnableParallelProcessingIf this global flag is false, it means that parallel processing + * has been globally disabled for the entire platform, so this function + * will always return one, irrespective of the number of existing + * processors.
Process/EnableParallelModuleProcessingIf this global flag is false, it means that parallel processing + * has been disabled for all installed modules, so this function will + * always return one, as in the previous case.
Process/MaxProcessorsThis global integer variable is the maximum number of processors + * allowed for installed modules, which is always less than or equal to + * the number of existing processors in the system. This function will + * never return a number of threads greater than the value of this + * variable.
+ * + * The number of processors term refers to the number of existing + * logical processors in the system. These include all physical + * processors in multiprocessor systems, as well as all existing processor + * cores in multicore processors, and virtual processors in systems with + * HyperThreading or equivalent technology. + * + * Since version 1.8.0 of the PixInsight core application, nested + * parallelism is fully supported. This means that multiple threads can be + * executed concurrently from a running thread. This function will take into + * account the number of already running threads, as provided by the + * Thread::NumberOfRunningThreads() static member function, to help prevent + * exceeding the maximum number of threads allowed by the platform (see the + * global variables in the table above). In any event, the calling module is + * entirely responsible to comply with these restrictions. + * + * \note A module must never try to run more threads concurrently than the + * amount returned by this function. Failure to follow this rule will + * invalidate a module for certification. + */ + static int NumberOfThreads( size_type count, size_type overheadLimit = 1u ); + + /*! + * Returns a list of per-thread counts optimized for parallel processing of + * a set of items. + * + * \param count Number of processing units. A processing unit can + * be a single pixel, a row of pixels, or any suitable item, + * according to the task being performed by the caller. + * + * \param overheadLimit %Thread overhead limit in processing units. The + * function returns a list with a maximum length such that no + * thread would have to process less processing units than this + * value. The default overhead limit is one processing unit. + * + * \param maxThreads Maximum number of threads to use. The length of the + * returned list will be at most either this value, or the + * maximum number of threads currently allowed for the calling + * process, whichever is less. The default value of this + * parameter does not impose a practical limit. + * + * This function takes into account the number of existing logical + * processors in the system, as well as the maximum number of processors + * currently allowed for external processes by the PixInsight core + * application, and the number of threads currently active. See the + * NumberOfThreads() static member function for more information on thread + * execution and the global settings governing their use in PixInsight. + * + * This function returns a dynamic array of unsigned integers, where each + * element is the number of items that the corresponding thread should + * process in order to make an optimal usage of the processor resources + * currently available. The length of the returned array is the maximum + * number of threads that the calling process should execute concurrently to + * process the specified number of items, with the specified overhead limit + * and maximum number of processors. + * + * In the current implementation of this function, the returned array tends + * to spread the total work load uniformly across the threads available. + * Future implementations may consider additional factors, including the + * possibility of using new global settings specific for thread execution + * optimization. For this reason, under normal conditions a module should + * always use the result of calling this function to define a thread + * execution schedule. See also OptimalThreadLoadsAligned() for a variant of + * this function with prescribed item alignment. + * + * \note A module must never try to run more threads concurrently than the + * length of the array returned by this function. Failure to follow this + * rule will invalidate a module for certification. + * + * \sa OptimalThreadLoadsAligned() + */ + static Array OptimalThreadLoads( size_type count, + size_type overheadLimit = 1u, + int maxThreads = PCL_MAX_PROCESSORS ); + + /*! + * Returns a list of per-thread counts optimized for parallel processing of + * a contiguous set of items stored with a prescribed alignment. + * + * \param count Number of processing units. A processing unit can + * be a single pixel, a row of pixels, or any suitable item, + * according to the task being performed by the caller. For + * optimal performance, the size in bytes of a processing unit + * should be even, assuming that the task will be applied to a + * contiguous list of \a count items. + * + * \param align Item alignment. The function will return a list of counts, + * where all counts but the last one are guaranteed to be + * integer multiples of this parameter. The default value is 16. + * + * \param overheadLimit %Thread overhead limit in processing units. The + * function returns a list with a maximum length such that no + * thread would have to process less processing units than this + * value. The default overhead limit is one processing unit. + * + * \param maxThreads Maximum number of threads to use. The length of the + * returned list will be at most either this value, or the + * maximum number of threads currently allowed for the calling + * process (whichever is less), or maybe a smaller length, if + * necessary to enforce the specified alignment. The default + * value of this parameter does not impose a practical limit. + * + * Other than the prescribed alignment, this function is equivalent to its + * unaligned counterpart OptimalThreadLoads(). + * + * \sa OptimalThreadLoads() + */ + static Array OptimalThreadLoadsAligned( size_type count, + int align = 16, + size_type overheadLimit = 1u, + int maxThreads = PCL_MAX_PROCESSORS ); +private: + + int m_processorIndex = -1; + + Thread( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + +protected: + + virtual bool IsStealth() const + { + return false; + } + + friend class ThreadDispatcher; +}; + +// ---------------------------------------------------------------------------- + +/*! + * Suspends the calling thread from execution until the specified time \a ms in + * milliseconds has elapsed, or until a signal is delivered to the calling + * thread that terminates the process or causes activation of a signal-catching + * routine. + * \ingroup thread_support + */ +void PCL_FUNC Sleep( unsigned ms ); + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Thread_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Thread.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ThresholdedTransformation.h b/3rdparty/include/pcl/ThresholdedTransformation.h new file mode 100644 index 0000000..406300f --- /dev/null +++ b/3rdparty/include/pcl/ThresholdedTransformation.h @@ -0,0 +1,170 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ThresholdedTransformation.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_ThresholdedTransformation_h +#define __PCL_ThresholdedTransformation_h + +/// \file pcl/ThresholdedTransformation.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ThresholdedTransformation + * \brief Thresholded image transformation. + * + * %ThresholdedTransformation represents a thresholded image + * transformation in PCL. A thresholded transformation modifies its effect + * when applied to pixels within a given range of pixel sample values. + * + * Instead of defining a fixed range of sample values, a thresholded + * transformation defines two \e threshold values in PCL. These thresholds are + * normalized \e distances measured from a \e floating reference value that can + * be specified on a per-pixel basis. + * + * In PCL, convolutions in the spatial domain and morphological transformations + * have been implemented as thresholded transformations. + */ +class PCL_CLASS ThresholdedTransformation : public virtual ImageTransformation +{ +public: + + /*! + * Constructs a %ThresholdedTransformation object with the specified \a low + * and \a high threshold values in the normalized real range [0,1]. + */ + ThresholdedTransformation( double low = 0, double high = 0 ) + : m_lowThreshold( low ) + , m_highThreshold( high ) + { + } + + /*! + * Copy constructor. + */ + ThresholdedTransformation( const ThresholdedTransformation& ) = default; + + /*! + * Destroys a %ThresholdedTransformation object. + */ + virtual ~ThresholdedTransformation() + { + } + + /*! + * Returns true iff this transformation is currently thresholded. + * + * The transformation is thresholded when either threshold (low or high) is + * nonzero. When both thresholds are zero, the transformation applies no + * thresholding at all. + */ + bool IsThresholded() const + { + return 1 + m_lowThreshold != 1 || 1 + m_highThreshold != 1; + } + + /*! + * Returns the current low threshold in the normalized real range. + */ + double LowThreshold() const + { + return m_lowThreshold; + } + + /*! + * Sets the low threshold to the specified sample value \a t in the + * normalized real range. + */ + void SetLowThreshold( double t ) + { + m_lowThreshold = t; + } + + /*! + * Returns the current high threshold in the normalized real range. + */ + double HighThreshold() const + { + return m_highThreshold; + } + + /*! + * Sets the high threshold to the specified sample value \a t in the + * normalized real range. + */ + void SetHighThreshold( double t ) + { + m_highThreshold = t; + } + +private: + + /* + * Normalized threshold values. + */ + double m_lowThreshold = 0; + double m_highThreshold = 0; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ThresholdedTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ThresholdedTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/TimePoint.h b/3rdparty/include/pcl/TimePoint.h new file mode 100644 index 0000000..e2f1fa9 --- /dev/null +++ b/3rdparty/include/pcl/TimePoint.h @@ -0,0 +1,1210 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/TimePoint.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_TimePoint_h +#define __PCL_TimePoint_h + +/// \file pcl/TimePoint.h + +#include + +#include +#include + +/* + * N.B.: Remove potentially conflicting names that may be defined by 3rd-party + * packages used by some standard modules. + */ +#ifdef J2000 +# undef J2000 +#endif +#ifdef J2100 +# undef J2100 +#endif +#ifdef B1950 +# undef B1950 +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup time_representation Time Representation and Utilities + */ + +// ---------------------------------------------------------------------------- + +struct FileTime; + +/*! + * \class TimePoint + * \brief An instant in any timescale + * + * %TimePoint represents an instant, an infinitesimal point in time, in any + * timescale. The internal representation of time consists of the separate + * integer and fractional components of a Julian date. This guarantees a + * numerical resolution better than one nanosecond, as well as fast time + * relational and arithmetic operations. + * + * \ingroup time_representation + * \sa ISO8601ConversionOptions, IsoString::ParseISO8601DateTime() + */ +class PCL_CLASS TimePoint +{ +public: + + /*! + * Default constructor. Yields an invalid %TimePoint object that cannot be + * used until properly initialized. + */ + TimePoint() = default; + + /*! + * Constructs a %TimePoint object for a given instant represented as a + * Julian date. + */ + TimePoint( double jd ) + : m_jdi( TruncInt( jd ) ) + , m_jdf( Frac( jd ) ) + { + } + + /*! + * Constructs a %TimePoint object from two separate Julian date components, + * \a jd1 and \a jd2, where the resulting JD is jd1 + jd2. + * + * Specifying a JD in two parts greatly improves the accuracy of time + * representation, by increasing the effective bit length used to store time + * points. To maximize time resolution and calculation efficiency, + * %TimePoint normalizes its internal representation as the separate integer + * and fractional components of a JD. This guarantees a numerical resolution + * better than one nanosecond. + */ + TimePoint( double jd1, double jd2 ) + : m_jdi( TruncInt( jd1 ) + TruncInt( jd2 ) ) + , m_jdf( Frac( jd1 ) + Frac( jd2 ) ) + { + Normalize(); + } + + /*! + * Constructs a %TimePoint object from separate date components. + */ + TimePoint( int year, int month, double days ) + { + CalendarTimeToJD( m_jdi, m_jdf, year, month, TruncInt( days ), Frac( days ) ); + } + + /*! + * Constructs a %TimePoint object from separate date components plus a day + * fraction. + */ + TimePoint( int year, int month, int day, double dayFraction ) + { + CalendarTimeToJD( m_jdi, m_jdf, year, month, day, dayFraction ); + } + + /*! + * Constructs a %TimePoint object from separate date and time components. + */ + TimePoint( int year, int month, int day, int hour, int minute, double seconds ) + { + CalendarTimeToJD( m_jdi, m_jdf, year, month, day, (hour + (minute + seconds/60)/60)/24 ); + } + + /*! + * Constructs a %TimePoint object from an ISO 8601 extended date/time + * representation specified as an 8-bit ISO/IEC-8859-1 string. + * + * If the source representation specifies a nonzero time zone, it will be + * subtracted from the time point represented by this object. In other + * words, the newly constructed object will always transport a time point in + * the UTC timescale. + */ + TimePoint( const IsoString& dateTime ) + { + int year, month, day; + double dayf, tz; + dateTime.ParseISO8601DateTime( year, month, day, dayf, tz ); + CalendarTimeToJD( m_jdi, m_jdf, year, month, day, dayf - tz/24 ); + } + + /*! + * Constructs a %TimePoint object from an ISO 8601 extended date/time + * representation specified as a UTF-16 string. + * + * If the source representation specifies a nonzero time zone, it will be + * subtracted from the time point represented by this object. In other + * words, the newly constructed object will always transport a time point in + * the UTC timescale. + */ + TimePoint( const String& dateTime ) + { + int year, month, day; + double dayf, tz; + dateTime.ParseISO8601DateTime( year, month, day, dayf, tz ); + CalendarTimeToJD( m_jdi, m_jdf, year, month, day, dayf - tz/24 ); + } + + /*! + * Constructs a %TimePoint object from a time_t value. The specified \a time + * value will be interpreted as UTC. + */ + TimePoint( time_t time ); + + /*! + * Constructs a %TimePoint object from a FileTime object. + * + * \param fileTime Reference to a FileTime structure, from which date and + * time elements will be obtained to construct a + * %TimePoint object. The file time is expected to be + * represented as UTC, which is coherent with most file + * systems. + */ + TimePoint( const FileTime& fileTime ); + + /*! + * Copy constructor. + */ + TimePoint( const TimePoint& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + TimePoint& operator =( const TimePoint& ) = default; + + /*! + * Returns true iff this is a valid %TimePoint instance. An invalid + * %TimePoint does not represent a valid time point, generates empy string + * representations, and cannot be used until properly initialized. + */ + constexpr bool IsValid() const + { + return ((m_jdi > 0) ? m_jdi : -m_jdi) < 2147438065; + } + + /*! + * Extracts the individual date components. + * + * \param[out] year Reference to a variable that will receive the year + * component of this time point. + * + * \param[out] month Reference to a variable that will receive the month + * component of this time point, in the range [1,12]. + * + * \param[out] day Reference to a variable that will receive the day + * component of this time point, in the range [1,31]. + */ + void GetCalendarTime( int& year, int& month, int& day ) const + { + double dum; + JDToCalendarTime( year, month, day, dum, m_jdi, m_jdf ); + } + + /*! + * Extracts the individual date and day fraction components. + * + * \param[out] year Reference to a variable that will receive the year + * component of this time point. + * + * \param[out] month Reference to a variable that will receive the month + * component of this time point, in the range [1,12]. + * + * \param[out] day Reference to a variable that will receive the day + * component of this time point, in the range [1,31]. + * + * \param[out] dayf Reference to a variable that will receive the day + * fraction component of this time point, in the range + * [0,1). + */ + void GetCalendarTime( int& year, int& month, int& day, double& dayf ) const + { + JDToCalendarTime( year, month, day, dayf, m_jdi, m_jdf ); + } + + /*! + * Extracts the individual date and time components. + * + * \param[out] year Reference to a variable that will receive the year + * component of this time point. + * + * \param[out] month Reference to a variable that will receive the month + * component of this time point, in the range [1,12]. + * + * \param[out] day Reference to a variable that will receive the day + * component of this time point, in the range [1,31]. + * + * \param[out] hour Reference to a variable that will receive the hour + * component of this time point, in the range [0,23]. + * + * \param[out] minute Reference to a variable that will receive the minute + * component of this time point, in the range [0,59]. + * + * \param[out] seconds Reference to a variable that will receive the + * seconds component of this time point, in the range + * [0,60). + */ + void GetCalendarTime( int& year, int& month, int& day, int& hour, int& minute, double& seconds ) const + { + double dayf; + JDToCalendarTime( year, month, day, dayf, m_jdi, m_jdf ); + double h = Frac( dayf )*24; + double m = Frac( h )*60; + seconds = Frac( m )*60; + minute = TruncInt( m ); + hour = TruncInt( h ); + } + + /*! + * Returns the year component of this time point. + */ + int Year() const + { + int year, foo; double bar; + JDToCalendarTime( year, foo, foo, bar, m_jdi, m_jdf ); + return year; + } + + /*! + * Returns the month component of this time point in the range [1,12]. + */ + int Month() const + { + int foo, month; double bar; + JDToCalendarTime( foo, month, foo, bar, m_jdi, m_jdf ); + return month; + } + + /*! + * Returns the day component of this time point in the range [1,31]. + */ + int Day() const + { + int foo, day; double bar; + JDToCalendarTime( foo, foo, day, bar, m_jdi, m_jdf ); + return day; + } + + /*! + * Returns the day fraction component of this time point in the range [0,1). + */ + double DayFraction() const + { + int foobar; double dayf; + JDToCalendarTime( foobar, foobar, foobar, dayf, m_jdi, m_jdf ); + return dayf; + } + + /*! + * Returns an ISO 8601 extended date/time representation of this time point + * as a UTF-16 string. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 extended format. + * + * \param tz Time zone offset in hours. The default value is zero. + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), this function returns an empty string. + * + * \sa ISO8601ConversionOptions, String::ParseISO8601DateTime(), IsValid() + */ + String ToString( const ISO8601ConversionOptions& options = ISO8601ConversionOptions(), double tz = 0 ) const + { + return ToString( options, tz, (String*)0 ); + } + + /*! + * Returns an ISO 8601 extended date/time representation of this time point + * as a UTF-16 string. + * + * \param timeItems Number of represented time items. Can be 0, 1, 2 or 3. + * All items but the last one are represented as integer + * values. The last item is represented as a floating + * point value with the specified \a precision. + * + * \param precision Number of decimal digits for the last represented time + * item. The default value is three decimal digits. + * + * \param tz Time zone offset in hours. The default value is zero. + * + * \param timeZone Whether to append a time zone specifier to the ISO 8601 + * representation. The default value is true. + * + * \param zuluTime Whether to append the 'Z' special time zone specifier + * for UTC time without offset, or the '+00:00' specifier + * otherwise. The default value is true. + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), this function returns an empty string. + * + * \sa ISO8601ConversionOptions, String::ParseISO8601DateTime(), IsValid() + */ + String ToString( unsigned timeItems, unsigned precision = 3, double tz = 0, bool timeZone = true, bool zuluTime = true ) const + { + return ToString( ISO8601ConversionOptions( timeItems, precision, timeZone, zuluTime ), tz ); + } + + /*! + * Returns an ISO 8601 extended date/time representation of this time point + * as an 8-bit ISO/IEC-8859-1 string. + * + * \param options Optional settings to control the representation of date + * and time in ISO 8601 extended format. + * + * \param tz Time zone offset in hours. The default value is zero. + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), this function returns an empty string. + * + * \sa ISO8601ConversionOptions, IsoString::ParseISO8601DateTime(), IsValid() + */ + IsoString ToIsoString( const ISO8601ConversionOptions& options = ISO8601ConversionOptions(), double tz = 0 ) const + { + return ToString( options, tz, (IsoString*)0 ); + } + + /*! + * Returns an ISO 8601 extended date/time representation of this time point + * as an 8-bit ISO/IEC-8859-1 string. + * + * \param timeItems Number of represented time items. Can be 0, 1, 2 or 3. + * All items but the last one are represented as integer + * values. The last item is represented as a floating + * point value with the specified \a precision. + * + * \param precision Number of decimal digits for the last represented time + * item. The default value is three decimal digits. + * + * \param tz Time zone offset in hours. The default value is zero. + * + * \param timeZone Whether to append a time zone specifier to the ISO 8601 + * representation. The default value is true. + * + * \param zuluTime Whether to append the 'Z' special time zone specifier + * for UTC time without offset, or the '+00:00' specifier + * otherwise. The default value is true. + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), this function returns an empty string. + * + * \sa ISO8601ConversionOptions, IsoString::ParseISO8601DateTime(), IsValid() + */ + IsoString ToIsoString( unsigned timeItems, unsigned precision = 3, double tz = 0, bool timeZone = true, bool zuluTime = true ) const + { + return ToIsoString( ISO8601ConversionOptions( timeItems, precision, timeZone, zuluTime ), tz ); + } + + /*! + * Returns a custom representation of this time point as a UTF-16 string. + * + * \param format A date and time format string. The following format + * tokens will be replaced with formatted date and time + * items, as described in the following table:\n + * \n + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
\%YThe four-digit year.
\%MZero padded, two-digit month number, '01' through '12'.
\%nThe month number, '1' through '12'.
\%NThe English month name, 'January' through 'December'.
\%DZero padded, two-digit day of month, '01' through '31'.
\%dThe day of the month, '1' through '31'.
\%hZero padded, two digits of hour, '00' through '23'.
\%mZero padded, two digits of minute, '00' through '59'.
\%sZero padded, two digits of the seconds truncated to an integer, + * '00' through '59'.
\%s<p>Zero padded representation of seconds rounded or truncated to + * <p> decimal digits, with <p> in [0,9]. Truncation + * instead of rounding will we used if the rounded value is equal to + * 60 seconds.
\n + * Other characters in the format string will be included literally in + * the result. To include a percent sign '\%', escape it by preceding it + * with a backslash: "\\%". To include a backslash character, it must + * also be escaped as two consecutive slashes: "\\\\". + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), this function returns an empty string. + * + * Example: + * + * \code + * TimePoint t = TimePoint::Now(); + * std::cout << t.ToString( "%Y-%M-%D %h:%m:%s" ) << '\n' + * << t.ToString( "%Y-%M-%D %h:%m:%s2" ) << '\n' + * << t.ToString( "Today is: %N %d, %Y %h:%m:%s" ) << '\n'; + * \endcode + */ + String ToString( const String& format ) const; + + /*! + * Returns a custom representation of this time point as an 8-bit + * ISO/IEC-8859-1 string. + * + * See ToString( const String& ) for detailed information on the format + * string argument. + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), this function returns an empty string. + */ + IsoString ToIsoString( const IsoString& format ) const; + + IsoString ToIsoString( const char* format ) const + { + return ToIsoString( IsoString( format ) ); + } + + /*! + * String conversion operator. Equivalent to ToString(). + */ + explicit operator String() const + { + return ToString(); + } + + /*! + * IsoString conversion operator. Equivalent to ToIsoString(). + */ + explicit operator IsoString() const + { + return ToIsoString(); + } + + /*! + * Returns the integer part of the Julian date (also referred to as + * Julian day number) corresponding to this time point. + */ + constexpr int JDI() const + { + return m_jdi; + } + + /*! + * Returns the fractional part of the Julian date corresponding to this time + * point. + */ + constexpr double JDF() const + { + return m_jdf; + } + + /*! + * Returns the Julian date corresponding to this time point. + * + * The time point representation returned by this member function only has + * millisecond resolution. For higher resolution time point representations + * up to one nanosecond, use the separate integer and fractional components + * given by JDI() and JDF(). + * + * If this is an invalid %TimePoint (for example, a default constructed + * instance), the value returned by this function is meaningless as a Julian + * date. + */ + constexpr double JD() const + { + return m_jdi + m_jdf; + } + + /*! + * Returns the modified Julian date (MJD) corresponding to this time point. + * + * This function returns JD() - 2400000.5. Refer to the JD() member function + * for more information. + */ + constexpr double MJD() const + { + return (m_jdi-2400000) + (m_jdf-0.5); + } + + /*! + * Returns the value of Delta T, or the difference TT-UT1, corresponding to + * this time point. + * + * If possible, this member function returns an interpolated value from the + * global Delta T database, which will be loaded and parsed upon the first + * call to this function as a thread-safe procedure. See + * EphemerisFile::DeltaTDataFilePath() and + * EphemerisFile::OverrideDeltaTDataFilePath() for more information. + * + * Otherwise, if this time point falls outside the Delta T database time + * span, this function will use the polynomial expressions for Delta T + * included in Five Millennium Canon of Solar Eclipses, by Fred + * Espenak and Jean Meeus (NASA/TP–2006–214141, Revision 1.0, 2007). + * + * The returned value is the difference TT-UT1 in seconds. + */ + double DeltaT() const; + + /*! + * Returns the value of Delta AT, or the difference TAI-UTC, corresponding + * to this time point, which is assumed to represent an instant in the UTC + * timescale. + * + * If possible, this member function returns an interpolated value from the + * global Delta AT database, which will be loaded and parsed upon the first + * call to this function as a thread-safe procedure. See + * EphemerisFile::DeltaATDataFilePath() and + * EphemerisFile::OverrideDeltaATDataFilePath() for more information. + * + * UTC does not exist before 1960, so calling this function for a TimePoint + * before that year is a conceptual error. For convenience, zero is returned + * in such case instead of throwing an exception. + * + * The returned value is the difference TAI-UTC in seconds. + */ + double DeltaAT() const; + + /*! + * Adds the specified number of \a days to this time point. Returns a + * reference to this object. + */ + TimePoint& operator +=( double days ) + { + m_jdf += days; + Normalize(); + return *this; + } + + /*! + * Subtracts the specified number of \a days from this time point. Returns a + * reference to this object. + */ + TimePoint& operator -=( double days ) + { + m_jdf -= days; + Normalize(); + return *this; + } + + /*! + * Returns the time interval in days elapsed since the specified time point + * \a t. + */ + constexpr double DaysSince( const TimePoint& t ) const + { + return m_jdi-t.m_jdi + m_jdf-t.m_jdf; + } + + /*! + * Returns the time interval in Julian years (365.25 days) elapsed since the + * specified time point \a t. + */ + constexpr double YearsSince( const TimePoint& t ) const + { + return DaysSince( t )/365.25; + } + + /*! + * Returns the time interval in Julian centuries (36525 days) elapsed since + * the specified time point \a t. + */ + constexpr double CenturiesSince( const TimePoint& t ) const + { + return DaysSince( t )/36525; + } + + /*! + * Returns the time interval in seconds elapsed since the specified time + * point \a t. + */ + constexpr double SecondsSince( const TimePoint& t ) const + { + return DaysSince( t )*86400; + } + + /*! + * Returns the time interval in days elapsed since the standard J2000 epoch + * (JD 2451545.0 = 2000 January 1.5). + */ + constexpr double DaysSinceJ2000() const + { + return m_jdi-2451545 + m_jdf; + } + + /*! + * Returns the time interval in Julian years (365.25 days) elapsed since the + * standard J2000 epoch (JD 2451545.0 = 2000 January 1.5). + */ + constexpr double YearsSinceJ2000() const + { + return DaysSinceJ2000()/365.25; + } + + /*! + * Returns the time interval in Julian centuries (36525 days) elapsed since + * the standard J2000 epoch (JD 2451545.0 = 2000 January 1.5). + */ + constexpr double CenturiesSinceJ2000() const + { + return DaysSinceJ2000()/36525; + } + + /*! + * Returns the time interval in seconds elapsed since the standard J2000 + * epoch (JD 2451545.0 = 2000 January 1.5). + */ + constexpr double SecondsSinceJ2000() const + { + return DaysSinceJ2000()*86400; + } + + /*! + * Returns the time interval in days elapsed since the standard UNIX epoch + * (JD 2440587.5 = 1970 January 1.0). + */ + constexpr double DaysSinceUNIXEpoch() const + { + return m_jdi-2440587 + m_jdf-0.5; + } + + /*! + * Returns the time interval in Julian years (365.25 days) elapsed since the + * standard UNIX epoch (JD 2440587.5 = 1970 January 1.0). + */ + constexpr double YearsSinceUNIXEpoch() const + { + return DaysSinceUNIXEpoch()/365.25; + } + + /*! + * Returns the time interval in Julian centuries (36525 days) elapsed since + * the standard UNIX epoch (JD 2440587.5 = 1970 January 1.0). + */ + constexpr double CenturiesSinceUNIXEpoch() const + { + return DaysSinceUNIXEpoch()/36525; + } + + /*! + * Returns the time interval in seconds elapsed since the standard UNIX + * epoch (JD 2440587.5 = 1970 January 1.0). + */ + constexpr double SecondsSinceUNIXEpoch() const + { + return DaysSinceUNIXEpoch()*86400; + } + + /*! + * Returns the time interval in milliseconds elapsed since the standard UNIX + * epoch (JD 2440587.5 = 1970 January 1.0). + */ + constexpr double MillisecondsSinceUNIXEpoch() const + { + return DaysSinceUNIXEpoch()*86400000; + } + + /*! + * Returns the UTC offset for this time point on the host machine, or the + * difference Local Standard Time (LST) minus Universal Coordinated Time + * (UTC), in hours, at the date represented by this object. This + * function takes into account daylight saving time when applicable. + */ + double SystemOffsetFromUTC() const; + + /*! + * Returns this time point represented as Local Standard Time (LST), + * assuming that this object represents a time point in the UTC timescale. + */ + TimePoint UTCToLocalTime() const + { + return TimePoint( m_jdi, m_jdf + SystemOffsetFromUTC()/24 ); + } + + /*! + * Returns this time point represented as UTC, assuming that this object + * represents a time point in Local Standard Time (LST). + */ + TimePoint LocalTimeToUTC() const + { + return TimePoint( m_jdi, m_jdf - SystemOffsetFromUTC()/24 ); + } + + /*! + * Returns a %TimePoint object corresponding to the current date and time in + * the UTC timescale. + */ + static TimePoint Now(); + + /*! + * Returns a %TimePoint object corresponding to the standard J2000 epoch, + * namely JD 2451545.0, corresponding to the midday of 2000 January 1. + */ + static TimePoint J2000() + { + TimePoint t; + t.m_jdi = 2451545; + t.m_jdf = 0; + return t; + } + + /*! + * Returns a %TimePoint object corresponding to the standard J2100 epoch, + * namely JD 2488070.0, corresponding to the midday of 2100 January 1. + */ + static TimePoint J2100() + { + TimePoint t; + t.m_jdi = 2488070; + t.m_jdf = 0; + return t; + } + + /*! + * Returns a %TimePoint object corresponding to the B1950.0 epoch, namely + * JD 2433282.42345905, corresponding to 1949 December 31.92345905. + */ + static TimePoint B1950() + { + TimePoint t; + t.m_jdi = 2433282; + t.m_jdf = 0.42345905; + return t; + } + + /*! + * Returns a %TimePoint object corresponding to the standard UNIX epoch, + * namely JD 2440587.5, corresponding to 1970 January 1.0. + */ + static TimePoint UNIXEpoch() + { + TimePoint t; + t.m_jdi = 2440587; + t.m_jdf = 0.5; + return t; + } + + /*! + * Returns a %TimePoint object constructed from an ISO 8601 extended + * date/time representation specified as an 8-bit ISO/IEC-8859-1 string. If + * successful, stores the evaluated time zone offset, in hours, in the + * specified variable \a tz. Otherwise this function throws the appropriate + * Error exception. + * + * If the source representation specifies a nonzero time zone, it will be + * subtracted from the time point constructed by this function. In other + * words, the newly constructed object will always transport a time point in + * the UTC timescale without offset. + * + * \sa TryFromString( TimePoint&, double&, const IsoString& ), + * IsoString::ParseISO8601DateTime() + */ + static TimePoint FromString( double& tz, const IsoString& dateTime ) + { + int year, month, day; + double dayf; + dateTime.ParseISO8601DateTime( year, month, day, dayf, tz ); + return TimePoint( year, month, day, dayf - tz/24 ); + } + + /*! + * Returns a %TimePoint object constructed from an ISO 8601 extended + * date/time representation specified as a UTF-16 string. If successful, + * stores the evaluated time zone offset, in hours, in the specified + * variable \a tz. Otherwise this function throws the appropriate Error + * exception. + * + * If the source representation specifies a nonzero time zone, it will be + * subtracted from the time point constructed by this function. In other + * words, the newly constructed object will always transport a time point in + * the UTC timescale without offset. + * + * \sa TryFromString( TimePoint&, double&, const String& ), + * String::ParseISO8601DateTime() + */ + static TimePoint FromString( double& tz, const String& dateTime ) + { + int year, month, day; + double dayf; + dateTime.ParseISO8601DateTime( year, month, day, dayf, tz ); + return TimePoint( year, month, day, dayf - tz/24 ); + } + + /*! + * Returns a %TimePoint object constructed from an ISO 8601 extended + * date/time representation specified as an 8-bit ISO/IEC-8859-1 string. + * + * If the source representation specifies a nonzero time zone, it will be + * subtracted from the time point constructed by this function. In other + * words, the newly constructed object will always transport a time point in + * the UTC timescale without offset. + * + * \sa TryFromString( TimePoint&, const IsoString& ), + * IsoString::ParseISO8601DateTime() + */ + static TimePoint FromString( const IsoString& dateTime ) + { + return TimePoint( dateTime ); + } + + /*! + * Returns a %TimePoint object constructed from an ISO 8601 extended + * date/time representation specified as a UTF-16 string. + * + * If the source representation specifies a nonzero time zone, it will be + * subtracted from the time point constructed by this function. In other + * words, the newly constructed object will always transport a time point in + * the UTC timescale without offset. + * + * \sa TryFromString( TimePoint&, const String& ), + * String::ParseISO8601DateTime() + */ + static TimePoint FromString( const String& dateTime ) + { + return TimePoint( dateTime ); + } + + /*! + * Attempts to evaluate the specified 8-bit string as a date and time + * specification in ISO 8601 extended format. If successful, stores the + * evaluated UTC time point in the specified variable \a t, and the + * evaluated time zone offset, in hours, in the variable \a tz, then returns + * \c true. + * + * If the specified string cannot be evaluated as a valid date and time in + * ISO 8601 extended format, this function returns \c false and does not + * change the passed variables \a t and \a tz. This function does not throw + * any parsing exceptions. + * + * If the source string contains a time zone offset, it is subtracted from + * the evaluated time point. In other words, the %TimePoint value stored in + * \a t is always represented in the UTC timescale without any offset. + * + * \sa FromString( const IsoString& ), IsoString::TryParseISO8601DateTime() + */ + static bool TryFromString( TimePoint& t, double& tz, const IsoString& dateTime ) + { + int year, month, day; + double dayf; + if ( dateTime.TryParseISO8601DateTime( year, month, day, dayf, tz ) ) + { + t = TimePoint( year, month, day, dayf - tz/24 ); + return true; + } + return false; + } + + /*! + * Attempts to evaluate the specified UTF-16 string as a date and time + * specification in ISO 8601 extended format. If successful, stores the + * evaluated UTC time point in the specified variable \a t, and the + * evaluated time zone offset, in hours, in the variable \a tz, then returns + * \c true. + * + * If the specified string cannot be evaluated as a valid date and time in + * ISO 8601 extended format, this function returns \c false and does not + * change the passed variables \a t and \a tz. This function does not throw + * any parsing exceptions. + * + * If the source string contains a time zone offset, it is subtracted from + * the evaluated time point. In other words, the %TimePoint value stored in + * \a t is always represented in the UTC timescale without any offset. + * + * \sa FromString( const String& ), String::TryParseISO8601DateTime() + */ + static bool TryFromString( TimePoint& t, double& tz, const String& dateTime ) + { + int year, month, day; + double dayf; + if ( dateTime.TryParseISO8601DateTime( year, month, day, dayf, tz ) ) + { + t = TimePoint( year, month, day, dayf - tz/24 ); + return true; + } + return false; + } + + /*! + * Attempts to evaluate the specified 8-bit string as a date and time + * specification in ISO 8601 extended format. If successful, stores the + * evaluated UTC time point in the specified variable \a t, then returns + * \c true. + * + * If the specified string cannot be evaluated as a valid date and time in + * ISO 8601 extended format, this function returns \c false and does not + * change the passed variable \a t. This function does not throw any parsing + * exceptions. + * + * If the source string contains a time zone offset, it is subtracted from + * the evaluated time point. In other words, the %TimePoint value stored in + * \a t is always represented in the UTC timescale without any offset. + * + * \sa FromString( const IsoString& ), IsoString::TryParseISO8601DateTime() + */ + static bool TryFromString( TimePoint& t, const IsoString& dateTime ) + { + double tz; + return TryFromString( t, tz, dateTime ); + } + + /*! + * Attempts to evaluate the specified UTF-16 string as a date and time + * specification in ISO 8601 extended format. If successful, stores the + * evaluated UTC time point in the specified variable \a t, then returns + * \c true. + * + * If the specified string cannot be evaluated as a valid date and time in + * ISO 8601 extended format, this function returns \c false and does not + * change the passed variable \a t. This function does not throw any parsing + * exceptions. + * + * If the source string contains a time zone offset, it is subtracted from + * the evaluated time point. In other words, the %TimePoint value stored in + * \a t is always represented in the UTC timescale without any offset. + * + * \sa FromString( const String& ), String::TryParseISO8601DateTime() + */ + static bool TryFromString( TimePoint& t, const String& dateTime ) + { + double tz; + return TryFromString( t, tz, dateTime ); + } + +private: + + int32 m_jdi = int32_max; // invalid by default + double m_jdf = 0.0; + + /*! + * \internal + * Ensures that the internal Julian date separate representation is optimal + * in terms of time resolution by constraining JDF to [0,1). + */ + void Normalize() + { + if ( Abs( m_jdf ) >= 1 ) + { + m_jdi += TruncInt( m_jdf ); + m_jdf = Frac( m_jdf ); + } + } + + template + S ToString( const ISO8601ConversionOptions& options, double tz, S* ) const + { + if ( IsValid() ) + { + int year, month, day; + double dayf; + JDToCalendarTime( year, month, day, dayf, m_jdi, m_jdf ); + return S::ToISO8601DateTime( year, month, day, dayf, tz, options ); + } + return S(); + } +}; + +/* + * ### N.B.: TimePoint cannot have virtual member functions. + * This is because sizeof( TimePoint ) _must_ be equal to + * sizeof( uint32 ) + sizeof( uint64 ). + */ +struct PCL_AssertTimePointSize +{ + struct TestData { uint32 x; uint64 y; }; + static_assert( sizeof( TimePoint ) == sizeof( TestData ), "Invalid sizeof( TimePoint )" ); +}; + +/*! + * Returns true iff two %TimePoint objects, \a t1 and \a t2, represent the same + * time point. + * \ingroup time_representation + */ +inline constexpr bool operator ==( const TimePoint& t1, const TimePoint& t2 ) +{ + return t1.JDI() == t2.JDI() && t1.JDF() == t2.JDF(); +} + +/*! + * Returns true iff a %TimePoint object \a t1 represents the specified time + * point \a jd2, expressed as a Julian date. + * \ingroup time_representation + */ +inline constexpr bool operator ==( const TimePoint& t1, double jd2 ) +{ + return t1.JD() == jd2; +} + +/*! + * Returns true iff a %TimePoint object \a t2 represents the specified time + * point \a jd1, expressed as a Julian date. This operator implements the + * commutative property of scalar time point equality. + * \ingroup time_representation + */ +inline constexpr bool operator ==( double jd1, const TimePoint& t2 ) +{ + return t2.JD() == jd1; +} + +/*! + * Returns true iff a %TimePoint object \a t1 represents a time point that + * precedes the time point represented by another object \a t2. + * + * Invalid %TimePoint instances are always in the infinite past: if + * \a t1 is invalid, this function returns true; if \a t1 is valid and \a t2 is + * not valid, this function returns false. + * + * \ingroup time_representation + */ +inline constexpr bool operator <( const TimePoint& t1, const TimePoint& t2 ) +{ + return !t1.IsValid() || t2.IsValid() && ((t1.JDI() != t2.JDI()) ? t1.JDI() < t2.JDI() : t1.JDF() < t2.JDF()); +} + +/*! + * Returns true iff a %TimePoint object \a t1 represents a time point that + * precedes another time point \a jd2, expressed as a Julian date. + * + * Invalid %TimePoint instances are always in the infinite past: if + * \a t1 is invalid, this function returns true. + * + * \ingroup time_representation + */ +inline constexpr bool operator <( const TimePoint& t1, double jd2 ) +{ + return !t1.IsValid() || t1.JD() < jd2; +} + +/*! + * Returns true iff a time point \a jd1, expressed as a Julian date, precedes + * the time point represented by a %TimePoint object \a t2. + * + * Invalid %TimePoint instances are always in the infinite past: if + * \a t2 is invalid, this function returns false. + * + * \ingroup time_representation + */ +inline constexpr bool operator <( double jd1, const TimePoint& t2 ) +{ + return t2.IsValid() && t2.JD() < jd1; +} + +/*! + * Returns the time interval in days elapsed from the specified time point + * \a t1 to another time point \a t2. The returned value is positive if \a t2 + * precedes \a t1, negative if \a t1 precedes \a t2. + * \ingroup time_representation + */ +inline constexpr double operator -( const TimePoint& t1, const TimePoint& t2 ) +{ + return (t1.JDI() - t2.JDI()) + (t1.JDF() - t2.JDF()); +} + +/*! + * Returns the time point resulting after \a d days transcurred since a time + * point \a t. + * \ingroup time_representation + */ +inline TimePoint operator +( const TimePoint& t, double d ) +{ + return TimePoint( t.JDI(), t.JDF()+d ); +} + +/*! + * Returns the time point resulting after \a d days transcurred since a time + * point \a t. This operator implements the commutative property of scalar time + * point addition. + * \ingroup time_representation + */ +inline TimePoint operator +( double d, const TimePoint& t ) +{ + return t + d; +} + +/*! + * Returns the time point \a d days before a time point \a t. Note that scalar + * time point subtraction is not a commutative operation, so 'd-t' cannot be + * used. + * \ingroup time_representation + */ +inline TimePoint operator -( const TimePoint& t, double d ) +{ + return TimePoint( t.JDI(), t.JDF()-d ); +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_TimePoint_h + +// ---------------------------------------------------------------------------- +// EOF pcl/TimePoint.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Timer.h b/3rdparty/include/pcl/Timer.h new file mode 100644 index 0000000..93f7387 --- /dev/null +++ b/3rdparty/include/pcl/Timer.h @@ -0,0 +1,238 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Timer.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_Timer_h +#define __PCL_Timer_h + +/// \file pcl/Timer.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Timer + * \brief Client-side interface to a PixInsight %Timer object. + * + * A %Timer object can work in two ways: + * + * \li As a periodic timer, which generates a sequence of timer events + * at regular time intervals. + * + * \li As a single-shot timer, which generates a single timer event + * after a prescribed time interval. + * + * ### TODO: Write a detailed description for %Timer. + */ +class PCL_CLASS Timer : public UIObject +{ +public: + + /*! + * Constructs a %Timer object. + */ + Timer(); + + /*! + * Destroys a %Timer object. + */ + virtual ~Timer() + { + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * Since timers are unique objects by definition, calling this member + * function has no effect. + */ + void EnsureUnique() override + { + // Timers are unique objects by definition + } + + /*! + * Returns a reference to a null %Timer instance. A null %Timer does not + * correspond to an existing timer in the PixInsight core application. + */ + static Timer& Null(); + + /*! + * Returns the timer interval in seconds. + */ + double Interval() const; + + /*! + * Sets the timer interval in seconds. + */ + void SetInterval( double seconds ); + + /*! + * Returns true iff this is a single-shot timer. + */ + bool IsSingleShot() const; + + /*! + * Returns true iff this is a periodic timer. + * + * This is a convenience member function, equivalent to + * !IsSingleShot() + */ + bool IsPeriodic() const + { + return !IsSingleShot(); + } + + /*! + * Enables or disables single-shot mode for this %Timer object. + */ + void SetSingleShot( bool = true ); + + /*! + * Enables or disables periodic mode for this %Timer object. + */ + void SetPeriodic( bool p = true ) + { + SetSingleShot( !p ); + } + + /*! + * Returns true iff this %Timer object is active. An active timer is + * generating timer events. + */ + bool IsRunning() const; + + /*! + * Activates this %Timer object. Starts generation of timer event(s). + */ + void Start(); + + /*! + * Stops this %Timer object, if it is currently active. + */ + void Stop(); + + /*! + * Returns the number of timer events generated after the last call to + * Start(). + */ + unsigned Count() const + { + return count; + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnTimer( Timer& sender ); + + /*! + * \defgroup timer_event_handlers Timer Event Handlers + */ + + /*! + * Defines the prototype of a timer event handler. + * + * A timer event is generated by an active %Timer object, either at regular + * intervals (periodic timer), or just once when the timer period elapses + * (single-shot timer). + * + * \param sender The control that sends a timer event. + * + * \ingroup timer_event_handlers + */ + typedef void (Control::*timer_event_handler)( Timer& sender ); + + /*! + * Sets the timer event handler for this %Timer object. + * + * \param handler The timer event handler. Must be a member function of + * the receiver object's class. + * + * \param receiver The control that will receive timer events from this + * %Timer. + * + * \ingroup timer_event_handlers + */ + void OnTimer( timer_event_handler handler, Control& receiver ); + +private: + + timer_event_handler onTimer = nullptr; + unsigned count = 0; + + Timer( void* h ) : UIObject( h ) + { + } + + void* CloneHandle() const override; + + friend class TimerEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_Timer_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Timer.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ToolButton.h b/3rdparty/include/pcl/ToolButton.h new file mode 100644 index 0000000..da9f113 --- /dev/null +++ b/3rdparty/include/pcl/ToolButton.h @@ -0,0 +1,126 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ToolButton.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_ToolButton_h +#define __PCL_ToolButton_h + +/// \file pcl/ToolButton.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ToolButton + * \brief Client-side interface to a PixInsight %ToolButton control. + * + * ### TODO: Write a detailed description for %ToolButton + */ +class PCL_CLASS ToolButton : public Button +{ +public: + + /*! + * Constructs a %ToolButton with the specified \a text, \a icon and \a + * checkable state, as a child control of \a parent. + */ + ToolButton( const String& text = String(), + const pcl::Bitmap& icon = Bitmap::Null(), + bool checkable = false, + Control& parent = Control::Null() ); + + /*! + * Destroys a %ToolButton control. + */ + virtual ~ToolButton() + { + } + + /*! + * Returns \c true, since tool buttons are pushable buttons. + */ + bool IsPushable() const override + { + return true; + } + + /*! + * Returns true iff this %ToolButton is \a e checkable. + * + * \sa SetCheckable() + */ + bool IsCheckable() const override; + + /*! + * Enables or disables the checkable state of this %ToolButton. + * + * \sa IsCheckable() + */ + void SetCheckable( bool = true ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ToolButton_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ToolButton.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Translation.h b/3rdparty/include/pcl/Translation.h new file mode 100644 index 0000000..2a02410 --- /dev/null +++ b/3rdparty/include/pcl/Translation.h @@ -0,0 +1,210 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Translation.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_Translation_h +#define __PCL_Translation_h + +/// \file pcl/Translation.h + +#include +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Translation + * \brief %Image translation algorithm. + * + * ### TODO: Write a detailed description for %Translation + */ +class PCL_CLASS Translation : public InterpolatingGeometricTransformation, + public ParallelProcess +{ +public: + + /*! + * Constructs a %Translation object using the specified pixel interpolation + * \a p, with translation increments \a dx and \a dy in pixels. + * + * The specified pixel interpolation object \a p must remain valid while + * this object exists. + */ + Translation( PixelInterpolation& p, double dx = 0, double dy = 0 ) + : InterpolatingGeometricTransformation( p ) + , m_delta( dx, dy ) + { + } + + /*! + * Constructs a %Translation object using the specified pixel interpolation + * \a p, with translation increments in pixels given by the components of a + * point \a d in the plane. + * + * The specified pixel interpolation object \a p must remain valid while + * this object exists. + */ + Translation( PixelInterpolation& p, const DPoint& d ) + : InterpolatingGeometricTransformation( p ) + , m_delta( d ) + { + } + + /*! + * Copy constructor. + */ + Translation( const Translation& ) = default; + + /*! + * Returns the translation increments in pixels for both axes, as the + * corresponding components of a point in the plane. + */ + const DPoint& Delta() const + { + return m_delta; + } + + /*! + * Returns the horizontal translation increment in pixels. + */ + double DeltaX() const + { + return m_delta.x; + } + + /*! + * Returns the vertical translation increment in pixels. + */ + double DeltaY() const + { + return m_delta.y; + } + + /*! + * Sets the translation increments in pixels as the components of a point + * \a d in the plane. + */ + void SetDelta( const DPoint& d ) + { + m_delta = d; + } + + /*! + * Sets the translation increments \a dx and \a dy in pixels. + */ + void SetDelta( double dx, double dy ) + { + m_delta.x = dx; m_delta.y = dy; + } + + /*! + * Returns the current vector of per-channel filling values for uncovered + * image regions. + * + * See the documentation for SetFillValues() for more information. + */ + const DVector& FillValues() const + { + return m_fillValues; + } + + /*! + * Sets a vector of per-channel filling values for uncovered image regions. + * + * Uncovered regions result each time an image is translated. Note that + * uncovering can be \e partial for one row or column of pixels, when + * fractional displacements are applied in the corresponding plane + * directions. + * + * By default, there are no filling values defined (and hence the returned + * vector is empty by default). When the %Translation instance is executed + * and a filling value is not defined for a channel of the target image, + * uncovered regions are filled with the minimum sample value in the native + * range of the image (usually zero). + */ + void SetFillValues( const DVector& fillValues ) + { + m_fillValues = fillValues; + } + + /*! + */ + void GetNewSizes( int& width, int& height ) const override + { + // No changes + } + +protected: + + DPoint m_delta; // displacements in pixels + DVector m_fillValues; + + // Inherited from ImageTransformation. + void Apply( pcl::Image& ) const override; + void Apply( pcl::DImage& ) const override; + void Apply( pcl::UInt8Image& ) const override; + void Apply( pcl::UInt16Image& ) const override; + void Apply( pcl::UInt32Image& ) const override; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Translation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Translation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/TreeBox.h b/3rdparty/include/pcl/TreeBox.h new file mode 100644 index 0000000..255296d --- /dev/null +++ b/3rdparty/include/pcl/TreeBox.h @@ -0,0 +1,962 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/TreeBox.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_TreeBox_h +#define __PCL_TreeBox_h + +/// \file pcl/TreeBox.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class TreeBox + * \brief Client-side interface to a PixInsight %TreeBox control + * + * ### TODO: Write a detailed description for %TreeBox. + */ +class PCL_CLASS TreeBox : public ScrollBox +{ +public: + + /*! + * \class pcl::TreeBox::Node + * \brief Client-side interface to a PixInsight %TreeBox node + * + * ### TODO: Write a detailed description for %TreeBox::Node. + */ + class PCL_CLASS Node : public UIObject + { + public: + + /*! # + */ + Node(); + + /* + * ### N.B.: If we define a default parameter value index=-1 for the + * following constructor (as expected), the static member function Null() + * cannot be compiled with g++ 4.9.x. The compiler issues the error: + * + * no matching function for call to + * 'pcl::TreeBox::Node::Node(pcl::TreeBox::Node)' + * + * which is obviously incorrect and looks like an obscure compiler bug. + * Note that the same problem exists with g++ 4.8.x (at least). + */ + /*! # + */ + Node( Node& parent, int index ); + + /*! # + */ + Node( TreeBox& parentTree, int index = -1 ); + + /*! + * Destroys a %TreeBox::Node object. + */ + virtual ~Node(); + + /*! # + */ + static Node Null() + { + // ### See note above for Node::Node( Node&, int ). + return Node( nullptr ); + } + + /*! # + */ + const TreeBox& ParentTree() const; + + /*! # + */ + TreeBox& ParentTree(); + + /*! # + */ + const Node* Parent() const; + + /*! # + */ + Node* Parent(); + + /*! # + */ + int NumberOfChildren() const; + + /*! # + */ + const Node* Child( int idx ) const; + + /*! # + */ + Node* Child( int idx ); + + /*! # + */ + const Node* operator []( int idx ) const + { + return Child( idx ); + } + + /*! # + */ + Node* operator []( int idx ) + { + return Child( idx ); + } + + /*! # + */ + int ChildIndex( const Node* ) const; + + /*! # + */ + void Insert( int idx, Node* ); + + /*! # + */ + void Add( Node* node ) + { + Insert( NumberOfChildren(), node ); + } + + /*! # + */ + void Remove( int idx ); + + /*! # + */ + bool IsEnabled() const; + + /*! # + */ + void Enable( bool = true ); + + /*! # + */ + void Disable( bool disable = true ) + { + Enable( !disable ); + } + + /*! # + */ + bool IsExpanded() const; + + /*! # + */ + bool IsCollapsed() const + { + return !IsExpanded(); + } + + /*! # + */ + void Expand( bool expand = true ); + + /*! # + */ + void Collapse( bool collapse = true ) + { + Expand( !collapse ); + } + + /*! # + */ + bool IsSelectable() const; + + /*! # + */ + void SetSelectable( bool = true ); + + /*! # + */ + bool IsSelected() const; + + /*! # + */ + void Select( bool = true ); + + /*! # + */ + void Unselect( bool unselect = true ) + { + Select( !unselect ); + } + + /*! # + */ + bool IsCheckable() const; + + /*! # + */ + void SetCheckable( bool = true ); + + /*! # + */ + bool IsChecked() const; + + /*! # + */ + void Check( bool = true ); + + /*! # + */ + void Uncheck( bool uncheck = true ) + { + Check( !uncheck ); + } + + /*! # + */ + String Text( int col ) const; + + /*! # + */ + void SetText( int col, const String& ); + + /*! # + */ + Bitmap Icon( int col ) const; + + /*! # + */ + void SetIcon( int col, const Bitmap& ); + + /*! # + */ + int Alignment( int col ) const; + + /*! # + */ + void SetAlignment( int col, int align ); + + /*! # + */ + String ToolTip( int col ) const; + + /*! # + */ + void SetToolTip( int col, const String& ); + + /*! # + */ + pcl::Font Font( int col ) const; + + /*! # + */ + void SetFont( int col, const pcl::Font& ); + + /*! # + */ + RGBA BackgroundColor( int col ) const; + + /*! # + */ + void SetBackgroundColor( int col, RGBA ); + + /*! # + */ + RGBA TextColor( int col ) const; + + /*! # + */ + void SetTextColor( int col, RGBA ); + + protected: + + /*! + * \internal + */ + Node( void* h ) : UIObject( h ) + { + } + + /*! + * \internal + */ + Node( std::nullptr_t ) : UIObject( nullptr ) + { + } + + /*! + * \internal + */ + void* CloneHandle() const override; + + private: + + typedef SortedArray child_node_list; + child_node_list m_children; + bool m_removed = false; + + friend class TreeBox; + }; + + // ------------------------------------------------------------------------- + + /*! + * Constructs a %TreeBox as a child control of \a parent. + */ + TreeBox( Control& parent = Control::Null() ); + + /*! + * Destroys a %TreeBox control. + */ + virtual ~TreeBox(); + + /*! # + */ + static TreeBox& NullTree(); + + // + + /*! # + */ + int NumberOfChildren() const; + + /*! # + */ + const Node* Child( int idx ) const; + + /*! # + */ + Node* Child( int idx ); + + /*! # + */ + const Node* operator []( int idx ) const + { + return Child( idx ); + } + + /*! # + */ + Node* operator []( int idx ) + { + return Child( idx ); + } + + /*! # + */ + int ChildIndex( const Node* ) const; + + /*! # + */ + void Insert( int idx, Node* ); + + /*! # + */ + void Add( Node* n ) + { + Insert( NumberOfChildren(), n ); + } + + /*! # + */ + void Remove( int idx ); + + /*! # + */ + void Clear(); + + // + + /*! # + */ + const Node* CurrentNode() const; + + /*! # + */ + Node* CurrentNode(); + + /*! # + */ + void SetCurrentNode( Node* ); + + // + + /*! # + */ + bool AreMultipleSelectionsEnabled() const; + + /*! # + */ + bool AreMultipleSelectionsDisabled() const + { + return !AreMultipleSelectionsEnabled(); + } + + /*! # + */ + void EnableMultipleSelections( bool enable = true ); + + /*! # + */ + void DisableMultipleSelections( bool disable = true ) + { + EnableMultipleSelections( !disable ); + } + + /*! + * Returns a dynamic array of pointers to all selected nodes in this tree. + * If this tree has no selected nodes, an empty array is returned. + * + * The returned object is an instantiation of IndirectArray for the + * TreeBox::Node class: IndirectArray\. + */ + IndirectArray SelectedNodes() const; + + /*! + * Selects all nodes in this tree, that is the entire %TreeBox contents. + */ + void SelectAllNodes(); + + /*! + * Returns true if this %TreeBox object has one or more selected toplevel + * nodes; false if no toplevel nodes are selected. + */ + bool HasSelectedTopLevelNodes() const; + + // + + /*! # + */ + const Node* NodeByPosition( const pcl::Point& p ) const + { + return NodeByPosition( p.x, p.y ); // in client coordinates + } + + /*! # + */ + Node* NodeByPosition( const pcl::Point& p ) + { + return NodeByPosition( p.x, p.y ); + } + + /*! # + */ + const Node* NodeByPosition( int x, int y ) const; + + /*! # + */ + Node* NodeByPosition( int x, int y ); + + /*! # + */ + void SetNodeIntoView( Node* ); + + /*! # + */ + pcl::Rect NodeRect( const Node* ) const; + + // + + /*! # + */ + int NumberOfColumns() const; + + /*! # + */ + void SetNumberOfColumns( int nCols ); + + // Visibility + + /*! # + */ + bool IsColumnVisible( int col ) const; + + /*! # + */ + void ShowColumn( int col, bool show = true ); + + /*! # + */ + void HideColumn( int col, bool hide = true ) + { + ShowColumn( col, !hide ); + } + + // + + /*! # + */ + int ColumnWidth( int col ) const; + + /*! # + */ + void SetColumnWidth( int col, int width ); + + /*! # + */ + int ScaledColumnWidth( int col ) const + { + return PhysicalPixelsToLogical( ColumnWidth( col ) ); + } + + /*! # + */ + void SetScaledColumnWidth( int col, int width ) + { + SetColumnWidth( col, LogicalPixelsToPhysical( width ) ); + } + + /*! # + */ + void AdjustColumnWidthToContents( int col ); + + // + + /*! # + */ + String HeaderText( int col ) const; + + /*! # + */ + void SetHeaderText( int col, const String& ); + + // + + /*! # + */ + Bitmap HeaderIcon( int col ) const; + + /*! # + */ + void SetHeaderIcon( int col, const Bitmap& ); + + // + + /*! # + */ + int HeaderAlignment( int col ) const; + + /*! # + */ + void SetHeaderAlignment( int col, int align ); + + /*! # + */ + bool IsHeaderVisible() const; + + /*! # + */ + void ShowHeader( bool show = true ); + + /*! # + */ + void HideHeader( bool hide = true ) + { + ShowHeader( !hide ); + } + + // + + /*! # + */ + int IndentSize() const; + + /*! # + */ + void SetIndentSize( int ); + + /*! # + */ + int ScaledIndentSize() const + { + return PhysicalPixelsToLogical( IndentSize() ); + } + + /*! # + */ + void SetScaledIndentSize( int size ) + { + SetIndentSize( LogicalPixelsToPhysical( size ) ); + } + + // + + /*! # + */ + bool IsNodeExpansionEnabled() const; + + /*! # + */ + void EnableNodeExpansion( bool = true ); + + /*! # + */ + void DisableNodeExpansion( bool disable = true ) + { + EnableNodeExpansion( !disable ); + } + + // + + /*! # + */ + bool IsRootDecorationEnabled() const; + + /*! # + */ + void EnableRootDecoration( bool = true ); + + /*! # + */ + void DisableRootDecoration( bool disable = true ) + { + EnableRootDecoration( !disable ); + } + + // Alternating row colors + // Even row color is Control::CanvasColor() + // Odd row color is Control::AlternateCanvasColor() + + /*! # + */ + bool IsAlternateRowColorEnabled() const; + + /*! # + */ + void EnableAlternateRowColor( bool = true ); + + /*! # + */ + void DisableAlternateRowColor( bool disable = true ) + { + EnableAlternateRowColor( !disable ); + } + + // + + /*! # + */ + bool IsUniformRowHeightEnabled() const; + + /*! # + */ + void EnableUniformRowHeight( bool = true ); + + /*! # + */ + void DisableUniformRowHeight( bool disable = true ) + { + EnableUniformRowHeight( !disable ); + } + + // + + /*! # + */ + void GetIconSize( int& width, int& height ) const; + + /*! # + */ + int IconWidth() const + { + int w, dum; GetIconSize( w, dum ); return w; + } + + /*! # + */ + int IconHeight() const + { + int dum, h; GetIconSize( dum, h ); return h; + } + + /*! # + */ + void SetIconSize( int width, int height ); + + /*! # + */ + void SetIconSize( int size ) + { + SetIconSize( size, size ); + } + + /*! # + */ + void GetScaledIconSize( int& width, int& height ) const + { + GetIconSize( width, height ); width = PhysicalPixelsToLogical( width ); height = PhysicalPixelsToLogical( height ); + } + + /*! # + */ + int ScaledIconWidth() const + { + int width, dum; GetIconSize( width, dum ); return PhysicalPixelsToLogical( width ); + } + + /*! # + */ + int ScaledIconHeight() const + { + int dum, height; GetIconSize( dum, height ); return PhysicalPixelsToLogical( height ); + } + + /*! # + */ + void SetScaledIconSize( int width, int height ) + { + SetIconSize( LogicalPixelsToPhysical( width ), LogicalPixelsToPhysical( height ) ); + } + + /*! # + */ + void SetScaledIconSize( int size ) + { + size = LogicalPixelsToPhysical( size ); + SetIconSize( size, size ); + } + + // + + /*! # + */ + bool IsHeaderSortingEnabled() const; + + /*! # + */ + void EnableHeaderSorting( bool = true ); + + /*! # + */ + void DisableHeaderSorting( bool disable = true ) + { + EnableHeaderSorting( !disable ); + } + + /*! # + */ + void Sort( int col = 0, bool ascending = true ); + + // + + /*! # + */ + bool IsNodeDraggingEnabled() const; + + /*! # + */ + void EnableNodeDragging( bool = true ); + + /*! # + */ + void DisableNodeDragging( bool disable = true ) + { + EnableNodeDragging( !disable ); + } + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnCurrentNodeUpdated( TreeBox& sender, TreeBox::Node& current, TreeBox::Node& oldCurrent ); + // void OnNodeActivated( TreeBox& sender, TreeBox::Node& node, int col ); + // void OnNodeUpdated( TreeBox& sender, TreeBox::Node& node, int col ); + // void OnNodeEntered( TreeBox& sender, TreeBox::Node& node, int col ); + // void OnNodeClicked( TreeBox& sender, TreeBox::Node& node, int col ); + // void OnNodeDoubleClicked( TreeBox& sender, TreeBox::Node& node, int col ); + // void OnNodeExpanded( TreeBox& sender, TreeBox::Node& node ); + // void OnNodeCollapsed( TreeBox& sender, TreeBox::Node& node ); + // void OnNodeSelectionUpdated( TreeBox& sender ); + + /*! + * \defgroup tree_box_event_handlers TreeBox Event Handlers + */ + + /*! # + * \ingroup tree_box_event_handlers + */ + typedef void (Control::*tree_event_handler)( TreeBox& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + typedef void (Control::*node_event_handler)( TreeBox&, TreeBox::Node&, int ); + + /*! # + * \ingroup tree_box_event_handlers + */ + typedef void (Control::*node_expand_event_handler)( TreeBox&, TreeBox::Node& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + typedef void (Control::*node_navigation_event_handler)( TreeBox&, TreeBox::Node&, TreeBox::Node& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnCurrentNodeUpdated( node_navigation_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeActivated( node_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeUpdated( node_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeEntered( node_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeClicked( node_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeDoubleClicked( node_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeExpanded( node_expand_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeCollapsed( node_expand_event_handler, Control& ); + + /*! # + * \ingroup tree_box_event_handlers + */ + void OnNodeSelectionUpdated( tree_event_handler, Control& ); + +private: + + struct EventHandlers + { + node_navigation_event_handler onCurrentNodeUpdated = nullptr; + node_event_handler onNodeActivated = nullptr; + node_event_handler onNodeUpdated = nullptr; + node_event_handler onNodeEntered = nullptr; + node_event_handler onNodeClicked = nullptr; + node_event_handler onNodeDoubleClicked = nullptr; + node_expand_event_handler onNodeExpanded = nullptr; + node_expand_event_handler onNodeCollapsed = nullptr; + tree_event_handler onNodeSelectionUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + typedef SortedArray child_node_list; + child_node_list m_children; + + static pcl::Font FontFromHandle( void* h ) + { + return pcl::Font( h ); + } + + static const void* HandleFromFont( const pcl::Font& f ) + { + return f.handle; + } + + static Bitmap BitmapFromHandle( void* h ) + { + return Bitmap( h ); + } + + static const void* HandleFromBitmap( const Bitmap& p ) + { + return p.handle; + } + +protected: + + /*! + * \internal + */ + TreeBox( void* ); + + friend class Node; + friend class TreeBoxEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_TreeBox_h + +// ---------------------------------------------------------------------------- +// EOF pcl/TreeBox.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/UIObject.h b/3rdparty/include/pcl/UIObject.h new file mode 100644 index 0000000..49c404f --- /dev/null +++ b/3rdparty/include/pcl/UIObject.h @@ -0,0 +1,409 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/UIObject.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_UIObject_h +#define __PCL_UIObject_h + +/// \file pcl/UIObject.h + +#include + +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class UIObject + * \brief Root base class for all user interface objects. + * + * %UIObject is a high-level, managed client-side interface to a server-side + * object living in the PixInsight core application. %UIObject is the root base + * class of all PCL classes representing objects that can be constructed and + * destroyed in the PixInsight platform, such as most user interface elements, + * file format instances, and process instances. + * + * For example, Bitmap and ProcessInstance are derived classes of %UIObject + * because you can generate new instances of the server-side objects + * represented by these classes. Contrarily, FileFormat and Process are not + * %UIObject descendants because these classes represent installed components + * that cannot be created or modified by a module. + * + * All the server-side objects represented by %UIObject and its derived classes + * are reference counted objects. When you create an instance of + * %UIObject (or a derived class) in your module, you either generate a new + * object in the platform, or increase the reference counter of an already + * existing object. When a server-side object becomes unreferenced, that is, + * when no living %UIObject represents it, it is either destroyed or recycled + * by the PixInsight core application as soon as possible, in order to reuse + * and optimize the available resources. This process is known as garbage + * collection, and works in a completely automatic and transparent fashion + * in the PixInsight platform. + */ +class PCL_CLASS UIObject +{ +public: + + /*! + * Destroys a %UIObject instance. + * + * After destruction of this %UIObject, the server-side object is also + * destroyed or recycled if it is no longer referenced by other high-level + * interfaces (e.g., other instances of %UIObject in this or other modules). + */ + virtual ~UIObject() noexcept( false ); + + /*! + * Returns true iff this is a \e null %UIObject instance. + * + * A null %UIObject does not represent an existing object in the PixInsight + * core application. + */ + bool IsNull() const + { + return handle == nullptr; + } + + /*! + * Returns a reference to a null %UIObject instance. + * + * A null %UIObject does not represent an existing object in the PixInsight + * core application. + */ + static UIObject& Null(); + + /*! + * Returns the total number of existing references to the server-side object + * managed by this %UIObject. + * + * The returned value is the sum of all references to the server-side object + * on the whole PixInsight platform, including all installed modules and the + * PixInsight core application. + */ + size_type RefCount() const; + + /*! + * Returns true iff the server-side object is uniquely referenced by this + * %UIObject instance. + * + * A uniquely referenced server-side object will be destroyed or recycled + * upon destruction of this %UIObject. + */ + bool IsUnique() const + { + return RefCount() < 2; + } + + /*! + * Returns true iff this %UIObject instance is an alias to an existing object + * in the calling module. + * + * An alias and its aliased object are interchangeable; other than + * module-specific functionality, their behaviors are identical since they + * refer to a unique object living in the PixInsight core application. An + * alias %UIObject is generated each time a new %UIObject descendant class + * is instantiated using (explicitly or indirectly) a copy constructor. For + * example: + * + * \code + * ImageWindow w1( 256, 256 ); // ImageWindow is an UIObject derived class + * ImageWindow w2 = w1; // w2 is an alias to w1. + * bool b1 = w1.IsAlias(); // b1 is now false + * bool b2 = w2.IsAlias(); // b2 is now true + * w2.Show(); // OK, shows w1. + * w1.HideMask(); + * bool b3 = w2.IsMaskVisible(); // b3 is now false + * w2.Close(); // OK, the window is destroyed and both w1 and w2 are now invalid objects. + * \endcode + * + * The only limit specific to aliased objects is the fact that an alias + * Control (or descendant) cannot set event handlers. See the documentation + * for Control( const Control& ) for more information. + */ + bool IsAlias() const + { + return alias; + } + + /*! + * Returns true iff this managed object represents an unreferenced + * server-side object. Such objects are said to be 'garbage' in the + * programming jargon, and are subject to eventual destruction through a + * process known as \e garbage \e collection. + */ + bool IsGarbage() const + { + return RefCount() < 1; + } + + /*! + * Returns true iff this instance and other %UIObject \a o reference the same + * server-side object. + * + * If two %UIObject instances reference the same server-side object, each of + * them act as an alias for the other: In all respects, both high-level + * instances are interchangeable. + */ + bool IsSameObject( const UIObject& o ) const + { + return handle == o.handle; + } + + /*! + * Ensures that the server-side object managed by this instance is uniquely + * referenced. + * + * If there are other %UIObject instances that refer to the same server-side + * object, this member function attempts to create a new server-side object + * as a copy of the currently managed object, and references it. + * + * If the server-side object is only referenced by this %UIObject instance, + * calling this member function has no effect. + * + * Some derived classes represent object types whose instances are unique by + * nature. In those cases, calling this member function has no effect. + */ + virtual void EnsureUnique(); + + /*! + * A convenience synonym for IsSameObject( o ). + */ + bool operator ==( const UIObject& o ) const + { + return IsSameObject( o ); + } + + /*! + * Returns true iff this %UIObject instance precedes another %UIObject \a o. + * Performs a comparison based on the low-level handle internally maintained + * by each %UIObject. + * + * This member function is actually intended for fast access to large sets + * of %UIObject instances stored in containers (as for example the whole set + * of user interface objects defined in a module). It is seldom used + * explicitly by modules. + */ + bool operator <( const UIObject& o ) const + { + return handle < o.handle; + } + + /*! + * Returns a string that uniquely identifies the type of the server-side UI + * object managed by this %UIObject. + */ + IsoString ObjectType() const; + + /*! + * Returns the identifier of this UI object. The object identifier is a + * text string associated with the server-side UI object managed by this + * %UIObject instance. + * + * When this function is called for the first time for a given object, and + * no object identifier has been set explicitly in a previous call to + * SetObjectId(), a new identifier is generated automatically. In this case + * the generated object identifier is guaranteed to be unique across the + * entire PixInsight platform. + * + * Object identifiers are useful to select individual instances. For + * example, an object identifier can be used to restrict the scope of an + * interface style sheet to a particular control. See the documentation for + * Control::SetStyleSheet() for more information. + * + * \sa SetObjectId() + */ + String ObjectId() const; + + /*! + * Sets the identifier of this UI object. Forcing an object identifier can + * be useful to select one or more controls for CSS styling with the + * Control::SetStyleSheet() member function. See the documentation for + * ObjectId() for more information. + * + * \sa ObjectId() + */ + void SetObjectId( const String& id ); + +protected: + + void* handle = nullptr; + bool alias = false; + + /*! + * Constructs a null %UIObject instance. + * + * A null %UIObject does not correspond to an existing object in the + * PixInsight core application. + */ + UIObject() = default; + + /*! + * Copy constructor. + * + * Unless a derived class redefines it otherwise (which is rare), this + * constructor does not create a new object in the PixInsight core + * application. It simply creates an alias %UIObject instance that + * references the same server-side object as the source instance \a x. + */ + UIObject( const UIObject& x ); + + /*! + * Move constructor. + */ + UIObject( UIObject&& x ) + : handle( x.handle ) + , alias( x.alias ) + { + x.handle = nullptr; + x.alias = false; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + UIObject& operator =( const UIObject& x ) + { + Assign( x ); + return *this; + } + + /*! + * Move assignment operator. Returns a reference to this object. + */ + UIObject& operator =( UIObject&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * \internal + */ + UIObject( void* ); + + /*! + * \internal + */ + UIObject( const void* ); + + /*! + * \internal + */ + UIObject( std::nullptr_t ) + { + } + + /*! + * \internal + */ + void SetHandle( void* ); + + /*! + * \internal + */ + void TransferHandle( void* ); + + /*! + * \internal + * This virtual function is called to construct object duplicates. Derived + * classes must reimplement this function to return the handle of a newly + * constructed UI object. + */ + virtual void* CloneHandle() const + { + return nullptr; + } + + /*! + * \internal + */ + bool Assign( const UIObject& x ) + { + if ( x.handle != handle ) + { + SetHandle( x.handle ); + return true; + } + return false; + } + + /*! + * \internal + */ + bool Transfer( UIObject& x ) + { + if ( &x != this ) + { + SetHandle( nullptr ); + handle = x.handle; + alias = x.alias; + x.handle = nullptr; + x.alias = false; + return true; + } + return false; + } + + friend class UIObjectIndex; + friend class UIEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_UIObject_h + +// ---------------------------------------------------------------------------- +// EOF pcl/UIObject.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/UIScaling.h b/3rdparty/include/pcl/UIScaling.h new file mode 100644 index 0000000..281ee93 --- /dev/null +++ b/3rdparty/include/pcl/UIScaling.h @@ -0,0 +1,362 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/UIScaling.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_UIScaling_h +#define __PCL_UIScaling_h + +/// \file pcl/UIScaling.h + +#include +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup ui_scaling_functions User Interface Scaling Functions + */ + +#define PCL_UIScaling_LUT_Length 7 + +extern PCL_DATA const double PCL_UIScalingFactor_LUT[ PCL_UIScaling_LUT_Length ]; +extern PCL_DATA const char* PCL_UIScalingSubdir_LUT[ PCL_UIScaling_LUT_Length ]; + +/*! + * Returns the resource scaling index corresponding to the specified resource + * scaling factor. + * + * Resource scaling indexes pertain to the set {0,1,2,3,4,5,6}, respectively + * for the resource scaling factors {1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0}. + * + * \ingroup ui_scaling_functions + */ +inline int UIResourceScalingIndex( double scalingFactor ) +{ + if ( scalingFactor > 1 ) + { + int index = Min( RoundInt( 2*scalingFactor ), PCL_UIScaling_LUT_Length+1 ); + if ( index > 2 ) + return index-2; + } + return 0; +} + +/*! + * Returns the resource scaling factor corresponding to the specified display + * scaling factor. + * + * A display scaling factor is the ratio of physical device pixels to + * device-independent logical pixel units for a particular control or resource. + * A resource scaling factor has the same definition, but is constrained to the + * finite set {1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0}. + * + * On the PixInsight platform, the reference display density is 109 dpi, + * corresponding to a 27-inch monitor at QHD resolution (2560x1440 physical + * display pixels). This density corresponds to a display/resource scaling + * factor of 1.0. + * + * \ingroup ui_scaling_functions + */ +inline double UIResourceScalingFactor( double scalingFactor ) +{ + return PCL_UIScalingFactor_LUT[UIResourceScalingIndex( scalingFactor )]; +} + +/*! + * Returns the resource scaling factor corresponding to the specified resource + * scaling index. + * + * Resource scaling indexes pertain to the set {0,1,2,3,4,5,6}, respectively + * for the resource scaling factors {1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0}. + * + * On the PixInsight platform, the reference display density is 109 dpi, + * corresponding to a 27-inch monitor at QHD resolution (2560x1440 physical + * display pixels). This density corresponds to a display/resource scaling + * factor of 1.0 and a zero resource scaling index. + * + * \ingroup ui_scaling_functions + */ +inline double UIResourceScalingFactorForIndex( int index ) +{ + return PCL_UIScalingFactor_LUT[Range( index, 0, PCL_UIScaling_LUT_Length-1 )]; +} + +/*! + * Applies the specified scaling factor to convert \a size from + * device-independent logical pixel units to physical device pixels. The + * returned value is always rounded to the nearest integer. + * + * \ingroup ui_scaling_functions + */ +inline int UIScaled( double scalingFactor, int size ) +{ + return (scalingFactor <= 1) ? size : RoundInt( scalingFactor*size ); +} + +/*! + * Applies the specified scaling factor to convert \a size from physical device + * pixels to device-independent logical pixel units. The returned value is + * always rounded to the nearest integer. + * + * \ingroup ui_scaling_functions + */ +inline int UIUnscaled( double scalingFactor, int size ) +{ + return (scalingFactor <= 1) ? size : RoundInt( size/scalingFactor ); +} + +/*! + * Returns a user interface resource path corresponding to the specified + * \a resource path scaled for the specified resource scaling \a index. + * + * For example, if this function is called as follows: + * + * \code UIScaledResourceForIndex( 3, "/:icons/delete.png" ); \endcode + * + * the returned string will be "/:icons/2.5/delete.png" for a resource scaling + * factor of 2.5. + * + * \ingroup ui_scaling_functions + */ +template +inline String UIScaledResourceForIndex( int index, R resource ) +{ + String path( resource ); + index = Range( index, 0, PCL_UIScaling_LUT_Length-1 ); + if ( index > 0 ) + { + size_type p = path.FindLast( '/' ); + if ( p != String::notFound && p > 0 ) // assume resource starts with ":/" + return path.Left( p+1 ) + PCL_UIScalingSubdir_LUT[index] + path.Substring( p ); + } + return path; +} + +/*! + * Returns a user interface resource path corresponding to the specified + * \a resource path scaled for the specified resource scaling factor. + * + * For example, if this function is called as follows: + * + * \code UIScaledResourceForIndex( 1.47, "/:icons/pencil.png" ); \endcode + * + * the returned string will be "/:icons/1.5/pencil.png" for a resource scaling + * factor of 1.5. + * + * \ingroup ui_scaling_functions + */ +template +inline String UIScaledResource( double scalingFactor, R resource ) +{ + return UIScaledResourceForIndex( UIResourceScalingIndex( scalingFactor ), resource ); +} + +/* + * Auxiliary structure used by UIScaledStyleSheet(). + */ +struct PCL_UIStringSection +{ + size_type pos = 0; + size_type len = 0; + + PCL_UIStringSection( size_type i, size_type j ) + : pos( i ) + , len( j - i ) + { + } + + PCL_UIStringSection() = default; + PCL_UIStringSection( const PCL_UIStringSection& ) = default; +}; + +/*! + * Returns a CSS source code string transformed with scaled dimensions in + * pixels and scaled resource file paths, and optionally font sizes in points + * converted to scaled pixels. + * + * \param displayScalingFactor The display scaling factor that will be + * applied to scale pixel dimensions and + * (optionally) font sizes. + * + * \param resourceScalingFactor The resource scaling factor that will be + * applied to select bitmap resources. + * + * \param styleSheet A string containing valid input CSS source + * code. The function will return a transformed + * version of this string. + * + * \param fontDPI If greater than zero, this is the font + * resolution, in dots per inch (dpi), for + * transformation of point sizes to scaled pixel + * sizes. If this parameter is zero (the default + * value), this routine will use the font + * resolution currently selected in core user + * preferences (which is the value of the + * "Application/FontResolution" global integer + * variable; see PixInsightSettings). If this + * parameter is a negative integer, no + * point-to-pixel conversions will be applied. + * + * See Control::ScaledStyleSheet() for a detailed example. + * + * \ingroup ui_scaling_functions + */ +template +String UIScaledStyleSheet( double displayScalingFactor, double resourceScalingFactor, S styleSheet, int fontDPI = 0 ) +{ +#define PCL_UI_IS_NUMBER_DIGIT( c ) (CharTraits::IsDigit( c ) || CharTraits::IsDecimalSeparator( c )) + + String cssCode( styleSheet ); + + /* + * Scale resource file paths. + */ + if ( resourceScalingFactor > 0 ) + { + Array urlSections; + for ( size_type p = 0; ; ) + { + p = cssCode.Find( ":/", p ); + if ( p == String::notFound ) + break; + size_type q = cssCode.Find( ')', p+2 ); + if ( q != String::notFound ) + { + urlSections.Add( PCL_UIStringSection( p, q ) ); + p = q+1; + } + else + p += 2; + } + if ( !urlSections.IsEmpty() ) + { + int index = UIResourceScalingIndex( resourceScalingFactor ); + for ( const PCL_UIStringSection& s : ReverseIterable( urlSections ) ) + cssCode.Replace( s.pos, s.len, String( UIScaledResourceForIndex( index, cssCode.Substring( s.pos, s.len ) ) ) ); + } + } + + /* + * Scale pixel dimensions and convert points to scaled pixels. + */ + if ( displayScalingFactor > 0 ) + { + Array pxSections; + for ( size_type q = 0; ; q += 2 ) + { + q = cssCode.Find( "px", q ); + if ( q == String::notFound ) + break; + size_type p = q; + while ( p > 0 && PCL_UI_IS_NUMBER_DIGIT( cssCode[p-1] ) ) + --p; + if ( p < q ) + pxSections.Add( PCL_UIStringSection( p, q ) ); + } + for ( const PCL_UIStringSection& s : ReverseIterable( pxSections ) ) + { + double px; + if ( cssCode.Substring( s.pos, s.len ).TryToDouble( px ) ) + cssCode.Replace( s.pos, s.len, String().Format( "%d", RoundInt( px * displayScalingFactor ) ) ); + } + + /* + * If fontDPI=0 (the default value), use core font resolution settings for + * point-to-pixel conversions. + */ + if ( fontDPI == 0 ) + fontDPI = PixInsightSettings::GlobalInteger( "Application/FontResolution" ); + + /* + * If a valid font resolution is available, convert points to scaled pixels. + */ + if ( fontDPI > 0 ) + { + Array ptSections; + for ( size_type q = 0; ; q += 2 ) + { + q = cssCode.Find( "pt", q ); + if ( q == String::notFound ) + break; + size_type p = q; + while ( p > 0 && PCL_UI_IS_NUMBER_DIGIT( cssCode[p-1] ) ) + --p; + if ( p < q ) + ptSections.Add( PCL_UIStringSection( p, q ) ); + } + for ( const PCL_UIStringSection& s : ReverseIterable( ptSections ) ) + { + double pt; + if ( cssCode.Substring( s.pos, s.len ).TryToDouble( pt ) ) + cssCode.Replace( s.pos, s.len+2, String().Format( "%dpx", RoundInt( displayScalingFactor*pt*fontDPI/72 ) ) ); + } + } + } + + return cssCode; + +#undef PCL_UI_IS_NUMBER_DIGIT +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_UIScaling_h + +// ---------------------------------------------------------------------------- +// EOF pcl/UIScaling.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/UnidimensionalInterpolation.h b/3rdparty/include/pcl/UnidimensionalInterpolation.h new file mode 100644 index 0000000..5f6dfb8 --- /dev/null +++ b/3rdparty/include/pcl/UnidimensionalInterpolation.h @@ -0,0 +1,218 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/UnidimensionalInterpolation.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_UnidimensionalInterpolation_h +#define __PCL_UnidimensionalInterpolation_h + +/// \file pcl/UnidimensionalInterpolation.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class UnidimensionalInterpolation + * \brief A generic interface to one-dimensional interpolation algorithms. + * + * %UnidimensionalInterpolation is an abstract base class for all + * one-dimensional interpolation algorithm implementations in PCL. + */ +template +class PCL_CLASS UnidimensionalInterpolation +{ +public: + + /*! + * Represents a vector of independent and dependent variable values. + */ + typedef GenericVector vector_type; + + /*! + * Constructs a %UnidimensionalInterpolation object. + */ + UnidimensionalInterpolation() = default; + + /*! + * Copy constructor. + */ + UnidimensionalInterpolation( const UnidimensionalInterpolation& ) = default; + + /*! + * Destroys a %UnidimensionalInterpolation object. + */ + virtual ~UnidimensionalInterpolation() + { + Clear(); + } + + /*! + * Initializes a new interpolation. + * + * \param x %Vector of x-values:\n + * \n + * \li If this vector is not empty: Must be a set of monotonically\n + * increasing, distinct values: x[0] < x[1] < ... < x[n-1].\n + * \li If this vector is empty: The interpolation will use implicit + * x[i] = i for i = {0,1,...,n-1}. + * + * \param y %Vector of function values for i = {0,1,...,n-1}. + */ + virtual void Initialize( const vector_type& x, const vector_type& y ) + { + if ( !y || x && x.Length() < y.Length() ) + throw Error( "Invalid vector length in UnidimensionalInterpolation::Initialize()" ); + m_x = x; + m_y = y; + } + + /*! + * Initializes a new interpolation. + * + * \param x %Array of x-values:\n + * \n + * \li If \a x != 0: Must be a list of monotonically increasing, + * distinct values: x[0] < x[1] < ... < x[n-1].\n + * \li If \a x == 0: The interpolation will use implicit + * x[i] = i for i = {0,1,...,n-1}. + * + * \param y %Array of function values for i = {0,1,...,n-1}. + * + * \param n Number of data points. The minimum number of required data + * points depends on the interpolation algorithm. In general, + * all algorithms require at least \a n >= 2. + * + * \deprecated This member function has been deprecated. For newly produced + * code, use Initialize( const vector_type&, const vector_type& ). + */ + void Initialize( const T* x, const T* y, int n ) + { + Initialize( vector_type( x, n ), vector_type( y, n ) ); + } + + /*! + * Returns an interpolated function value at \a x location. + */ + virtual double operator()( double x ) const = 0; + + /*! + * Clears auxiliary or intermediate interpolation data. Derived classes + * overriding this function should call their base class version via + * explicit downcast. + */ + virtual void Clear() + { + m_x.Clear(); + m_y.Clear(); + } + + /*! + * Returns true iff this interpolation is valid, i.e. if it has been + * correctly initialized and is ready to interpolate function values. + */ + virtual bool IsValid() const + { + return m_y; + } + + /*! + * Returns a reference to the x-value data vector. Returns an empty vector + * if this interpolation uses implicit x[i] = i for i = {0,1,...,n-1}. + */ + const vector_type& X() const + { + return m_x; + } + + /*! + * Returns a reference to the interpolated function value vector. + */ + const vector_type& Y() const + { + return m_y; + } + + /*! + * Returns true iff this interpolation uses implicit + * x[i] = i for i = {0,1,...,n-1}. + */ + bool UsingImplicitX() const + { + return !m_x && m_y; + } + + /*! + * Returns the length of the interpolated function value vector. + */ + int Length() const + { + return m_y.Length(); + } + +protected: + + vector_type m_x; // x-vector (empty if implicit grid x-values) + vector_type m_y; // y-vector +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_UnidimensionalInterpolation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/UnidimensionalInterpolation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/UnixSignalException.h b/3rdparty/include/pcl/UnixSignalException.h new file mode 100644 index 0000000..c6c9fb0 --- /dev/null +++ b/3rdparty/include/pcl/UnixSignalException.h @@ -0,0 +1,240 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/UnixSignalException.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_UnixSignalException_h +#define __PCL_UnixSignalException_h + +/// \file pcl/UnixSignalException.h + +#if defined( __PCL_WINDOWS ) || !defined( __PCL_LINUX ) && !defined( __PCL_FREEBSD ) && !defined( __PCL_MACOSX ) +# error UnixSignalException can only be used on Linux, FreeBSD and macOS platforms. +#endif + +#include + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class UnixSignalException + * \brief A UNIX synchronous signal handler that throws C++ exceptions. + * + * This class can only be used on Linux, FreeBSD and macOS platforms. On + * Windows platforms, including this header file from compilable code raises a + * compilation error. + * + * For this handler to work properly, all code that may raise synchronous + * signals (SIGSEGV and the like) must be compiled with GCC's + * '-fnon-call-exceptions' flag. Otherwise the exceptions will be thrown + * but terminate() will be called, which is the default critical signal + * management behavior. + * + * To generate a backtrace report (see the UnixSignalException::Details() + * member function), the code must be compiled with the '-rdynamic' GCC flag, + * which instructs the linker to add all symbols to the dynamic symbol table. + * In addition, the generated binaries should not be stripped with the '-s' + * linker flag. + */ +class PCL_CLASS UnixSignalException : public pcl::Exception +{ +public: + + /*! + * Constructs a new %UnixSignalException object with the specified \a signal + * number and optional backtrace \a details. + */ + UnixSignalException( int signal, const IsoString& details = IsoString() ) + : m_signal( signal ) + , m_details( details ) + { + } + + /*! + * Copy constructor. + */ + UnixSignalException( const UnixSignalException& ) = default; + + /*! + * Returns the signal number associated with this object. + */ + int SignalNumber() const + { + return m_signal; + } + + /*! + * Returns the backtrace information associated with this exception. + * + * The returned string will be empty if no backtrace data were available at + * the time this signal exception was generated. This happens when the code + * has not been compiled and linked with the appropriate options (see the + * -rdynamic compiler flag). + */ + const IsoString& Details() const + { + return m_details; + } + + /*! + * Returns an error or warning message corresponding to this signal + * exception. Typical messages are "segmentation violation", "bus error" and + * "floating point exception", returned by specific derived classes. + */ + String Message() const override + { + return "Undefined signal"; + } + + /*! + * Returns a formatted error message with information on this signal + * exception. + */ + String FormatInfo() const override + { + String info = String().Format( "Critical signal caught (%d): ", SignalNumber() ) + Message(); + if ( !m_details.IsEmpty() ) + { + info.Append( '\n' ); + info.Append( m_details ); + } + return info; + } + + /*! + * Returns the type of this exception, intended to be used as a caption for + * a message box. As reimplemented in this class, this member function + * returns the string "PCL Unix Signal Handler". + */ + String Caption() const override + { + return "PCL Unix Signal Handler"; + } + + /*! + * Writes a formatted representation of this exception on the platform + * console. A plain text version of the same textual representation will + * also be written on stdout. + * + * \note UNIX synchronous interrupts are never reported on interactive + * graphical interfaces, such as message boxes, irrespective of global + * platform settings or local settings defined through calls to + * EnableGUIOutput() and similar functions. + */ + void Show() const override; + + /*! + * Initializes the UNIX synchronous signal handler. This static member + * function must be called before the calling process can raise any + * synchronous signal. + * + * \note A module should never call this member function. It is invoked when + * appropriate by the PixInsight core application and internal PCL routines. + */ + static void Initialize(); + +protected: + + int m_signal; // signal number + IsoString m_details; // backtrace information +}; + +// ---------------------------------------------------------------------------- + +#define DECLARE_UNIX_SIGNAL_EXCEPTION( className, sigNum, message ) \ + class PCL_CLASS className : public pcl::UnixSignalException \ + { \ + public: \ + className( const IsoString& details = IsoString() ) : \ + pcl::UnixSignalException( sigNum, details ) \ + { \ + } \ + className( const className& ) = default; \ + String Message() const override \ + { \ + return message; \ + } \ + } + +// ---------------------------------------------------------------------------- + +DECLARE_UNIX_SIGNAL_EXCEPTION( EUnixSegmentationViolation, SIGSEGV, + "Segmentation violation" ); + +DECLARE_UNIX_SIGNAL_EXCEPTION( EUnixBusError, SIGBUS, + "Bus error" ); + +DECLARE_UNIX_SIGNAL_EXCEPTION( EUnixFloatingPointException, SIGFPE, + "Floating point exception" ); + +DECLARE_UNIX_SIGNAL_EXCEPTION( EUnixIllegalInstructionException, SIGILL, + "Illegal instruction" ); + +DECLARE_UNIX_SIGNAL_EXCEPTION( EUnixIBrokenPipeException, SIGPIPE, + "Broken pipe" ); + +// ---------------------------------------------------------------------------- + +#undef DECLARE_UNIX_SIGNAL_EXCEPTION + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_UnixSignalException_h + +// ---------------------------------------------------------------------------- +// EOF pcl/UnixSignalException.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Utility.h b/3rdparty/include/pcl/Utility.h new file mode 100644 index 0000000..a99abd4 --- /dev/null +++ b/3rdparty/include/pcl/Utility.h @@ -0,0 +1,705 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Utility.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_Utility_h +#define __PCL_Utility_h + +/// \file pcl/Utility.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup utility_algorithms Utility Algorithms + * + * Template formal parameters: + * + * FI Forward iterator \n + * BI Bidirectional iterator \n + * RI Random access iterator \n + * UP Unary predicate \n + * BP Binary predicate \n + * T Item type \n + * F Function + */ + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the smaller of two objects \a a and \a b. Returns + * \a b if b < a. Returns \a a if a <= b. + * + * \ingroup utility_algorithms + */ +template inline constexpr +const T& Min( const T& a, const T& b ) noexcept +{ + return (b < a) ? b : a; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the smallest of two objects \a a and \a b, as + * specified by the binary predicate \a p. Returns \a b if p(b,a) is true; + * returns \a a otherwise. + * + * \ingroup utility_algorithms + */ +template inline +const T& Min( const T& a, const T& b, BP p ) noexcept( noexcept( p ) ) +{ + return p( b, a ) ? b : a; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the largest of two objects \a a and \a b. Returns + * \a b if a < b. Returns \a a if b <= a. + * + * \ingroup utility_algorithms + */ +template inline constexpr +const T& Max( const T& a, const T& b ) noexcept +{ + return (a < b) ? b : a; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the largest of two objects \a a and \a b, as + * specified by the binary predicate \a p. Returns \a b if p(a,b) is true; + * returns \a a otherwise. + * + * \ingroup utility_algorithms + */ +template inline +const T& Max( const T& a, const T& b, BP p ) noexcept( noexcept( p ) ) +{ + return p( a, b ) ? b : a; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the median of three objects \a a, \a b and \a c: + * + * \li \a a if (c <= a < b) || (b <= a < c) + * \li \a b if (a < b < c) || (c <= b <= a) + * \li \a c if (a < c < b) || (b < c <= a) + * + * \ingroup utility_algorithms + */ +template inline constexpr +const T& Median( const T& a, const T& b, const T& c ) noexcept +{ + return (a < b) ? ((b < c) ? b : ((a < c) ? c : a)) : + ((a < c) ? a : ((b < c) ? c : b)); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the median of three objects \a a, \a b and \a c, as + * specified by the binary predicate \a p: + * + * \li \a a if p(a,b) && !p(b,c) && !p(a,c) || !p(a,b) && p(a,c) + * \li \a b if p(a,b) && p(b,c) || !p(a,b) && !p(a,c) && !p(b,c) + * \li \a c if p(a,b) && !p(b,c) && p(a,c) || !p(a,b) && !p(a,c) && p(b,c) + * + * \ingroup utility_algorithms + */ +template inline +const T& Median( const T& a, const T& b, const T& c, BP p ) noexcept( noexcept( p ) ) +{ + return p( a, b ) ? (p( b, c ) ? b : (p( a, c ) ? c : a)) : + (p( a, c ) ? a : (p( b, c ) ? c : b)); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the specified object \a x, if and only if it belongs + * to the range [a,b]. Returns a reference to the nearest range bounding object + * otherwise. Returns: + * + * \li \a x if (a <= x <= b) + * \li \a a if (x < a) + * \li \a b if (b < x) + * + * \ingroup utility_algorithms + */ +template inline constexpr +const T& Range( const T& x, const T& a, const T& b ) noexcept +{ + PCL_PRECONDITION( a < b ) + return (x < a) ? a : ((b < x) ? b : x); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a reference to the specified object \a x, if and only if it belongs + * to the range [a,b], as specified by the binary predicate \a p. Returns a + * reference to the nearest range bounding object otherwise. Returns: + * + * \li \a x if !p(x,a) && !p(b,x) + * \li \a a if p(x,a) + * \li \a b if p(b,x) + * + * \ingroup utility_algorithms + */ +template inline +const T& Range( const T& x, const T& a, const T& b, BP p ) noexcept( noexcept( p ) ) +{ + PCL_PRECONDITION( p( a, b ) ) + return p( x, a ) ? a : (p( b, x ) ? b : x); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the number of elements in the specified C array \a a. + * + * \ingroup utility_algorithms + */ +#define ItemsInArray( a ) (sizeof( a )/sizeof( *a )) + +// ---------------------------------------------------------------------------- + +/*! + * Exchanges two objects \a a and \a b. + * + * \ingroup utility_algorithms + */ +template inline +void Swap( T& a, T& b ) noexcept( std::is_nothrow_copy_constructible::value + && std::is_nothrow_copy_assignable::value + && std::is_nothrow_move_assignable::value ) +{ + T c( a ); a = b; b = std::move( c ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Applies a unary function \a f to the range [i,j). For each iterator t in the + * range [i,j) this function performs the function call f(*t). + * + * \ingroup utility_algorithms + */ +template inline +void Apply( FI i, FI j, F f ) noexcept( noexcept( f ) ) +{ + for( ; i != j; ++i ) + f( *i ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Applies a binary function \a f to the range [i,j) with the specified + * right-hand constant argument \a x. For each iterator t in the range [i,j) + * this function performs the function call f(*t,x). + * + * \ingroup utility_algorithms + */ +template inline +void Apply( FI i, FI j, F f, T1 x ) noexcept( noexcept( f ) ) +{ + for( ; i != j; ++i ) + f( *i, x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Applies a unary function \a f to those elements in the range [i,j) that + * satisfy a condition given by a unary predicate \a p. For each iterator t in + * the range [i,j) this function performs the function call f(*t) if and only + * if p(*t) is true. + * + * \ingroup utility_algorithms + */ +template inline +void ApplyIf( FI i, FI j, F f, UP p ) noexcept( noexcept( f ) && noexcept( p ) ) +{ + for( ; i != j; ++i ) + if ( p( *i ) ) + f( *i ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Applies a unary function \a f to those elements in the range [i,j) that + * satisfy a condition given by a unary predicate \a p, with right-hand + * constant argument \a x. For each iterator t in the range [i,j) this function + * performs the function call f(*t,x) if and only if p(*t) is true. + * + * \ingroup utility_algorithms + */ +template inline +void ApplyIf( FI i, FI j, F f, UP p, T1 x ) noexcept( noexcept( f ) && noexcept( p ) ) +{ + for( ; i != j; ++i ) + if ( p( *i ) ) + f( *i, x ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the first iterator t in the range [i,j) such that the specified + * unary predicate p(*t) is true, or j if no such iterator exists. + * + * \ingroup utility_algorithms + */ +template inline +FI FirstThat( FI i, FI j, UP p ) noexcept( noexcept( p ) ) +{ + for ( ; i != j; ++i ) + if ( p( *i ) ) + break; + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the first iterator t in the range [i,j) such that the specified + * unary predicate p(*t,x) is true, or j if no such iterator exists. + * + * \ingroup utility_algorithms + */ +template inline +FI FirstThat( FI i, FI j, UP p, T1 x ) noexcept( noexcept( p ) ) +{ + for ( ; i != j; ++i ) + if ( p( *i, x ) ) + break; + return i; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the last iterator t in the range [i,j) such that the specified + * unary predicate p(*t) is true, or j if no such iterator exists. + * + * \ingroup utility_algorithms + */ +template inline +BI LastThat( BI i, BI j, UP p ) noexcept( noexcept( p ) ) +{ + for ( BI k = j; i != k; ) + if ( p( *--k ) ) + return k; + return j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the last iterator t in the range [i,j) such that the specified + * unary predicate p(*t,x) is true, or j if no such iterator exists. + * + * \ingroup utility_algorithms + */ +template inline +BI LastThat( BI i, BI j, UP p, T1 x ) noexcept( noexcept( p ) ) +{ + for ( BI k = j; i != k; ) + if ( p( *--k, x ) ) + return k; + return j; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the total number of objects in the range [i,j) that are equal to + * the specified constant object \a v. + * + * \ingroup utility_algorithms + */ +template inline +size_type Count( FI i, FI j, const T& v ) noexcept +{ + size_type N = 0; + for( ; i != j; ++i ) + if ( *i == v ) + ++N; + return N; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the total number of objects in the range [i,j) that are equal to + * a constant object \a v, as specified by the binary predicate \a p. For each + * iterator t in the range [i,j), counts the number of objects for which + * p(*t,v) is true. + * + * \ingroup utility_algorithms + */ +template inline +size_type Count( FI i, FI j, const T& v, BP p ) noexcept( noexcept( p ) ) +{ + size_type N = 0; + for( ; i != j; ++i ) + if ( p( *i, v ) ) + ++N; + return N; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the total number of objects in the range [i,j) that satisfy a + * condition given by a unary predicate \a p. For each iterator t in the range + * [i,j), counts the number of objects for which p(*t) is true. + * + * \ingroup utility_algorithms + */ +template inline +size_type CountIf( FI i, FI j, UP p ) noexcept( noexcept( p ) ) +{ + size_type N = 0; + for( ; i != j; ++i ) + if ( p( *i ) ) + ++N; + return N; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns an iterator m in the range [i,j) such that *m <= *t for any t != m + * in [i,j). Returns j if and only if i == j. + * + * \ingroup utility_algorithms + */ +template inline +FI MinItem( FI i, FI j ) noexcept +{ + FI k = i; + if ( i != j ) + while ( ++i != j ) + if ( *i < *k ) + k = i; + return k; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns an iterator m in the range [i,j) such that p(*t,*m) is false for any + * t != m in [i,j). Returns j if and only if i == j. + * + * \ingroup utility_algorithms + */ +template inline +FI MinItem( FI i, FI j, BP p ) noexcept( noexcept( p ) ) +{ + FI k = i; + if ( i != j ) + while ( ++i != j ) + if ( p( *i, *k ) ) + k = i; + return k; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns an iterator m in the range [i,j) such that *m >= *t for any t != m + * in [i,j). Returns j if and only if i == j. + * + * \ingroup utility_algorithms + */ +template inline +FI MaxItem( FI i, FI j ) noexcept +{ + FI k = i; + if ( i != j ) + while ( ++i != j ) + if ( *k < *i ) + k = i; + return k; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns an iterator m in the range [i,j) such that p(*m,*t) is false for any + * t != m in [i,j). Returns j if and only if i == j. + * + * \ingroup utility_algorithms + */ +template inline +FI MaxItem( FI i, FI j, BP p ) noexcept( noexcept( p ) ) +{ + FI k = i; + if ( i != j ) + while ( ++i != j ) + if ( p( *k, *i ) ) + k = i; + return k; +} + +// ---------------------------------------------------------------------------- + +/*! + * Finds two iterators n and m in the range [i,j) such that *n <= *u for any + * u != n in [i,j) and *m >= *v for any v != m in [i,j). + * + * \ingroup utility_algorithms + */ +template inline +void FindExtremeItems( FI& kmin, FI& kmax, FI i, FI j ) noexcept +{ + kmin = kmax = i; + if ( i != j ) + while ( ++i != j ) + { + if ( *i < *kmin ) + kmin = i; + if ( *kmax < *i ) + kmax = i; + } +} + +// ---------------------------------------------------------------------------- + +/*! + * Finds two iterators n and m in the range [i,j) such that p(*u,*n) is false + * for any u != n in [i,j) and p(*m,*v) is false for any v != m in [i,j). + * + * \ingroup utility_algorithms + */ +template inline +void FindExtremeItems( FI& kmin, FI& kmax, FI i, FI j, BP p ) noexcept( noexcept( p ) ) +{ + kmin = kmax = i; + if ( i != j ) + while ( ++i != j ) + { + if ( p( *i, *kmin ) ) + kmin = i; + if ( p( *kmax, *i ) ) + kmax = i; + } +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a tuple {i,j} such that *i != *j, where i >= i1 and j is in the + * range [i2,j2), or a tuple {i>=i1,j2} if no such j exists. + * + * \ingroup utility_algorithms + */ +template inline +Association FindNotEqual( FI1 i1, FI2 i2, FI2 j2 ) noexcept +{ + for ( ; i2 != j2 && *i1 == *i2; ++i1, ++i2 ) {} + return Associate( i1, i2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns a tuple {i,j} such that p(*i,*j) is false, where i >= i1 and j is in + * the range [i2,j2), or a tuple {i>=i1,j2} if no such j exists. + * + * \ingroup utility_algorithms + */ +template inline +Association FindNotEqual( FI1 i1, FI2 i2, FI2 j2, BP p ) noexcept +{ + for ( ; i2 != j2 && p( *i1, *i2 ); ++i1, ++i2 ) {} + return Associate( i1, i2 ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff the objects in the range [i1,j1) are equal to the + * corresponding objects in the range [i2,j2), with + * j1 = Advance(i1,Distance(i2,j2)). + * + * \ingroup utility_algorithms + */ +template inline +bool Equal( FI1 i1, FI2 i2, FI2 j2 ) noexcept +{ + return FindNotEqual( i1, i2, j2 ).second == j2; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns true iff the objects in the range [i1,j1) satisfy the condition + * specified by the binary predicate \a p for the corresponding objects in the + * range [i2,j2), with j1 = Advance(i1,Distance(i2,j2)). + * + * \ingroup utility_algorithms + */ +template inline +bool Equal( FI1 i1, FI2 i2, FI2 j2, BP p ) noexcept( noexcept( p ) ) +{ + return FindNotEqual( i1, i2, j2, p ).second == j2; +} + +// ---------------------------------------------------------------------------- + +/*! + * Performs a comparison of the objects in the ranges [i1,j1) and [i2,j2). + * Returns the result of the comparison encoded as an integer: + * + * Returns 0 if: + * + * \li (1) Distance(i1,j1) == Distance(i2,j2). + * \li (2) For each pair {u,v} of iterators such that u in [i1,j1) and v in + * [i2,j2) and Distance(i1,u) == Distance(i2,v), *u == *v. + * + * Returns -1 if: + * + * \li (3) A pair {u,v} of iterators exists such that u in [i1,j1) and v in + * [i2,j2) and Distance(i1,u) == Distance(i2,v) and *u < *v. + * \li (4) Condition (2) is true and Distance(i1,j1) < Distance(i2,j2). + * + * Returns +1 if: + * + * \li (5) A pair {u,v} of iterators exists such that u in [i1,j1) and v in + * [i2,j2) and Distance(i1,u) == Distance(i2,v) and *v < *u. + * \li (6) Condition (2) is true and Distance(i1,j1) > Distance(i2,j2). + * + * \ingroup utility_algorithms + */ +template inline +int Compare( FI1 i1, FI1 j1, FI2 i2, FI2 j2 ) noexcept +{ + for ( ; ; ++i1, ++i2 ) + { + if ( i1 == j1 ) + return (i2 == j2) ? 0 : -1; + if ( i2 == j2 ) + return +1; + if ( *i1 < *i2 ) + return -1; + if ( *i2 < *i1 ) + return +1; + } +} + +// ---------------------------------------------------------------------------- + +/*! + * Performs a comparison of the objects in the ranges [i1,j1) and [i2,j2) as + * specified by a binary predicate \a p. Returns the result of the comparison + * encoded as an integer: + * + * Returns 0 if: + * + * \li (1) Distance(i1,j1) == Distance(i2,j2). + * \li (2) For each pair {u,v} of iterators such that u in [i1,j1) and v in + * [i2,j2) and Distance(i1,u) == Distance(i2,v), both p(*u,*v) and p(*v,*u) are + * false. + * + * Returns -1 if: + * + * \li (3) A pair {u,v} of iterators exists such that u in [i1,j1) and v in + * [i2,j2) and Distance(i1,u) == Distance(i2,v) and p(*u,*v) is true. + * \li (4) Condition (2) is true and Distance(i1,j1) < Distance(i2,j2). + * + * Returns +1 if: + * + * \li (5) A pair {u,v} of iterators exists such that u in [i1,j1) and v in + * [i2,j2) and Distance(i1,u) == Distance(i2,v) and p(*v,*u) is true. + * \li (6) Condition (2) is true and Distance(i1,j1) > Distance(i2,j2). + * + * \ingroup utility_algorithms + */ +template inline +int Compare( FI1 i1, FI1 j1, FI2 i2, FI2 j2, BP p ) noexcept( noexcept( p ) ) +{ + for ( ; ; ++i1, ++i2 ) + { + if ( i1 == j1 ) + return (i2 == j2) ? 0 : -1; + if ( i2 == j2 ) + return +1; + if ( p( *i1, *i2 ) ) + return -1; + if ( p( *i2, *i1 ) ) + return +1; + } +} + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Utility_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Utility.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/VariableShapeFilter.h b/3rdparty/include/pcl/VariableShapeFilter.h new file mode 100644 index 0000000..75178f3 --- /dev/null +++ b/3rdparty/include/pcl/VariableShapeFilter.h @@ -0,0 +1,531 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/VariableShapeFilter.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_VariableShapeFilter_h +#define __PCL_VariableShapeFilter_h + +/// \file pcl/VariableShapeFilter.h + +#include + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class VariableShapeFilter + * \brief A kernel filter with variable kurtosis. + * + * A %VariableShapeFilter object is a specialized KernelFilter whose elements + * are calculated as a discrete representation of the following elliptical + * function centered at the origin: + * + * G(x,y) = Exp( -( x^k/(k*sx^k) + y^k/(k*sy^k) ) ) + * + * where sx and sy are the standard deviations of the filter distribution on + * the horizontal and vertical axes, respectively, and k is a shape + * parameter controlling the kurtosis of the filter function. When k < 2 + * the distribution is leptokurtic (peaked), while k > 2 leads to a platykurtic + * (flat) distribution. When k = 2 the distribution is normal (Gaussian) and + * the %VariableShapeFilter is equivalent to a GaussianFilter object with the + * same standard deviations. + * + * %VariableShapeFilter also supports arbitrary rotation around the origin. + * When the filter is rotated, the coordinates x, y in the equation above are + * replaced by their rotated counterparts. + * + * A %VariableShapeFilter instance is formally defined by the following set of + * parameters: + * + * + * + * + * + * + * + *
\e sigma Standard deviation of the filter distribution on the X axis (sigma > 0).
\e shape Filter shape: 2 = Gaussian, < 2 = leptokurtic, > 2 = platykurtic (shape > 0).
\e rho The ratio sy/sx (see equation above) of the generated filter distribution (0 ≤ rho ≤ 1).
\e theta Rotation angle of the horizontal axis in radians (0 ≤ theta < PI). This parameter only makes sense when rho < 1.
\e epsilon Maximum truncation error of the computed filter coefficients (eps > 0).
+ * + * \sa KernelFilter, GaussianFilter, MoffatFilter, LinearFilter + */ +class PCL_CLASS VariableShapeFilter : public KernelFilter +{ +public: + + /*! + * Constructs an empty %VariableShapeFilter object with default functional + * parameters: sigma=2, shape=2, epsilon=0.01, rho=1, theta=0. + */ + VariableShapeFilter() = default; + + /*! + * Constructs a %VariableShapeFilter object given the standard deviation + * \a sigma > 0, \a shape > 0, and coefficient truncation \a epsilon > 0. + * Assigns an optional \a name to the new filter object. + */ + VariableShapeFilter( float sigma, float shape = 2, float epsilon = 0.01, const String& name = String() ) + { + Initialize( sigma, shape, epsilon, 1, 0 ); + Rename( name ); + } + + /*! + * Constructs a %VariableShapeFilter object given the standard deviation + * \a sigma > 0, \a shape > 0, coefficient truncation error \a epsilon > 0, + * aspect ratio 0 <= \a rho <= 1, and rotation angle 0 <= \a theta <= PI in + * radians. Assigns an optional \a name to the new filter object. + */ + VariableShapeFilter( float sigma, float shape, float epsilon, float rho, float theta = 0, const String& name = String() ) + { + Initialize( sigma, shape, epsilon, rho, theta ); + Rename( name ); + } + + /*! + * Constructs a %VariableShapeFilter object given the odd kernel size + * \a n >= 3, \a shape > 0, and coefficient truncation error \a epsilon > 0. + * Assigns an optional \a name to the new filter object. + */ + VariableShapeFilter( int n, float shape = 2, float epsilon = 0.01, const String& name = String() ) + { + Initialize( n, shape, epsilon, 1, 0 ); + Rename( name ); + } + + /*! + * Constructs a %VariableShapeFilter object given the odd kernel size + * \a n >= 3, \a shape > 0, coefficient truncation \a epsilon > 0, aspect + * ratio 0 <= \a rho <= 1, and rotation angle 0 <= \a theta <= PI in + * radians. Assigns an optional \a name to the new filter object. + */ + VariableShapeFilter( int n, float shape, float epsilon, float rho, float theta = 0, const String& name = String() ) + { + Initialize( n, shape, epsilon, rho, theta ); + Rename( name ); + } + + /*! + * Copy constructor. + */ + VariableShapeFilter( const VariableShapeFilter& ) = default; + + /*! + * Move constructor. + */ + VariableShapeFilter( VariableShapeFilter&& ) = default; + + /*! + * Returns a pointer to a dynamically allocated duplicate of this kernel + * filter. + */ + KernelFilter* Clone() const override + { + return new VariableShapeFilter( *this ); + } + + /*! + * Returns a separable filter equivalent to this %VariableShapeFilter + * object. + * + * A %VariableShapeFilter is separable when it represents an undistorted + * Gaussian distribution. This is only true when shape=2 and the filter is + * circular (rho=1). Otherwise an empty SeparableFilter object is returned + * because this filter is not separable. + */ + SeparableFilter AsSeparableFilter( float tolerance = __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE ) const override + { + if ( m_shape == 2 && m_rho == 1 ) + { + FVector v = coefficients.RowVector( Size()>>1 ); + return SeparableFilter( v, v ); + } + return SeparableFilter(); + } + + /*! + * Returns true iff this filter is separable. + * + * A %VariableShapeFilter is separable only when it represents an + * undistorted Gaussian distribution. This is only true when shape=2 and the + * filter is circular (rho=1). + */ + bool IsSeparable() const override + { + return m_shape == 2 && m_rho == 1; + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + VariableShapeFilter& operator =( const VariableShapeFilter& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + VariableShapeFilter& operator =( VariableShapeFilter&& ) = default; + + /*! + * Returns the standard deviation of the filter distribution on the X + * (horizontal) axis. + */ + float SigmaX() const + { + return m_sigma; + } + + /*! + * Returns the standard deviation of the filter distribution on the Y + * (vertical) axis. + */ + float SigmaY() const + { + return m_rho*m_sigma; + } + + /*! + * Returns the standard deviation of the filter distribution on the X + * (horizontal) axis. + * + * This function is an alias to SigmaX(). + */ + float Sigma() const + { + return SigmaX(); + } + + /*! + * Returns the \e shape parameter of this %VariableShapeFilter object. The + * shape parameter controls the kurtosis of the filter distribution: + * + * + * + * + * + *
shape \< 2 Leptokurtic distribution
shape = 2 Normal (Gaussian) distribution
shape \> 2 Platykurtic distribution
+ */ + float Shape() const + { + return m_shape; + } + + /*! + * Returns the maximum truncation error of calculated filter coefficients. + */ + float Truncation() const + { + return m_epsilon; + } + + /*! + * Returns the aspect ratio of the filter distribution. This is the ratio + * vertical:horizontal between filter axes in the range [0,1]. + */ + float AspectRatio() const + { + return m_rho; + } + + /*! + * Returns the rotation angle of the filter distribution. This is the + * rotation angle in radians with respect to the central pixel, in the + * range [0,+PI]. + */ + float RotationAngle() const + { + return m_theta; + } + + /*! + * Returns the full width at half maximum (FWHM), in sigma units, for the + * horizontal axis of the elliptical filter distribution. + */ + double FWHMx() const + { + return 2 * m_sigma * Pow( m_shape*0.6931471805599453, 1.0/m_shape ); + + } + + /*! + * Returns the full width at half maximum (FWHM), in sigma units, for the + * vertical axis of the elliptical filter distribution. + */ + double FWHMy() const + { + return m_rho * FWHMx(); + + } + + /*! + * Returns the full width at half maximum, in sigma units, for the + * horizontal axis of the elliptical filter distribution. + * + * This function is an alias to FWHMx(). + */ + double FWHM() const + { + return FWHMx(); + } + + /*! + * Recalculates filter coefficients for the specified \a sigma > 0, + * \a shape > 0, coefficient truncation error \a epsilon > 0, aspect ratio + * 0 <= \a rho <= 1, and rotation angle 0 <= \a theta <= PI in radians. + */ + void Set( float sigma, float shape, float epsilon, float rho, float theta ) + { + Initialize( sigma, shape, epsilon, rho, theta ); + } + + /*! + * Recalculates filter coefficients for the specified \a sigma > 0, + * \a shape > 0, coefficient truncation error \a epsilon > 0, and aspect + * ratio 0 <= \a rho <= 1. Does not change the current rotation angle. + */ + void Set( float sigma, float shape, float epsilon, float rho ) + { + Initialize( sigma, shape, epsilon, rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified \a sigma > 0, + * \a shape > 0, and coefficient truncation error \a epsilon > 0. Does not + * change the current aspect ratio and rotation angle. + */ + void Set( float sigma, float shape, float epsilon ) + { + Initialize( sigma, shape, epsilon, m_rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified \a sigma > 0 and + * \a shape > 0. Coefficient truncation, aspect ratio and rotation angle are + * not changed. + */ + void Set( float sigma, float shape ) + { + Initialize( sigma, shape, m_epsilon, m_rho, m_theta ); + } + + /*! + * Recalculates filter coefficients for the specified \a sigma > 0. The + * current shape, coefficient truncation error, aspect ratio and rotation + * angle are not changed. + */ + void Set( float sigma ) + { + Initialize( sigma, m_shape, m_epsilon, m_rho, m_theta ); + } + + /*! + * This is a convenience member function, equivalent to Set( sigma ). + */ + void SetSigma( float sigma ) + { + Set( sigma ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), shape ). + */ + void SetShape( float shape ) + { + Set( m_sigma, shape ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Shape(), epsilon ). + */ + void SetTruncation( float epsilon ) + { + Set( m_sigma, m_shape, epsilon ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Shape(), Truncation(), rho ). + */ + void SetAspectRatio( float rho ) + { + Set( m_sigma, m_shape, m_epsilon, rho ); + } + + /*! + * This is a convenience member function, equivalent to + * Set( Sigma(), Shape(), Truncation(), AspectRatio(), theta ). + */ + void SetRotationAngle( float theta ) + { + Set( m_sigma, m_shape, m_epsilon, m_rho, theta ); + } + + /*! + * Recalculates filter coefficients for the given odd kernel size \a n >= 3. + * This routine computes the required standard deviation to sample the + * filter function on a matrix of the specified size, preserving the + * current shape, coefficient truncation, aspect ratio and rotation angle. + */ + void Resize( int n ) override + { + Initialize( n, m_shape, m_epsilon, m_rho, m_theta ); + } + +private: + + float m_sigma = 2.0F; // standard deviation, horizontal axis + float m_shape = 2.0F; // controls the kurtosis of the filter distribution (2=normal) + float m_rho = 1.0F; // vertical:horizontal axes ratio + float m_theta = 0.0F; // rotation angle in radians, [0,+pi] + float m_epsilon = 0.01F; // maximum truncation error in sigma units + + void Initialize( float s, float k, float e, float r, float a ) + { + PCL_PRECONDITION( s > 0 ) + PCL_PRECONDITION( k > 0 ) + PCL_PRECONDITION( e > 0 ) + PCL_PRECONDITION( r >= 0 && r <= 1 ) + PCL_PRECONDITION( a >= 0 && a <= Const::pi() ) + m_sigma = s; + m_shape = k; + m_epsilon = Abs( e ); + m_rho = Range( r, 0.0F, 1.0F ); + m_theta = Range( a, 0.0F, Const::pi() ); + KernelFilter::Resize( 1 + (Max( 1, RoundInt( Pow( -m_shape*Pow( m_sigma, m_shape )*Ln( m_epsilon ), 1/m_shape ) ) ) << 1) ); + Rebuild(); + } + + void Initialize( int n, float k, float e, float r, float a ) + { + PCL_PRECONDITION( n == 0 || n >= 3 && (n & 1) != 0 ) + PCL_PRECONDITION( k > 0 ) + PCL_PRECONDITION( e > 0 ) + PCL_PRECONDITION( r >= 0 && r <= 1 ) + PCL_PRECONDITION( a >= 0 && a <= Const::pi() ) + KernelFilter::Resize( n ); + m_shape = k; + m_epsilon = Abs( e ); + m_sigma = (Size() >> 1)/Pow( -m_shape*Ln( m_epsilon ), 1/m_shape ); + m_rho = Range( r, 0.0F, 1.0F ); + m_theta = Range( a, 0.0F, Const::pi() ); + Rebuild(); + } + + void Rebuild() + { + int size = Size(); + if ( size == 0 ) + return; + + float* h = *coefficients; + float rk = m_shape * Pow( m_sigma, m_shape ); + + for ( int n2 = size >> 1, y = -n2; y <= n2; ++y ) + if ( y > 0 ) + for ( int x = 0; x < size; ++x, ++h ) + *h = *(h - ((y+y)*size)); + else + for ( int x = -n2; x <= n2; ++x, ++h ) + *h = (x > 0) ? *(h - (x+x)) : float( Exp( -Pow( Sqrt( float( x*x + y*y ) ), m_shape )/rk ) ); + + if ( m_rho != 1 ) + { + BicubicPixelInterpolation B; + + { + coefficient_matrix ctemp( coefficients ); + ctemp.EnsureUnique(); // because we need invariant *ctemp for interpolation + AutoPointer > + interpolator( B.NewInterpolator( *ctemp, size, size ) ); + h = *coefficients; + float r = Max( 0.5F/size, m_rho ); + for ( int n2 = size >> 1, i = -n2; i <= n2; ++i ) + { + float y = float( i )/r + n2; + for ( int x = 0; x < size; ++x ) + *h++ = (y < 0 || y >= size) ? 0.0F : (*interpolator)( float( x ), y ); + } + } + + if ( m_theta != 0 ) + { + coefficient_matrix ctemp( coefficients ); + ctemp.EnsureUnique(); // because we need invariant *ctemp for interpolation + AutoPointer > + interpolator( B.NewInterpolator( *ctemp, size, size ) ); + h = *coefficients; + float sa, ca; + SinCos( -m_theta, sa, ca ); + for ( int n2 = size >> 1, i = -n2; i <= n2; ++i ) + for ( int j = -n2; j <= n2; ++j ) + { + float x = ca*j + sa*i + n2; + float y = -sa*j + ca*i + n2; + *h++ = (x < 0 || y < 0 || x >= size || y >= size) ? 0.0F : (*interpolator)( x, y ); + } + } + } + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_VariableShapeFilter_h + +// ---------------------------------------------------------------------------- +// EOF pcl/VariableShapeFilter.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Variant.h b/3rdparty/include/pcl/Variant.h new file mode 100644 index 0000000..683bce3 --- /dev/null +++ b/3rdparty/include/pcl/Variant.h @@ -0,0 +1,1900 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Variant.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_Variant_h +#define __PCL_Variant_h + +/// \file pcl/Variant.h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::VariantType + * \brief %Variant data types. + * + * Currently %Variant supports the following data types: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
VariantType::Invalid Symbolic value used to denote an invalid, undefined or unavailable property.
VariantType::Bool A Boolean value, equivalent to the \c bool C++ type.
VariantType::Boolean A synonym for VariantType::Bool.
VariantType::Int8 Signed 8-bit integer (int8).
VariantType::Char A synonym for VariantType::Int8.
VariantType::Int16 Signed 16-bit integer (int16).
VariantType::Short A synonym for VariantType::Int16.
VariantType::Int32 Signed 32-bit integer (int32).
VariantType::Integer A synonym for VariantType::Int32.
VariantType::Int64 Signed 64-bit integer (int64).
VariantType::UInt8 Unsigned 8-bit integer (uint8).
VariantType::Byte A synonym for VariantType::UInt8.
VariantType::UInt16 Unsigned 16-bit integer (uint16).
VariantType::UShort A synonym for VariantType::UInt16.
VariantType::UInt32 Unsigned 32-bit integer (uint32).
VariantType::UInt A synonym for VariantType::UInt32.
VariantType::UInt64 Unsigned 64-bit integer (uint64).
VariantType::Float32 32-bit floating point real value (\c float).
VariantType::Float A synonym for VariantType::Float32.
VariantType::Float64 64-bit floating point real value (\c float).
VariantType::Double A synonym for VariantType::Float64.
VariantType::Real A synonym for VariantType::Double.
VariantType::Complex32 32-bit floating point complex value (fcomplex).
VariantType::FComplex A synonym for VariantType::Complex32.
VariantType::Complex64 64-bit floating point complex value (dcomplex).
VariantType::DComplex A synonym for VariantType::Complex64.
VariantType::Complex A synonym for VariantType::DComplex.
VariantType::TimePoint A time point value (TimePoint).
VariantType::I32Point Two-dimensional point with 32-bit integer coordinates (Point).
VariantType::Point A synonym for VariantType::I32Point.
VariantType::F32Point Two-dimensional point with 32-bit floating point coordinates (FPoint).
VariantType::FPoint A synonym for VariantType::F32Point.
VariantType::F64Point Two-dimensional point with 64-bit floating point coordinates (DPoint).
VariantType::DPoint A synonym for VariantType::F64Point.
VariantType::I32Rect Rectangle with 32-bit integer coordinates (Rect).
VariantType::Rect A synonym for VariantType::I32Rect.
VariantType::F32Rect Rectangle with 32-bit floating point coordinates (FRect).
VariantType::FRect A synonym for VariantType::F32Rect.
VariantType::F64Rect Rectangle with 64-bit floating point coordinates (DRect).
VariantType::DRect A synonym for VariantType::F64Rect.
VariantType::I8Vector Vector of 8-bit signed integer components (I8Vector).
VariantType::CharVector A synonym for VariantType::I8Vector
VariantType::UI8Vector Vector of 8-bit unsigned integer components (UI8Vector).
VariantType::ByteVector A synonym for VariantType::UI8Vector
VariantType::I16Vector Vector of 16-bit signed integer components (I16Vector).
VariantType::UI16Vector Vector of 16-bit unsigned integer components (UI16Vector).
VariantType::I32Vector Vector of 32-bit signed integer components (I32Vector).
VariantType::IVector A synonym for VariantType::I32Vector
VariantType::UI32Vector Vector of 32-bit unsigned integer components (UI32Vector).
VariantType::UIVector A synonym for VariantType::UI32Vector
VariantType::I64Vector Vector of 64-bit signed integer components (I64Vector).
VariantType::UI64Vector Vector of 64-bit unsigned integer components (UI64Vector).
VariantType::F32Vector Vector of 32-bit floating point real components (F32Vector).
VariantType::FVector A synonym for VariantType::F32Vector
VariantType::F64Vector Vector of 64-bit floating point real components (F64Vector).
VariantType::DVector A synonym for VariantType::F64Vector
VariantType::C32Vector Vector of 32-bit floating point complex components (C32Vector).
VariantType::C64Vector Vector of 64-bit floating point complex components (C64Vector).
VariantType::I8Matrix Matrix of 8-bit signed integer elements (I8Matrix).
VariantType::CharMatrix A synonym for VariantType::I8Matrix
VariantType::UI8Matrix Matrix of 8-bit unsigned integer elements (UI8Matrix).
VariantType::ByteMatrix A synonym for VariantType::UI8Matrix
VariantType::I16Matrix Matrix of 16-bit signed integer elements (I16Matrix).
VariantType::UI16Matrix Matrix of 16-bit unsigned integer elements (UI16Matrix).
VariantType::I32Matrix Matrix of 32-bit signed integer elements (I32Matrix).
VariantType::IMatrix A synonym for VariantType::I32Matrix
VariantType::UI32Matrix Matrix of 32-bit unsigned integer elements (UI32Matrix).
VariantType::UIMatrix A synonym for VariantType::UI32Matrix
VariantType::I64Matrix Matrix of 64-bit signed integer elements (I64Matrix).
VariantType::UI64Matrix Matrix of 64-bit unsigned integer elements (UI64Matrix).
VariantType::F32Matrix Matrix of 32-bit floating point real elements (F32Matrix).
VariantType::FMatrix A synonym for VariantType::F32Matrix
VariantType::F64Matrix Matrix of 64-bit floating point real elements (F64Matrix).
VariantType::DMatrix A synonym for VariantType::F64Matrix
VariantType::C32Matrix Matrix of 32-bit floating point complex elements (C32Matrix).
VariantType::C64Matrix Matrix of 64-bit floating point complex elements (C64Matrix).
VariantType::ByteArray Dynamic array of unsigned 8-bit integers (ByteArray).
VariantType::String UTF-16 Unicode string (String).
VariantType::IsoString 8-bit ISO/IEC 8859-1 or UTF-8 Unicode string (IsoString).
VariantType::StringList Dynamic list of UTF-16 Unicode strings (StringList).
VariantType::IsoStringList Dynamic list of 8-bit strings (IsoStringList).
VariantType::StringKeyValue Key/value pair of UTF-16 Unicode strings (StringKeyValue).
VariantType::IsoStringKeyValue Key/value pair of 8-bit strings (IsoStringKeyValue).
VariantType::StringKeyValueList Dynamic list of key/value pairs of UTF-16 Unicode strings (StringKeyValueList).
VariantType::IsoStringKeyValueList Dynamic list of key/value pairs of 8-bit strings (IsoStringKeyValueList).
+ */ +namespace VariantType +{ + enum value_type + { + Invalid = 0, + + Bool, + Boolean = Bool, + + Int8, + Char = Int8, + Int16, + Short = Int16, + Int32, + Integer = Int32, + Int64, + + UInt8, + Byte = UInt8, + UInt16, + UShort = UInt16, + UInt32, + UInt = UInt32, + UInt64, + + Float32, + Float = Float32, + Float64, + Double = Float64, + Real = Double, + + Complex32, + FComplex = Complex32, + Complex64, + DComplex = Complex64, + Complex = DComplex, + + TimePoint, + + I32Point, + Point = I32Point, + F32Point, + FPoint = F32Point, + F64Point, + DPoint = F64Point, + + I32Rect, + Rect = I32Rect, + F32Rect, + FRect = F32Rect, + F64Rect, + DRect = F64Rect, + + I8Vector, + CharVector = I8Vector, + UI8Vector, + ByteVector = UI8Vector, + I16Vector, + UI16Vector, + I32Vector, + IVector = I32Vector, + UI32Vector, + UIVector = UI32Vector, + I64Vector, + UI64Vector, + F32Vector, + FVector = F32Vector, + F64Vector, + DVector = F64Vector, + C32Vector, + C64Vector, + + I8Matrix, + CharMatrix = I8Matrix, + UI8Matrix, + ByteMatrix = UI8Matrix, + I16Matrix, + UI16Matrix, + I32Matrix, + IMatrix = I32Matrix, + UI32Matrix, + UIMatrix = UI32Matrix, + I64Matrix, + UI64Matrix, + F32Matrix, + FMatrix = F32Matrix, + F64Matrix, + DMatrix = F64Matrix, + C32Matrix, + C64Matrix, + + ByteArray, + + String, + IsoString, + + StringList, + IsoStringList, + + StringKeyValue, + IsoStringKeyValue, + + StringKeyValueList, + IsoStringKeyValueList, + + NumberOfVariantTypes, + + FirstCustomType = 1024 + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class Variant + * \brief Acts like a union to store instances of different data types. + * + * Sometimes you have to implement a single class or function able to work with + * several data types. In C++ and other languages supporting template + * metaprogramming, the obvious way to implement this functionality is by using + * class or function templates. + * + * However, in order to use templates all of the types must be known without + * ambiguity at compile time, which is not always feasible. When the data types + * can only be known at runtime, \e variant constructs are the only practical + * way to implement code able to work with multiple data types dynamically. + * + * An instance of the %Variant class can store one object of any of the + * supported %Variant types, which have been enumerated in the VariantType + * namespace. In this way %Variant can be used as a sort of envelope to + * transport objects of different types under a common interface. + * + * %Variant supports explicit type conversions through a set of dedicated + * %ToXXX() member functions. For example, one of the most useful and often + * used conversion functions is Variant::ToString(): + * + * \code + * Variant v( 3 ); // v transports an integer value + * Console().WriteLn( v.ToString() ); // writes "3" to the console + * \endcode + * + * This conversion function is extremely useful for object serialization. Using + * this conversion, a function can generate string representations of all the + * data types supported by %Variant: + * + * \code + * void PrintVariable( const String& name, const Variant& value ) + * { + * Console().WriteLn( name + " = " + value.ToString() ); + * } + * \endcode + * + * A %Variant instance owns its stored object and cannot share it with other + * objects, including other %Variant instances; it can only provide temporary + * rvalues generated from its stored object, but never references to it. This + * prevents unexpected object destruction and other problems with the objects + * transported by %Variant instances. + * + * %Variant is an essential component of the introspection mechanisms + * implemented by the Process, ProcessParameter and ProcessInstance classes. + * Thanks to %Variant, these classes are able to represent and interface with + * any installed process on the PixInsight platform. + */ +class PCL_CLASS Variant +{ +public: + + /*! + * An enumeration of all supported %Variant data types. + */ + typedef VariantType::value_type data_type; + + /*! + * Constructs an invalid %Variant instance that stores no object. + */ + Variant() + : m_type( VariantType::Invalid ) + { + m_data.anyValue = 0; + } + + /*! + * Constructs a %Variant instance to store a \c bool value. + */ + Variant( bool b ) + : m_type( VariantType::Bool ) + { + m_data.boolValue = b; + } + + /*! + * Constructs a %Variant instance to store a signed 8-bit integer value. + */ + Variant( int8 i8 ) + : m_type( VariantType::Int8 ) + { + m_data.int8Value = i8; + } + + /*! + * Constructs a %Variant instance to store a signed 16-bit integer value. + */ + Variant( int16 i16 ) + : m_type( VariantType::Int16 ) + { + m_data.int16Value = i16; + } + + /*! + * Constructs a %Variant instance to store a signed 32-bit integer value. + */ + Variant( int32 i32 ) + : m_type( VariantType::Int32 ) + { + m_data.int32Value = i32; + } + + /*! + * Constructs a %Variant instance to store a signed 64-bit integer value. + */ + Variant( int64 i64 ) + : m_type( VariantType::Int64 ) + { + m_data.int64Value = i64; + } + + /*! + * Constructs a %Variant instance to store an unsigned 8-bit integer value. + */ + Variant( uint8 u8 ) + : m_type( VariantType::UInt8 ) + { + m_data.uint8Value = u8; + } + + /*! + * Constructs a %Variant instance to store an unsigned 16-bit integer value. + */ + Variant( uint16 u16 ) + : m_type( VariantType::UInt16 ) + { + m_data.uint16Value = u16; + } + + /*! + * Constructs a %Variant instance to store an unsigned 32-bit integer value. + */ + Variant( uint32 u32 ) : m_type( VariantType::UInt32 ) + { + m_data.uint32Value = u32; + } + + /*! + * Constructs a %Variant instance to store an unsigned 64-bit integer value. + */ + Variant( uint64 u64 ) + : m_type( VariantType::UInt64 ) + { + m_data.uint64Value = u64; + } + + /*! + * Constructs a %Variant instance to store a \c float value (32-bit floating + * point). + */ + Variant( float f ) + : m_type( VariantType::Float ) + { + m_data.float32Value = f; + } + + /*! + * Constructs a %Variant instance to store a \c double value (64-bit + * floating point). + */ + Variant( double d ) + : m_type( VariantType::Double ) + { + m_data.float64Value = d; + } + + /*! + * Constructs a %Variant instance to store a complex number with \c float + * components (fcomplex). + */ + Variant( fcomplex fc ) + : m_type( VariantType::FComplex ) + { + m_data.anyValue = 0; + m_data.complex32Value = new fcomplex( fc ); + } + + /*! + * Constructs a %Variant instance to store a complex number with \c double + * components (dcomplex). + */ + Variant( dcomplex dc ) + : m_type( VariantType::DComplex ) + { + m_data.anyValue = 0; + m_data.complex64Value = new dcomplex( dc ); + } + + /*! + * Constructs a %Variant instance to store a time point value (TimePoint). + */ + Variant( const TimePoint& t ) + : m_type( VariantType::TimePoint ) + { + m_data.anyValue = 0; + m_data.timePointValue = new TimePoint( t ); + } + + /*! + * Constructs a %Variant instance to store a two-dimensional point with + * integer coordinates (Point). + */ + Variant( const Point& p ) + : m_type( VariantType::Point ) + { + m_data.anyValue = 0; + m_data.i32PointValue = new Point( p ); + } + + /*! + * Constructs a %Variant instance to store a two-dimensional point with + * \c float coordinates (FPoint). + */ + Variant( const FPoint& fp ) + : m_type( VariantType::FPoint ) + { + m_data.anyValue = 0; + m_data.f32PointValue = new FPoint( fp ); + } + + /*! + * Constructs a %Variant instance to store a two-dimensional point with + * \c double coordinates (DPoint). + */ + Variant( const DPoint& dp ) + : m_type( VariantType::DPoint ) + { + m_data.anyValue = 0; + m_data.f64PointValue = new DPoint( dp ); + } + + /*! + * Constructs a %Variant instance to store a two-dimensional rectangle with + * integer coordinates (Rect). + */ + Variant( const Rect& r ) + : m_type( VariantType::Rect ) + { + m_data.anyValue = 0; + m_data.i32RectValue = new Rect( r ); + } + + /*! + * Constructs a %Variant instance to store a two-dimensional rectangle with + * \c float coordinates (FRect). + */ + Variant( const FRect& fr ) + : m_type( VariantType::FRect ) + { + m_data.anyValue = 0; + m_data.f32RectValue = new FRect( fr ); + } + + /*! + * Constructs a %Variant instance to store a two-dimensional rectangle with + * \c double coordinates (DRect). + */ + Variant( const DRect& dr ) + : m_type( VariantType::DRect ) + { + m_data.anyValue = 0; + m_data.f64RectValue = new DRect( dr ); + } + + /*! + * Constructs a %Variant instance to store a vector of 8-bit signed integer + * components (CharVector). + */ + Variant( const CharVector& cv ) + : m_type( VariantType::CharVector ) + { + m_data.anyValue = 0; + m_data.i8VectorValue = new CharVector( cv ); + } + + /*! + * Constructs a %Variant instance to store a vector of 8-bit unsigned + * integer components (ByteVector). + */ + Variant( const ByteVector& bv ) + : m_type( VariantType::ByteVector ) + { + m_data.anyValue = 0; + m_data.ui8VectorValue = new ByteVector( bv ); + } + + /*! + * Constructs a %Variant instance to store a vector of 16-bit signed integer + * components (I16Vector). + */ + Variant( const I16Vector& i16v ) + : m_type( VariantType::I16Vector ) + { + m_data.anyValue = 0; + m_data.i16VectorValue = new I16Vector( i16v ); + } + + /*! + * Constructs a %Variant instance to store a vector of 16-bit unsigned + * integer components (UI16Vector). + */ + Variant( const UI16Vector& ui16v ) + : m_type( VariantType::UI16Vector ) + { + m_data.anyValue = 0; + m_data.ui16VectorValue = new UI16Vector( ui16v ); + } + + /*! + * Constructs a %Variant instance to store a vector of 32-bit signed integer + * components (IVector). + */ + Variant( const IVector& iv ) + : m_type( VariantType::IVector ) + { + m_data.anyValue = 0; + m_data.i32VectorValue = new IVector( iv ); + } + + /*! + * Constructs a %Variant instance to store a vector of 32-bit unsigned + * integer components (UIVector). + */ + Variant( const UIVector& uiv ) + : m_type( VariantType::UIVector ) + { + m_data.anyValue = 0; + m_data.ui32VectorValue = new UIVector( uiv ); + } + + /*! + * Constructs a %Variant instance to store a vector of 64-bit signed integer + * components (I64Vector). + */ + Variant( const I64Vector& i64v ) + : m_type( VariantType::I64Vector ) + { + m_data.anyValue = 0; + m_data.i64VectorValue = new I64Vector( i64v ); + } + + /*! + * Constructs a %Variant instance to store a vector of 64-bit unsigned + * integer components (UI64Vector). + */ + Variant( const UI64Vector& ui64v ) + : m_type( VariantType::UI64Vector ) + { + m_data.anyValue = 0; + m_data.ui64VectorValue = new UI64Vector( ui64v ); + } + + /*! + * Constructs a %Variant instance to store a vector of 32-bit floating point + * real components (FVector). + */ + Variant( const FVector& fv ) + : m_type( VariantType::FVector ) + { + m_data.anyValue = 0; + m_data.f32VectorValue = new FVector( fv ); + } + + /*! + * Constructs a %Variant instance to store a vector of 64-bit floating point + * real components (DVector). + */ + Variant( const DVector& dv ) + : m_type( VariantType::DVector ) + { + m_data.anyValue = 0; + m_data.f64VectorValue = new DVector( dv ); + } + + /*! + * Constructs a %Variant instance to store a vector of 32-bit floating point + * complex components (C32Vector). + */ + Variant( const C32Vector& c32v ) + : m_type( VariantType::C32Vector ) + { + m_data.anyValue = 0; + m_data.c32VectorValue = new C32Vector( c32v ); + } + + /*! + * Constructs a %Variant instance to store a vector of 64-bit floating point + * complex components (C64Vector). + */ + Variant( const C64Vector& c64v ) + : m_type( VariantType::C64Vector ) + { + m_data.anyValue = 0; + m_data.c64VectorValue = new C64Vector( c64v ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 8-bit signed integer + * elements (CharMatrix). + */ + Variant( const CharMatrix& cm ) + : m_type( VariantType::CharMatrix ) + { + m_data.anyValue = 0; + m_data.i8MatrixValue = new CharMatrix( cm ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 8-bit unsigned + * integer elements (ByteMatrix). + */ + Variant( const ByteMatrix& bm ) + : m_type( VariantType::ByteMatrix ) + { + m_data.anyValue = 0; + m_data.ui8MatrixValue = new ByteMatrix( bm ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 16-bit signed integer + * elements (I16Matrix). + */ + Variant( const I16Matrix& i16m ) + : m_type( VariantType::I16Matrix ) + { + m_data.anyValue = 0; + m_data.i16MatrixValue = new I16Matrix( i16m ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 16-bit unsigned + * integer elements (UI16Matrix). + */ + Variant( const UI16Matrix& ui16m ) + : m_type( VariantType::UI16Matrix ) + { + m_data.anyValue = 0; + m_data.ui16MatrixValue = new UI16Matrix( ui16m ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 32-bit signed integer + * elements (IMatrix). + */ + Variant( const IMatrix& im ) + : m_type( VariantType::IMatrix ) + { + m_data.anyValue = 0; + m_data.i32MatrixValue = new IMatrix( im ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 32-bit unsigned + * integer elements (UIMatrix). + */ + Variant( const UIMatrix& uim ) + : m_type( VariantType::UIMatrix ) + { + m_data.anyValue = 0; + m_data.ui32MatrixValue = new UIMatrix( uim ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 64-bit integer + * elements (I64Matrix). + */ + Variant( const I64Matrix& i64m ) + : m_type( VariantType::I64Matrix ) + { + m_data.anyValue = 0; + m_data.i64MatrixValue = new I64Matrix( i64m ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 64-bit unsigned + * integer elements (UI64Matrix). + */ + Variant( const UI64Matrix& ui64m ) + : m_type( VariantType::UI64Matrix ) + { + m_data.anyValue = 0; + m_data.ui64MatrixValue = new UI64Matrix( ui64m ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 32-bit floating point + * real elements (FMatrix). + */ + Variant( const FMatrix& fm ) + : m_type( VariantType::FMatrix ) + { + m_data.anyValue = 0; + m_data.f32MatrixValue = new FMatrix( fm ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 64-bit floating point + * real elements (DMatrix). + */ + Variant( const DMatrix& dm ) + : m_type( VariantType::DMatrix ) + { + m_data.anyValue = 0; + m_data.f64MatrixValue = new DMatrix( dm ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 32-bit floating point + * complex elements (C32Matrix). + */ + Variant( const C32Matrix& c32m ) + : m_type( VariantType::C32Matrix ) + { + m_data.anyValue = 0; + m_data.c32MatrixValue = new C32Matrix( c32m ); + } + + /*! + * Constructs a %Variant instance to store a matrix of 64-bit floating point + * complex elements (C64Matrix). + */ + Variant( const C64Matrix& c64m ) + : m_type( VariantType::C64Matrix ) + { + m_data.anyValue = 0; + m_data.c64MatrixValue = new C64Matrix( c64m ); + } + + /*! + * Constructs a %Variant instance to store a dynamic array of unsigned 8-bit + * integers (ByteArray). + */ + Variant( const ByteArray& ba ) + : m_type( VariantType::ByteArray ) + { + m_data.anyValue = 0; + m_data.byteArrayValue = new ByteArray( ba ); + } + + /*! + * Constructs a %Variant instance to store a UTF-16 Unicode string (String). + */ + Variant( const String& s ) + : m_type( VariantType::String ) + { + m_data.anyValue = 0; + m_data.stringValue = new String( s ); + } + + /*! + * Constructs a %Variant instance to store an 8-bit ISO/IEC 8859-1 or UTF-8 + * Unicode string (IsoString). + */ + Variant( const IsoString& s8 ) + : m_type( VariantType::IsoString ) + { + m_data.anyValue = 0; + m_data.isoStringValue = new IsoString( s8 ); + } + + /*! + * Constructs a %Variant instance to store an 8-bit ISO/IEC 8859-1 or UTF-8 + * Unicode string (IsoString), constructed from a null-terminated C string. + */ + Variant( const char* cp ) + : m_type( VariantType::IsoString ) + { + m_data.anyValue = 0; + m_data.isoStringValue = new IsoString( cp ); + } + + /*! + * Constructs a %Variant instance to store a list of UTF-16 Unicode strings + * (StringList). + */ + Variant( const StringList& sl ) + : m_type( VariantType::StringList ) + { + m_data.anyValue = 0; + m_data.stringListValue = new StringList( sl ); + } + + /*! + * Constructs a %Variant instance to store a list of 8-bit strings + * (IsoStringList). + */ + Variant( const IsoStringList& isl ) + : m_type( VariantType::IsoStringList ) + { + m_data.anyValue = 0; + m_data.isoStringListValue = new IsoStringList( isl ); + } + + /*! + * Constructs a %Variant instance to store a key/value pair of UTF-16 + * Unicode strings (StringKeyValue). + */ + Variant( const StringKeyValue& skv ) + : m_type( VariantType::StringKeyValue ) + { + m_data.anyValue = 0; + m_data.stringKeyValueValue = new StringKeyValue( skv ); + } + + /*! + * Constructs a %Variant instance to store a key/value pair of 8-bit strings + * (IsoStringKeyValue). + */ + Variant( const IsoStringKeyValue& iskv ) + : m_type( VariantType::IsoStringKeyValue ) + { + m_data.anyValue = 0; + m_data.isoStringKeyValueValue = new IsoStringKeyValue( iskv ); + } + + /*! + * Constructs a %Variant instance to store a list of key/value pairs of + * UTF-16 Unicode strings (StringKeyValueList). + */ + Variant( const StringKeyValueList& skvl ) + : m_type( VariantType::StringKeyValueList ) + { + m_data.anyValue = 0; + m_data.stringKeyValueListValue = new StringKeyValueList( skvl ); + } + + /*! + * Constructs a %Variant instance to store a list of key/value pairs of + * 8-bit strings (IsoStringKeyValueList). + */ + Variant( const IsoStringKeyValueList& iskvl ) + : m_type( VariantType::IsoStringKeyValueList ) + { + m_data.anyValue = 0; + m_data.isoStringKeyValueListValue = new IsoStringKeyValueList( iskvl ); + } + + /*! + * Copy constructor. This %Variant will store a copy of the object stored in + * another %Variant \a x. + */ + Variant( const Variant& x ) + : m_type( VariantType::Invalid ) + { + m_data.anyValue = 0; + Copy( x ); + } + + /*! + * Move constructor. + */ + Variant( Variant&& x ) + { + m_type = x.m_type; + m_data.anyValue = x.m_data.anyValue; + x.m_type = VariantType::Invalid; + } + + /*! + * Virtual destructor. The object stored in this %Variant will be destroyed. + */ + virtual ~Variant() + { + Clear(); + } + + /*! + * Copy assignment operator. This %Variant will store a copy of the object + * stored in another %Variant \a x. Returns a reference to this object. + */ + Variant& operator =( const Variant& x ) + { + Assign( x ); + return *this; + } + + /*! + * Causes this %Variant to store a copy of the object stored in another + * %Variant \a x. + */ + void Assign( const Variant& x ) + { + if ( &x != this ) + { + Clear(); + Copy( x ); + } + } + + /*! + * Move assignment operator. + */ + Variant& operator =( Variant&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers the object stored in another %Variant \a x to this %Variant. + * The source object \a x is left empty/invalid. + */ + void Transfer( Variant& x ) + { + if ( &x != this ) + { + Clear(); + m_type = x.m_type; + m_data.anyValue = x.m_data.anyValue; + x.m_type = VariantType::Invalid; + } + } + + /*! + * Transfers the object stored in another %Variant \a x to this %Variant. + * The source object \a x is left empty/invalid. + */ + void Transfer( Variant&& x ) + { + if ( &x != this ) + { + Clear(); + m_type = x.m_type; + m_data.anyValue = x.m_data.anyValue; + x.m_type = VariantType::Invalid; + } + } + + /*! + * Returns true iff this %Variant stores an object. Returns false if this is + * an invalid %Variant object. + */ + bool IsValid() const + { + return m_type != VariantType::Invalid; + } + + /*! + * Returns the type of the object currently stored in this %Variant. + */ + data_type Type() const + { + return data_type( m_type ); + } + + /*! + * Converts the object currently stored in this %Variant instance to the + * specified \a type. + * + * Returns a %Variant object with the result of the conversion. + * + * If this %Variant is invalid, or if the currently stored object cannot be + * converted to the requested type, this function throws an Error exception + * with a descriptive message. + */ + Variant ToType( data_type type ) const; + + /*! + * Destroys the object stored in this %Variant and leaves this object in an + * invalid state. + */ + void Clear(); + + /*! + * Compares the object stored in this %Variant with the object stored in + * another %Variant \a x. + * + * If both %Variant instances store objects of different types, the object + * in \a x is converted to the type of this %Variant as a temporary object, + * and the comparison is made between the object in this %variant and the + * temporary object. If the object in \a x cannot be converted to the type + * of this %Variant, an Error exception is thrown. + * + * On success, returns an integer indicating the comparison result: + * + * 0 if the objects are equal. \n + * -1 if this object precedes the object in \a x. \n + * +1 if this object postcedes the object in \a x. + * + * \sa operator ==(), operator <() + */ + int Compare( const Variant& x ) const; + + /*! + * Returns true iff the object stored in this %Variant is equal to the object + * in another %Variant \a x. + * + * This operator is equivalent to: + * + * \code Compare( x ) == 0; \endcode + */ + bool operator ==( const Variant& x ) const + { + return Compare( x ) == 0; + } + + /*! + * Returns true iff the object stored in this %Variant precedes the object + * in another %Variant \a x. + * + * This operator is equivalent to: + * + * \code Compare( x ) < 0; \endcode + */ + bool operator <( const Variant& x ) const + { + return Compare( x ) < 0; + } + + /*! + * Converts the object stored in this %Variant to a Boolean value, and + * returns the result of the conversion. + * + * Throws an Error exception if a Boolean conversion is not possible for the + * object currently stored in this %Variant. + */ + bool ToBool() const; + + /*! + * A convenience synonym for ToBool(). + */ + bool ToBoolean() const + { + return ToBool(); + } + + /*! + * Converts the object stored in this %Variant to a 32-bit integer value, + * and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c int type is not + * possible for the object currently stored in this %Variant. + */ + int ToInt() const; + + /*! + * Converts the object stored in this %Variant to a 64-bit integer value, + * and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c int64 type is not + * possible for the object currently stored in this %Variant. + */ + int64 ToInt64() const; + + /*! + * Converts the object stored in this %Variant to an unsigned 32-bit integer + * value, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c unsigned \c int type + * is not possible for the object currently stored in this %Variant. + */ + unsigned int ToUInt() const; + + /*! + * Converts the object stored in this %Variant to an unsigned 64-bit integer + * value, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c uint64 type is not + * possible for the object currently stored in this %Variant. + */ + uint64 ToUInt64() const; + + /*! + * Converts the object stored in this %Variant to a 32-bit floating point + * value, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c float type is not + * possible for the object currently stored in this %Variant. + */ + float ToFloat() const; + + /*! + * Converts the object stored in this %Variant to a 64-bit floating point + * value, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c double type is not + * possible for the object currently stored in this %Variant. + */ + double ToDouble() const; + + /*! + * Converts the object stored in this %Variant to a complex value with + * \c float components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c fcomplex type is not + * possible for the object currently stored in this %Variant. + */ + fcomplex ToFComplex() const; + + /*! + * Converts the object stored in this %Variant to a complex value with + * \c double components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the \c dcomplex type is not + * possible for the object currently stored in this %Variant. + */ + dcomplex ToDComplex() const; + + /*! + * A convenience synonym for ToDComplex(). + */ + complex ToComplex() const + { + return ToDComplex(); + } + + /*! + * Converts the object stored in this %Variant to a time point value, and + * returns the result of the conversion. + * + * Throws an Error exception if a conversion to the TimePoint class is not + * possible for the object currently stored in this %Variant. + */ + TimePoint ToTimePoint() const; + + /*! + * Converts the object stored in this %Variant to a two-dimensional point + * with integer coordinates, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the Point class is not + * possible for the object currently stored in this %Variant. + */ + Point ToPoint() const; + + /*! + * Converts the object stored in this %Variant to a two-dimensional point + * with \c float coordinates, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the FPoint class is not + * possible for the object currently stored in this %Variant. + */ + FPoint ToFPoint() const; + + /*! + * Converts the object stored in this %Variant to a two-dimensional point + * with \c double coordinates, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the DPoint class is not + * possible for the object currently stored in this %Variant. + */ + DPoint ToDPoint() const; + + /*! + * Converts the object stored in this %Variant to a two-dimensional + * rectangle with integer coordinates, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the Rect class is not + * possible for the object currently stored in this %Variant. + */ + Rect ToRect() const; + + /*! + * Converts the object stored in this %Variant to a two-dimensional + * rectangle with \c float coordinates, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the FRect class is not + * possible for the object currently stored in this %Variant. + */ + FRect ToFRect() const; + + /*! + * Converts the object stored in this %Variant to a two-dimensional + * rectangle with \c double coordinates, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the DRect class is not + * possible for the object currently stored in this %Variant. + */ + DRect ToDRect() const; + + /*! + * Converts the object stored in this %Variant to a vector of 8-bit signed + * integer components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the CharVector class is not + * possible for the object currently stored in this %Variant. + */ + CharVector ToCharVector() const; + + /*! + * Converts the object stored in this %Variant to a vector of 8-bit unsigned + * integer components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the ByteVector class is not + * possible for the object currently stored in this %Variant. + */ + ByteVector ToByteVector() const; + + /*! + * Converts the object stored in this %Variant to a vector of 16-bit signed + * integer components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the I16Vector class is not + * possible for the object currently stored in this %Variant. + */ + I16Vector ToI16Vector() const; + + /*! + * Converts the object stored in this %Variant to a vector of 16-bit + * unsigned integer components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the UI16Vector class is not + * possible for the object currently stored in this %Variant. + */ + UI16Vector ToUI16Vector() const; + + /*! + * Converts the object stored in this %Variant to a vector of integer + * components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the IVector class is not + * possible for the object currently stored in this %Variant. + */ + IVector ToIVector() const; + + /*! + * Converts the object stored in this %Variant to a vector of unsigned + * integer components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the UIVector class is not + * possible for the object currently stored in this %Variant. + */ + UIVector ToUIVector() const; + + /*! + * Converts the object stored in this %Variant to a vector of 64-bit integer + * components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the I64Vector class is not + * possible for the object currently stored in this %Variant. + */ + I64Vector ToI64Vector() const; + + /*! + * Converts the object stored in this %Variant to a vector of 64-bit + * unsigned integer components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the UI64Vector class is not + * possible for the object currently stored in this %Variant. + */ + UI64Vector ToUI64Vector() const; + + /*! + * Converts the object stored in this %Variant to a vector of \c float + * components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the FVector class is not + * possible for the object currently stored in this %Variant. + */ + FVector ToFVector() const; + + /*! + * Converts the object stored in this %Variant to a vector of \c double + * components, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the DVector class is not + * possible for the object currently stored in this %Variant. + */ + DVector ToDVector() const; + + /*! + * A convenience synonym for ToDVector(). + */ + Vector ToVector() const + { + return ToDVector(); + } + + /*! + * Converts the object stored in this %Variant to a vector of 32-bit + * floating point complex components, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the C32Vector class is not + * possible for the object currently stored in this %Variant. + */ + C32Vector ToC32Vector() const; + + /*! + * Converts the object stored in this %Variant to a vector of 64-bit + * floating point complex components, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the C64Vector class is not + * possible for the object currently stored in this %Variant. + */ + C64Vector ToC64Vector() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 8-bit signed + * integer elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the CharMatrix class is not + * possible for the object currently stored in this %Variant. + */ + CharMatrix ToCharMatrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 8-bit unsigned + * integer elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the ByteMatrix class is not + * possible for the object currently stored in this %Variant. + */ + ByteMatrix ToByteMatrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 16-bit signed + * integer elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the I16Matrix class is not + * possible for the object currently stored in this %Variant. + */ + I16Matrix ToI16Matrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 16-bit + * unsigned integer elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the UI16Matrix class is not + * possible for the object currently stored in this %Variant. + */ + UI16Matrix ToUI16Matrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of integer + * elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the IMatrix class is not + * possible for the object currently stored in this %Variant. + */ + IMatrix ToIMatrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of unsigned + * integer elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the UIMatrix class is not + * possible for the object currently stored in this %Variant. + */ + UIMatrix ToUIMatrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 64-bit integer + * elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the I64Matrix class is not + * possible for the object currently stored in this %Variant. + */ + I64Matrix ToI64Matrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 64-bit + * unsigned integer elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the UI64Matrix class is not + * possible for the object currently stored in this %Variant. + */ + UI64Matrix ToUI64Matrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of \c float + * elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the FMatrix class is not + * possible for the object currently stored in this %Variant. + */ + FMatrix ToFMatrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of \c double + * elements, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the DMatrix class is not + * possible for the object currently stored in this %Variant. + */ + DMatrix ToDMatrix() const; + + /*! + * A convenience synonym for ToDMatrix(). + */ + Matrix ToMatrix() const + { + return ToDMatrix(); + } + + /*! + * Converts the object stored in this %Variant to a matrix of 32-bit + * floating point complex elements, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the C32Matrix class is not + * possible for the object currently stored in this %Variant. + */ + C32Matrix ToC32Matrix() const; + + /*! + * Converts the object stored in this %Variant to a matrix of 64-bit + * floating point complex elements, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the C64Matrix class is not + * possible for the object currently stored in this %Variant. + */ + C64Matrix ToC64Matrix() const; + + /*! + * Converts the object stored in this %Variant to a dynamic array of + * unsigned 8-bit integers, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the ByteArray class is not + * possible for the object currently stored in this %Variant. + */ + ByteArray ToByteArray() const; + + /*! + * Converts the object stored in this %Variant to a UTF-16 Unicode string, + * and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the String class is not + * possible for the object currently stored in this %Variant. + */ + String ToString() const; + + /*! + * Converts the object stored in this %Variant to an 8-bit ISO/IEC 8859-1 or + * UTF-8 Unicode string, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the IsoString class is not + * possible for the object currently stored in this %Variant. + */ + IsoString ToIsoString() const; + + /*! + * Converts the object stored in this %Variant to a dynamic list of UTF-16 + * Unicode strings, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the StringList class is not + * possible for the object currently stored in this %Variant. + */ + StringList ToStringList() const; + + /*! + * Converts the object stored in this %Variant to a dynamic list of 8-bit + * strings, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the IsoStringList class is + * not possible for the object currently stored in this %Variant. + */ + IsoStringList ToIsoStringList() const; + + /*! + * Converts the object stored in this %Variant to a key/value pair of UTF-16 + * Unicode strings, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the StringKeyValue class is + * not possible for the object currently stored in this %Variant. + */ + StringKeyValue ToStringKeyValue() const; + + /*! + * Converts the object stored in this %Variant to a key/value pair of 8-bit + * strings, and returns the result of the conversion. + * + * Throws an Error exception if a conversion to the IsoStringKeyValue class is + * not possible for the object currently stored in this %Variant. + */ + IsoStringKeyValue ToIsoStringKeyValue() const; + + /*! + * Converts the object stored in this %Variant to a dynamic list of + * key/value pairs of UTF-16 Unicode strings, and returns the result of the + * conversion. + * + * Throws an Error exception if a conversion to the StringKeyValueList class + * is not possible for the object currently stored in this %Variant. + */ + StringKeyValueList ToStringKeyValueList() const; + + /*! + * Converts the object stored in this %Variant to a dynamic list of + * key/value pairs of 8-bit strings, and returns the result of th + * conversion. + * + * Throws an Error exception if a conversion to the IsoStringKeyValueList + * class is not possible for the object currently stored in this %Variant. + */ + IsoStringKeyValueList ToIsoStringKeyValueList() const; + + /*! + * Returns a pointer to the immutable block of data stored in this %Variant + * object. + * + * For scalar and complex data types (bool, int32, float, fcomplex, etc.), + * this member function returns a pointer to the transported object. + * + * For vector, matrix and string types, this function returns the starting + * address of the contiguous data block stored by the transported object. + * For example, if a ByteArray object is being transported by this %Variant + * object, this function returns ByteArray::Begin(). + * + * For other structured types such as points, rectangles and lists, this + * function throws an Error exception. + */ + const void* InternalBlockAddress() const; + + /*! + * Returns the length of the vector stored in this %Variant object. + * + * If this %Variant does not transport a vector or vector-like object + * (IVector, FVector, DVector, ByteArray, String or IsoString), this member + * function throws an Error exception. + */ + size_type VectorLength() const; + + /*! + * Returns the dimensions of the matrix stored in this %Variant object. + * + * If this %Variant does not transport a matrix object (IMatrix, FMatrix, + * DMatrix), this member function throws an Error exception. + * + * The returned rectangle is anchored at {0,0} and has the same dimensions + * as the transported matrix: Rect::Height() or Rect::y1 is the number of + * matrix rows, and Rect::Width() or Rect::x1 is the number of matrix + * columns. + */ + Rect MatrixDimensions() const; + + /*! + * Returns the size in bytes of the scalar, complex, point, rectangle, + * vector or matrix object transported by this %Variant object. + * + * The value returned by this function can be used along with + * InternalBlockAddress() for object serialization purposes. + * + * If this %Variant does not transport a scalar, complex, vector-like or + * matrix object, this member function throws an Error exception. + */ + size_type BlockSize() const; + + /*! + * Returns the length in bytes of a block element for the specified \a type. + * + * \a type must be a scalar, complex, vector, matrix or string type. + * Otherwise this function will throw an Error exception. + */ + static int BytesPerBlockElementForType( int type ); + + /*! + * Returns the length in bytes of a block element, if this %Variant object + * transports a scalar, complex, vector, matrix or string object. + * + * If this %Variant does not transport a scalar, complex, vector-like or + * matrix object, this function throws an Error exception. + */ + int BytesPerBlockElement() const + { + return BytesPerBlockElementForType( m_type ); + } + + /*! + * Returns true only if the specified \a type is a scalar %Variant type: + * bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float or + * double. + */ + static bool IsScalarType( int type ); + + /*! + * Returns true only if the object transported by this %Variant is of a + * scalar type: bool, int8, int16, int32, int64, uint8, uint16, uint32, + * uint64, float or double. + */ + bool IsScalar() const + { + return IsScalarType( m_type ); + } + + /*! + * Returns true only if the specified \a type is a complex %Variant type: + * Complex32 or Complex64. + */ + static bool IsComplexType( int type ) + { + return type == VariantType::Complex32 || type == VariantType::Complex64; + } + + /*! + * Returns true only if the object transported by this %Variant is of a + * complex type: Complex32 or Complex64. + */ + bool IsComplex() const + { + return IsComplexType( m_type ); + } + + /*! + * Returns true only if the specified \a type is VariantType::TimePoint. + */ + static bool IsTimePointType( int type ) + { + return type == VariantType::TimePoint; + } + + /*! + * Returns true only if the object transported by this %Variant is of the + * TimePoint type. + */ + bool IsTimePoint() const + { + return IsTimePointType( m_type ); + } + + /*! + * Returns true only if the specified \a type is a vector or vector-like + * %Variant type: CharVector, ByteVector, IVector, UIVector, I64Vector, + * UI64Vector, FVector, DVector, ByteArray, String or IsoString. + */ + static bool IsVectorType( int type ); + + /*! + * Returns true only if the object transported by this %Variant is of a + * vector or vector-like type: CharVector, ByteVector, IVector, UIVector, + * I64Vector, UI64Vector, FVector, DVector, ByteArray, String or IsoString. + */ + bool IsVector() const + { + return IsVectorType( m_type ); + } + + /*! + * Returns true only if the specified \a type is a matrix %Variant type: + * CharMatrix, ByteMatrix, IMatrix, UIMatrix, I64Matrix, UI64Matrix, FMatrix + * or DMatrix. + */ + static bool IsMatrixType( int type ); + + /*! + * Returns true only if the object transported by this %Variant is of a + * matrix type: CharMatrix, ByteMatrix, IMatrix, UIMatrix, I64Matrix, + * UI64Matrix, FMatrix or DMatrix. + */ + bool IsMatrix() const + { + return IsMatrixType( m_type ); + } + + /*! + * Returns true only if the specified \a type is a character string %Variant + * type: String or IsoString. + */ + static bool IsStringType( int type ) + { + return type == VariantType::String || type == VariantType::IsoString; + } + + /*! + * Returns true only if the object transported by this %Variant is of a + * character string type: String or IsoString. + */ + bool IsString() const + { + return IsStringType( m_type ); + } + + /*! + * Returns true only if the specified \a type is a structured %Variant type: + * fcomplex, dcomplex, Point, FPoint, DPoint, Rect, FRect, DRect, + * StringList, IsoStringList, StringKeyValue, IsoStringKeyValue, + * StringKeyValueList or IsoStringKeyValueList. + */ + static bool IsStructuredType( int type ); + + /*! + * Returns true only if the object transported by this %Variant is of a + * structured type: fcomplex, dcomplex, Point, FPoint, DPoint, Rect, FRect, + * DRect, StringList, IsoStringList, StringKeyValue, IsoStringKeyValue, + * StringKeyValueList or IsoStringKeyValueList. + * + * For structured objects the InternalBlockAddress() and BlockSize() member + * functions cannot be used, since these objects cannot be accessed through + * a unique pointer and a length in bytes. + */ + bool IsStructured() const + { + return IsStructuredType( m_type ); + } + + /*! + * Returns a static null-terminated string with the name of the specified + * %Variant \a type. + */ + static const char* TypeAsString( int type ); + +private: + + union Data + { + bool boolValue; + + int8 int8Value; + int16 int16Value; + int32 int32Value; + int64 int64Value; + + uint8 uint8Value; + uint16 uint16Value; + uint32 uint32Value; + uint64 uint64Value; + + float float32Value; + double float64Value; + + fcomplex* complex32Value; + dcomplex* complex64Value; + + TimePoint* timePointValue; + + I32Point* i32PointValue; + F32Point* f32PointValue; + F64Point* f64PointValue; + + I32Rect* i32RectValue; + F32Rect* f32RectValue; + F64Rect* f64RectValue; + + I8Vector* i8VectorValue; + UI8Vector* ui8VectorValue; + I16Vector* i16VectorValue; + UI16Vector* ui16VectorValue; + I32Vector* i32VectorValue; + UI32Vector* ui32VectorValue; + I64Vector* i64VectorValue; + UI64Vector* ui64VectorValue; + F32Vector* f32VectorValue; + F64Vector* f64VectorValue; + C32Vector* c32VectorValue; + C64Vector* c64VectorValue; + + I8Matrix* i8MatrixValue; + UI8Matrix* ui8MatrixValue; + I16Matrix* i16MatrixValue; + UI16Matrix* ui16MatrixValue; + I32Matrix* i32MatrixValue; + UI32Matrix* ui32MatrixValue; + I64Matrix* i64MatrixValue; + UI64Matrix* ui64MatrixValue; + F32Matrix* f32MatrixValue; + F64Matrix* f64MatrixValue; + C32Matrix* c32MatrixValue; + C64Matrix* c64MatrixValue; + + ByteArray* byteArrayValue; + + String* stringValue; + IsoString* isoStringValue; + + StringList* stringListValue; + IsoStringList* isoStringListValue; + + StringKeyValue* stringKeyValueValue; + IsoStringKeyValue* isoStringKeyValueValue; + + StringKeyValueList* stringKeyValueListValue; + IsoStringKeyValueList* isoStringKeyValueListValue; + + uint64 anyValue; + }; + + Data m_data; + int m_type; + + // Internal + void Copy( const Variant& ); + + friend class PCL_AssertVariantSize; +}; + +class PCL_AssertVariantSize +{ +#ifndef _MSC_VER +# ifdef __clang__ + _Pragma("clang diagnostic push") + _Pragma("clang diagnostic ignored \"-Wunused-private-field\"") +# endif + Variant* v; + static_assert( sizeof( v->m_data ) == sizeof( uint64 ), "Invalid sizeof( Variant::m_data )" ); + static_assert( sizeof( v->m_data.anyValue ) == sizeof( v->m_data ), "Invalid sizeof( Variant::m_data.anyValue )" ); +# ifdef __clang__ + _Pragma("clang diagnostic pop") +# endif +#else + static_assert( sizeof( Variant::Data ) == sizeof( uint64 ), "Invalid sizeof( Variant::m_data )" ); +#endif +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +/*! + * \internal + * API helper routines for internal use. + */ +struct api_property_value; +namespace pcl +{ + Variant VariantFromAPIPropertyValue( const api_property_value& ); + void APIPropertyValueFromVariant( api_property_value&, const Variant& ); + Variant::data_type VariantTypeFromAPIPropertyType( uint64 ); + uint64 APIPropertyTypeFromVariantType( Variant::data_type ); +} // pcl + +#endif // __PCL_Variant_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Variant.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Vector.h b/3rdparty/include/pcl/Vector.h new file mode 100644 index 0000000..db34e44 --- /dev/null +++ b/3rdparty/include/pcl/Vector.h @@ -0,0 +1,3325 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Vector.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_Vector_h +#define __PCL_Vector_h + +/// \file pcl/Vector.h + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef __PCL_NO_VECTOR_STATISTICS +# include +#endif + +#ifndef __PCL_NO_VECTOR_INSTANTIATE +# include +#endif + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class GenericVector + * \brief Generic vector of arbitrary length. + * + * %GenericVector is a lightweight template class implementing a vector of + * arbitrary length. This class provides the following main features: + * + * \li Implicit data sharing with reference counting and copy-on-write + * functionality. %GenericVector instances can safely be passed as function + * return values and by-value function arguments. + * + * \li Thread-safe. %GenericVector instances can safely be accessed from + * multiple threads. The reference counter implements atomic reference and + * dereference operations. + * + * \li Efficient vector storage and access to vector elements. Vector + * elements are allocated as a single, contiguous memory block. + * + * \li Support for a large set of vector operations, including scalar-to-vector + * and vector-to-vector arithmetic operations, dot and cross products. + * + * \li Calculation of a variety of descriptive statistics of vector components. + * + * \sa GenericMatrix, \ref vector_operators, \ref vector_types + */ +template +class PCL_CLASS GenericVector : public DirectContainer +{ +public: + + /*! + * Represents a scalar. + */ + typedef T scalar; + + /*! + * Represents a vector component. + */ + typedef T component; + + /*! + * Represents a mutable vector iterator. + */ + typedef T* iterator; + + /*! + * Represents an immutable vector iterator. + */ + typedef const T* const_iterator; + + /*! + * Constructs an empty vector. An empty vector has no components and its + * length is zero. + */ + GenericVector() + { + m_data = new Data; + } + + /*! + * Constructs an uninitialized vector of the specified length. + * + * \param len Number of vector components (≥ 0). + * + * This constructor does not initialize vector components. The newly created + * vector will contain unpredictable values. + */ + GenericVector( int len ) + { + PCL_PRECONDITION( len >= 0 ) + m_data = new Data( len ); + } + + /*! + * Constructs a vector and fills it with a constant component value. + * + * \param x Initial value for all vector components. + * \param len Number of vector components (≥ 0). + */ + GenericVector( const component& x, int len ) + { + PCL_PRECONDITION( len >= 0 ) + m_data = new Data( len ); + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = x; + } + + /*! + * Constructs a vector and initializes it with component values taken from a + * static array. + * + * \param a Address of the first item of a static array for + * initialization of vector components. The array must provide + * at least \a len consecutive items. + * + * \param len Number of vector components (≥ 0). + */ + template + GenericVector( const T1* a, int len ) + { + PCL_PRECONDITION( len >= 0 ) + m_data = new Data( len ); + if ( a != nullptr ) + { + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + const T1* __restrict__ k = a; + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i = component( *k ); + } + } + + /*! + * Constructs a vector and initializes it with component values taken from + * the specified initializer list \a c. + * + * This constructor is equivalent to: + * + * \code GenericVector( c.begin(), int( c.size() ) ) \endcode + */ + template + GenericVector( std::initializer_list c ) + : GenericVector( c.begin(), int( c.size() ) ) + { + } + + /*! + * Constructs a three-component vector initialized with the specified \a x, + * \a y and \a z component values. + */ + template + GenericVector( const T1& x, const T1& y, const T1& z ) + { + m_data = new Data( 3 ); + iterator v = m_data->Begin(); + *v++ = component( x ); + *v++ = component( y ); + *v = component( z ); + } + + /*! + * Constructs a four-component vector initialized with the specified \a x, + * \a y, \a z and \a t component values. + */ + template + GenericVector( const T1& x, const T1& y, const T1& z, const T1& t ) + { + m_data = new Data( 4 ); + iterator v = m_data->Begin(); + *v++ = component( x ); + *v++ = component( y ); + *v++ = component( z ); + *v = component( t ); + } + + /*! + * Copy constructor. This object references the same data that is being + * referenced by the specified vector \a x. + */ + GenericVector( const GenericVector& x ) + : m_data( x.m_data ) + { + m_data->Attach(); + } + + /*! + * Move constructor. + */ + GenericVector( GenericVector&& x ) + : m_data( x.m_data ) + { + x.m_data = nullptr; + } + + /*! + * Constructs a vector and initializes it with component values taken from + * an instance \a x of a different vector template instantiation. + * + * This constructor is equivalent to: + * + * \code GenericVector( x.Begin(), x.Length() ) \endcode + */ + template + GenericVector( const GenericVector& x ) + : GenericVector( x.Begin(), x.Length() ) + { + } + + /*! + * Destroys a %GenericVector object. This destructor dereferences the vector + * data. If the vector data becomes unreferenced, it is destroyed and + * deallocated immediately. + */ + virtual ~GenericVector() + { + if ( m_data != nullptr ) + { + DetachFromData(); + m_data = nullptr; + } + } + + /*! + * Deallocates vector data, yielding an empty vector. + */ + void Clear() + { + if ( !IsEmpty() ) + if ( m_data->IsUnique() ) + m_data->Deallocate(); + else + { + Data* newData = new Data( 0 ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Copy assignment operator. Returns a reference to this object. + * + * See the Assign() member function for more information. + */ + GenericVector& operator =( const GenericVector& x ) + { + Assign( x ); + return *this; + } + + /*! + * Assigns a vector \a x to this object. + * + * If this instance and the specified source instance \a x reference + * different vector data, the data previously referenced by this object is + * dereferenced. If the previous data becomes unreferenced, it is destroyed + * and deallocated. Then the data being referenced by \a x is also + * referenced by this object. + * + * If this instance and the specified source instance \a x already reference + * the same vector data, then this function does nothing. + */ + void Assign( const GenericVector& x ) + { + x.m_data->Attach(); + DetachFromData(); + m_data = x.m_data; + } + + /*! + * Move assignment operator. Returns a reference to this object. + * + * See the Transfer() member function for more information. + */ + GenericVector& operator =( GenericVector&& x ) + { + Transfer( x ); + return *this; + } + + /*! + * Transfers data from another vector \a x to this object. + * + * Decrements the reference counter of the current vector data. If the data + * becomes unreferenced, it is destroyed and deallocated. The vector data + * referenced by the source object \a x is then transferred to this object, + * and the source object \a x is left as an invalid empty vector. + * + * \warning The source vector \a x will be an invalid object after calling + * this function, and hence should be destroyed immediately. Any attempt to + * access an invalid object will most likely lead to a crash. + */ + void Transfer( GenericVector& x ) + { + DetachFromData(); + m_data = x.m_data; + x.m_data = nullptr; + } + + /*! + * Transfers data from another vector \a x to this object. + * + * Decrements the reference counter of the current vector data. If the data + * becomes unreferenced, it is destroyed and deallocated. The vector data + * referenced by the source object \a x is then transferred to this object, + * and the source object \a x is left as an invalid empty vector. + * + * \warning The source vector \a x will be an invalid object after calling + * this function, and hence should be destroyed immediately. Any attempt to + * access an invalid object will most likely lead to a crash. + */ + void Transfer( GenericVector&& x ) + { + DetachFromData(); + m_data = x.m_data; + x.m_data = nullptr; + } + + /*! + * Exchanges two vectors \a x1 and \a x2. + * + * This function is efficient because it simply swaps the internal vector + * data pointers owned by the objects. + */ + friend void Swap( GenericVector& x1, GenericVector& x2 ) noexcept + { + pcl::Swap( x1.m_data, x2.m_data ); + } + + /*! + * Assigns a constant scalar \a x to all components of this vector. Returns + * a reference to this object. + * + * Before assigning a constant value to all vector components, this function + * ensures that this instance uniquely references its vector data, + * generating a new vector data block if necessary. + */ + GenericVector& operator =( const scalar& x ) + { + if ( !IsUnique() ) + { + Data* newData = new Data( m_data->Length() ); + DetachFromData(); + m_data = newData; + } + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = x; + return *this; + } + + /*! + * Vector addition/assignment. Adds each component of the specified vector + * \a x to the corresponding component of this vector. Returns a reference + * to this object. + * + * Before operating vector components, this function ensures that this + * instance uniquely references its vector data, generating a duplicate if + * necessary. + * + * If the specified vectors are incompatible for component-wise operations + * (because the length of \a x is less than the length of this object), this + * function throws an appropriate Error exception. + */ + GenericVector& operator +=( const GenericVector& x ) + { + if ( x.Length() < Length() ) + throw Error( "Invalid vector addition." ); + EnsureUnique(); + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + const_iterator __restrict__ k = x.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i += *k; + return *this; + } + + /*! + * Vector subtraction/assignment. Subtracts each component of the specified + * vector \a x from the corresponding component of this vector. Returns a + * reference to this object. + * + * Before operating vector components, this function ensures that this + * instance uniquely references its vector data, generating a duplicate if + * necessary. + * + * If the specified vectors are incompatible for component-wise operations + * (because the length of \a x is less than the length of this object), this + * function throws an appropriate Error exception. + */ + GenericVector& operator -=( const GenericVector& x ) + { + if ( x.Length() < Length() ) + throw Error( "Invalid vector subtraction." ); + EnsureUnique(); + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + const_iterator __restrict__ k = x.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i -= *k; + return *this; + } + + /*! + * Component-wise vector multiplication/assignment. Multiplies each + * component of this vector by the corresponding component of the specified + * vector \a x. Returns a reference to this object. + * + * Before operating vector components, this function ensures that this + * instance uniquely references its vector data, generating a duplicate if + * necessary. + * + * If the specified vectors are incompatible for component-wise operations + * (because the length of \a x is less than the length of this object), this + * function throws an appropriate Error exception. + */ + GenericVector& operator *=( const GenericVector& x ) + { + if ( x.Length() < Length() ) + throw Error( "Invalid vector multiplication." ); + EnsureUnique(); + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + const_iterator __restrict__ k = x.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i *= *k; + return *this; + } + + /*! + * Component-wise vector division/assignment. Divides each component of this + * vector by the corresponding component of the specified vector \a x. + * Returns a reference to this object. + * + * Before operating vector components, this function ensures that this + * instance uniquely references its vector data, generating a duplicate if + * necessary. + * + * If the specified vectors are incompatible for component-wise operations + * (because the length of \a x is less than the length of this object), this + * function throws an appropriate Error exception. + * + * \note Make sure that no component of the specified divisor vector \a x is + * zero or insignificant, or calling this member function will lead to + * division(s) by zero. + */ + GenericVector& operator /=( const GenericVector& x ) + { + if ( x.Length() < Length() ) + throw Error( "Invalid vector division." ); + EnsureUnique(); + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + const_iterator __restrict__ k = x.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *i /= *k; + return *this; + } + +#define IMPLEMENT_SCALAR_ASSIGN_OP( op ) \ + if ( IsUnique() ) \ + { \ + iterator __restrict__ i = m_data->Begin(); \ + const_iterator __restrict__ j = m_data->End(); \ + PCL_IVDEP \ + for ( ; i < j; ++i ) \ + *i op##= x; \ + } \ + else \ + { \ + Data* newData = new Data( m_data->Length() ); \ + const_iterator __restrict__ i = m_data->Begin(); \ + const_iterator __restrict__ j = m_data->End(); \ + iterator __restrict__ k = newData->Begin(); \ + PCL_IVDEP \ + for ( ; i < j; ++i, ++k ) \ + *k = *i op x; \ + DetachFromData(); \ + m_data = newData; \ + } \ + return *this; + + /*! + * Adds a constant scalar \a x to all components of this vector. Returns a + * reference to this object. + * + * Before adding a constant value to all vector components, this function + * ensures that this instance uniquely references its vector data, + * generating a duplicate if necessary. + */ + GenericVector& operator +=( const scalar& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( + ) + } + + /*! + * Subtracts a constant scalar \a x from all components of this vector. + * Returns a reference to this object. + * + * Before subtracting a constant value from all vector components, this + * function ensures that this instance uniquely references its vector data, + * generating a duplicate if necessary. + */ + GenericVector& operator -=( const scalar& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( - ) + } + + /*! + * Multiplies all components of this vector by a constant scalar \a x. + * Returns a reference to this object. + * + * Before multiplying all vector components by a constant value, this + * function ensures that this instance uniquely references its vector data, + * generating a duplicate if necessary. + */ + GenericVector& operator *=( const scalar& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( * ) + } + + /*! + * Divides all components of this vector by a constant scalar \a x. Returns + * a reference to this object. + * + * Before dividing all vector components by a constant value, this function + * ensures that this instance uniquely references its vector data, + * generating a duplicate if necessary. + */ + GenericVector& operator /=( const scalar& x ) + { + IMPLEMENT_SCALAR_ASSIGN_OP( / ) + } + + /*! + * Raises all components of this vector to a constant scalar \a x. Returns + * a reference to this object. + * + * Before raising all vector components to a constant value, this function + * ensures that this instance uniquely references its vector data, + * generating a duplicate if necessary. + */ + GenericVector& operator ^=( const scalar& x ) + { + if ( IsUnique() ) + { + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = pcl::Pow( *i, x ); + } + else + { + Data* newData = new Data( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = pcl::Pow( *i, x ); + DetachFromData(); + m_data = newData; + } + return *this; + } + +#undef IMPLEMENT_SCALAR_ASSIGN_OP + + /*! + * Returns the dot product of this vector and a vector \a v. + * + * \note For performance reasons, this function does not check whether the + * specified vector has at least the same number of components as this + * vector. If that condition does not hold, this function will invoke + * undefined behavior. + */ + scalar Dot( const GenericVector& v ) const noexcept + { + PCL_PRECONDITION( v.Length() >= Length() ) + scalar r = scalar( 0 ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + const_iterator __restrict__ k = v.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + r += scalar( *i ) * scalar( *k ); + return r; + } + + /*! + * Returns the cross product of this vector and a vector \a v2. + * + * \note The cross product is only defined for vectors of three components. + * For performance reasons, this function does not check vector lengths. For + * vectors of length < 3, this function will invoke undefined behavior. + */ + GenericVector Cross( const GenericVector& v2 ) const + { + PCL_PRECONDITION( Length() == 3 && v2.Length() == 3 ) + component x1 = *At( 0 ); + component y1 = *At( 1 ); + component z1 = *At( 2 ); + component x2 = v2[0]; + component y2 = v2[1]; + component z2 = v2[2]; + return GenericVector( y1*z2 - z1*y2, + z1*x2 - x1*z2, + x1*y2 - y1*x2 ); + } + + /*! + * Unary sign reversal operator: returns a vector with the components of + * this vector multiplied by -1. + */ + GenericVector operator -() const + { + GenericVector R( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = R.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = -*i; + return R; + } + + /*! + * Reverses the sign of all components of this vector. + * + * Before performing its task, this function ensures that this instance + * uniquely references its vector data, generating a duplicate if necessary. + */ + void ReverseSign() + { + if ( IsUnique() ) + { + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = -*i; + } + else + { + Data* newData = new Data( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = -*i; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the square of this vector. The result is a new vector of the same + * length where each component is the square of its counterpart in this + * vector. + */ + GenericVector Sqr() const + { + GenericVector R( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = R.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = *i * *i; + return R; + } + + /*! + * Replaces all components of this vector with their squares. + * + * Before performing its task, this function ensures that this instance + * uniquely references its vector data, generating a duplicate if necessary. + */ + void SetSqr() + { + if ( IsUnique() ) + { + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i *= *i; + } + else + { + Data* newData = new Data( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = *i * *i; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the square root of this vector. The result is a new vector of the + * same length where each component is the square root of its counterpart in + * this vector. + */ + GenericVector Sqrt() const + { + GenericVector R( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = R.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = pcl::Sqrt( *i ); + return R; + } + + /*! + * Replaces all components of this vector with their square roots. + * + * Before performing its task, this function ensures that this instance + * uniquely references its vector data, generating a duplicate if necessary. + */ + void SetSqrt() + { + if ( IsUnique() ) + { + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + for ( ; i < j; ++i ) + *i = pcl::Sqrt( *i ); + } + else + { + Data* newData = new Data( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = pcl::Sqrt( *i ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the absolute value of this vector. The result is a new vector of + * the same length where each component is the absolute value of its + * counterpart in this vector. + */ + GenericVector Abs() const + { + GenericVector R( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = R.Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = pcl::Abs( *i ); + return R; + } + + /*! + * Replaces all components of this vector with their absolute values. + * + * Before performing its task, this function ensures that this instance + * uniquely references its vector data, generating a duplicate if necessary. + */ + void SetAbs() + { + if ( IsUnique() ) + { + iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + PCL_IVDEP + for ( ; i < j; ++i ) + *i = pcl::Abs( *i ); + } + else + { + Data* newData = new Data( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = pcl::Abs( *i ); + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the norm of this vector. For any real p > 0, the norm N of a + * vector v is given by: + * + * N = sum( abs( x )^p )^(1/p) + * + * for all vector components x of v. + * + * \sa L1Norm(), L2Norm() + */ + scalar Norm( double p ) const noexcept + { + return pcl::Norm( m_data->Begin(), m_data->End(), p ); + } + + /*! + * Returns the L1 norm (or Manhattan norm) of this vector. The L1 norm is + * the sum of the absolute values of all vector components. + */ + scalar L1Norm() const noexcept + { + return pcl::L1Norm( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the L2 norm (or Euclidean norm) of this vector. The L2 norm is + * the square root of the sum of squared vector components. + */ + scalar L2Norm() const noexcept + { + return pcl::L2Norm( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the L2 norm (or Euclidean norm) of this vector. This function is + * a synonym for L2Norm(). + */ + scalar Norm() const noexcept + { + return L2Norm(); + } + + /*! + * Returns a unit vector with the same direction as this vector. A unit + * vector has a norm (or magnitude) of 1. + */ + GenericVector Unit() const + { + GenericVector R( *this ); + scalar N = L2Norm(); + if ( scalar( 1 ) + N > scalar( 1 ) ) + R /= N; + return R; + } + + /*! + * Transforms this vector to a unit vector with the same direction. A unit + * vector has a norm (or magnitude) of 1. + */ + void SetUnit() + { + scalar N = L2Norm(); + if ( scalar( 1 ) + N > scalar( 1 ) ) + (void)operator /=( N ); + } + + /*! + * Sorts the components of this vector in ascending order. + */ + void Sort() + { + EnsureUnique(); + pcl::Sort( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns a sorted copy of this vector. + */ + GenericVector Sorted() const + { + GenericVector R( *this ); + R.Sort(); + return R; + } + + /*! + * Sorts the components of this vector in reverse (descending) order. + */ + void ReverseSort() + { + EnsureUnique(); + pcl::Sort( m_data->Begin(), m_data->End(), + []( const scalar& a, const scalar& b ){ return b < a; } ); + } + + /*! + * Returns a reverse sorted copy of this vector. + */ + GenericVector ReverseSorted() const + { + GenericVector R( *this ); + R.ReverseSort(); + return R; + } + + /*! + * Sorts the components of this vector in ascending order. Ordering of + * vector components is defined such that for any pair a, b of vector + * components, the specified binary predicate p( a, b ) is true if a + * precedes b. + */ + template + void Sort( BP p ) + { + EnsureUnique(); + pcl::Sort( m_data->Begin(), m_data->End(), p ); + } + + /*! + * Returns a sorted copy of this vector, where ordering of vector components + * is defined by the specified binary predicate \a p. See Sort( BP p ). + */ + template + GenericVector Sorted( BP p ) const + { + GenericVector R( *this ); + R.Sort( p ); + return R; + } + + /*! + * Returns the index of the first vector element with the specified value + * \a x, or -1 if this vector does not contain such value. + */ + int Find( const component& x ) const noexcept + { + const_iterator p = pcl::LinearSearch( m_data->Begin(), m_data->End(), x ); + return (p != m_data->End()) ? int( p - m_data->Begin() ) : -1; + } + + /*! + * Returns the index of the first vector element with the specified value + * \a x, or -1 if this vector does not contain such value. + * This function is an alias to Find(). + */ + int FindFirst( const component& x ) const noexcept + { + return Find( x ); + } + + /*! + * Returns the index of the last vector element with the specified value + * \a x, or -1 if this vector does not contain such value. + */ + int FindLast( const component& x ) const noexcept + { + const_iterator p = pcl::LinearSearchLast( m_data->Begin(), m_data->End(), x ); + return (p != m_data->End()) ? int( p - m_data->Begin() ) : -1; + } + + /*! + * Returns true iff this vector contains the specified value \a x. + */ + bool Contains( const component& x ) const noexcept + { + return pcl::LinearSearch( m_data->Begin(), m_data->End(), x ) != m_data->End(); + } + +#ifndef __PCL_NO_VECTOR_STATISTICS + + /*! + * Returns the index of the smallest vector component. + * + * For empty vectors, this function returns zero. For vectors where the + * smallest component occurs more than once, this function returns the index + * of the first occurrence. + */ + int IndexOfSmallestComponent() const noexcept + { + return int( pcl::MinItem( m_data->Begin(), m_data->End() ) - m_data->Begin() ); + } + + /*! + * Returns the index of the largest vector component. + * + * For empty vectors, this function returns zero. For vectors where the + * largest component occurs more than once, this function returns the index + * of the first occurrence. + */ + int IndexOfLargestComponent() const noexcept + { + return int( pcl::MaxItem( m_data->Begin(), m_data->End() ) - m_data->Begin() ); + } + + /*! + * Returns the index of the last occurrence of the smallest vector + * component. + * + * For empty vectors, this function returns zero. For vectors where the + * smallest component occurs more than once, this function returns the index + * of the last occurrence. + */ + int IndexOfLastSmallestComponent() const noexcept + { + iterator i = m_data->Begin(); + if ( m_data->Length() > 0 ) + for ( iterator j = m_data->Begin(); ++j < m_data->End(); ) + if ( *j <= *i ) + i = j; + return i - m_data->Begin(); + } + + /*! + * Returns the index of the last occurrence of the largest vector + * component. + * + * For empty vectors, this function returns zero. For vectors where the + * largest component occurs more than once, this function returns the index + * of the last occurrence. + */ + int IndexOfLastLargestComponent() const noexcept + { + iterator i = m_data->Begin(); + if ( m_data->Length() > 0 ) + for ( iterator j = m_data->Begin(); ++j < m_data->End(); ) + if ( *i <= *j ) + i = j; + return i - m_data->Begin(); + } + + /*! + * Returns the index of the smallest nonzero vector component. + * + * For empty vectors, this function returns zero. For vectors where the + * smallest nonzero component occurs more than once, this function returns + * the index of the first occurrence. + */ + int IndexOfSmallestNonzeroComponent() const noexcept + { + iterator i = m_data->Begin(); + if ( m_data->Length() > 0 ) + for ( iterator j = m_data->Begin(); ++j < m_data->End(); ) + if ( *j != component( 0 ) ) + if ( *j < *i ) + i = j; + return i - m_data->Begin(); + } + + /*! + * Returns the index of the last occurrence of the smallest nonzero vector + * component. + * + * For empty vectors, this function returns zero. For vectors where the + * smallest nonzero component occurs more than once, this function returns + * the index of the last occurrence. + */ + int IndexOfLastSmallestNonzeroComponent() const noexcept + { + iterator i = m_data->Begin(); + if ( m_data->Length() > 0 ) + for ( iterator j = m_data->Begin(); ++j < m_data->End(); ) + if ( *j != component( 0 ) ) + if ( *j <= *i ) + i = j; + return i - m_data->Begin(); + } + + /*! + * Returns the value of the smallest vector component. + * For empty vectors, this function returns zero conventionally. + */ + component MinComponent() const noexcept + { + if ( m_data->Length() > 0 ) + return *pcl::MinItem( m_data->Begin(), m_data->End() ); + return component( 0 ); + } + + /*! + * Returns the value of the largest vector component. + * For empty vectors, this function returns zero conventionally. + */ + component MaxComponent() const noexcept + { + if ( m_data->Length() > 0 ) + return *pcl::MaxItem( m_data->Begin(), m_data->End() ); + return component( 0 ); + } + + /*! + * Returns the \a kth order statistic of the sample in this vector. + * + * Before selecting the specified vector component, this function ensures + * that this instance uniquely references its vector data, generating a + * duplicate if necessary. + * + * The specified index \a k must be valid, that is, it must be in the range + * [0,Length()-1]. If a value of \a k outside the valid range is specified, + * or equivalently, if this function is called for an empty vector, this + * member function will invoke undefined behavior. + * + * \note This function uses a \e destructive selection algorithm: it alters + * the order in the sequence of vector components. For a nondestructive + * version, see the const version of this member function. + */ + component OrderStatistic( int k ) + { + PCL_PRECONDITION( !IsEmpty() ) + PCL_PRECONDITION( k >= 0 && k < m_data->Length() ) + EnsureUnique(); + return *pcl::Select( m_data->Begin(), m_data->End(), k ); + } + + /*! + * Returns the \a kth order statistic of the sample in this vector, without + * modifying this instance. + * + * The specified index \a k must be valid, that is, it must be in the range + * [0,Length()-1]. If a value of \a k outside the valid range is specified, + * or equivalently, if this function is called for an empty vector, this + * member function will invoke undefined behavior. + * + * This is a \e nondestructive selection routine that doesn't modify the + * order of existing vector components. To achieve that goal, this routine + * simply generates a temporary working vector as a copy of this object, + * then calls its OrderStatistic() member function to obtain the function's + * return value. + */ + component OrderStatistic( int k ) const + { + return GenericVector( *this ).OrderStatistic( k ); + } + + /*! + * Returns the sum of vector components. + * For empty vectors, this function returns zero. + */ + double Sum() const noexcept + { + return pcl::Sum( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the sum of vector components using a numerically stable + * summation algorithm to minimize roundoff error. + * + * For empty vectors, this function returns zero. + */ + double StableSum() const noexcept + { + return pcl::StableSum( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the sum of the absolute values of all vector components. + * For empty vectors, this function returns zero. + */ + double Modulus() const noexcept + { + return pcl::Modulus( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the sum of the absolute values of all vector components using a + * numerically stable summation algorithm to minimize roundoff error. + * + * For empty vectors, this function returns zero. + */ + double StableModulus() const noexcept + { + return pcl::StableModulus( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the sum of the squares of all vector components. + * For empty vectors, this function returns zero. + */ + double SumOfSquares() const noexcept + { + return pcl::SumOfSquares( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the sum of the squares of all vector components using a + * numerically stable summation algorithm to minimize roundoff error. + * + * For empty vectors, this function returns zero. + */ + double StableSumOfSquares() const noexcept + { + return pcl::StableSumOfSquares( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the mean of the values in this vector. + * For empty vectors, this function returns zero. + */ + double Mean() const + { + return pcl::Mean( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the mean of the values in this vector using a numerically stable + * summation algorithm to minimize roundoff error. + * + * For empty vectors, this function returns zero. + */ + double StableMean() const noexcept + { + return pcl::StableMean( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the two-sided, asymmetric trimmed mean of the values in this + * vector. See pcl::TrimmedMean() for a complete description of the + * implemented algorithm with information on function parameters. + * + * For empty vectors, this function returns zero. + */ + double TrimmedMean( distance_type l = 1, distance_type h = 1 ) const noexcept + { + return pcl::TrimmedMean( m_data->Begin(), m_data->End(), l, h ); + } + + /*! + * Computes the two-sided, asymmetric trimmed mean of the squared values in + * this vector. See pcl::TrimmedMeanOfSquares() for a complete description + * of the implemented algorithm with information on function parameters. + * + * For empty vectors, this function returns zero. + */ + double TrimmedMeanOfSquares( distance_type l = 1, distance_type h = 1 ) const noexcept + { + return pcl::TrimmedMeanOfSquares( m_data->Begin(), m_data->End(), l, h ); + } + + /*! + * Returns the variance from the mean for the values in this vector. + * + * For vectors with less than two components, this function returns zero. + */ + double Variance() const noexcept + { + return pcl::Variance( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the standard deviation from the mean for the values in this + * vector. + * + * For vectors with less than two components, this function returns zero. + */ + double StdDev() const noexcept + { + return pcl::StdDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the median of the values in this vector. + * + * For vectors of length < 2, this function returns zero conventionally. + */ + double Median() const + { + return pcl::Median( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the average absolute deviation with respect to the specified + * \a center value. + * + * When the median of the vector elements is used as the center value, this + * function returns the average absolute deviation from the median, which is + * a well-known estimator of dispersion. + * + * For vectors with less than two components, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double AvgDev( double center ) const noexcept + { + return pcl::AvgDev( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Computes the average absolute deviation with respect to the specified + * \a center value, using a numerically stable summation algorithm to + * minimize roundoff error. + * + * When the median of the vector elements is used as the center value, this + * function returns the average absolute deviation from the median, which is + * a well-known estimator of dispersion. + * + * For vectors with less than two components, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double StableAvgDev( double center ) const noexcept + { + return pcl::StableAvgDev( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the average absolute deviation from the median. + * + * The mean absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For vectors with less than two components, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double AvgDev() const + { + return pcl::AvgDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Computes the average absolute deviation from the median using a + * numerically stable summation algorithm to minimize roundoff error. + * + * The mean absolute deviation from the median is a well-known estimator of + * dispersion. + * + * For vectors with less than two components, this function returns zero. + * + * \note To make the average absolute deviation about the median consistent + * with the standard deviation of a normal distribution, it must be + * multiplied by the constant 1.2533. + */ + double StableAvgDev() const + { + return pcl::StableAvgDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the two-sided average absolute deviation with respect to the + * specified \a center value. + * + * See AvgDev( double ) for more information. + */ + TwoSidedEstimate TwoSidedAvgDev( double center ) const noexcept + { + return pcl::TwoSidedAvgDev( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the two-sided average absolute deviation from the median. + * + * See AvgDev() for more information. + */ + TwoSidedEstimate TwoSidedAvgDev() const + { + return pcl::TwoSidedAvgDev( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the median absolute deviation (MAD) with respect to the specified + * \a center value. + * + * The MAD is a well-known robust estimator of scale. + * + * For vectors with less than two components, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, it must be multiplied by the constant 1.4826. + */ + double MAD( double center ) const + { + return pcl::MAD( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the median absolute deviation from the median (MAD). + * + * The MAD is a well-known robust estimator of scale. + * + * For vectors with less than two components, this function returns zero. + * + * \note To make the MAD estimator consistent with the standard deviation of + * a normal distribution, it must be multiplied by the constant 1.4826. + */ + double MAD() const + { + return pcl::MAD( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the two-sided median absolute deviation (MAD) with respect to the + * specified \a center value. + * + * See MAD( double ) for more information. + */ + TwoSidedEstimate TwoSidedMAD( double center ) const + { + return pcl::TwoSidedMAD( m_data->Begin(), m_data->End(), center ); + } + + /*! + * Returns the two-sided median absolute deviation from the median (MAD). + * + * See MAD() for more information. + */ + TwoSidedEstimate TwoSidedMAD() const + { + return pcl::TwoSidedMAD( m_data->Begin(), m_data->End() ); + } + + /*! + * Returns the biweight midvariance (BWMV). + * + * \param center Reference center value. Normally, the median of the vector + * components should be used. + * + * \param sigma A reference estimate of dispersion. Normally, the median + * absolute deviation from the median (MAD) of the vector + * components should be used. + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param reducedLength If true, reduce the sample size to exclude + * rejected vector components. This tends to approximate the + * true dispersion of the data more accurately for relatively + * small samples, or samples with large amounts of outliers. + * Note that this departs from the standard definition of + * biweight midvariance, where the total number of data items + * is used to scale the variance estimate. If false, use the + * full vector length, including rejected components, which + * gives a standard biweight midvariance estimate. + * + * The square root of the biweight midvariance is a robust estimator of + * scale. It is an efficient estimator with respect to many statistical + * distributions (about 87% Gaussian efficiency), and appears to have a + * breakdown point close to 0.5 (the same as MAD). + * + * For vectors with less than two components, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.1. + */ + double BiweightMidvariance( double center, double sigma, int k = 9, bool reducedLength = false ) const noexcept + { + return pcl::BiweightMidvariance( m_data->Begin(), m_data->End(), center, sigma, k, reducedLength ); + } + + /*! + * Returns the biweight midvariance (BWMV) with respect to the median and + * the median absolute deviation from the median (MAD). + * + * \param k Rejection limit in sigma units. The default value is k=9. + * + * \param reducedLength If true, reduce the sample size to exclude + * rejected vector components. This tends to approximate the + * true dispersion of the data more accurately for relatively + * small samples, or samples with large amounts of outliers. + * Note that this departs from the standard definition of + * biweight midvariance, where the total number of data items + * is used to scale the variance estimate. If false, use the + * full vector length, including rejected components, which + * gives a standard biweight midvariance estimate. + * + * The square root of the biweight midvariance is a robust estimator of + * scale. It is an efficient estimator with respect to many statistical + * distributions (about 87% Gaussian efficiency), and appears to have a + * breakdown point close to 0.5 (the same as MAD). + * + * For vectors with less than two components, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.1. + */ + double BiweightMidvariance( int k = 9, bool reducedLength = false ) const + { + double center = Median(); + return BiweightMidvariance( center, MAD( center ), k, reducedLength ); + } + + /*! + * Returns the two-sided biweight midvariance (BWMV). + * + * \param center Reference center value. Normally, the median of the vector + * components should be used. + * + * \param sigma A two-sided reference estimate of dispersion. Normally, + * the two-sided median absolute deviation from the median + * (MAD) of the vector components should be used. See the + * TwoSidedMAD() member function. + * + * See BiweightMidvariance( double, double, int, bool ) for more information + * on the rest of parameters and references. + */ + TwoSidedEstimate TwoSidedBiweightMidvariance( double center, const TwoSidedEstimate& sigma, + int k = 9, bool reducedLength = false ) const noexcept + { + return pcl::TwoSidedBiweightMidvariance( m_data->Begin(), m_data->End(), center, sigma, k, reducedLength ); + } + + /*! + * Returns the two-sided biweight midvariance (BWMV) with respect to the + * median and the two-sided median absolute deviation from the median (MAD). + * + * See BiweightMidvariance( int, bool ) for more information and references. + */ + TwoSidedEstimate TwoSidedBiweightMidvariance( int k = 9, bool reducedLength = false ) const + { + double center = Median(); + return TwoSidedBiweightMidvariance( center, TwoSidedMAD( center ), k, reducedLength ); + } + + /*! + * Returns a percentage bend midvariance (PBMV). + * + * \param center Reference center value. Normally, the median of the vector + * components should be used. + * + * \param beta Rejection parameter in the [0,0.5] range. Higher values + * improve robustness to outliers (i.e., increase the + * breakdown point of the estimator) at the expense of a + * lower efficiency. The default value is beta=0.2. + * + * The square root of the percentage bend midvariance is a robust estimator + * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With + * beta=0.1, its efficiency is 85% but its breakdown is only 0.1. + * + * For vectors with less than two components, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.3. + */ + double BendMidvariance( double center, double beta = 0.2 ) const + { + return pcl::BendMidvariance( m_data->Begin(), m_data->End(), center, beta ); + } + + /*! + * Returns a percentage bend midvariance (PBMV) with respect to the median. + * + * \param beta Rejection parameter in the [0,0.5] range. Higher values + * improve robustness to outliers (i.e., increase the + * breakdown point of the estimator) at the expense of a + * lower efficiency. The default value is beta=0.2. + * + * The square root of the percentage bend midvariance is a robust estimator + * of scale. With the default beta=0.2, its Gaussian efficiency is 67%. With + * beta=0.1, its efficiency is 85% but its breakdown is only 0.1. + * + * For vectors with less than two components, this function returns zero. + * + * \b References + * + * Rand R. Wilcox (2017), Introduction to Robust Estimation and + * Hypothesis Testing, 4th Edition, Elsevier Inc., Section 3.12.3. + */ + double BendMidvariance( double beta = 0.2 ) const + { + return pcl::BendMidvariance( m_data->Begin(), m_data->End(), Median(), beta ); + } + + /*! + * Returns the Sn scale estimator of Rousseeuw and Croux: + * + *

+    * Sn = c * low_median( high_median( |x_i - x_j| ) )
+    * 
+ * + * where low_median() is the order statistic of rank (n + 1)/2, and + * high_median() is the order statistic of rank n/2 + 1. + * + * For vectors with less than two components, this function returns zero. + * + * The constant c = 1.1926 must be used to make the Sn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for + * consistency with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median + * Absolute Deviation, Journal of the American Statistical Association, + * Vol. 88, pp. 1273-1283. + */ + double Sn() const + { + GenericVector v( *this ); + return pcl::Sn( v.Begin(), v.End() ); + } + + /*! + * Returns the Qn scale estimator of Rousseeuw and Croux: + * + *
+    * Qn = c * first_quartile( |x_i - x_j| : i < j )
+    * 
+ * + * where first_quartile() is the order statistic of rank (n + 1)/4. + * + * For vectors with less than two components, this function returns zero. + * + * The constant c = 2.2219 must be used to make the Qn estimator converge to + * the standard deviation of a pure normal distribution. However, this + * implementation does not apply it (it uses c=1 implicitly), for consistency + * with other implementations of scale estimators. + * + * \b References + * + * P.J. Rousseeuw and C. Croux (1993), Alternatives to the Median + * Absolute Deviation, Journal of the American Statistical Association, + * Vol. 88, pp. 1273-1283. + */ + double Qn() const + { + GenericVector v( *this ); + return pcl::Qn( v.Begin(), v.End() ); + } + +#endif // !__PCL_NO_VECTOR_STATISTICS + + /*! + * Returns a 64-bit non-cryptographic hash value computed for this vector. + * + * This function calls pcl::Hash64() for the internal vector data. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint64 Hash64( uint64 seed = 0 ) const noexcept + { + return pcl::Hash64( m_data->Begin(), m_data->Size(), seed ); + } + + /*! + * Returns a 32-bit non-cryptographic hash value computed for this vector. + * + * This function calls pcl::Hash32() for the internal vector data. + * + * The \a seed parameter can be used to generate repeatable hash values. It + * can also be set to a random value in compromised environments. + */ + uint32 Hash32( uint32 seed = 0 ) const noexcept + { + return pcl::Hash32( m_data->Begin(), m_data->Size(), seed ); + } + + /*! + * Returns a non-cryptographic hash value computed for this vector. This + * function is a synonym for Hash64(). + */ + uint64 Hash( uint64 seed = 0 ) const noexcept + { + return Hash64( seed ); + } + + /*! + * Returns true iff this instance uniquely references its vector data. + */ + bool IsUnique() const noexcept + { + return m_data->IsUnique(); + } + + /*! + * Returns true iff this instance references (shares) the same vector data as + * another instance \a x. + */ + bool IsAliasOf( const GenericVector& x ) const noexcept + { + return m_data == x.m_data; + } + + /*! + * Ensures that this instance uniquely references its vector data. + * + * If necessary, this member function generates a duplicate of the vector + * data, references it, and then decrements the reference counter of the + * original vector data. + */ + void EnsureUnique() + { + if ( !IsUnique() ) + { + Data* newData = new Data( m_data->Length() ); + const_iterator __restrict__ i = m_data->Begin(); + const_iterator __restrict__ j = m_data->End(); + iterator __restrict__ k = newData->Begin(); + PCL_IVDEP + for ( ; i < j; ++i, ++k ) + *k = *i; + DetachFromData(); + m_data = newData; + } + } + + /*! + * Returns the number of components in this vector. If this object is an + * empty vector, this member function returns zero. + */ + int Length() const noexcept + { + return m_data->Length(); + } + + /*! + * Returns the total number of bytes required to store the data contained in + * this vector. + */ + size_type Size() const noexcept + { + return m_data->Size(); + } + + /*! + * Returns true only if this vector is valid. A vector is valid if it + * references an internal vector structure, even if it is an empty vector. + * + * In general, all %GenericVector objects are valid with only two + * exceptions: + * + * \li Objects that have been move-copied or move-assigned to other vectors. + * \li Objects that have been invalidated explicitly by calling Transfer(). + * + * An invalid vector object cannot be used and should be destroyed + * immediately. Invalid vectors are always destroyed automatically during + * move construction and move assignment operations. + */ + bool IsValid() const noexcept + { + return m_data != nullptr; + } + + /*! + * Returns true iff this is an empty vector. An empty vector has no + * components, and hence its length is zero. + */ + bool IsEmpty() const noexcept + { + return Length() == 0; + } + + /*! + * Returns true iff this vector is not empty. This operator is equivalent to: + * + * \code !IsEmpty(); \endcode + */ + operator bool() const noexcept + { + return !IsEmpty(); + } + + /*! + * Equality operator. Returns true if this vector is equal to another vector + * \a x. Two vectors are equal if both have the same length and identical + * component values. + */ + bool operator ==( const GenericVector& x ) const noexcept + { + return IsAliasOf( x ) || SameLength( x ) && pcl::Equal( Begin(), x.Begin(), x.End() ); + } + + /*! + * Less than relational operator. Returns true if this vector is less than + * another vector \a x. + * + * In this operator, vector comparisons are performed component-wise, + * irrespective of vector lengths, until either two vector components differ + * or until the end of one of the vectors is reached. In the latter case, + * the shortest vector is the lesser one. + */ + bool operator <( const GenericVector& x ) const noexcept + { + return !IsAliasOf( x ) && pcl::Compare( Begin(), End(), x.Begin(), x.End() ) < 0; + } + + /*! + * Returns true iff this vector has the same length as other vector \a x. + */ + bool SameLength( const GenericVector& x ) const noexcept + { + return Length() == x.Length(); + } + + /*! + * Returns a mutable vector iterator pointing to the \a i-th component of + * this vector. + * + * Before returning, this function ensures that this instance uniquely + * references its vector data. + */ + iterator At( int i ) + { + EnsureUnique(); + return m_data->At( i ); + } + + /*! + * Returns an immutable vector iterator pointing to the \a i-th component of + * this vector. + */ + const_iterator At( int i ) const noexcept + { + return m_data->At( i ); + } + + /*! + * Returns a mutable vector iterator pointing to the first vector component, + * i.e. to the component at index 0 of this vector. + * + * All vector components are guaranteed to be stored at consecutive + * locations addressable from the iterator returned by this function. + * + * Before returning, this function ensures that this instance uniquely + * references its vector data. + */ + iterator Begin() + { + EnsureUnique(); + return m_data->Begin(); + } + + /*! + * Returns an immutable vector iterator pointing to the first vector + * component, i.e. to the component at index 0 of this vector. + * + * All vector components are guaranteed to be stored at consecutive + * locations addressable from the iterator returned by this function. + */ + const_iterator Begin() const noexcept + { + return m_data->Begin(); + } + + /*! + * A synonym for Begin() const. + */ + const_iterator ConstBegin() const noexcept + { + return Begin(); + } + + /*! + * Returns a mutable vector iterator pointing to the first vector component, + * i.e. to the component at index 0 of this vector. + * + * This member function is a convenience alias to Begin(). + */ + iterator operator *() + { + return Begin(); + } + + /*! + * Returns an immutable vector iterator pointing to the first vector + * component, i.e. to the component at index 0 of this vector. + * + * This member function is a convenience alias to Begin() const. + */ + const_iterator operator *() const noexcept + { + return Begin(); + } + + /*! + * Returns a mutable iterator past the last vector component, i.e. a + * pointer to a (nonexistent) component located at index=Length(). + * + * All vector components are guaranteed to be stored in reverse order at + * consecutive locations addressable from the iterator returned by this + * function. + * + * Before returning, this function ensures that this instance uniquely + * references its vector data. + */ + iterator End() + { + EnsureUnique(); + return m_data->End(); + } + + /*! + * Returns an immutable iterator past the last vector component, i.e. a + * pointer to a (nonexistent) component located at index=Length(). + * + * All vector components are guaranteed to be stored in reverse order at + * consecutive locations addressable from the iterator returned by this + * function. + */ + const_iterator End() const noexcept + { + return m_data->End(); + } + + /*! + * A synonym for End() const. + */ + const_iterator ConstEnd() const noexcept + { + return End(); + } + + /*! + * Returns a reference to the mutable vector component at the specified + * index \a i. Vector indices are relative to zero. + * + * Before returning, this function ensures that this instance uniquely + * references its vector data. + */ + component& operator []( int i ) + { + return *At( i ); + } + + /*! + * Returns a reference to the immutable vector component at the specified + * index \a i. Vector indices are relative to zero. + */ + const component& operator []( int i ) const noexcept + { + return *At( i ); + } + + /*! + * Returns a pointer to the first component in this vector. + * + * The returned pointer can be used as a common C array, where all vector + * components are guaranteed to be stored consecutively starting from the + * pointer returned by this function. + * + * This member function does nothing to ensure that this instance uniquely + * references its vector data. Consequently, the caller must take into + * account that all modifications made to vector components accessed through + * the value returned by this function will apply to all instances sharing + * the same vector data. + * + * This function can be used to perform fast operations on vector components + * avoiding the overhead caused by deep copies of vector data, when such + * copies are not necessary. Typically this happens when two or more threads + * work simultaneously on non-overlapping regions of the same vector. + */ + iterator DataPtr() noexcept + { + return m_data->v; + } + + /*! + * Returns a pointer to the \a ith component in this vector. + * + * All vector components are guaranteed to be stored at consecutive + * locations addressable from the iterator returned by this function. + * + * This member function does not ensure that the data referenced by this + * vector is unique. See DataPtr() for more information on how to use this + * member function. + */ + iterator ComponentPtr( int i ) noexcept + { + return m_data->At( i ); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const noexcept + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + iterator end() + { + return End(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const noexcept + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Computes spherical coordinates from this three-component vector. + * + * \param[out] lon Reference to a variable where the computed longitude + * in radians, in the range [-pi,+pi], will be stored. If + * the vector points to one pole, that is, if *lat is + * either -pi/2 or +pi/2, the computed longitude will be + * zero. + * + * \param[out] lat Reference to a variable where the computed latitude + * in radians, in the range [-pi/2,+pi/2], will be stored. + * + * This function requires a vector with at least three coordinates. For + * performance reasons, the vector length is not verified. + * + * The returned coordinates lie on a sphere of unit radius, that is, only + * the direction of the input vector is taken into account, never its + * magnitude. + * + * \sa ToSpherical2Pi(), FromSpherical() + */ + template + void ToSpherical( T1& lon, T2& lat ) const noexcept + { + PCL_PRECONDITION( Length() >= 3 ) + double x = *At( 0 ); + double y = *At( 1 ); + double z = *At( 2 ); + double m2 = x*x + y*y; + lon = T1( (m2 == 0) ? 0.0 : ArcTan( y, x ) ); + lat = T2( (z == 0) ? 0.0 : ArcTan( z, pcl::Sqrt( m2 ) ) ); + } + + /*! + * Computes spherical coordinates from this three-component vector. + * + * This function is identical to ToSpherical(), but the output longitude + * component is normalized to the range [0,2pi) in radians. + * + * \sa ToSpherical(), FromSpherical() + */ + template + void ToSpherical2Pi( T1& lon, T2& lat ) const noexcept + { + ToSpherical( lon, lat ); + if ( lon < 0 ) + lon += TwoPi(); + } + + /*! + * Returns a three-component vector with rectangular coordinates computed + * from spherical coordinates, given by their sines and cosines + * + * \param slon Sine of the longitude. + * \param clon Cosine of the longitude. + * \param slat Sine of the latitude. + * \param clat Cosine of the latitude. + * + * The returned vector contains the direction cosines for the + * specified position on the sphere. It is a unit vector (unit magnitude) + * pointing from the center of the sphere to the specified location. + * + * \sa ToSpherical(), ToSpherical2Pi() + */ + static GenericVector FromSpherical( double slon, double clon, double slat, double clat ) + { + return GenericVector( clon*clat, slon*clat, slat ); + } + + /*! + * Returns a three-component vector with rectangular coordinates computed + * from the specified spherical coordinates. + * + * \param lon Longitude in radians. + * \param lat Latitude in radians. + * + * The returned vector contains the direction cosines for the + * specified position on the sphere. It is a unit vector (unit magnitude) + * pointing from the center of the sphere to the specified location. + * + * \sa ToSpherical() + */ + template + static GenericVector FromSpherical( const T1& lon, const T2& lat ) + { + double slon, clon, slat, clat; + SinCos( double( lon ), slon, clon ); + SinCos( double( lat ), slat, clat ); + return FromSpherical( slon, clon, slat, clat ); + } + + /*! + * Returns the angle between this vector and another vector \a v, with both + * vectors being defined in two-dimensional space. + * + * The returned value is the angle between both vectors in radians, in the + * range [-pi,+pi]. + * + * \note This member function is only defined for vectors of two components. + * For performance reasons, this condition is not verified; if it doesn't + * hold, this function will invoke undefined behavior. + */ + double Angle2D( const GenericVector& v ) const noexcept + { + /* + * https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors + * https://stackoverflow.com/questions/243945/calculating-a-2d-vectors-cross-product + */ + component x1 = *At( 0 ); + component y1 = *At( 1 ); + component x2 = v[0]; + component y2 = v[1]; + return ArcTan( x1*y2 - y1*x2, Dot( v ) ); + } + + /*! + * Returns the angle between this vector and another vector \a v, with both + * vectors being defined in three-dimensional space. + * + * The returned value is the angle between both vectors in radians, in the + * range [0,pi]. + * + * \note This member function is only defined for vectors of three + * components. For performance reasons, this condition is not verified; if + * it doesn't hold, this function will invoke undefined behavior. + */ + double Angle3D( const GenericVector& v ) const noexcept + { + /* + * https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors + */ + return ArcTan( Cross( v ).L2Norm(), Dot( v ) ); + } + + /*! + * Returns the angle between this vector and another vector \a v, being both + * vectors defined in three-dimensional space, with sign determined by the + * direction of an additional 3D vector \a n. + * + * The returned value is the angle between both vectors in radians, in the + * range [-pi,+pi]. The angle is positive if this vector is clockwise with + * respect to the direction of \a n, negative otherwise. + * + * \note This member function is only defined for vectors of three + * components. For performance reasons, this condition is not verified; if + * it doesn't hold, this function will invoke undefined behavior. + */ + double Angle3D( const GenericVector& v, const GenericVector& n ) const + { + /* + * https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors + */ + GenericVector c = Cross( v ); + return ArcTan( (((n * c) >= 0) ? 1 : -1) * c.L2Norm(), Dot( v ) ); + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string. Returns a reference to the target string \a s. + * + * For each vector component, this function appends a string representation + * (known as a \e token) to the target string \a s. If the vector has more + * than one component, successive tokens are separated with the specified + * \a separator. + * + * The string type S must have a meaningful %Append() member function and + * type conversion semantics to transform a vector component to a string. + * The standard String and IsoString PCL classes provide the required + * functionality for most scalar types, although it is probably better to + * use String::ToSeparated() and IsoString::ToSeparated() instead of calling + * these functions directly. + */ + template + S& ToSeparated( S& s, SP separator ) const + { + const_iterator i = m_data->Begin(), j = m_data->End(); + if ( i < j ) + { + s.Append( S( *i ) ); + if ( ++i < j ) + do + { + s.Append( separator ); + s.Append( S( *i ) ); + } + while ( ++i < j ); + } + return s; + } + + /*! + * Generates a sequence of string tokens separated with the specified + * \a separator string by calling an \a append function. Returns a reference + * to the target string \a s. + * + * For each vector component x, this function appends a string + * representation (known as a \e token) to the target string \a s by calling + * the \a append function: + * + *\code append( s, S( x ) ); \endcode + * + * If the vector has more than one component, successive tokens are + * separated by calling: + * + * \code append( s, S( separator ) ); \endcode + * + * The string type S must have type conversion semantics to transform a + * vector component to a string. The standard String and IsoString PCL + * classes provide the required functionality for most scalar types, + * although it is probably better to use String::ToSeparated() and + * IsoString::ToSeparated() instead of calling these functions directly. + */ + template + S& ToSeparated( S& s, SP separator, AF append ) const + { + const_iterator i = m_data->Begin(), j = m_data->End(); + if ( i < j ) + { + append( s, S( *i ) ); + if ( ++i < j ) + { + S p( separator ); + do + { + append( s, p ); + append( s, S( *i ) ); + } + while ( ++i < j ); + } + } + return s; + } + + /*! + * Generates a comma-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ',' ); \endcode + */ + template + S& ToCommaSeparated( S& s ) const + { + return ToSeparated( s, ',' ); + } + + /*! + * Generates a space-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, ' ' ); \endcode + */ + template + S& ToSpaceSeparated( S& s ) const + { + return ToSeparated( s, ' ' ); + } + + /*! + * Generates a tabulator-separated sequence of string tokens. Returns a + * reference to the target string \a s. + * + * This function is equivalent to: + * + * \code ToSeparated( s, '\t' ); \endcode + */ + template + S& ToTabSeparated( S& s ) const + { + return ToSeparated( s, '\t' ); + } + +private: + + /*! + * \struct Data + * \internal + * Reference-counted vector data structure. + */ + struct Data : public ReferenceCounter + { + int n = 0; //!< The vector length + component* v = nullptr; //!< The vector components + + Data() = default; + + Data( int len ) + { + if ( len > 0 ) + Allocate( len ); + } + + ~Data() + { + Deallocate(); + } + + int Length() const noexcept + { + return n; + } + + size_type Size() const noexcept + { + return size_type( n )*sizeof( component ); + } + + iterator At( int i ) const noexcept + { + return v + i; + } + + iterator Begin() const noexcept + { +// if ( likely( std::is_scalar::value ) ) +// return reinterpret_cast( PCL_ASSUME_ALIGNED_32( v ) ); + return v; + } + + iterator End() const noexcept + { + return At( n ); + } + + void Allocate( int len ) + { + n = len; + if ( likely( std::is_scalar::value ) ) + { + v = reinterpret_cast( PCL_ALIGNED_MALLOC( Size(), 32 ) ); + if ( unlikely( v == nullptr ) ) + { + n = 0; + throw std::bad_alloc(); + } + } + else + v = new component[ len ]; + } + + void Deallocate() + { + PCL_PRECONDITION( refCount == 0 ) + if ( likely( std::is_scalar::value ) ) + PCL_ALIGNED_FREE( v ); + else + delete [] v; + v = nullptr; + n = 0; + } + }; + + /*! + * \internal + * The reference-counted vector data. + */ + Data* m_data = nullptr; + + /*! + * \internal + * Dereferences vector data and disposes it if it becomes garbage. + */ + void DetachFromData() + { + if ( !m_data->Detach() ) + delete m_data; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup vector_operators Vector Operators + * + * This section includes scalar-to-vector and vector-to-vector arithmetic + * operator functions that are not members of the GenericVector template class. + */ + +/*! + * Returns the sum of two vectors \a A and \a B. + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( const GenericVector& A, const GenericVector& B ) +{ + int n = A.Length(); + if ( B.Length() < n ) + throw Error( "Invalid vector addition." ); + GenericVector R( n ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + if ( likely( !A.IsAliasOf( B ) ) ) + { + typename GenericVector::const_iterator __restrict__ b = B.Begin(); + PCL_IVDEP + for ( ; a < c; ++a, ++b, ++r ) + *r = *a + *b; + } + else + { + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a + *a; + } + return R; +} + +/*! + * Returns the sum of two vectors \a A (rvalue reference) and \a B. + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( GenericVector&& A, const GenericVector& B ) +{ + A += B; + return std::move( A ); +} + +/*! + * Returns the sum of two vectors \a A and \a B (rvalue reference). + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( const GenericVector& A, GenericVector&& B ) +{ + B += A; + return std::move( B ); +} + +/*! + * Returns the sum of two vectors \a A (rvalue reference) and \a B (rvalue + * reference). + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( GenericVector&& A, GenericVector&& B ) +{ + A += B; + return std::move( A ); +} + +/*! + * Returns the sum of a vector \a A and a scalar \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( const GenericVector& A, const S& x ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a + x; + return R; +} + +/*! + * Returns the sum of a vector \a A (rvalue reference) and a scalar \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( GenericVector&& A, const S& x ) +{ + A += typename GenericVector::scalar( x ); + return std::move( A ); +} + +/*! + * Returns the sum of a scalar \a x and a vector \a A. + * + * This function exists to implement the commutative property of + * scalar-to-vector addition; it is equivalent to A + x. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( const S& x, const GenericVector& A ) +{ + return A + x; +} + +/*! + * Returns the sum of a scalar \a x and a vector \a A (rvalue reference). + * + * This function exists to implement the commutative property of + * scalar-to-vector addition; it is equivalent to A + x. + * \ingroup vector_operators + */ +template inline +GenericVector operator +( const S& x, GenericVector&& A ) +{ + A += typename GenericVector::scalar( x ); + return std::move( A ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the result of subtracting a vector \a B from another vector \a A. + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator -( const GenericVector& A, const GenericVector& B ) +{ + int n = A.Length(); + if ( B.Length() < n ) + throw Error( "Invalid vector subtraction." ); + + GenericVector R( n ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + if ( likely( !A.IsAliasOf( B ) ) ) + { + typename GenericVector::const_iterator __restrict__ b = B.Begin(); + PCL_IVDEP + for ( ; a < c; ++a, ++b, ++r ) + *r = *a - *b; + } + else + { + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a - *a; + } + return R; +} + +/*! + * Returns the result of subtracting a vector \a B from another vector \a A + * (rvalue reference). + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator -( GenericVector&& A, const GenericVector& B ) +{ + A -= B; + return std::move( A ); +} + +/*! + * Returns the result of subtracting a vector \a B (rvalue reference) from + * another vector \a A. + * + * If the specified vectors are incompatible for vector addition (because \a A + * has less components than \a B), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator -( const GenericVector& A, GenericVector&& B ) +{ + if ( A.Length() < B.Length() ) + throw Error( "Invalid vector subtraction." ); + + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::iterator __restrict__ b = B.Begin(); + typename GenericVector::const_iterator __restrict__ c = B.End(); + PCL_IVDEP + for ( ; b < c; ++a, ++b ) + *b = *a - *b; + return std::move( B ); +} + +/*! + * Returns the result of subtracting a vector \a B (rvalue reference) from + * another vector \a A (rvalue reference). + * + * If the specified vectors are incompatible for vector addition (because \a B + * has less components than \a A), this function throws an Error exception. + * \ingroup vector_operators + */ +template inline +GenericVector operator -( GenericVector&& A, GenericVector&& B ) +{ + A -= B; + return std::move( A ); +} + +/*! + * Returns the subtraction of a scalar \a x from a vector \a A. + * \ingroup vector_operators + */ +template inline +GenericVector operator -( const GenericVector& A, const S& x ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a - x; + return R; +} + +/*! + * Returns the subtraction of a scalar \a x from a vector \a A (rvalue + * reference). + * \ingroup vector_operators + */ +template inline +GenericVector operator -( GenericVector&& A, const S& x ) +{ + A -= typename GenericVector::scalar( x ); + return std::move( A ); +} + +/*! + * Returns the subtraction of a vector \a A from a scalar \a x. + * + * This function exists because scalar-to-vector subtraction is not a + * commutative operation. A - x is not equal to x - A (the resulting vector + * components have the same magnitudes but opposite signs). + * \ingroup vector_operators + */ +template inline +GenericVector operator -( const S& x, const GenericVector& A ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = x - *a; + return R; +} + +/*! + * Returns the subtraction of a vector \a A (rvalue reference) from a scalar + * \a x. + * + * This function exists because scalar-to-vector subtraction is not a + * commutative operation. A - x is not equal to x - A (the resulting vector + * components have the same magnitudes but opposite signs). + * \ingroup vector_operators + */ +template inline +GenericVector operator -( const S& x, GenericVector&& A ) +{ + typename GenericVector::iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a ) + *a = x - *a; + return std::move( A ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the cross product of two vectors \a A and \a B. + * + * \note The cross product is only defined for vectors of three components. For + * performance reasons, this function does not check vector lengths. For + * vectors of length < 3, this function will invoke undefined behavior. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( const GenericVector& A, const GenericVector& B ) +{ + PCL_PRECONDITION( A.Length() == 3 && B.Length() == 3 ) + return GenericVector( A[1]*B[2] - A[2]*B[1], + A[2]*B[0] - A[0]*B[2], + A[0]*B[1] - A[1]*B[0] ); +} + +/*! + * Returns the cross product of two vectors \a A (rvalue reference) and \a B. + * + * \note The cross product is only defined for vectors of three components. For + * performance reasons, this function does not check vector lengths. For + * vectors of length < 3, this function will invoke undefined behavior. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( GenericVector&& A, const GenericVector& B ) +{ + T x = A[1]*B[2] - A[2]*B[1], + y = A[2]*B[0] - A[0]*B[2], + z = A[0]*B[1] - A[1]*B[0]; + typename GenericVector::iterator a = A.Begin(); + a[0] = x; a[1] = y; a[2] = z; + return std::move( A ); +} + +/*! + * Returns the cross product of two vectors \a A and \a B (rvalue reference). + * + * \note The cross product is only defined for vectors of three components. For + * performance reasons, this function does not check vector lengths. For + * vectors of length < 3, this function will invoke undefined behavior. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( const GenericVector& A, GenericVector&& B ) +{ + T x = A[1]*B[2] - A[2]*B[1], + y = A[2]*B[0] - A[0]*B[2], + z = A[0]*B[1] - A[1]*B[0]; + typename GenericVector::iterator b = B.Begin(); + b[0] = x; b[1] = y; b[2] = z; + return std::move( B ); +} + +/*! + * Returns the cross product of two vectors \a A (rvalue reference) and \a B + * (rvalue reference). + * + * \note The cross product is only defined for vectors of three components. For + * performance reasons, this function does not check vector lengths. For + * vectors of length < 3, this function will invoke undefined behavior. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( GenericVector&& A, GenericVector&& B ) +{ + T x = A[1]*B[2] - A[2]*B[1], + y = A[2]*B[0] - A[0]*B[2], + z = A[0]*B[1] - A[1]*B[0]; + typename GenericVector::iterator a = A.Begin(); + a[0] = x; a[1] = y; a[2] = z; + return std::move( A ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the dot product of two vectors \a A and \a B. + * + * \note For performance reasons, this function does not check whether the + * specified vectors have compatible lengths; in case \a B has less components + * than \a A, this function will invoke undefined behavior. + * \ingroup vector_operators + */ +template inline +T operator *( const GenericVector& A, const GenericVector& B ) noexcept +{ + PCL_PRECONDITION( B.Length() >= A.Length() ) + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + T r = T( 0 ); + if ( likely( !A.IsAliasOf( B ) ) ) + { + typename GenericVector::const_iterator __restrict__ b = B.Begin(); + PCL_IVDEP + for ( ; a < c; ++a, ++b ) + r += *a * *b; + } + else + { + PCL_IVDEP + for ( ; a < c; ++a ) + r += *a * *a; + } + return r; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the product of a vector \a A by a scalar \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator *( const GenericVector& A, const S& x ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a * x; + return R; +} + +/*! + * Returns the product of a vector \a A (rvalue reference) by a scalar \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator *( GenericVector&& A, const S& x ) +{ + A *= typename GenericVector::scalar( x ); + return std::move( A ); +} + +/*! + * Returns the product of a scalar \a x and a vector \a A. + * + * This function exists to implement the commutative property of + * scalar-to-vector multiplication. It is equivalent to A * x. + * \ingroup vector_operators + */ +template inline +GenericVector operator *( const S& x, const GenericVector& A ) +{ + return A * x; +} + +/*! + * Returns the product of a scalar \a x and a vector \a A (rvalue reference). + * + * This function exists to implement the commutative property of + * scalar-to-vector multiplication. It is equivalent to A * x. + * \ingroup vector_operators + */ +template inline +GenericVector operator *( const S& x, GenericVector&& A ) +{ + A *= typename GenericVector::scalar( x ); + return std::move( A ); +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the result of dividing a vector \a A by a scalar \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator /( const GenericVector& A, const S& x ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a / x; + return R; +} + +/*! + * Returns the result of dividing a vector \a A (rvalue reference) by a scalar + * \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator /( GenericVector&& A, const S& x ) +{ + A /= typename GenericVector::scalar( x ); + return std::move( A ); +} + +/*! + * Returns the result of dividing a scalar \a x by a vector \a A. + * + * This function exists because scalar-to-vector division is not a + * commutative operation. A/x is not equal to x/A. + * \ingroup vector_operators + */ +template inline +GenericVector operator /( const S& x, const GenericVector& A ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = x / *a; + return R; +} + +/*! + * Returns the result of dividing a scalar \a x by a vector \a A (rvalue + * reference). + * + * This function exists because scalar-to-vector division is not a + * commutative operation. A/x is not equal to x/A. + * \ingroup vector_operators + */ +template inline +GenericVector operator /( const S& x, GenericVector&& A ) +{ + typename GenericVector::iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a ) + *a = x / *a; + return std::move( A ); +} + +/*! + * Returns the result of the element wise division of a vector \a A by another + * vector \a B. + * \ingroup vector_operators + */ +template inline +GenericVector operator /( const GenericVector& A, const GenericVector& B ) +{ + int n = A.Length(); + if ( B.Length() < n ) + throw Error( "Invalid vector division." ); + + GenericVector R( n ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + if ( likely( !A.IsAliasOf( B ) ) ) + { + typename GenericVector::const_iterator __restrict__ b = B.Begin(); + PCL_IVDEP + for ( ; a < c; ++a, ++b, ++r ) + *r = *a / *b; + } + else + { + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = *a / *a; + } + return R; +} + +/*! + * Returns the result of the element-wise division of an r-value reference to a + * vector \a A by a vector \a B. + * \ingroup vector_operators + */ +template inline +GenericVector operator /( GenericVector&& A, const GenericVector& B ) +{ + return A /= B; +} + +// ---------------------------------------------------------------------------- + +/*! + * Returns the result of raising a vector \a A to a scalar \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( const GenericVector& A, const S& x ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = pcl::Pow( *a, x ); + return R; +} + +/*! + * Returns the result of raising a vector \a A (rvalue reference) to a scalar + * \a x. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( GenericVector&& A, const S& x ) +{ + A ^= typename GenericVector::scalar( x ); + return std::move( A ); +} + +/*! + * Returns the result of raising a scalar \a x to a vector \a A. + * + * This function exists because scalar-to-vector exponentiation is not a + * commutative operation. A^x is not equal to x^A. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( const S& x, const GenericVector& A ) +{ + GenericVector R( A.Length() ); + typename GenericVector::iterator __restrict__ r = R.Begin(); + typename GenericVector::const_iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a, ++r ) + *r = pcl::Pow( x, *a ); + return R; +} + +/*! + * Returns the result of raising a scalar \a x to a vector \a A (rvalue + * reference). + * + * This function exists because scalar-to-vector exponentiation is not a + * commutative operation. A^x is not equal to x^A. + * \ingroup vector_operators + */ +template inline +GenericVector operator ^( const S& x, GenericVector&& A ) +{ + typename GenericVector::iterator __restrict__ a = A.Begin(); + typename GenericVector::const_iterator __restrict__ c = A.End(); + PCL_IVDEP + for ( ; a < c; ++a ) + *a = pcl::Pow( x, *a ); + return std::move( A ); +} + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_NO_VECTOR_INSTANTIATE + +/*! + * \defgroup vector_types Vector Types + */ + +/*! + * \class pcl::I8Vector + * \ingroup vector_types + * \brief 8-bit signed integer vector. + * + * %I8Vector is a template instantiation of GenericVector for \c int8. + */ +typedef GenericVector I8Vector; + +/*! + * \class pcl::CharVector + * \ingroup vector_types + * \brief 8-bit signed integer vector. + * + * %CharVector is an alias for I8Vector. It is a template instantiation of + * GenericVector for \c int8. + */ +typedef I8Vector CharVector; + +/*! + * \class pcl::UI8Vector + * \ingroup vector_types + * \brief 8-bit unsigned integer vector. + * + * %UI8Vector is a template instantiation of GenericVector for \c uint8. + */ +typedef GenericVector UI8Vector; + +/*! + * \class pcl::ByteVector + * \ingroup vector_types + * \brief 8-bit unsigned integer vector. + * + * %ByteVector is an alias for UI8Vector. It is a template instantiation of + * GenericVector for \c uint8. + */ +typedef UI8Vector ByteVector; + +/*! + * \class pcl::I16Vector + * \ingroup vector_types + * \brief 16-bit signed integer vector. + * + * %I16Vector is a template instantiation of GenericVector for \c int16. + */ +typedef GenericVector I16Vector; + +/*! + * \class pcl::UI16Vector + * \ingroup vector_types + * \brief 16-bit unsigned integer vector. + * + * %UI16Vector is a template instantiation of GenericVector for \c uint16. + */ +typedef GenericVector UI16Vector; + +/*! + * \class pcl::I32Vector + * \ingroup vector_types + * \brief 32-bit signed integer vector. + * + * %I32Vector is a template instantiation of GenericVector for \c int32. + */ +typedef GenericVector I32Vector; + +/*! + * \class pcl::IVector + * \ingroup vector_types + * \brief 32-bit signed integer vector. + * + * %IVector is an alias for I32Vector. It is a template instantiation of + * GenericVector for \c int32. + */ +typedef I32Vector IVector; + +/*! + * \class pcl::UI32Vector + * \ingroup vector_types + * \brief 32-bit unsigned integer vector. + * + * %UI32Vector is a template instantiation of GenericVector for \c uint32. + */ +typedef GenericVector UI32Vector; + +/*! + * \class pcl::UIVector + * \ingroup vector_types + * \brief 32-bit unsigned integer vector. + * + * %UIVector is an alias for UI32Vector. It is a template instantiation of + * GenericVector for \c uint32. + */ +typedef UI32Vector UIVector; + +/*! + * \class pcl::I64Vector + * \ingroup vector_types + * \brief 64-bit integer vector. + * + * %I64Vector is a template instantiation of GenericVector for \c int64. + */ +typedef GenericVector I64Vector; + +/*! + * \class pcl::UI64Vector + * \ingroup vector_types + * \brief 64-bit unsigned integer vector. + * + * %UI64Vector is a template instantiation of GenericVector for \c uint64. + */ +typedef GenericVector UI64Vector; + +/*! + * \class pcl::SzVector + * \ingroup vector_types + * \brief size_type integer vector. + * + * %SzVector is a template instantiation of GenericVector for \c size_type. + */ +typedef GenericVector SzVector; + +/*! + * \class pcl::F32Vector + * \ingroup vector_types + * \brief 32-bit floating point real vector. + * + * %F32Vector is a template instantiation of GenericVector for \c float. + */ +typedef GenericVector F32Vector; + +/*! + * \class pcl::FVector + * \ingroup vector_types + * \brief 32-bit floating point real vector. + * + * %FVector is an alias for F32Vector. It is a template instantiation of + * GenericVector for \c float. + */ +typedef F32Vector FVector; + +/*! + * \class pcl::F64Vector + * \ingroup vector_types + * \brief 64-bit floating point real vector. + * + * %F64Vector is a template instantiation of GenericVector for \c double. + */ +typedef GenericVector F64Vector; + +/*! + * \class pcl::DVector + * \ingroup vector_types + * \brief 64-bit floating point real vector. + * + * %DVector is an alias for F64Vector. It is a template instantiation of + * GenericVector for \c double. + */ +typedef F64Vector DVector; + +/*! + * \class pcl::Vector + * \ingroup vector_types + * \brief 64-bit floating point real vector. + * + * %Vector is an alias for DVector. It is a template instantiation of + * GenericVector for \c double. + */ +typedef DVector Vector; + +/*! + * \class pcl::C32Vector + * \ingroup vector_types + * \brief 32-bit floating point complex vector. + * + * %C32Vector is a template instantiation of GenericVector for \c Complex32. + */ +typedef GenericVector C32Vector; + +/*! + * \class pcl::C64Vector + * \ingroup vector_types + * \brief 64-bit floating point complex vector. + * + * %C64Vector is a template instantiation of GenericVector for \c Complex64. + */ +typedef GenericVector C64Vector; + +#ifndef _MSC_VER + +/*! + * \class pcl::F80Vector + * \ingroup vector_types + * \brief 80-bit extended precision floating point real vector. + * + * %F80Vector is a template instantiation of GenericVector for \c long + * \c double. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef GenericVector F80Vector; + +/*! + * \class pcl::LDVector + * \ingroup vector_types + * \brief 80-bit extended precision floating point real vector. + * + * %LDVector is an alias for F80Vector. It is a template instantiation of + * GenericVector for \c long \c double. + * + * \note This template instantiation is not available on Windows with Visual + * C++ compilers. + */ +typedef F80Vector LDVector; + +#endif // !_MSC_VER + +#endif // !__PCL_NO_VECTOR_INSTANTIATE + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Vector_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Vector.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Version.h b/3rdparty/include/pcl/Version.h new file mode 100644 index 0000000..11f415a --- /dev/null +++ b/3rdparty/include/pcl/Version.h @@ -0,0 +1,295 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Version.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_Version_h +#define __PCL_Version_h + +/// \file pcl/Version.h + +#include +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Version + * \brief Provides PCL version numbers. + * + * The %Version class reads PCL version data stored in static read-only + * variables. It provides version information for the PCL libraries that have + * been linked to the current module. + */ +class PCL_CLASS Version +{ +public: + + /*! + * Default constructor. This constructor is disabled because %Version is not + * an instantiable class. + */ + Version() = delete; + + /*! + * Copy constructor. This constructor is disabled because %Version is not an + * instantiable class. + */ + Version( const Version& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %Version is not an + * instantiable class. + */ + Version& operator =( const Version& ) = delete; + + /*! + * Destructor. This destructor is disabled because %Version is not an + * instantiable class. + */ + ~Version() = delete; + + /*! + * Returns the current PCL major version number. + */ + static int Major(); + + /*! + * Returns the current PCL minor version number. + */ + static int Minor(); + + /*! + * Returns the current PCL release version number. + */ + static int Release(); + + /*! + * Returns the current PCL build number. + * + * \note Since core version 1.8.7 build numbers have been deprecated. They + * are maintained exclusively for compatibility with previous versions and + * existing code. + */ + static int Build(); + + /*! + * Returns the beta version number of PCL, or zero if the current PCL + * framework is a release (non-beta) version. + */ + static int BetaRelease(); + + /*! + * Returns an ISO 639.2 language code that identifies the primary language + * of the current PCL framework. + */ + static String LanguageCode(); // ISO 639.2 language code + + /*! + * Returns an integer that corresponds to the full PCL version. + * + * The returned value is equal to: + * + * \code Major()*1000000 + Minor()*1000 + Release(); \endcode + */ + static int Number() + { + return Major()*1000000 + Minor()*1000 + Release(); + } + + /*! + * Returns a human-readable representation of the current PCL version. + */ + static String AsString(); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class PixInsightVersion + * \brief Provides version information for the PixInsight core application. + * + * The %PixInsightVersion class retrieves version data from the PixInsight core + * application where the current module has been installed. + */ +class PCL_CLASS PixInsightVersion +{ +public: + + /*! + * Default constructor. This constructor is disabled because + * %PixInsightVersion is not an instantiable class. + */ + PixInsightVersion() = delete; + + /*! + * Copy constructor. This constructor is disabled because %PixInsightVersion + * is not an instantiable class. + */ + PixInsightVersion( const PixInsightVersion& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %PixInsightVersion is + * not an instantiable class. + */ + PixInsightVersion& operator =( const PixInsightVersion& ) = delete; + + /*! + * Destructor. This destructor is disabled because %PixInsightVersion is not + * an instantiable class. + */ + ~PixInsightVersion() = delete; + + /*! + * Returns the major version number of the PixInsight core application. + */ + static int Major(); + + /*! + * Returns the minor version number of the PixInsight core application. + */ + static int Minor(); + + /*! + * Returns the release version number of the PixInsight core application. + */ + static int Release(); + + /*! + * Returns the revision version number of the PixInsight core application. + */ + static int Revision(); + + /*! + * Returns the build number of the PixInsight core application. + * + * \deprecated Since core version 1.8.7 build numbers have been deprecated. + * They are maintained exclusively for compatibility with previous versions + * and existing code. + */ + static int Build(); + + /*! + * Returns the beta or release candidate version number of the PixInsight + * core application: + * + * \li Returns zero for a release version. + * \li Returns a positive nonzero integer for a beta version. + * \li Returns a negative integer for a release candidate (RC) version. + */ + static int BetaRelease(); + + /*! + * Returns true iff the PixInsight core is a confidential (pre-release) + * edition. + */ + static bool Confidential(); + + /*! + * Returns true iff the PixInsight core is a limited edition (LE) release. + */ + static bool LE(); + + /*! + * Returns an ISO 639.2 language code that identifies the primary language + * of the PixInsight core application. + */ + static String LanguageCode(); + + /*! + * Returns the codename for the current PixInsight core application version. + * Starting from version 1.7, each major PixInsight version is given a + * codename that uniquely identifies it. + * + * Codename history: + * + * PixInsight 1.7 Starbuck \n + * PixInsight 1.8 Ripley + */ + static String Codename(); + + /*! + * Returns an integer that corresponds to the full PixInsight core version. + * + * The returned value is equal to: + * + * \code Major()*1000000 + Minor()*1000 + Release(); \endcode + */ + static int Number() + { + return Major()*1000000 + Minor()*1000 + Release(); + } + + /*! + * Returns a human-readable textual representation of the current PixInsight + * core version. + * + * \param withCodename If this parameter is true, the returned version + * string will include the codename of the running + * PixInsight core application. The default value of + * this parameter is false. + */ + static String AsString( bool withCodename = false ); + + friend class GlobalContextDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Version_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Version.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/View.h b/3rdparty/include/pcl/View.h new file mode 100644 index 0000000..36d48fa --- /dev/null +++ b/3rdparty/include/pcl/View.h @@ -0,0 +1,1121 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/View.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_View_h +#define __PCL_View_h + +/// \file pcl/View.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS ImageWindow; + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup view_properties Module-Defined View Properties + */ + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::ViewPropertyAttribute + * \brief Attributes of view properties. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ViewPropertyAttribute::WriteProtectedOnly the module that has created the property can modify it (e.g., + * change its value, or delete it).
ViewPropertyAttribute::ReadProtectedOnly the module that has created the property can read its value. + * Implies write protection, even if the WriteProtected attribute has + * not been set explicitly.
ViewPropertyAttribute::VolatileVolatile properties are not stored in processing histories and get + * lost across undo/redo operations.
ViewPropertyAttribute::PermanentPermanent properties are not stored in processing histories, but + * unlike volatile properties, they are preserved across undo/redo + * operations. A permanent property is not deleted automatically when + * the current process terminates. Permanent properties are mostly + * useful to store metadata that does not depend on pixel values, such + * as astrometric solutions, or image acquisition conditions and similar + * ancillary data.
ViewPropertyAttribute::NotSerializableThe property will not be stored in projects.
ViewPropertyAttribute::StorableThe property can be stored in XISF files.
ViewPropertyAttribute::ReservedThe property has been reserved by the PixInsight core application. It + * can only be generated by calling the View::ComputeProperty() member + * function. This attribute cannot be set explicitly by a modue.
ViewPropertyAttribute::ProtectedThe property will not be deleted after completing execution of the + * current process, even if the Permanent attribute is not set. This + * special flag will be removed automatically after process execution. + * A protected property represents ancillary data that depends on pixel + * values and has been generated by the process that has just finished + * its execution.
ViewPropertyAttribute::NoChangeThis is a special flag used to preserve the existing property + * attributes. Normally it is intended for internal PCL use.
+ * + * \ingroup view_properties + */ +namespace ViewPropertyAttribute +{ + enum mask_type + { + WriteProtected = 0x00000001, + ReadProtected = 0x00000002, + Volatile = 0x00000010, + Permanent = 0x00000020, + NotSerializable = 0x00000040, + Storable = 0x00000080, + Reserved = 0x10000000, + Protected = 0x20000000, + NoChange = 0x80000000 + }; +} + +/*! + * A combination of ViewPropertyAttribute flags. + * \ingroup view_properties + */ +typedef Flags ViewPropertyAttributes; + +// ---------------------------------------------------------------------------- + +/*! + * \class View + * \brief High-level interface to a PixInsight view object. + * + * Instances of %View are managed aliases of actual view objects in the + * PixInsight core application. Views are the main image holders in the + * PixInsight platform. + * + * Views can be main views or \e previews. A main view holds the + * entire image of an image window. A preview is a volatile subimage defined on + * an image window. In all respects, both types of views can be manipulated + * transparently with the abstract interface provided by the %View class. + * The View::IsPreview() and View::IsMainView() members inform you about the + * particular type of a given %View object. + * + * Each view has a unique identifier, which you can get and set through the + * View::Id(), View::FullId(), and View::Rename() member functions. + * + * View::Image() gives you full access to the image in a view as an + * ImageVariant object. + * + * Each view in PixInsight holds a set of histograms and statistical data as + * shared resources that can be accessed by all installed processes and + * interfaces. The View::CalculateHistograms() and View::CalculateStatistics() + * families of member functions give full access to these shared resources. + * + * In a similar way, each view maintains a set of histogram transformations + * used as screen transfer functions (STF). A STF is applied to modify + * the screen representation of an image, without altering actual image data. + * The View::GetScreenTransferFunctions() / View::SetScreenTransferFunctions() + * family of functions allow you to acquire and modify the STF of any view. + * + * The View::Lock() / View::Unlock() family of functions allow you to write + * thread-safe processing routines in current and future PixInsight + * multithreaded environments. + * + * Finally, the static functions View::ViewById(), View::AllViews() and + * View::AllPreviews() provide for global searching and listing of existing + * view objects. + * + * \sa ImageWindow + */ +class PCL_CLASS View : public UIObject +{ +public: + + /*! + * A container of HistogramTransformation instances used to represent the + * managed Screen Transfer Functions (STF) of a view object in the core + * PixInsight application. + */ + typedef Array stf_list; + + /*! + * Constructs a null view. A null view does not correspond to an existing + * view in the PixInsight core application. + */ + View() = default; + + /*! + * Constructs a %View instance as an alias of an existing %View object. + * + * \note It cannot be overemphasized that this constructor does not + * create a new view. It only creates an \e alias object for an + * existing view in the calling module. In all respects, the alias + * and aliased objects are completely interchangeable; they behave exactly + * in the same way because both refer to the same server-side object. + */ + View( const View& v ) : UIObject( v ) + { + } + + /*! + * Destroys this %View object. + * + * Note that this destructor does not destroy the actual view object, which + * is part of the PixInsight core application. Only the managed alias object + * living in the user-defined module is destroyed. + */ + virtual ~View() + { + } + + /*! + * Returns a reference to a null %View instance. A null %View does not + * correspond to an existing view in the PixInsight core application. + */ + static View& Null(); + + /*! + * Returns true iff this is a main view. A main view holds the entire image + * in an image window. + */ + bool IsMainView() const; + + /*! + * Returns true iff this view corresponds to a preview object. A preview is + * a volatile subimage defined in an image window. + */ + bool IsPreview() const; + + /*! + * Returns true iff this view is a preview and is in volatile state. A + * volatile preview contains a temporary image that can be undone/redone + * with the Preview > Undo and Preview > Redo core + * application commands. + */ + bool IsVolatilePreview() const; + + /*! + * Returns true iff this view is a preview and has one or more stored states. + * When a preview has been stored, it behaves as an independent image with + * its own processing history. A stored preview does not rely on its mother + * image to return to a 'base' state. + */ + bool IsStoredPreview() const; + + /*! + * Returns a managed alias for the image window this view pertains to. + */ + ImageWindow Window() const; + + /*! + * Returns the identifier of this view. + * + * %View identifiers are unique within their naming context. Identifiers of + * main views are unique in the global context, since each main view holds + * an image in the core application. The identifier of a preview is unique + * in the context of its parent image window. + */ + IsoString Id() const; + + /*! + * Returns the full identifier of this view. + * + * If this is a main view, this function returns its identifier, which is + * the same string returned by the Id() member function. + * + * If this view corresponds to a preview, this function returns a unique + * identifier of the form: + * + * \-\>\ + * + * where \ is the identifier of the preview's parent image, and + * \ is the identifier of the preview. The "->" sequence is the + * scope resolution operator, used to specify pertenence of a + * preview to its parent image in the PixInsight environment. + */ + IsoString FullId() const; + + /*! + * Changes the identifier of this view to \a newId. + * + * If \a newId is not unique in the naming context of this view, a unique + * identifier is obtained automatically by appending a suffix string to the + * specified \a newId string. + * + * After calling this function, a ImageRenamed() notification message will + * be sent to all process interfaces. + */ + void Rename( const IsoString& newId ); + + void Rename( const IsoString::ustring_base& newId ) + { + Rename( IsoString( newId ) ); + } + + /*! + * Returns true iff this view is not locked for reading. + */ + bool CanRead() const; + + /*! + * Returns true iff this view is not locked for writing. + */ + bool CanWrite() const; + + /*! + * Locks this view for read and write operations. + * + * Processes usually call this function to make sure that a target view's + * image cannot be modified by another thread while they are processing it. + * This is necessary because PixInsight is a multithreaded environment. If a + * process modifies an image without locking it, other processing threads + * could try to read or write the same pixels concurrently, with + * unpredictable results. + * + * If the view is not currently locked by other processing thread, this + * function locks it and returns immediately. If the view is already + * locked, this function waits until it becomes unlocked by other threads. + * + * If the \a notify argument is false, this function will not send + * ViewLocked() notifications to process interfaces. + * + * \warning Always make sure that you unlock a view that you have previously + * locked. If your processing routines leave views locked incorrectly, + * they'll cause serious problems. A locked view is inaccessible to other + * processes, and even the user may be unable to recover locked image data. + */ + void Lock( bool notify = true ) const; + + /*! + * Unlocks this view for read and write operations. + * + * Please read the \e important information given for the Lock() function + * member. + * + * You shouldn't call this function if your routines have not called the + * Lock() function before. In other words, call Unlock() just once for each + * previous call lo Lock(). + * + * \warning Be aware that \e just after this function returns, your + * processing routine \e must \e not try to modify this view or its + * associated image, since other thread might have locked it. If you need + * to gain exclusive read/write rights over this view, call Lock() again. + */ + void Unlock( bool notify = true ) const; + + /*! + * Locks this view for write operations only. + * + * Call this function if you need to make sure that a view's image will not + * be modified by other threads, but your processing routines will not + * modify it. + * + * For example, if your routines need reading this view's image as source + * data for your processing tasks, but not writing to it, you should call + * this function instead of Lock(). In this way you allow other processes + * (including the core application's GUI) to access this view and its image + * for read-only operations. This improves efficiency and useability of the + * whole PixInsight environment. + */ + void LockForWrite( bool notify = true ) const; + + /* + * Unlocks this view for write operations only. + * ### Undocumented (i.e., harmful) function. + */ + void UnlockForWrite( bool notify = true ) const; + + /*! + * Temporarily unlocks a view for reading. + * + * If your code has successfully called Lock() for this view, then its + * screen rendition cannot be updated, because the core application will + * never try to read pixel data from a view that is read-locked. This can be + * a problem if, for example, you need to refresh this view's screen + * rendition to provide feedback to the user at a given stage of your + * processing. + * + * The solution for such situations is calling this function to temporarily + * permit read-only accesses to this view and its image. When you no longer + * want to allow read-only operations for this view, call RelockForRead() + * and continue your processing work. + * + * Your code may call Unlock() safely after this function; you should not + * call RelockForRead() if your processing task has finished, or if this + * view is no longer needed for it. + * + * \warning Do not use this function if your code has not called Lock() + * previously. + */ + void UnlockForRead( bool notify = true ) const; + + /*! + * Relocks a view for reading (after UnlockForRead()). + * + * Call this function after UnlockForRead(), if necessary. Please read the + * information given for that function. + */ + void RelockForRead( bool notify = true ) const; + + /*! + * Returns true iff this view has been selected as a target of an active + * dynamic interface. + */ + bool IsDynamicTarget() const; + + /*! + * Adds this view to the list of targets of the current active dynamic + * interface. + * + * Dynamic interfaces call this function for views that get involved in + * active dynamic procedures. For example, the DynamicCrop interface calls + * this function when you select a view by defining an initial cropping + * rectangle with the mouse. + * + * Any images selected as dynamic targets cannot be closed or modified in + * any way while an active dynamic interface depends on them. + * + * If you implement a dynamic interface, always call this function for a + * view if your dynamic interface depends on it. Failing to do so will lead + * to unstable and incoherent behavior of the core application's GUI. + * + * \warning Once your dynamic interface ceases depending on this view, call + * the RemoveFromDynamicTargets() function for it. + */ + void AddToDynamicTargets(); + + /*! + * Removes this view from the list of targets of the current active + * dynamic interface. + * + * Call this function when your dynamic interface no longer depends on this + * view. Please read the important information given for + * AddToDynamicTargets(). + */ + void RemoveFromDynamicTargets(); + + /*! + * Returns an ImageVariant instance that transports the image in this view. + * + * The returned ImageVariant object transports a shared image. A + * shared image is a managed alias for an actual image living in the core + * PixInsight application. This is because a view is also a managed object. + * + * With this function you gain access to the image in a view, which is + * crucial to perform any kind of processing in the PixInsight/PCL + * framework. + * + * Before calling this function, however, you must make sure that your + * processing thread has the appropriate access rights to the view, since + * PixInsight is a multithreaded environment. This is done by calling the + * Lock() member function of %View. + */ + ImageVariant Image() const; + + /*! + * Returns an ImageVariant instance that transports the image in this view. + * + * \deprecated Use View::Image() in newly produced code. + */ + ImageVariant GetImage() const + { + return this->Image(); + } + + /*! + * Returns true iff this view holds a color image, false if it is a + * grayscale image. + */ + bool IsColor() const; + + /*! + * Copies the width and height in pixels of the image in this view to the + * specified variables. + */ + void GetSize( int& width, int& height ) const; + + /*! + * Returns the width in pixels of the image in this view. + */ + int Width() const + { + int w, dum; GetSize( w, dum ); return w; + } + + /*! + * Returns the height in pixels of the image in this view. + */ + int Height() const + { + int dum, h; GetSize( dum, h ); return h; + } + + /*! + * Returns the bounding rectangle of the image in this view. The upper left + * corner of the returned rectangle (x0, y0) is always (0,0). The lower + * right corner coordinates (x1, y1) correspond to the width and height of + * the image. + */ + Rect Bounds() const + { + int w, h; GetSize( w, h ); return Rect( w, h ); + } + + /*! + * Retrieves the set of screen transfer functions (STF) for this view in the + * specified container. + * + * The STF container is a dynamic array. Each array element is a + * HistogramTransformation object corresponding to the STF for an image + * channel or color component: + * + * %Array element #0 = Red/gray channels \n + * %Array element #1 = Green channel \n + * %Array element #2 = Blue channel \n + * %Array element #3 = Lightness/brightness/luminance components + */ + void GetScreenTransferFunctions( stf_list& ) const; + + /*! + * Sets the screen transfer functions (STF) for this view. + * + * The specified container is a dynamic array. Each array element is a + * HistogramTransformation object corresponding to the STF for an image + * channel or color component: + * + * %Array element #0 = Red/gray channels \n + * %Array element #1 = Green channel \n + * %Array element #2 = Blue channel \n + * %Array element #3 = Lightness/brightness/luminance components + */ + void SetScreenTransferFunctions( const stf_list&, bool notify = true ); + + /*! + * Destroys the screen transfer functions (STF) for this view. + */ + void DestroyScreenTransferFunctions( bool notify = true ); + + /*! + * Returns true iff screen transfer functions (STF) are enabled for this + * view. If STFs are disabled, they are not used for screen renditions. + */ + bool AreScreenTransferFunctionsEnabled() const; + + /*! + * Enables or disables screen transfer functions (STF) for this view. If + * STFs are enabled, each non-identity STF is used to modify screen + * renditions of the corresponding image channel. + */ + void EnableScreenTransferFunctions( bool = true, bool notify = true ); + + /*! + * Disables or enables screen transfer functions (STF) for this view. If + * STFs are enabled, each non-identity STF is used to modify screen + * renditions of the corresponding image channel. + */ + void DisableScreenTransferFunctions( bool disable = true, bool notify = true ) + { + EnableScreenTransferFunctions( !disable, notify ); + } + + /*! + * returns true iff the specified string \a id is the identifier of a + * reserved view property. + * + * Reserved view properties are computed and maintained automatically by the + * core application and cannot be modified arbitrarily by modules. + * + * This member function also returns true if the specified identifier starts + * with the string "PixInsight:". Although these identifiers are not + * strictly reserved, the core application defines a number of properties in + * the PixInsight namespace for its internal use. This namespace should not + * be used by modules. + * + * \sa ComputeProperty() + * \ingroup view_properties + */ + static bool IsReservedViewPropertyId( const IsoString& id ); + + /*! + * Returns a description of all data properties associated with this view. + * For each property, the returned array provides information on the unique + * identifier of a property and its data type. + * + * Returns an empty array if there are no properties in this view. + * + * \ingroup view_properties + */ + PropertyDescriptionArray PropertyDescriptions() const; + + /*! + * Returns an array with all readable (for the calling module) properties in + * this view. + * + * \ingroup view_properties + */ + PropertyArray Properties() const; + + /*! + * Returns an array with all readable (for the calling module) and storable + * properties in this view. + * + * Storable properties have the ViewPropertyAttribute::Storable attribute + * set and are intended to be persistent when writting view images to files. + * + * \sa SetStorableProperties() + * \ingroup view_properties + */ + PropertyArray StorableProperties() const; + + /*! + * Returns an array with all readable (for the calling module) and permanent + * properties in this view. + * + * Permanent properties are not stored in processing histories, but unlike + * volatile properties, they are preserved across undo/redo operations. + * + * \sa SetPermanentProperties() + * \ingroup view_properties + */ + PropertyArray PermanentProperties() const; + + /*! + * Returns an array with all readable (for the calling module), storable, + * permanent properties in this view. + * + * Storable properties have the ViewPropertyAttribute::Storable attribute + * set and are intended to be persistent when writting view images to files. + * + * Permanent properties are not stored in processing histories, but unlike + * volatile properties, they are preserved across undo/redo operations. + * + * \sa SetStorablePermanentProperties() + * \ingroup view_properties + */ + PropertyArray StorablePermanentProperties() const; + + /*! + * Sets the values of a set of properties in this view. + * + * \param properties The properties that will be defined. + * + * \param notify Whether to notify the platform on the property changes. + * This is true by default. + * + * \param attributes Optional attribute properties. If not specified, the + * current property attributes will be preserved. If not + * specified and the property is newly created, a default + * set of properties will be applied. + * + * For each item in the \a properties array, if the requested property is + * not a reserved property and does not exist in this view, a new one will + * be created with the specified identifier, value and attributes; see the + * Property class. + * + * If one or more properties exist but the calling module has no write + * access to them (see ViewPropertyAttribute::WriteProtected), an Error + * exception will be thrown. + * + * Reserved properties are simply ignored by this member function without + * raising exceptions. This allows for copying properties between views + * safely with a single-line call such as: + * + * \code view2.SetProperties( view1.Properties() ); \endcode + * + * \ingroup view_properties + */ + void SetProperties( const PropertyArray& properties, bool notify = true, + ViewPropertyAttributes attributes = ViewPropertyAttribute::NoChange ); + + /*! + * Sets the values of a set of storable properties in this view. + * + * Calling this function is equivalent to: + * + * \code + * SetProperties( properties, notify, + * ViewPropertyAttribute::Storable + * | ViewPropertyAttribute::NoChange ) + * \endcode + * + * This function simplifies defining view properties, where the Storable + * attribute is used very often to ensure that properties will be propagated + * to newly created and updated disk files. + * + * \sa StorableProperties() + * \ingroup view_properties + */ + void SetStorableProperties( const PropertyArray& properties, bool notify = true ) + { + SetProperties( properties, notify, + ViewPropertyAttribute::Storable + | ViewPropertyAttribute::NoChange ); + } + + /*! + * Sets the values of a set of storable and permanent properties in this + * view. + * + * Calling this function is equivalent to: + * + * \code + * SetProperties( properties, notify, + * ViewPropertyAttribute::Storable + * | ViewPropertyAttribute::Permanent + * | ViewPropertyAttribute::NoChange ) + * \endcode + * + * This function simplifies defining view properties, where the Storable and + * Permanent attributes are used very often to ensure that properties will + * be propagated to newly created and updated disk files, as well as + * preserved in views across process executions and undo/redo operations. + * + * \sa StorableProperties(), PermanentProperties() + * \ingroup view_properties + */ + void SetStorablePermanentProperties( const PropertyArray& properties, bool notify = true ) + { + SetProperties( properties, notify, + ViewPropertyAttribute::Storable + | ViewPropertyAttribute::Permanent + | ViewPropertyAttribute::NoChange ); + } + + /*! + * Returns the value of the specified \a property in this view. + * + * If the requested property has not been defined for this view, the + * returned Variant object will be invalid (that is, Variant::IsValid() will + * return false). + * + * If the property exists but the calling module has no read access to it + * (see ViewPropertyAttributes::ReadProtected), an Error exception will be + * thrown. + * + * \ingroup view_properties + */ + Variant PropertyValue( const IsoString& property ) const; + + Variant PropertyValue( const IsoString::ustring_base& property ) const + { + return PropertyValue( IsoString( property ) ); + } + + /*! + * Computes a reserved view property and returns its value. + * + * The PixInsight core application reserves a set of view property + * identifiers for standard use by all modules. These special properties + * can only be generated by calling this member function; they cannot be + * created or modified by other means (for example, by calling the + * SetPropertyValue() and SetPropertyAttributes() functions). This includes + * a number of statistical properties that are generated and computed on + * demand in a highly optimized way. + * + * The set of reserved view property identifiers includes at least the + * following list: + * + * Mean, Modulus, SumOfSquares, Median, Variance, StdDev, AvgDev, MAD, BWMV, + * PBMV, Sn, Qn, Minimum, MinimumPos, Maximum, MaximumPos, Histogram16, + * Histogram20. + * + * If the requested property is not recognized as a reserved view property, + * this member function returns an invalid %Variant object. + * + * \sa IsReservedViewPropertyId() + * \ingroup view_properties + */ + Variant ComputeProperty( const IsoString& property, bool notify = true ); + + Variant ComputeProperty( const IsoString::ustring_base& property, bool notify = true ) + { + return ComputeProperty( IsoString( property ), notify ); + } + + /*! + * Returns the value of a reserved view property if it is already available, + * or computes it otherwise and returns its newly calculated value. + * + * This member function is equivalent to the following sequence: + * + * \code + * if ( HasProperty( property ) ) + * return PropertyValue( property ); + * return ComputeProperty( property, notify ); + * \endcode + * + * See ComputeProperty() for information on reserved view properties. + * + * \ingroup view_properties + */ + template + Variant ComputeOrFetchProperty( const S& property, bool notify = true ) + { + IsoString propertyId( property ); + if ( HasProperty( propertyId ) ) + return PropertyValue( propertyId ); + return ComputeProperty( propertyId, notify ); + } + + /*! + * Sets the value and attributes of a property in this view. + * + * \param property Identifier of the view property. + * + * \param value A valid Variant object transporting the new property + * value. + * + * \param notify Whether to notify the platform on the property change. + * This is true by default. + * + * \param attributes Optional attribute properties. If not specified, the + * current property attributes will be preserved. If not + * specified and the property is newly created, a default + * set of properties will be applied. + * + * If the requested property does not exist in this view, a new one will be + * created with the specified identifier, value and attributes. + * + * If the property exists but the calling module has no write access to it + * (see ViewPropertyAttribute::WriteProtected), an Error exception will be + * thrown. + * + * \ingroup view_properties + */ + void SetPropertyValue( const IsoString& property, const Variant& value, bool notify = true, + ViewPropertyAttributes attributes = ViewPropertyAttribute::NoChange ); + + void SetPropertyValue( const IsoString::ustring_base& property, const Variant& value, bool notify = true, + ViewPropertyAttributes attributes = ViewPropertyAttribute::NoChange ) + { + SetPropertyValue( IsoString( property ), value, notify, attributes ); + } + + /*! + * Sets the value of a storable property in this view. + * + * This member function is equivalent to: + * + * \code + * SetPropertyValue( property, value, notify, + * ViewPropertyAttribute::Storable + * | ViewPropertyAttribute::NoChange ); + * \endcode + * + * This function simplifies defining view properties, where the Storable + * attribute is used very often to ensure that properties will be propagated + * to newly created and updated disk files. + * + * \ingroup view_properties + */ + void SetStorablePropertyValue( const IsoString& property, const Variant& value, bool notify = true ) + { + SetPropertyValue( property, value, notify, + ViewPropertyAttribute::Storable + | ViewPropertyAttribute::NoChange ); + } + + void SetStorablePropertyValue( const IsoString::ustring_base& property, const Variant& value, bool notify = true ) + { + SetStorablePropertyValue( IsoString( property ), value, notify ); + } + + /*! + * Sets the value of a storable property in this view. + * + * This member function is equivalent to: + * + * \code + * SetPropertyValue( property, value, notify, + * ViewPropertyAttribute::Storable + * | ViewPropertyAttribute::Permanent + * | ViewPropertyAttribute::NoChange ); + * \endcode + * + * This function simplifies defining view properties, where the Storable and + * Permanent attributes are used very often to ensure that properties will + * be propagated to newly created and updated disk files, as well as + * preserved in views across process executions and undo/redo operations. + * + * \ingroup view_properties + */ + void SetStorablePermanentPropertyValue( const IsoString& property, const Variant& value, bool notify = true ) + { + SetPropertyValue( property, value, notify, + ViewPropertyAttribute::Storable + | ViewPropertyAttribute::Permanent + | ViewPropertyAttribute::NoChange ); + } + + void SetStorablePermanentPropertyValue( const IsoString::ustring_base& property, const Variant& value, bool notify = true ) + { + SetStorablePropertyValue( IsoString( property ), value, notify ); + } + + /*! + * Returns the data type of an existing \a property in this view. + * + * If the requested \a property has not been defined for this view, this + * member function returns VariantType::Invalid. + * + * If the property exists but the calling module has no read access to it + * (see ViewPropertyAttributes::ReadProtected), an Error exception will be + * thrown. + * + * For a list of available view property types, see the VariantType + * namespace. + * + * \ingroup view_properties + */ + Variant::data_type PropertyType( const IsoString& property ) const; + + Variant::data_type PropertyType( const IsoString::ustring_base& property ) const + { + return PropertyType( IsoString( property ) ); + } + + /*! + * Returns the set of attributes currently associated with an existing + * \a property in this view. + * + * If the requested \a property has not been defined for this view, an Error + * exception is thrown. + * + * For a list of available view property attributes, see the + * ViewPropertyAttribute namespace. + * + * \ingroup view_properties + */ + ViewPropertyAttributes PropertyAttributes( const IsoString& property ) const; + + ViewPropertyAttributes PropertyAttributes( const IsoString::ustring_base& property ) const + { + return PropertyAttributes( IsoString( property ) ); + } + + /*! + * Sets new \a attributes for an existing \a property in this view. + * + * If the requested \a property is not currently defined for this view, or + * if the calling module has no write access to it (see + * ViewPropertyAttribute::WriteProtected), an Error exception will be + * thrown. + * + * Note that property attributes can be set for a newly created property + * with the View::SetPropertyValue() member function. For read-only + * properties, this is safer because the property never exists as a publicly + * writable object. + * + * \ingroup view_properties + */ + void SetPropertyAttributes( const IsoString& property, ViewPropertyAttributes attributes, bool notify = true ); + + void SetPropertyAttributes( const IsoString::ustring_base& property, ViewPropertyAttributes attributes, bool notify = true ) + { + SetPropertyAttributes( IsoString( property ), attributes, notify ); + } + + /*! + * Returns true iff the specified \a property exists in this view. + * + * \ingroup view_properties + */ + bool HasProperty( const IsoString& property ) const; + + bool HasProperty( const IsoString::ustring_base& property ) const + { + return HasProperty( IsoString( property ) ); + } + + /*! + * Deletes the specified \a property and its associated value in this view. + * + * If the requested \a property is not currently defined for this view, or + * if the calling module has no write access to it (see + * ViewPropertyAttribute::WriteProtected), an Error exception will be + * thrown. + * + * \ingroup view_properties + */ + void DeleteProperty( const IsoString& property, bool notify = true ); + + void DeleteProperty( const IsoString::ustring_base& property, bool notify = true ) + { + DeleteProperty( IsoString( property ), notify ); + } + + /*! + * Deletes the specified \a property and its associated value in this view, + * only if it is currently defined. If \a property is not defined, calling + * this member function has no effect. + * + * \ingroup view_properties + */ + void DeletePropertyIfExists( const IsoString& property, bool notify = true ) + { + if ( HasProperty( property ) ) + DeleteProperty( property, notify ); + } + + void DeletePropertyIfExists( const IsoString::ustring_base& property, bool notify = true ) + { + DeletePropertyIfExists( IsoString( property ), notify ); + } + + /*! + * Returns true iff the specified \a id string is a valid view identifier. + * + * A valid view identifier can include a preview separator (the sequence + * "->") to separate between a main view identifier and a preview + * identifier. + */ + template + static bool IsValidViewId( const S& id ) + { + size_type p = id.Find( "->" ); + if ( p == String::notFound ) + return id.IsValidIdentifier(); + return id.Left( p ).IsValidIdentifier() && id.Substring( p+2 ).IsValidIdentifier(); + } + + /*! + * Returns a view with the specified full identifier. If no view exists with + * the specified identifier, this function returns View::Null(). + */ + static View ViewById( const IsoString& fullId ); + + static View ViewById( const IsoString::ustring_base& fullId ) + { + return ViewById( IsoString( fullId ) ); + } + + /*! + * Returns a container with all the existing views. This includes all main + * views and previews. + */ + static Array AllViews( bool excludePreviews = false ); + + /*! + * Returns a container with the existing previews. Main views are excluded. + */ + static Array AllPreviews(); + +protected: + + View( void* h ) : UIObject( h ) + { + } + + View( const void* h ) : UIObject( h ) + { + } + + View( std::nullptr_t ) : UIObject( nullptr ) + { + } + + friend class ImageWindow; + friend class ProcessImplementation; // for LaunchOn() + friend class ProcessInterface; // for event broadcasting functions + friend class ProcessInstance; // for ExecuteOn() and related functions + friend class ViewList; + friend class ViewListEventDispatcher; + friend class ControlEventDispatcher; + friend class ProcessContextDispatcher; + friend class InterfaceDispatcher; + friend class InternalViewEnumerator; + friend class InternalPreviewEnumerator; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_View_h + +// ---------------------------------------------------------------------------- +// EOF pcl/View.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ViewList.h b/3rdparty/include/pcl/ViewList.h new file mode 100644 index 0000000..157936c --- /dev/null +++ b/3rdparty/include/pcl/ViewList.h @@ -0,0 +1,329 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ViewList.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_ViewList_h +#define __PCL_ViewList_h + +/// \file pcl/ViewList.h + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ViewList + * \brief Client-side interface to a PixInsight %ViewList object. + * + * ### TODO: Write a detailed description for %ViewList + */ +class PCL_CLASS ViewList : public Control +{ +public: + + /*! + * Constructs a %ViewList as a child control of \a parent. + */ + ViewList( Control& parent = Control::Null() ); + + /*! + * Destroys a %ViewList control. + */ + virtual ~ViewList() + { + } + + /*! + * Returns true iff this %ViewList control includes main views (images). + * + * \sa IncludesPreviews(), Regenerate() + */ + bool IncludesMainViews() const; + + /*! + * Returns true iff this %ViewList control includes previews. + * + * \sa IncludesMainViews(), Regenerate() + */ + bool IncludesPreviews() const; + + /*! + * Returns true iff this %ViewList control includes the virtual real-time + * preview. + * + * See the documentation for Regenerate() for more information about the + * virtual real-time preview. + * + * \sa Regenerate() + */ + bool IncludesRealTimePreview() const; + + /*! + * Updates this %ViewList control, regenerating the list of items for + * existing main views exclusively. + * + * This is a convenience member function, equivalent to: + * Regenerate( true, false ) + * + * Calling this member function implicitly disables the inclusion of + * previews in the list of items of this %ViewList control. + * + * \sa GetPreviews(), GetAll(), Regenerate() + */ + void GetMainViews() + { + Regenerate( true, false ); + } + + /*! + * Updates this %ViewList control, regenerating the list of items for + * existing previews exclusively. + * + * This is a convenience member function, equivalent to: + * Regenerate( false, true ) + * + * Calling this member function implicitly disables the inclusion of main + * views in the list of items of this %ViewList control. + * + * \sa GetMainViews(), GetAll(), Regenerate() + */ + void GetPreviews() + { + Regenerate( false, true ); + } + + /*! + * Updates this %ViewList control, regenerating the list of items for + * all existing views, including all main views and previews. + * + * This is a convenience member function, equivalent to: + * Regenerate( true, true ) + * + * Calling this member function implicitly enables the inclusion of main + * views and previews in the list of items of this %ViewList control. + * + * \sa GetMainViews(), GetPreviews(), Regenerate() + */ + void GetAll() + { + Regenerate( true, true ); + } + + /*! + * Regenerates the list of view items in this %ViewList control. + * + * \param mainViews Whether to enable inclusion of main views (images) - true by default. + * \param previews Whether to enable inclusion of previews - true by default. + * \param realTimePreview Whether to include the virtual real-time preview - false by default. + * + * The virtual real-time preview is a high-level interface to the + * image currently represented in the Real-Time Preview window. This is a + * special view that is not attached to any existing image window, and hence + * has only limited functionality. For example, the standard + * HistogramTransformation and Statistics tools enable access to this + * virtual view to obtain the histogram and statistical data, respectively, + * of the image being represented on the Real-Time Preview window. + * + * In general, a module must not gain access to the virtual real-time + * preview unless it implements some interactive functionality that depends + * on the current state of the Real-Time Preview window. + * + * \sa View + */ + void Regenerate( bool mainViews = true, bool previews = true, bool realTimePreview = false ); + + /*! + * Returns the excluded view of this %ViewList control, or + * View::Null() if this %ViewList excludes no view. + * + * The excluded view is never included in the list of items of a %ViewList + * control, regardless of the current state of inclusion for main views and + * previews. This feature is useful when there is a view that shouldn't be + * referenced in a processing interface. For example, a dynamic interface + * can easily avoid references to its own dynamic target by excluding it + * from a %ViewList. + * + * By default, %ViewList controls exclude no views. + * + * \sa ExcludeView() + */ + View ExcludedView() const; + + /*! + * Sets the excluded view of this %ViewList control, or clears it + * (to exclude no view) if View::Null() is specified. + * + * \sa ExcludedView() + */ + void ExcludeView( const View& v ); + + /*! + * Returns the view that is currently selected in this %ViewList control, or + * View::Null() if there is no view selected. + * + * \sa SelectView() + */ + View CurrentView() const; + + /*! + * Selects the specified \a view in this %ViewList control. + * + * If View::Null() is specified, the %ViewList control selects a special + * item (usually, the first item) with the "No View Selected" text. This is + * equivalent to a "no selection" state. + * + * If the specified view is not included in this %ViewList, calling this + * member function has no effect. + * + * \sa CurrentView(), HasView() + */ + void SelectView( const View& view ); + + /*! + * Returns true iff the specified \a view has been included in the list of + * items of this %ViewList control. + */ + bool HasView( const View& view ); + + /*! + * Removes the specified \a view from the list of existing items of this + * %ViewList control. + */ + void RemoveView( const View& view ); + + // ------------------------------------------------------------------------- + // Event handlers + // + // void OnViewSelected( ViewList& sender, View& view ); + // void OnCurrentViewUpdated( ViewList& sender, View& view ); + + /*! + * \defgroup view_list_event_handlers ViewList Event Handlers + */ + + /*! + * Defines the prototype of a view event handler. + * + * A view event is generated when the user activates a view item on a + * %ViewList control, or when she changes the current view item in a + * %ViewList control. + * + * \param sender The control that sends a view event. + * + * \param view The view whose associated item has been selected or + * activated. + * + * \ingroup view_list_event_handlers + */ + typedef void (Control::*view_event_handler)( ViewList& sender, View& view ); + + /*! + * Sets the view selection event handler of this %ViewList control. + * + * \param handler The event handler. Must be a member function of the + * receiver object's class. + * + * \param receiver The control that will receive view selection events + * from this %ViewList. + * + * \ingroup view_list_event_handlers + */ + void OnViewSelected( view_event_handler handler, Control& receiver ); + + /*! + * Sets the current view updated event handler for this %ViewList + * control. + * + * \param handler The event handler. Must be a member function of the + * receiver object's class. + * + * \param receiver The control that will receive current view + * updated events from this %ViewList. + * + * \ingroup view_list_event_handlers + */ + void OnCurrentViewUpdated( view_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + view_event_handler onViewSelected = nullptr; + view_event_handler onCurrentViewUpdated = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class ViewListEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#endif // __PCL_ViewList_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ViewList.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ViewSelectionDialog.h b/3rdparty/include/pcl/ViewSelectionDialog.h new file mode 100644 index 0000000..6310fae --- /dev/null +++ b/3rdparty/include/pcl/ViewSelectionDialog.h @@ -0,0 +1,149 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ViewSelectionDialog.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_ViewSelectionDialog_h +#define __PCL_ViewSelectionDialog_h + +/// \file pcl/ViewSelectionDialog.h + +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ViewSelectionDialog + * \brief A simple dialog box to select an existing view. + * + * %ViewSelectionDialog consists of a ViewList control populated with all + * existing views, and standard OK and Cancel push buttons. This class is a + * useful helper whenever a process needs access to a user-selected view. + * + * \sa MultiViewSelectionDialog, PreviewSelectionDialog, Dialog + */ +class PCL_CLASS ViewSelectionDialog : public Dialog +{ +public: + + /*! + * Constructs a %ViewSelectionDialog object. + * + * \param id If specified and a view exists with this identifier, the + * dialog will select the corresponding view upon execution. + * + * \param allowPreviews Whether to allow selection of previews, along + * with main views. For preview-only selections, see the + * PreviewSelectionDialog class. The default value is true. + */ + ViewSelectionDialog( const IsoString& id = IsoString(), bool allowPreviews = true ); + + ViewSelectionDialog( const IsoString::ustring_base& id, bool allowPreviews = true ) + : ViewSelectionDialog( IsoString( id ), allowPreviews ) + { + } + + /*! + * Destroys a %ViewSelectionDialog object. + */ + virtual ~ViewSelectionDialog() + { + } + + /*! + * Returns the identifier of the selected view. + */ + IsoString Id() const + { + return m_id; + } + + /*! + * Returns true if this dialog allows selection of previews along with main + * views; false if it can only select main views. This option can be + * controlled with a constructor parameter. + */ + bool PreviewsAllowed() const + { + return m_allowPreviews; + } + +private: + + IsoString m_id; + bool m_allowPreviews = true; + + VerticalSizer Global_Sizer; + ViewList Images_ViewList; + CheckBox IncludeMainViews_CheckBox; + CheckBox IncludePreviews_CheckBox; + HorizontalSizer Buttons_Sizer; + PushButton OK_PushButton; + PushButton Cancel_PushButton; + + void ViewSelected( ViewList& sender, View& view ); + void OptionClick( Button& sender, bool checked ); + void ButtonClick( Button& sender, bool checked ); + void ControlShow( Control& sender ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ViewSelectionDialog_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ViewSelectionDialog.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/WCSKeywords.h b/3rdparty/include/pcl/WCSKeywords.h new file mode 100644 index 0000000..e2d2ac4 --- /dev/null +++ b/3rdparty/include/pcl/WCSKeywords.h @@ -0,0 +1,172 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/WCSKeywords.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_WCSKeywords_h +#define __PCL_WCSKeywords_h + +/// \file pcl/WCSKeywords.h + +#include + +#include +#include +#include +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +class LinearTransformation; + +/*! + * \class WCSKeywords + * \brief A structure for management of WCS FITS header keywords and associated + * image properties. + * + * \b References + * + * M. R. Calabretta, E. W. Greisen (2002) Representations of World + * Coordinates in FITS, Astronomy & Astrophysics, 395, 1061-1075, + * 1077-1122. + * + * \ingroup astrometry_support + */ +class PCL_CLASS WCSKeywords +{ +public: + + Optional objctra; //!< Right ascension coordinate of the center of the image in degrees. + Optional objctdec; //!< Declination coordinate of the center of the image in degrees. + IsoString radesys; //!< Reference system of celestial coordinates. + Optional equinox; //!< Equinox in years for the celestial coordinate system (not applicable if radesys = ICRS | GCRS). + Optional dateobs; //!< Observation start time as a Julian date, UTC timescale. + Optional dateend; //!< Observation end time as a Julian date, UTC timescale. + Optional longobs; //!< Geodetic longitude of the observation location in degrees. Reckoned positive east of the reference meridian. + Optional latobs; //!< Geodetic latitude of the observation location in degrees. Reckoned positive north of the equator. + Optional altobs; //!< Geodetic height of the observation location in meters. + Optional focallen; //!< Focal length in millimeters. + Optional xpixsz; //!< Pixel size in micrometers. + Optional crval1; //!< WCS coordinate at the reference pixel, X axis. + Optional crval2; //!< WCS coordinate at the reference pixel, Y axis. + Optional crpix1; //!< Image coordinate of the reference pixel on the X axis. + Optional crpix2; //!< Image coordinate of the reference pixel on the Y axis. + Optional cd1_1; //!< Rotation and scaling matrix: CDELT1 * cos(CROTA2) + Optional cd1_2; //!< Rotation and scaling matrix: -CDELT2 * sin(CROTA2) + Optional cd2_1; //!< Rotation and scaling matrix: CDELT1 * sin(CROTA2) + Optional cd2_2; //!< Rotation and scaling matrix: CDELT2 * cos(CROTA2) + Optional cdelt1; //!< Plate scale in degrees per pixel at the reference pixel, X axis. + Optional cdelt2; //!< Plate scale in degrees per pixel at the reference pixel, Y axis. + Optional crota1; //!< Rotation angle around the reference pixel in degrees. Same as CROTA2, unused. + Optional crota2; //!< Rotation angle around the reference pixel in degrees. + IsoString ctype1; //!< Coordinate type and projection, X axis. + IsoString ctype2; //!< Coordinate type and projection, Y axis. + Optional pv1_1; //!< Native longitude of the reference point in degrees. + Optional pv1_2; //!< Native latitude of the reference point in degrees. + Optional lonpole; //!< Native longitude of the pole of the coordinate system in degrees. + Optional latpole; //!< Native latitude of the pole of the coordinate system in degrees. + IsoString refSpline; //!< If nonempty, the astrometric solution uses thin plate splines instead of WCS polynomials. + + /*! + * Default constructor. Constructs an uninitialized/undefined %WCSKeywords + * object. + */ + WCSKeywords() = default; + + /*! + * Copy constructor. + */ + WCSKeywords( const WCSKeywords& ) = default; + + /*! + * Constructs a %WCSKeywords object by extracting data from the specified + * arrays of image \a properties and %FITS \a keywords. + * + * Metadata items available as image properties take precedence over + * equivalent %FITS keywords. + */ + WCSKeywords( const PropertyArray& properties, const FITSKeywordArray& keywords = FITSKeywordArray() ) + { + Read( properties, keywords ); + } + + /*! + * Extracts WCS metadata from the specified arrays of image \a properties + * and %FITS \a keywords. + * + * If some metadata items are not included in the \a properties and + * \a keywords arrays, the previously defined items, if any, will be + * preserved. + * + * Metadata items available as image properties take precedence over + * equivalent %FITS keywords. + */ + void Read( const PropertyArray& properties, const FITSKeywordArray& keywords = FITSKeywordArray() ); + + /*! + * + */ + bool ExtractWorldTransformation( LinearTransformation& transIW, int imageHeight ); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_WCSKeywords_h + +// ---------------------------------------------------------------------------- +// EOF pcl/WCSKeywords.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/WebView.h b/3rdparty/include/pcl/WebView.h new file mode 100644 index 0000000..cfe8dcc --- /dev/null +++ b/3rdparty/include/pcl/WebView.h @@ -0,0 +1,553 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/WebView.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_WebView_h +#define __PCL_WebView_h + +/// \file pcl/WebView.h + +#include + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +#include +#include +#include +#include + +#endif // !__PCL_BUILDING_PIXINSIGHT_APPLICATION + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#ifndef __PCL_BUILDING_PIXINSIGHT_APPLICATION + +// ---------------------------------------------------------------------------- + +/*! + * \class WebView + * \brief Client-side interface to a PixInsight %WebView control. + * + * %WebView is a specialized control for rendering text and HTML content on the + * PixInsight platform. The underlying implementation, which is based on Qt5's + * QWebEngineView class, has full HTML 5.1 support and an advandced, + * last-generation JavaScript engine. + * + * It is very important to point out that this class is \e not intended to + * implement a web browser, even one with barebones functionality. The purpose + * of %WebView is to render high-quality, interactive contents such as tables, + * spreadsheets and graphics, where the contained data are dynamically + * generated as HTML and JavaScript code. + */ +class PCL_CLASS WebView : public Control +{ +public: + + /*! + * Constructs a %WebView control. + * + * \param parent The parent control of this object. The default value is + * a null control. + */ + WebView( Control& parent = Control::Null() ); + + /*! + * Destroys a %WebView control. + */ + virtual ~WebView() + { + } + + /*! + * Sets the content of this %WebView. + * + * \param data The content as a sequence of bytes, stored as a + * dynamic array of unsigned 8-bit integers. + * + * \param mimeType A MIME type describing the type of the data. By + * default, that is, if an empty string is + * specified, the type will be detected based on + * heuristics. + * + * The content loading process is asynchronous. This member function will + * return immediately before the content has actually been loaded and + * rendered in this %WebView. After calling this function, a sequence of + * events will be generated: + * + * \li A load started event. Can be received by a handler set with + * OnLoadStarted(). + * + * \li A number of successive load progress events. Can be received by a + * handler set with OnLoadProgress(). + * + * \li A final load finished event. Can be received by a handler set with + * OnLoadFinished(). This event handler in particular is necessary if the + * caller depends on (or has to wait for) the content being rendered by this + * %WebView. + * + * \sa SetHTML(), SetPlainText(), LoadContent() + */ + void SetContent( const ByteArray& data, const IsoString& mimeType = IsoString() ); + + /*! + * Sets the content of this %WebView in HTML format, encoded as UTF-8. See + * SetContent() for important information on %WebView's asynchronous content + * rendering. + */ + void SetHTML( const IsoString& html ); + + /*! + * Sets the content of this %WebView in HTML format, encoded as UTF-16. See + * SetContent() for important information on %WebView's asynchronous content + * rendering. + */ + void SetHTML( const String& html ); + + /*! + * Sets the content of this %WebView as plain Unicode \a text encoded as + * UTF-8. See SetContent() for important information on %WebView's + * asynchronous content rendering. + */ + void SetPlainText( const IsoString& text ); + + /*! + * Sets the content of this %WebView as plain Unicode \a text encoded as + * UTF-16. See SetContent() for important information on %WebView's + * asynchronous content rendering. + */ + void SetPlainText( const String& text ); + + /*! + * Loads the content of this %WebView from a local or external resource. + * + * \param uri A valid Uniform Resource Identifier, as defined + * by RFC 3986 (Uniform Resource Identifier: Generic + * Syntax). + * + * See SetContent() for important information on %WebView's asynchronous + * content rendering, also applicable to this member function. + * + * \sa SetContent() + */ + void LoadContent( const String& uri ); + + /*! + * Requests retrieval of the current content of this %WebView as plain + * Unicode text encoded in UTF-16, with all HTML markup removed. + * + * This function is asynchronous. Once the requested content is available, + * it will be sent to the OnPlainTextAvailable() event handler, if defined + * for this object. + */ + void RequestPlainText() const; + + /*! + * Requests retrieval of the current content of this %WebView as HTML code + * encoded in UTF-16. + * + * This function is asynchronous. Once the requested content is available, + * it will be sent to the OnHTMLAvailable() event handler, if defined for + * this object. + */ + void RequestHTML() const; + + /*! + * Writes the current content of this %WebView as a PDF document. + * + * \param filePath Path to the output file. + * + * \param pageWidth Page width in millimeters. The default width is + * 210 mm, corresponding to the standard A4 size. + * + * \param pageHeight Page height in millimeters. The default height is + * 297 mm, corresponding to the standard A4 size. + * + * \param marginLeft Left margin in millimeters. The default left + * margin is 10 mm. + * + * \param marginTop Top margin in millimeters. The default top margin + * is 10 mm. + * + * \param marginRight Right margin in millimeters. The default right + * margin is 10 mm. + * + * \param marginBottom Bottom margin in millimeters. The default bottom + * margin is 10 mm. + * + * \param landscape If true, the document will be generated with + * landscape orientation. This means that the width + * and height dimensions will be reversed. If false, + * the normal portrait orientation will be applied. + * This parameter is false by default. + */ + void SaveAsPDF( const String& filePath, double pageWidth = 210, double pageHeight = 297, + double marginLeft = 10, double marginTop = 10, double marginRight = 10, double marginBottom = 10, + bool landscape = false ); + + /*! + * Returns true if there is a non-empty text selection in this %WebView. + */ + bool HasSelection() const; + + /*! + * Returns the currently selected text as plain text. Returns an empty + * string if there is no text selection. + */ + String SelectedText() const; + + /*! + * Returns the zoom factor of this %WebView rendition. The returned value is + * in the range [0.25,5.0]. + */ + double ZoomFactor() const; + + /*! + * Sets the zoom factor of this %WebView rendition. The specified \a zoom + * factor must be in the range [0.25,5.0]. + */ + void SetZoomFactor( double zoom ); + + /*! + * Returns the background color of the %WebView rendition encoded in 32-bit + * RGBA format. + */ + RGBA BackgroundColor() const; + + /*! + * Sets the background color of the %WebView rendition. The specified + * \a color must be encoded in 32-bit RGBA format. + */ + void SetBackgroundColor( RGBA color ); + + /*! + * Reloads the content of this %WebView. If no content has previously been + * loaded, calling this function has no effect. + */ + void Reload(); + + /*! + * Stops loading the content of this %WebView. If there is no ongoing + * content loading operation, calling this function has no effect. + */ + void Stop(); + + /*! + * Executes a script in this %WebView. + * + * \param sourceCode A string containing valid source code in the + * specified \a language. + * + * \param language The name of a supported scripting language. + * Currently only the JavaScript language is supported + * by this function. JavaScript is assumed if this + * string is either empty or equal to "JavaScript". + * + * This function is asynchronous: It will return immediately without waiting + * for the script to complete execution. Once the script has finished, its + * result value will be sent to the OnScriptResultAvailable() event handler, + * if defined for this object. The result value is the value of the last + * executed expression statement in the script that is not in a function + * definition. Note that for scripts whose value is not required, the + * OnScriptResultAvailable event handler is not necessary. + * + * The script will be executed by a web-oriented JavaScript engine with full + * support of the HTML 5.1 standard in current versions of PixInsight. Note + * that this engine is completely different from the core JavaScript Runtime + * (PJSR), so no PJSR resources are available. If you want to execute + * JavaScript code in PJSR, use MetaModule::EvaluateScript() instead of this + * member function. + * + * This function has no way to know if script execution failed, for example + * as a result of syntax errors, invalid code, or exceptions thrown from + * JavaScript code. A Variant will always be generated to transport the + * result, but it may not transport a valid object (see Variant::IsValid()) + * if the script failed. How to diagnose script execution is completely up + * to the caller implementation. + * + * \note This function can only be called from the root thread, since the + * underlying JavaScript engine in not reentrant in current versions of + * PixInsight. Calling this function from a running thread will throw an + * Error exception. + * + * \warning You should make sure that your code has been well tested before + * calling this function. The core PixInsight application will wait until + * the script terminates execution. If your code enters an infinite loop, it + * may lead to a crash of the PixInsight platform. Also bear in mind that + * scripts are extremely powerful and potentially dangerous if you don't + * know well what you are doing. What happens during execution of your + * scripts is your entire responsibility. + */ + void EvaluateScript( const String& sourceCode, const IsoString& language = IsoString() ); + + /*! + * \defgroup web_view_event_handlers WebView Event Handlers + */ + + /*! + * Defines the prototype of a web view event handler. + * + * A web view event is generated when a %WebView instance changes its state + * or contents, or the value of one of its properties, either + * programmatically or because of user interaction. + * + * \param sender The control that sends a web view event. + * + * \ingroup web_view_event_handlers + */ + typedef void (Control::*view_event_handler)( WebView& sender ); + + /*! + * Defines the prototype of a progress event handler. + * + * A progress event is generated while the %WebView object is loading + * contents, to inform on the amount of data already loaded. + * + * \param sender The control that sends a progress event. + * + * \param loadPercent The percentage of content loaded. Should be in the + * range [0,100]. + * + * \ingroup web_view_event_handlers + */ + typedef void (Control::*progress_event_handler)( WebView& sender, int loadPercent ); + + /*! + * Defines the prototype of a state event handler. + * + * A state event is generated when the value of a Boolean %WebView property + * has changed. + * + * \param sender The control that sends a state event. + * + * \param state The current value of the Boolean property. + * + * \ingroup web_view_event_handlers + */ + typedef void (Control::*state_event_handler)( WebView& sender, bool state ); + + /*! + * Defines the prototype of a content event handler. + * + * A content event is generated after a call to RequestPlainText() or + * RequestHTML(), when the requested content is available to the caller. + * + * \param sender The control that sends a content event. + * + * \param content The requested content (HTML or plain text) encoded in + * UTF-16. + * + * \ingroup web_view_event_handlers + */ + typedef void (Control::*content_event_handler)( WebView& sender, const String& content ); + + /*! + * Defines the prototype of a result event handler. + * + * A result event is generated after a call to EvaluateScript(), when the + * script has finished execution. + * + * \param sender The control that sends a result event. + * + * \param result The result value of the executed script. The result + * value is the value of the last executed expression + * statement in the script that is not in a function + * definition. + * + * \ingroup web_view_event_handlers + */ + typedef void (Control::*result_event_handler)( WebView& sender, const Variant& result ); + + /*! + * Sets the handler for load started events generated by this + * %WebView object. A load started event is generated when the %WebView + * starts loading new content, after a call to SetContent(). + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive load started events from + * this %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnLoadStarted( view_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for progress events generated by this %WebView object. A + * progress event is generated while the %WebView is loading new content, + * after a call to SetContent(), to inform on the amount of data already + * loaded. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive progress events from this + * %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnLoadProgress( progress_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for load finished events generated by this + * %WebView object. A load finished event is generated when the %WebView + * finishes loading new content, after a call to SetContent(). + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. The handler will receive a + * Boolean value true if the loading process was completed + * successfully, false in the event of error. + * + * \param receiver The control that will receive load finished events from + * this %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnLoadFinished( state_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for selection updated events generated by this + * %WebView object. A selection updated event is generated each time the + * text selection is changed in this %WebView as a result of a direct user + * interaction. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive selection updated events + * from this %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnSelectionUpdated( view_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for plain text content available events + * generated by this %WebView object. These events are generated + * asynchronously after a call to RequestPlainText(), when the requested + * content is available to the caller. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive plain text content + * available events from this %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnPlainTextAvailable( content_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for HTML content available events generated by + * this %WebView object. These events are generated asynchronously after a + * call to RequestHTML(), when the requested content is available to the + * caller. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive HTML content available + * events from this %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnHTMLAvailable( content_event_handler handler, Control& receiver ); + + /*! + * Sets the handler for script result available events generated by + * this %WebView object. These events are generated asynchronously after a + * call to EvaluateScript(), when the script has finished execution and its + * result value is available to the caller. + * + * \param handler The event handler. Must be a member function of the + * \a receiver object's class. + * + * \param receiver The control that will receive script result available + * events from this %WebView. + * + * \ingroup web_view_event_handlers + */ + void OnScriptResultAvailable( result_event_handler handler, Control& receiver ); + +private: + + struct EventHandlers + { + view_event_handler onLoadStarted = nullptr; + progress_event_handler onLoadProgress = nullptr; + state_event_handler onLoadFinished = nullptr; + view_event_handler onSelectionUpdated = nullptr; + content_event_handler onPlainTextAvailable = nullptr; + content_event_handler onHTMLAvailable = nullptr; + result_event_handler onScriptResultAvailable = nullptr; + + EventHandlers() = default; + EventHandlers( const EventHandlers& ) = default; + EventHandlers& operator =( const EventHandlers& ) = default; + }; + + AutoPointer m_handlers; + + friend class WebViewEventDispatcher; +}; + +// ---------------------------------------------------------------------------- + +#endif // __PCL_BUILDING_PIXINSIGHT_APPLICATION + +} // pcl + +#endif // __PCL_WebView_h + +// ---------------------------------------------------------------------------- +// EOF pcl/WebView.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/Win32Exception.h b/3rdparty/include/pcl/Win32Exception.h new file mode 100644 index 0000000..8ff595c --- /dev/null +++ b/3rdparty/include/pcl/Win32Exception.h @@ -0,0 +1,317 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/Win32Exception.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_Win32Exception_h +#define __PCL_Win32Exception_h + +/// \file pcl/Win32Exception.h + +#if !defined( __PCL_WINDOWS ) || defined( __PCL_LINUX ) || defined( __PCL_FREEBSD ) || defined( __PCL_MACOSX ) +# error Win32Exception can only be used on MS Windows platforms. +#endif + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class Win32Exception + * \brief A Win32 structured exception handler that throws C++ exceptions. + * + * This class can only be used on Microsoft Windows platforms. On the rest of + * supported platforms, including this header file from compilable code raises + * a compiler error. + * + * For this handler to work properly, all code that may raise asynchronous + * (structured) exceptions must be compiled with the '-EHa' Visual C/C++ + * compiler option. Otherwise no asynchronous exception thrown in a try{} block + * will be caught by the corresponding catch{} block, and the program will + * terminate. + */ +class PCL_CLASS Win32Exception : public pcl::Exception +{ +public: + + /*! + * Represents a memory address associated with an exception. For example, + * the address that has been accessed to cause an access violation error. + */ + typedef const void* exception_address; + + /*! + * Represents a pointer to a data block that describes an exception. This is + * an opaque pointer to an EXCEPTION_RECORD structure. + */ + typedef const void* exception_data_pointer; + + /*! + * The type of an exception error code. + */ + typedef unsigned exception_code; + + /*! + * Constructs a new %Win32Exception object with the specified exception + * \a code and \a data, plus optional backtrace information \a details. + */ + Win32Exception( exception_code code, exception_data_pointer data, + const IsoString& details = IsoString() ) + : m_code( code ) + , m_data( data ) + , m_details( details ) + { + } + + /*! + * Copy constructor. + */ + Win32Exception( const Win32Exception& ) = default; + + /*! + * Returns the memory address associated with this exception. + */ + exception_address ExceptionAddress() const; + + /*! + * Returns the error code of this exception. + */ + exception_code ExceptionCode() const + { + return m_code; + } + + /*! + * Returns the backtrace information associated with this exception. + * + * The returned string will be empty if no backtrace data were available at + * the time this exception was generated. + */ + const IsoString& Details() const + { + return m_details; + } + + /*! + * Returns an error or warning message corresponding to this exception. + * For example, some typical messages are "access violation", "stack + * overflow" and "illegal instruction", returned by specific derived + * classes. + */ + String Message() const override + { + return "Undefined system exception"; + } + + /*! + * Returns a formatted error message with information on this exception. + */ + String FormatInfo() const override + { + String info = String().Format( "At address %p with exception code %X :\n", + ExceptionAddress(), ExceptionCode() ) + Message(); + if ( !m_details.IsEmpty() ) + { + info.Append( '\n' ); + info.Append( m_details ); + } + return info; + } + + /*! + * Returns the type of this exception, intended to be used as a caption for + * a message box. As reimplemented in this class, this member function + * returns the string "PCL Win32 System Exception". + */ + String Caption() const override + { + return "PCL Win32 System Exception"; + } + + /*! + * Writes a formatted representation of this exception on the platform + * console. A plain text version of the same textual representation will + * also be written on stdout; however, if there is no console currently + * attached to the process (which is the typical situation for GUI Windows + * applications), no console stream output will be generated. + * + * \note Asynchronous exceptions are never reported on interactive graphical + * interfaces, such as message boxes, irrespective of global platform + * settings or local settings defined through calls to EnableGUIOutput() and + * similar functions. + */ + void Show() const override; + + /*! + * Initializes the structured exception handler. This static member function + * must be called before the calling process can raise any system exception. + * + * \note A module should never call this member function. It is invoked when + * appropriate by the PixInsight core application and internal PCL routines. + */ + static void Initialize(); + +protected: + + exception_code m_code; + exception_data_pointer m_data; // points to an EXCEPTION_RECORD structure + IsoString m_details; // backtrace information +}; + +// ---------------------------------------------------------------------------- + +class PCL_CLASS Win32AccessViolationException : public Win32Exception +{ +public: + + Win32AccessViolationException( exception_code code, exception_data_pointer data, + const IsoString& details = IsoString() ) + : Win32Exception( code, data, details ) + { + } + + Win32AccessViolationException( const Win32AccessViolationException& ) = default; + + String Message() const override; +}; + +// ---------------------------------------------------------------------------- + +#define DECLARE_WIN32_EXCEPTION( className, message ) \ + class PCL_CLASS className : public pcl::Win32Exception \ + { \ + public: \ + className( exception_code code, exception_data_pointer data, \ + const IsoString& details = IsoString() ) : \ + pcl::Win32Exception( code, data, details ) \ + { \ + } \ + className( const className& ) = default; \ + String Message() const override \ + { \ + return message; \ + } \ + } + +// ---------------------------------------------------------------------------- + +DECLARE_WIN32_EXCEPTION( EWin32ArrayBoundsExceeded, + "Array bounds exceeded" ); + +DECLARE_WIN32_EXCEPTION( EWin32Breakpoint, + "A breakpoint was encountered" ); + +DECLARE_WIN32_EXCEPTION( EWin32DataMisalignment, + "Invalid read/write operation on misaligned data" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointDenormalOperand, + "Denormal operand in floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointDivideByZero, + "Division by zero in floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointInexactResult, + "Inexact result in floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointInvalidOperation, + "Invalid floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointOverflow, + "Overflow in floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointStackCheck, + "Stack limits exceeded in floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32FloatingPointUnderflow, + "Underflow in floating-point operation" ); + +DECLARE_WIN32_EXCEPTION( EWin32IllegalInstruction, + "Illegal processor instruction" ); + +DECLARE_WIN32_EXCEPTION( EWin32PageError, + "Memory page not found" ); + +DECLARE_WIN32_EXCEPTION( EWin32DivideByZero, + "Integer division by zero" ); + +DECLARE_WIN32_EXCEPTION( EWin32Overflow, + "Integer overflow" ); + +DECLARE_WIN32_EXCEPTION( EWin32InvalidDisposition, + "Invalid exception disposition" ); + +DECLARE_WIN32_EXCEPTION( EWin32NonContinuableException, + "Noncontinuable exception " ); + +DECLARE_WIN32_EXCEPTION( EWin32PrivilegedInstruction, + "Privileged processor instruction" ); + +DECLARE_WIN32_EXCEPTION( EWin32SingleStep, + "Single-instruction step" ); + +DECLARE_WIN32_EXCEPTION( EWin32StackOverflow, + "Stack overflow" ); + +// ---------------------------------------------------------------------------- + +#undef DECLARE_WIN32_EXCEPTION + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_Win32Exception_h + +// ---------------------------------------------------------------------------- +// EOF pcl/Win32Exception.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/WordArray.h b/3rdparty/include/pcl/WordArray.h new file mode 100644 index 0000000..44c86a1 --- /dev/null +++ b/3rdparty/include/pcl/WordArray.h @@ -0,0 +1,121 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/WordArray.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_WordArray_h +#define __PCL_WordArray_h + +/// \file pcl/WordArray.h + +#include + +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup word_arrays Word Array Classes + */ + +/*! + * \class pcl::WordArray + * \brief Dynamic array of 16-bit unsigned integers. + * + * %WordArray is a template instantiation of Array for \c uint16. + * + * \ingroup word_arrays + * \ingroup dynamic_arrays + */ +typedef Array WordArray; + +/*! + * \class pcl::SortedWordArray + * \brief Dynamic sorted array of 16-bit unsigned integers. + * + * %SortedWordArray is a template instantiation of SortedArray for \c uint16. + * + * \ingroup word_arrays + * \ingroup dynamic_arrays + */ +typedef SortedArray SortedWordArray; + +/*! + * \class pcl::ShortArray + * \brief Dynamic array of 16-bit signed integers. + * + * %ShortArray is a template instantiation of Array for \c int16. + * + * \ingroup word_arrays + * \ingroup dynamic_arrays +*/ +typedef Array ShortArray; + +/*! + * \class pcl::SortedShortArray + * \brief Dynamic sorted array of 16-bit signed integers. + * + * %SortedShortArray is a template instantiation of SortedArray for \c int16. + * + * \ingroup word_arrays + * \ingroup dynamic_arrays + */ +typedef SortedArray SortedShortArray; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_WordArray_h + +// ---------------------------------------------------------------------------- +// EOF pcl/WordArray.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/WorldTransformation.h b/3rdparty/include/pcl/WorldTransformation.h new file mode 100644 index 0000000..b747ab5 --- /dev/null +++ b/3rdparty/include/pcl/WorldTransformation.h @@ -0,0 +1,681 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/WorldTransformation.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_WorldTransformation_h +#define __PCL_WorldTransformation_h + +/// \file pcl/WorldTransformation.h + +#include + +#include +#include +#include +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +#define __PCL_WCS_DEFAULT_SPLINE_ORDER 2 +#define __PCL_WCS_DEFAULT_SPLINE_SMOOTHNESS 0.025F +#define __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_ENABLED true +#define __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_TOLERANCE 0.25F // px +#define __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_REJECT_FRACTION 0.10F +#define __PCL_WCS_MAX_SPLINE_POINTS 2100 + +// ---------------------------------------------------------------------------- + +/*! + * \class WorldTransformation + * \brief Abstract base class of world coordinate transformations + * + * \ingroup astrometry_support + */ +class PCL_CLASS WorldTransformation +{ +public: + + /*! + * Default constructor. + */ + WorldTransformation() = default; + + /*! + * Copy constructor. + */ + WorldTransformation( const WorldTransformation& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~WorldTransformation() + { + } + + /*! + * Returns true iff this transformation is empty (uninitialized, invalid). + */ + virtual bool IsEmpty() const + { + return false; + } + + /*! + * Returns a dynamically allocated copy of this object. + */ + virtual WorldTransformation* Clone() const = 0; + + /*! + * Transforms from native spherical coordinates to image coordinates. + * + * The point \a p contains native spherical coordinates: \a p.x is the + * native longitude and \a p.y is the native latitude, both expressed in + * degrees. Returns image coordinates in pixels corresponding to \a p. + */ + virtual DPoint Direct( const DPoint& p ) const = 0; + + /*! + * Transforms from image coordinates to native spherical coordinates. + * + * The specified point \a p contains image coordinates in pixels. Returns a + * point \a q where \a q.x is the native longitude and \a q.y is the native + * latitude, both expressed in degrees, corresponding to \a p. + */ + virtual DPoint Inverse( const DPoint& p ) const = 0; + + /*! + * Returns an approximate linear transformation from Image to World + * coordinates. + */ + virtual const LinearTransformation& ApproximateLinearTransform() const = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class LinearWorldTransformation + * \brief WCS linear world coordinate transformation + * + * \ingroup astrometry_support + */ +class PCL_CLASS LinearWorldTransformation : public WorldTransformation +{ +public: + + /*! + * Constructor from a linear transformation. The specified transformation + * \a transIW must transform from image coordinates to native spherical + * coordinates. + */ + LinearWorldTransformation( const LinearTransformation& transIW ) + : m_transWI( transIW.Inverse() ) + , m_transIW( transIW ) + { + } + + /*! + * Copy constructor. + */ + LinearWorldTransformation( const LinearWorldTransformation& ) = default; + + /*! + * Move constructor. + */ + LinearWorldTransformation( LinearWorldTransformation&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~LinearWorldTransformation() + { + } + + /*! + * Returns false, since a linear WCS transformation cannot be empty. + */ + bool IsEmpty() const override + { + return false; + } + + /*! + */ + WorldTransformation* Clone() const override + { + return new LinearWorldTransformation( *this ); + } + + /*! + */ + DPoint Direct( const DPoint& p ) const override + { + return m_transWI.Transform( p ); + } + + /*! + */ + DPoint Inverse( const DPoint& p ) const override + { + return m_transIW.Transform( p ); + } + + /*! + * Returns a reference to the internal linear transformation (from image to + * native spherical coordinates). + */ + const LinearTransformation& ApproximateLinearTransform() const override + { + return m_transIW; + } + +private: + + LinearTransformation m_transWI; // world -> image + LinearTransformation m_transIW; // image -> world +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class SplineWorldTransformation + * \brief Surface spline world coordinate transformation + * + * %SplineWorldTransformation implements a world coordinate transform based on + * 2-D interpolating/approximating surface splines (also known as thin + * plates). These mathematical modeling devices allow for accurate + * representations of coordinate systems subject to arbitrary local + * distortions, which are impossible to achieve with linear transformations. + * + * The underlying implementation of this class uses the SurfaceSpline, + * PointSurfaceSpline, SurfaceSimplifier and PointGridInterpolation classes. + * + * \ingroup astrometry_support + */ +class PCL_CLASS SplineWorldTransformation : public WorldTransformation +{ +public: + + /*! + * Constructs a 2-D spline based world coordinate transformation. + * + * \param controlPointsW Array of world control points. Each point in this + * array must contain spherical coordinates in the + * native world coordinate system of the astrometric + * solution, expressed in degrees. For a given + * point p in this array, p.x is the native + * longitude coordinate and p.y is the latitude. + * + * \param controlPointsI Array of image control points. Each point in this + * array must contain the coordinates on the X and Y + * axes of the image plane corresponding to the same + * point in the \a controlPointsW array. In other + * words, there must be a one-to-one correspondence + * between world and image control points. + * + * \param smoothness When this parameter is greater than zero, + * approximating splines will be generated instead + * of interpolating splines. The higher this value, + * the closest will be the 2-D approximating surface + * to the reference plane of the image. + * Approximating surface splines are robust to + * outlier control points and hence recommended in + * virtually all cases. The value of this parameter + * should be relatively small if \a enableSimplifier + * is true, since the surface simplification + * algorithm already performs robust rejection of + * outliers. The default value of 0.025 is normally + * quite appropriate. + * + * \param weights When the \a smoothness parameter is greater than + * zero and this vector is not empty, it must define + * a positive weight greater than zero for each + * point defined by the \a controlPointsW and + * \a controlPointsI arrays. If \a smoothness is + * zero or negative, this parameter will be ignored. + * See the PointSurfaceSpline::Initialize() member + * function for detailed information on 2-D spline + * node weights. If \a enableSimplifier is true, + * control point weights are not used and hence the + * value of this parameter will be ignored. + * + * \param order Derivative order of continuity. The default value + * is 2, which is also the recommended value. Higher + * orders may improve adaptability to complex field + * distortions only in some special cases, but at + * the risk of leading to ill-conditioned linear + * systems, and hence to errors while building the + * surface splines. + * + * \param enableSimplifier If true, a surface simplification algorithm will + * be applied to the lists of control points for + * surface spline generation. The use of surface + * simplification greatly improves efficiency of + * surface splines by removing all redundant points + * and keeping only the control points required to + * define the coordinate transformations accurately. + * In addition, the applied surface simplification + * algorithm implements robust PCA fitting and + * outlier rejection techniques that improve the + * generated interpolation devices in terms of + * resilience to noise and invalid data in the + * underlying astrometric solution. This option is + * enabled by default. When this parameter is true, + * the \a weights parameter is ignored. + * + * \param simplifierTolerance Tolerance of the surface simplification + * algorithm in pixels. The default value is 0.25 + * pixels. + * + * \param simplifierRejectFraction Fraction of rejected control points for + * simplification of surface subregions. The default + * value is 0.10. + * + * Thanks to the implemented surface simplification algorithms, we can work + * with very large sets of control points to generate astrometric solutions + * able to model strong and complex arbitrary field distortions accurately + * and efficiently. Surface simplification concentrates control points just + * where they are necessary to represent distortions, leaving undistorted + * regions of the image covered by a minimal grid. + * + * Newly constructed instances are guaranteed to be valid (in the structural + * and numerical senses; note that this does not necessarily imply that the + * underlying astrometric solution is valid). In the event of invalid input + * data or spline initialization problems, this constructor will throw an + * Error exception. + * + * After surface spline initialization, an approximate linear transformation + * will also be calculated automatically. + */ + SplineWorldTransformation( const Array& controlPointsW, + const Array& controlPointsI, + float smoothness = __PCL_WCS_DEFAULT_SPLINE_SMOOTHNESS, + const FVector& weights = FVector(), + int order = __PCL_WCS_DEFAULT_SPLINE_ORDER, + bool enableSimplifier = __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_ENABLED, + float simplifierTolerance = __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_TOLERANCE, + float simplifierRejectFraction = __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_REJECT_FRACTION ) + : m_controlPointsW( controlPointsW ) + , m_controlPointsI( controlPointsI ) + , m_order( order ) + , m_smoothness( smoothness ) + , m_weights( weights ) + , m_enableSimplifier( enableSimplifier ) + , m_simplifierTolerance( simplifierTolerance ) + , m_simplifierRejectFraction( simplifierRejectFraction ) + { + InitializeSplines(); + CalculateLinearApproximation(); + } + + /*! + * Constructs a %SplineWorldTransformation instance by deserializing the + * specified raw \a data. + * + * An approximate linear transformation will be calculated automatically. + */ + SplineWorldTransformation( const ByteArray& data ) + { + Deserialize( data ); + InitializeSplines(); + CalculateLinearApproximation(); + } + + /*! + * Constructs a %SplineWorldTransformation instance by deserializing the + * specified raw \a data, with a prescribed approximate linear + * transformation \a linearTransIW. + */ + SplineWorldTransformation( const ByteArray& data, const LinearTransformation& linearTransIW ) + { + Deserialize( data ); + InitializeSplines(); + m_linearIW = linearTransIW; + } + + /*! + * Copy constructor. + */ + SplineWorldTransformation( const SplineWorldTransformation& ) = default; + + /*! + * Move constructor. + */ + SplineWorldTransformation( SplineWorldTransformation&& ) = default; + + /*! + * Virtual destructor. + */ + virtual ~SplineWorldTransformation() + { + } + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + SplineWorldTransformation& operator =( const SplineWorldTransformation& ) = default; + + /*! + * Move assignment operator. Returns a reference to this object. + */ + SplineWorldTransformation& operator =( SplineWorldTransformation&& ) = default; + + /*! + * Returns true iff this object has no working data. + * + * With the restrictions imposed by class constructors, this can only happen + * if this object is an xvalue after move construction or assignment. + */ + bool IsEmpty() const override + { + return m_controlPointsW.IsEmpty() || m_controlPointsI.IsEmpty(); + } + + /*! + * Returns a dynamically allocated copy of this object. + */ + WorldTransformation* Clone() const override + { + return new SplineWorldTransformation( *this ); + } + + /*! + * Transforms from native spherical coordinates to image coordinates. + * + * The point \a p contains native spherical coordinates: \a p.x is the + * native longitude and \a p.y is the native latitude, both expressed in + * degrees. Returns image coordinates in pixels corresponding to \a p. + * + * If grid interpolations have been initialized for this object, and the + * specified point \a p is included in the reference rectangle used for grid + * initialization, they will be used transparently by this member function. + * Otherwise the surface splines will be evaluated directly, which can be + * much slower, depending on the number of control points defined by the + * astrometric solution. + * + * \sa Inverse(), InitializeGridInterpolations() + */ + DPoint Direct( const DPoint& p ) const override + { + if ( m_gridWI.IsValid() ) + if ( m_gridWI.ReferenceRect().IncludesFast( p ) ) + return m_gridWI( p ); + return m_splineWI( p ); + } + + /*! + * Transforms from image coordinates to native spherical coordinates. + * + * The specified point \a p contains image coordinates in pixels. Returns a + * point \a q where \a q.x is the native longitude and \a q.y is the native + * latitude, both expressed in degrees, corresponding to \a p. + * + * If grid interpolations have been initialized for this object, and the + * specified point \a p is included in the reference rectangle used for grid + * initialization, they will be used transparently by this member function. + * Otherwise the surface splines will be evaluated directly, which can be + * much slower, depending on the number of control points defined by the + * astrometric solution. + * + * \sa Direct(), InitializeGridInterpolations() + */ + DPoint Inverse( const DPoint& p ) const override + { + if ( m_gridIW.IsValid() ) + if ( m_gridIW.ReferenceRect().IncludesFast( p ) ) + return m_gridIW( p ); + return m_splineIW( p ); + } + + /*! + * Returns an approximate linear transformation from image to native + * spherical coordinates, computed from the internal point surface splines. + */ + const LinearTransformation& ApproximateLinearTransform() const override + { + return m_linearIW; + } + + /*! + * Initializes the internal grid interpolation devices for the specified + * reference rectangular region \a rect and grid distance \a delta in + * pixels. + * + * A grid distance of 24 pixels is applied by default. This is normally more + * than sufficient to yield accurate coordinate readouts, even for strongly + * distorted images. + * + * See GridInterpolation::Initialize() for detailed information on spline + * grid interpolation and its working parameters. + * + * \note This member function will show no console messages. If some + * feedback must be provided to the user during the potentially long + * operation, it must be given before calling this function. + */ + void InitializeGridInterpolations( const Rect& rect, int delta = 24 ) + { + m_gridWI.Initialize( rect, delta, m_splineWI, false/*verbose*/ ); + m_gridIW.Initialize( rect, delta, m_splineIW, false/*verbose*/ ); + } + + /*! + * Returns true if the internal grid interpolation devices have been + * initialized. See InitializeGridInterpolations() for information on grid + * interpolation. + */ + bool HasGridInterpolations() const + { + return m_gridWI.IsValid() && m_gridIW.IsValid(); + } + + /*! + * Serializes this %SplineWorldTransformation instance in raw binary format + * and stores the result in the specified \a data array. + */ + void Serialize( ByteArray& data ) const; + + /*! + * Returns the number of control points employed to generate the surface + * splines used for coordinate transformations. + * + * The value returned by this function is the length of the original list of + * control points specified upon object construction or deserialization; the + * actual sets of data points being used internally by surface splines are + * usually smaller because surface simplification is enabled by default. + * + * \sa NativeControlPoints(), ImageControlPoints(), GetSplineLengths() + */ + int NumberOfControlPoints() const + { + return int( m_controlPointsW.Length() ); + } + + /*! + * Returns a reference to the list of control points in native spherical + * coordinates. + * + * For each point \e p in the returned array, \e p.x is the native longitude + * and \e p.y is the native latitude, both expressed in degrees. + * + * For each point \a p in the returned array, there is a corresponding point + * \a q in the array of image control points returned by the + * \a ImageControlPoints() member function, whose \e q.x and \e q.y + * components are the image coordinates in pixels corresponding to \e p. + */ + const Array& NativeControlPoints() const + { + return m_controlPointsW; + } + + /*! + * Returns a reference to the list of control points in image coordinates. + * + * For each point \e p in the returned array, \e p.x and \e p.y are the + * components of a control point in image coordinates, expressed in pixels. + * + * For each point \a p in the returned array, there is a corresponding point + * \a q in the array of native control points returned by the + * \a NativeControlPoints() member function, whose \e q.x and \e q.y + * components are the spherical native coordinates in degrees corresponding + * to \e p. + */ + const Array& ImageControlPoints() const + { + return m_controlPointsI; + } + + /*! + * Provides the number of data points in the internal surface splines used + * for coordinate transformations. + * + * \param[out] xWI Number of spline points used for world-to-image + * coordinate transformations on the native longitude + * direction. + * + * \param[out] yWI Number of spline points used for world-to-image + * coordinate transformations on the native latitude + * direction. + * + * \param[out] xIW Number of spline points used for image-to-world + * coordinate transformations on the X-axis direction. + * + * \param[out] yIW Number of spline points used for image-to-world + * coordinate transformations on the Y-axis direction. + */ + void GetSplineLengths( int& xWI, int& yWI, int& xIW, int& yIW ) const + { + xWI = m_splineWI.SplineX().Length(); + yWI = m_splineWI.SplineY().Length(); + xIW = m_splineIW.SplineX().Length(); + yIW = m_splineIW.SplineY().Length(); + } + + /*! + * Returns true iff the lists of transformation control points were + * truncated before generation of surface splines. If surface simplification + * is enabled, truncation may happen, when necessary, after simplification. + * If no simplification is used, truncation may happen directly on the + * original lists of control points. + * + * A maximum of 2100 control points is imposed in the current implementation + * to prevent excessive execution times for surface spline generation, which + * grow approximately with O(n^3) complexity. + */ + bool TruncatedControlPoints() const + { + return m_truncated; + } + + /*! + * Returns true iff the surface simplification algorithm has been enabled + * for generation of surface splines. See the class constructor for more + * information. + */ + bool IsSimplifierEnabled() const + { + return m_enableSimplifier; + } + + /*! + * Returns the tolerance in pixels of the surface simplifier used for + * generation of surface splines. See the class constructor for more + * information. + */ + float SimplifierTolerance() const + { + return m_simplifierTolerance; + } + + /*! + * Returns the outlier rejection fraction of the surface simplifier used for + * generation of surface splines. See the class constructor for more + * information. + */ + float SimplifierRejectFraction() const + { + return m_simplifierRejectFraction; + } + +private: + + Array m_controlPointsW; + Array m_controlPointsI; + int m_order = __PCL_WCS_DEFAULT_SPLINE_ORDER; + float m_smoothness = __PCL_WCS_DEFAULT_SPLINE_SMOOTHNESS; + FVector m_weights; + bool m_enableSimplifier = __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_ENABLED; + float m_simplifierTolerance = __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_TOLERANCE; + float m_simplifierRejectFraction = __PCL_WCS_SURFACE_SIMPLIFIER_DEFAULT_REJECT_FRACTION; + bool m_truncated = false; + PointSurfaceSpline m_splineWI; + PointSurfaceSpline m_splineIW; + PointGridInterpolation m_gridWI; + PointGridInterpolation m_gridIW; + LinearTransformation m_linearIW; + + void Deserialize( const ByteArray& ); + void InitializeSplines(); + void CalculateLinearApproximation(); +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_WorldTransformation_h + +// ---------------------------------------------------------------------------- +// EOF pcl/WorldTransformation.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/XISF.h b/3rdparty/include/pcl/XISF.h new file mode 100644 index 0000000..7d22c8a --- /dev/null +++ b/3rdparty/include/pcl/XISF.h @@ -0,0 +1,1629 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/XISF.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_XISF_h +#define __PCL_XISF_h + +/// \file pcl/XISF.h + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup xisf_support XISF Support Classes + * + * This group of classes can be used to implement %XISF support in PixInsight + * modules as well as in external applications. They don't require a running + * PixInsight core application and don't have dependencies outside the standard + * PCL distribution on all supported platforms. + * + * All publicly declared classes in this group are thread-safe: they can be + * instantiated and their member functions can be called from different threads + * running concurrently. + * + * For introductory usage examples, see the utility command-line applications + * included in the PCL distribution. For an advanced example, see the source + * code of the %XISF format support PixInsight module. + * + * The latest %XISF specification document is available at: + * + * http://pixinsight.com/doc/docs/XISF-1.0-spec/XISF-1.0-spec.html + * + * For general information on %XISF, including the latest news on the format + * and its development: + * + * http://pixinsight.com/xisf/ + */ + +// ---------------------------------------------------------------------------- + +class XISFReaderEngine; +class XISFWriterEngine; + +class PCL_CLASS Compression; +class PCL_CLASS CryptographicHash; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::XISFChecksum + * \brief %XISF block checksum algorithms + * + * + * + * + * + * + * + *
XISFChecksum::Unknown Unknown or unsupported checksum algorithm.
XISFChecksum::None No checksums.
XISFChecksum::SHA1 SHA-1 checksums.
XISFChecksum::SHA256 SHA-256 checksums.
XISFChecksum::SHA512 SHA-512 checksums.
+ * + * \ingroup xisf_support + */ +namespace XISFChecksum +{ + enum value_type + { + Unknown = -1, + None = 0, + SHA1, + SHA256, + SHA512, + NumberOfSupportedAlgorithms + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::XISFCompression + * \brief %XISF block compression codecs + * + * + * + * + * + * + * + * + * + * + *
XISFCompression::Unknown Unknown or unsupported block compression algorithm.
XISFCompression::None No block compression.
XISFCompression::Zlib Zlib compression.
XISFCompression::LZ4 LZ4 compression.
XISFCompression::LZ4HC LZ4-HC compression.
XISFCompression::Zlib_Sh Zlib compression with byte shuffling.
XISFCompression::LZ4_Sh LZ4 compression with byte shuffling.
XISFCompression::LZ4HC_Sh Lz4-HC compression with byte shuffling.
+ * + * \ingroup xisf_support + */ +namespace XISFCompression +{ + enum value_type + { + Unknown = -1, + None = 0, + Zlib, + LZ4, + LZ4HC, + Zlib_Sh, + LZ4_Sh, + LZ4HC_Sh, + NumberOfSupportedCodecs + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::XISFByteOrder + * \brief %XISF block byte order + * + * + * + * + *
XISFByteOrder::LittleEndian Little-endian byte order.
XISFByteOrder::BigEndian Big-endian byte order.
+ * + * \ingroup xisf_support + */ +namespace XISFByteOrder +{ + enum value_type + { + LittleEndian, + BigEndian + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class XISF + * \brief Utility functions, data and constants for %XISF support + * \ingroup xisf_support + */ +class PCL_CLASS XISF +{ +public: + + /*! + * Represents a supported %XISF property type. + */ + typedef VariantType::value_type property_type; + + /*! + * Represents a supported color space. + */ + typedef ColorSpace::value_type color_space; + + /*! + * Represents a supported block checksum algorithm. + */ + typedef XISFChecksum::value_type block_checksum; + + /*! + * Represents a supported block compression codec. + */ + typedef XISFCompression::value_type block_compression; + + /*! + * Represents a block byte order (endianness). + */ + typedef XISFByteOrder::value_type block_endianness; + + /*! + * Default constructor. This constructor is disabled because %XISF is not an + * instantiable class. + */ + XISF() = delete; + + /*! + * Copy constructor. This constructor is disabled because %XISF is not an + * instantiable class. + */ + XISF( const XISF& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %XISF is not an + * instantiable class. + */ + XISF& operator =( const XISF& ) = delete; + + /*! + * Destructor. This destructor is disabled because %XISF is not an + * instantiable class. + */ + ~XISF() = delete; + + /* + * ### N.B.: As of version 1.8.5.1309: Clang on macOS does not know how to + * compile the following constexpr static members, giving buggy 'Undefined + * symbols for architecture x86_64' errors on some modules... + */ +#ifndef __clang__ + + /*! + * Default block size in bytes for optional alignment of %XISF data + * structures. + */ + constexpr static fsize_type DefaultBlockAlignSize = 4096; + + /*! + * Default maximum size in bytes of an inline %XISF block. + */ + constexpr static fsize_type DefaultMaxBlockInlineSize = 3072; // 3072*4/3 = 4096 (base64) + + /*! + * Maximum allowed width or height of an %XISF image thumbnail in pixels. + */ + constexpr static int MaxThumbnailSize = 1024; + + /*! + * Default block checksum algorithm. + */ + constexpr static block_checksum DefaultChecksum = XISFChecksum::None; + + /*! + * Default block compression codec. + */ + constexpr static block_compression DefaultCompression = XISFCompression::None; + + /*! + * Default compression level. This is zero by default, which means that the + * specific compression level used will be chosen as a good compromise for + * the selected compression codec. + */ + constexpr static int DefaultCompressionLevel = 0; + + /*! + * Maximum codec-independent compression level. + */ + constexpr static int MaxCompressionLevel = 100; + + /*! + * The default verbosity level: 0=quiet, 1=normal, 2=quite, >2=very. + */ + constexpr static int DefaultVerbosity = 1; + + /*! + * Whether to replace NaNs, infinities and negative zeros with lower bound + * values (usually zero) in floating point images. This applies only to + * input operations. + */ + constexpr static bool DefaultFixNonFinite = true; + + /*! + * The default lower bound of the output floating point pixel sample range. + */ + constexpr static double DefaultOutputLowerBound = 0.0; + + /*! + * The default upper bound of the output floating point pixel sample range. + */ + constexpr static double DefaultOutputUpperBound = 1.0; + + /*! + * Whether to serialize FITS keywords by default. Has to be true because + * some components of our standard tool set still depend heavily on FITS + * keywords. Should be false, and it will be, eventually. + */ + constexpr static bool DefaultStoreFITSKeywords = true; + + /*! + * Whether to ignore existing FITS keywords by default. Has to be false + * because some components of our standard tool set still depend heavily on + * FITS keywords. Should be true, and it will be, eventually. + */ + constexpr static bool DefaultIgnoreFITSKeywords = false; + + /*! + * Whether to import FITS keywords as %XISF properties by default. Can be + * useful for digestions of data stored in legacy formats, but is a bad idea + * on a regular basis. + */ + constexpr static bool DefaultImportFITSKeywords = false; + + /*! + * Whether to ignore all embedded data by default. + */ + constexpr static bool DefaultIgnoreEmbeddedData = false; + + /*! + * Whether to ignore embedded image properties by default. + */ + constexpr static bool DefaultIgnoreProperties = false; + + /*! + * Whether to generate %XISF standard metadata properties by default. + */ + constexpr static bool DefaultAutoMetadata = true; + + /*! + * Whether to silent warning conditions by default. + */ + constexpr static bool DefaultNoWarnings = false; + + /*! + * Whether to treat warnings as unrecoverable errors by default. + */ + constexpr static bool DefaultWarningsAreErrors = false; + + /*! + * The namespace prefix of all %XISF reserved properties. + */ + constexpr static const char* InternalNamespacePrefix = "XISF:"; + +#else + + static const fsize_type DefaultBlockAlignSize; + static const fsize_type DefaultMaxBlockInlineSize; + static const int MaxThumbnailSize; + static const block_checksum DefaultChecksum; + static const block_compression DefaultCompression; + static const int DefaultCompressionLevel; + static const int MaxCompressionLevel; + static const int DefaultVerbosity; + static const bool DefaultFixNonFinite; + static const double DefaultOutputLowerBound; + static const double DefaultOutputUpperBound; + static const bool DefaultStoreFITSKeywords; + static const bool DefaultIgnoreFITSKeywords; + static const bool DefaultImportFITSKeywords; + static const bool DefaultIgnoreEmbeddedData; + static const bool DefaultIgnoreProperties; + static const bool DefaultAutoMetadata; + static const bool DefaultNoWarnings; + static const bool DefaultWarningsAreErrors; + static const char* InternalNamespacePrefix; + +#endif // !__clang__ + + /*! + * Returns the identifier of a pixel sample data type. Used as %XML element + * attribute values in %XISF headers. + * + * %XISF 1.0 supports seven pixel sample formats: + * + * \li 32-bit IEEE 754 floating point real (float) + * \li 64-bit IEEE 754 floating point real (double) + * \li 32-bit IEEE 754 floating point complex (fcomplex) + * \li 64-bit IEEE 754 floating point complex (dcomplex) + * \li 8-bit unsigned integer real (uint8) + * \li 16-bit unsigned integer real (uint16) + * \li 32-bit unsigned integer real (uint32) + */ + static const char* SampleFormatId( int bitsPerSample, bool floatSample, bool complexSample ); + + /*! + * Returns the identifier of the pixel sample data type corresponding to the + * specified \a image. + */ + template + static const char* SampleFormatId( const GenericImage

& image ) + { + return SampleFormatId( P::BitsPerSample(), P::IsFloatSample(), P::IsComplexSample() ); + } + + /*! + * Provides the parameters (bit size, complex/float/integer format) of a + * pixel sample format, given its identifier. Used for deserialization from + * %XML file headers. + */ + static bool GetSampleFormatFromId( int& bitsPerSample, bool& floatSample, bool& complexSample, const String& id ); + + /*! + * Returns the identifier of a color space. Used as %XML element attribute + * values in %XISF headers. + * + * XISF 1.0 supports three color spaces: + * + * \li Grayscale + * \li RGB + * \li CIE L*a*b* + * + * For more information on color spaces, see RGBColorSystem. + */ + static const char* ColorSpaceId( color_space colorSpace ); + + /*! + * Returns the identifier of the color space corresponding to the specified + * \a image. + */ + static const char* ColorSpaceId( const AbstractImage& image ) + { + return ColorSpaceId( image.ColorSpace() ); + } + + /*! + * Returns a color space, given its identifier. Used for deserialization + * from %XML file headers. + */ + static color_space ColorSpaceFromId( const String& id ); + + /*! + * Returns the identifier of a property data \a type. Used as %XML element + * attribute values in %XISF headers. + * + * %XISF can store image properties in a variety of scalar, vector and + * matrix types. See the code below and pcl/Variant.h for details. + */ + static const char* PropertyTypeId( property_type type ); + + /*! + * Get a property data type, given its identifier. Used for deserialization + * from %XML file headers. + */ + static property_type PropertyTypeFromId( const String& id ); + + /*! + * Returns the identifier of a supported compression \a codec. Used as %XML + * element attribute values in %XISF headers. + */ + static const char* CompressionCodecId( block_compression codec ); + + /*! + * Returns a compression codec, given its identifier. Used for + * deserialization from %XML file headers. + */ + static block_compression CompressionCodecFromId( const String& id ); + + /*! + * Returns a pointer to a dynamically allocated Compression object. The + * returned object implements the specified compression \a codec. + * \a itemSize is the length in bytes of a data element, for byte shufflig. + */ + static Compression* NewCompression( block_compression codec, size_type itemSize = 1 ); + + /*! + * Returns the codec-specific compression level to be used for the specified + * compression \a codec and abstract compression \a level. + */ + static int CompressionLevelForMethod( block_compression codec, int level ); + + /*! + * Returns true iff the specified compression \a codec uses byte shuffling + * to preprocess uncompressed data. + */ + static bool CompressionUsesByteShuffle( block_compression codec ); + + /*! + * Given a compression \a codec, returns the equivalent codec without byte + * shuffling. + */ + static block_compression CompressionCodecNoShuffle( block_compression codec ); + + /*! + * Returns true iff a compression \a codec needs to know the size of each + * element in a compressed block (for example, for byte shuffling). + */ + static bool CompressionNeedsItemSize( block_compression codec ); + + /*! + * Returns the identifier of a supported checksum \a algorithm. Used as %XML + * element attribute values in %XISF headers. + */ + static const char* ChecksumAlgorithmId( block_checksum algorithm ); + + /*! + * Returns a checksum algorithm, given its identifier. Used for + * deserialization from %XML file headers. + */ + static block_checksum ChecksumAlgorithmFromId( const String& id ); + + /*! + * Returns the length in bytes of a cryptographic digest computed with the + * specified \a algorithm. + */ + static size_type ChecksumLength( block_checksum algorithm ); + + /*! + * Returns a pointer to a dynamically allocated CryptographicHash object. + * The returned object implements the specified hashing \a algorithm. + */ + static CryptographicHash* NewCryptographicHash( block_checksum algorithm ); + + /*! + * Returns true iff the specified string \a id is a valid XISF property + * identifier. + * + * A valid XISF property identifier is a sequence: + * + * t1[:t2[:...:tn]] + * + * where each \a ti satisfies the following conditions: + * + * \li It is not an empty string. + * + * \li Its first character is either an alphabetic character or an + * underscore character. + * + * \li Its second and successive characters, if they exist, are all of them + * either alphabetic characters, decimal digits, or underscores. + */ + static bool IsValidPropertyId( const IsoString& id ) + { + return Property::IsValidIdentifier( id ); + } + + static bool IsValidPropertyId( const IsoString::ustring_base& id ) + { + return IsValidPropertyId( IsoString( id ) ); + } + + /*! + * Returns true iff the specified string \a id is the identifier of a + * reserved %XISF property. + * + * Property identifiers starting with the XISF: namespace prefix are + * reserved by the %XISF format and cannot be defined by external client + * applications. + */ + static bool IsInternalPropertyId( const IsoString& id ) + { + return id.StartsWith( InternalNamespacePrefix ); + } + + static bool IsInternalPropertyId( const IsoString::ustring_base& id ) + { + return IsInternalPropertyId( IsoString( id ) ); + } + + /*! + * Returns a property identifier 'internalized' with the XISF: prefix. + */ + static IsoString InternalPropertyId( const IsoString& id ) + { + if ( !IsInternalPropertyId( id ) ) + return InternalNamespacePrefix + id; + return id; + } + + static IsoString InternalPropertyId( const IsoString::ustring_base& id ) + { + return InternalPropertyId( IsoString( id ) ); + } + + /*! + * Ensures that the internal pixel traits lookup tables have been properly + * allocated and initialized. This is a thread-safe function used internally + * by the XISFReader and XISFWriter classes to accelerate conversions among + * all supported pixel sample data types. This allows external applications + * to perform image I/O operations without a running PixInsight core + * application. + * + * \note This is an internal routine. You normally should not need to call + * it, unless you are hacking the current %XISF implementation. + */ + static void EnsurePTLUTInitialized(); +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XISFOptions + * \brief %XISF-specific file options + * + * This structure stores a collection of settings and options that control the + * way %XISF units are loaded and generated by this implementation. + * + * %XISFOptions, along with ImageOptions, allow client modules and applications + * to manipulate properties and images serialized in %XISF units with a high + * degree of flexibility, tailoring them to the needs of each application. + * + * \ingroup xisf_support + */ +class PCL_CLASS XISFOptions +{ +public: + + bool storeFITSKeywords : 1; //!< Include FITS header keywords in output %XISF files. + bool ignoreFITSKeywords : 1; //!< Do not load FITS keywords from input %XISF files. + bool importFITSKeywords : 1; //!< Import FITS keywords as %XISF properties. + bool ignoreEmbeddedData : 1; //!< Do not load existing embedded data (such as ICC profiles for example). + bool ignoreProperties : 1; //!< Do not load existing %XISF properties. + bool autoMetadata : 1; //!< Automatically generate a number of reserved %XISF properties. + bool noWarnings : 1; //!< Suppress all warning and diagnostics messages. + bool warningsAreErrors : 1; //!< Treat warnings as fatal errors. + XISF::block_checksum checksumAlgorithm : 4; //!< The algorithm used for block checksum calculations. + XISF::block_compression compressionCodec : 4; //!< The codec used for compression of %XISF blocks. + uint8 compressionLevel : 7; //!< Codec-independent compression level: 0 = auto, 1 = fast, 100 = maximum compression. + uint8 verbosity : 3; //!< Verbosity level: 0 = quiet, > 0 = write console state messages. + bool fixNonFinite : 1; //!< Replace NaNs, infinities and negative zeros with lower bound values in floating point images (reading only). + uint16 blockAlignmentSize; //!< Block alignment size in bytes (0 = 1 = unaligned). + uint16 maxInlineBlockSize; //!< Maximum size in bytes of an inline/embedded block. + double outputLowerBound; //!< Lower bound for output floating point pixel samples (=0.0 by default). + double outputUpperBound; //!< Upper bound for output floating point pixel samples (=1.0 by default). + + /*! + * Constructs a default set of %XISF format-specific options. + */ + XISFOptions() + { + Reset(); + } + + /*! + * Copy constructor. + */ + XISFOptions( const XISFOptions& ) = default; + + /*! + * Copy-assignment operator. Returns a reference to this object. + */ + XISFOptions& operator =( const XISFOptions& ) = default; + + /*! + * Resets this object to a default set of format-specific options. + */ + void Reset() + { + storeFITSKeywords = XISF::DefaultStoreFITSKeywords; + ignoreFITSKeywords = XISF::DefaultIgnoreFITSKeywords; + importFITSKeywords = XISF::DefaultImportFITSKeywords; + ignoreEmbeddedData = XISF::DefaultIgnoreEmbeddedData; + ignoreProperties = XISF::DefaultIgnoreProperties; + autoMetadata = XISF::DefaultAutoMetadata; + noWarnings = XISF::DefaultNoWarnings; + warningsAreErrors = XISF::DefaultWarningsAreErrors; + checksumAlgorithm = XISF::DefaultChecksum; + compressionCodec = XISF::DefaultCompression; + compressionLevel = XISF::DefaultCompressionLevel; + verbosity = XISF::DefaultVerbosity; + fixNonFinite = XISF::DefaultFixNonFinite; + blockAlignmentSize = XISF::DefaultBlockAlignSize; + maxInlineBlockSize = XISF::DefaultMaxBlockInlineSize; + outputLowerBound = XISF::DefaultOutputLowerBound; + outputUpperBound = XISF::DefaultOutputUpperBound; + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \struct XISFFileSignature + * \brief %XISF monolithic file signature + * + * All %XISF version 1.0 monolithic files begin with the following sequence: + * + * XISF0100<header-length><reserved> + * + * where 'XISF0100' is the 'magic marker' identifying the format, and + * <header-length> is the size in bytes of the XML file header encoded as + * a 32-bit unsigned integer with little-endian byte order. <reserved> is + * a 32-bit integer reserved for future use; it must be zero. After the file + * signature sequence comes the %XML header and all attached blocks. + * + * \ingroup xisf_support + */ +struct PCL_CLASS XISFFileSignature +{ + uint8 magic[ 8 ] = { 'X', 'I', 'S', 'F', '0', '1', '0', '0' }; + uint32 headerLength = 0; // length in bytes of the XML file header + uint32 reserved = 0; // reserved - must be zero + + /*! + * Default constructor. Yields an invalid %XISF signature that cannot be + * used without explicit initialization. + */ + XISFFileSignature() = default; + + /*! + * Copy constructor. + */ + XISFFileSignature( const XISFFileSignature& ) = default; + + /*! + * Copy assignment operator. Returns a reference to this object. + */ + XISFFileSignature& operator =( const XISFFileSignature& ) = default; + + /*! + * Constructs a monolithic %XISF file signature initialized for the + * specified header \a length. + */ + XISFFileSignature( uint32 length ) + : headerLength( length ) + { + } + + /*! + * Validates this monolithic %XISF file signature. Throws an Error exception + * if it is not valid. + */ + void Validate() const; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::XISFMessageType + * \brief %XISF log message types + * + * + * + * + * + * + *
XISFMessageType::Informative A regular informative message.
XISFMessageType::Note A note or remark message.
XISFMessageType::Warning A warning message.
XISFMessageType::RecoverableError A recoverable error message.
+ * + * \ingroup xisf_support + * \sa XISFLogHandler + */ +namespace XISFMessageType +{ + enum value_type + { + Informative, + Note, + Warning, + RecoverableError + }; +} + +// ---------------------------------------------------------------------------- + +/*! + * \class XISFLogHandler + * \brief %XISF stream message logger + * + * %XISFLogHandler is a simple handler object which logs messages generated + * by the XISFReader and XISFWriter classes during %XISF file transactions. + * These messages can be informative, warnings, and recoverable error messages. + * + * Note that unrecoverable errors are not logged and hence not sent to this + * class (or derived); they are always thrown as Exception instances, which the + * caller must catch and manage appropriately. + * + * \ingroup xisf_support + * \sa XISFReader, XISFWriter + */ +class PCL_CLASS XISFLogHandler +{ +public: + + /*! + * Represents a log message type. Supported values are enumerated in the + * XISFMessageType namespace. + */ + typedef XISFMessageType::value_type message_type; + + /*! + * Default constructor. + */ + XISFLogHandler() = default; + + /*! + * Virtual destructor. + */ + virtual ~XISFLogHandler() + { + } + + /*! + * Initializes this log handler object. This function will be called by + * internal XISFReader and XISFWriter engines at the beginning of an %XISF + * file transaction. + * + * \param filePath Full path to the %XISF file about to be loaded or + * generated. + * + * \param writing Will be true at the beginning of a file generation + * process; false at the beginning of a file loading + * process. + * + * The default implementation does nothing. This virtual function can be + * reimplemented in a derived class requiring special initialization at the + * beginning of a file loading or generation process. + */ + virtual void Init( const String& filePath, bool writing ) + { + } + + /*! + * Handles a log message. This function will be called by internal + * XISFReader and XISFWriter engines at different points during %XISF file + * transactions. + * + * \param text The log text message. + * + * \param type The type of this log message. See the XISFMessageType + * namespace for possible values. + * + * The default implementation does nothing. This virtual function should be + * reimplemented in a derived class. Typically, the received \a text + * messages are sent directly to the platform console; for example, the + * standard %XISF format support module does just that. Other options are + * writing messages to text files, or sending them to other processes. + */ + virtual void Log( const String& text, message_type type ) + { + } + + /*! + * Closes this log handler object. This function will be called by internal + * XISFReader and XISFWriter engines at the end of an %XISF file + * transaction. + * + * The default implementation does nothing. This virtual function can be + * reimplemented in a derived class requiring special cleanup or + * initialization at the end of a file loading or generation process. + */ + virtual void Close() + { + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XISFReader + * \brief %XISF input file stream + * + * %XISFReader allows you to read properties, images and metadata serialized in + * monolithic %XISF units stored as local files. This class can be used without + * a running PixInsight core application to implement %XISF support in external + * applications. + * + * \ingroup xisf_support + * \sa XISFWriter + */ +class PCL_CLASS XISFReader +{ +public: + + /*! + * Constructs an %XISFReader object. The stream is created in a default + * closed state. + */ + XISFReader(); + + /*! + * Destroys an %XISFReader object. If the stream is open, the destructor + * calls the Close() member function before destroying this object. + */ + virtual ~XISFReader() noexcept( false ); + + /* + * Copy constructor. This constructor is disabled because %XISF streams are + * unique objects. + */ + XISFReader( const XISFReader& ) = delete; + + /* + * Copy assignment. This operator is disabled because %XISF streams are + * unique objects. + */ + XISFReader& operator =( const XISFReader& ) = delete; + + /*! + * Define a set of format-specific \a options. + */ + void SetOptions( const pcl::XISFOptions& options ); + + /*! + * Returns the current set of format-specific options. + */ + pcl::XISFOptions Options() const + { + return m_options; + } + + /*! + * Tell the reader which format hints have been specified, for inclusion as + * a reserved metadata property. + */ + void SetHints( const IsoString& ); + + /*! + * Associates a log \a handler with this %XISF input stream. + * + * The specified \a handler object must be allocated dynamically by the + * caller. It will be owned by this %XISFReader instance, which will destroy + * and deallocate it when appropriate. To force destruction of the + * associated log handler (if any), call this function with a null pointer + * as argument. + */ + void SetLogHandler( XISFLogHandler* handler ); + + /*! + * Returns true iff this stream is currently open for file read operations. + * The stream is open only after a successful call to Open(). + */ + bool IsOpen() const; + + /*! + * Opens an existing file for reading at the specified file \a path. + */ + void Open( const String& path ); + + /*! + * If this stream is open, closes the disk file and clears all internal data + * structures. If this stream is closed, calling this member function has no + * effect. + */ + void Close(); + + /*! + * Returns the full path of the file being accessed through this %XISFReader + * object, or an empty string if no file has been opened. + */ + String FilePath() const; + + /*! + * Returns the number of images available in this %XISF input stream. + */ + int NumberOfImages() const; + + /*! + * Sets the current image \a index in this input stream. \a index must be + * in the range [0,NumberOfImages()-1]. + */ + void SelectImage( int index ); + + /*! + * Returns the index of the currently selected image, or -1 if either no + * file has been opened, or if the file does not contain any images. + */ + int SelectedImageIndex() const; + + /*! + * Returns geometry and color space parameters for the current image in this + * input stream. + */ + pcl::ImageInfo ImageInfo() const; + + /*! + * Returns format-independent options corresponding to the current image in + * this input stream. + */ + pcl::ImageOptions ImageOptions() const; + + /*! + * Defines a new set of format-independent options for the current image in + * this input stream. + * + * Only options that modify the reading behavior of the stream will be taken + * into account; the rest will be ignored, irrespective of their values. + */ + void SetImageOptions( const pcl::ImageOptions& options ); + + /*! + * Returns the identifier of the current image in this input stream. + * + * If no identifier is available for the current image, if no file has been + * opened, or if the current file contains no images, this function returns + * an empty string. + */ + IsoString ImageId() const; + + /*! + * Extracts a list of FITS header keywords from the current image in this + * input stream, and returns the extracted keywords as a dynamic array. + * + * If no FITS keywords are available for the current image, if no file has + * been opened, or if the current file contains no images, this function + * returns an empty array. + */ + FITSKeywordArray ReadFITSKeywords(); + + /*! + * Extracts an ICC profile from the current image in this input stream, and + * returns the extracted ICC profile structure. + * + * If no ICC profile is available for the current image, if no file has been + * opened, or if the current file contains no images, this function returns + * an empty ICCProfile structure. + */ + ICCProfile ReadICCProfile(); + + /*! + * Extracts a thumbnail image from the current image in this input stream, + * and returns the extracted thumbnail as an 8-bit unsigned integer image. + * + * If no thumbnail is available for the current image, if no file has been + * opened, or if the current file contains no images, this function returns + * an empty image. + */ + UInt8Image ReadThumbnail(); + + /*! + * Extracts RGB working space parameters from the current image in this + * input stream, and returns them as a RGBColorSystem object. + * + * If no RGB working space has been defined for the current image, if no + * file has been opened, or if the current file contains no images, this + * function returns a duplicate of the sRGB color space, since this is the + * default %XISF color space. + */ + RGBColorSystem ReadRGBWorkingSpace(); + + /*! + * Extracts display function parameters from the current image in this input + * stream, and returns them as a pcl::DisplayFunction object. + * + * If no display function has been defined for the current image, if no file + * has been opened, or if the current file contains no images, this function + * returns an identity display function. + */ + DisplayFunction ReadDisplayFunction(); + + /*! + * Extracts a color filter array (CFA) description from the current image in + * this input stream, and returns it as a pcl::ColorFilterArray object. + * + * If no CFA has been defined for the current image, if no file has been + * opened, or if the current file contains no images, this function returns + * an invalid ColorFilterArray instance. + */ + ColorFilterArray ReadColorFilterArray(); + + /*! + * Returns a list of property identifiers and data types describing the set + * of properties associated with the current image in this %XISF unit. The + * returned list can be empty if no image is available, or if the current + * image has no properties. + */ + PropertyDescriptionArray ImagePropertyDescriptions() const; + + /*! + * Extracts a \a property from the current image with the specified + * \a identifier, and returns its value as a Variant object. + * + * If no property with the specified \a identifier is available for the + * current image, if no file has been opened, or if the current file + * contains no images, this function returns an invalid %Variant object. + */ + Variant ReadImageProperty( const IsoString& identifier ); + + /*! + * Returns an array with all properties extracted from the current image. + * + * If no property is available for the current image, if no file has been + * opened, or if the current file contains no images, this function returns + * an empty array. + */ + PropertyArray ReadImageProperties(); + + /*! + * Returns a list of property identifiers and data types describing the set + * of properties associated with the %XISF unit. The returned list can be + * empty if no file has been opened, or if the %XISF unit has no properties. + */ + PropertyDescriptionArray PropertyDescriptions() const; + + /*! + * Extracts a \a property associated with the %XISF unit with the specified + * \a identifier, and returns its value as a Variant object. + * + * If no property with the specified \a identifier is available for this + * %XISF unit, or if no file has been opened, this function returns an + * invalid %Variant object. + */ + Variant ReadProperty( const IsoString& identifier ); + + /*! + * Returns an array with all properties associated with the %XISF unit. + * + * If no property is available for the %XISF unit, or if no file has been + * opened, this function returns an empty array. + */ + PropertyArray ReadProperties(); + + /*! + * Reads a 32-bit floating point image from this input stream. + */ + void ReadImage( FImage& image ); + + /*! + * Reads a 64-bit floating point image from this input stream. + */ + void ReadImage( DImage& image ); + + /*! + * Reads a 32-bit floating point complex image from this input stream. + */ + void ReadImage( ComplexImage& image ); + + /*! + * Reads a 64-bit floating point complex image from this input stream. + */ + void ReadImage( DComplexImage& image ); + + /*! + * Reads an 8-bit unsigned integer image from this input stream. + */ + void ReadImage( UInt8Image& image ); + + /*! + * Reads a 16-bit unsigned integer image from this input stream. + */ + void ReadImage( UInt16Image& image ); + + /*! + * Reads a 32-bit unsigned integer image from this input stream. + */ + void ReadImage( UInt32Image& image ); + + /*! + * Returns true iff this stream supports incremental read operations. + * + * Incremental reads are not supported for compressed images. The reader + * will be forced to load and uncompresses a compressed image transparently + * upon the first call to a ReadSamples() member function, and the entire + * pixel data of the image will be stored in a temporary memory buffer. + * Pixel samples returned by succesive calls to ReadSamples() will be copied + * from this temporary buffer. Note that this is just a convenience feature + * that provides none of the benefits of incremental stream I/O operations. + */ + bool ImplementsIncrementalRead() const; + + /*! + * Incremental random access read of 32-bit floating point pixel samples. + * + * \param[out] buffer Address of the destination pixel sample buffer. + * \param startRow First pixel row to read. + * \param rowCount Number of pixel rows to read. + * \param channel Channel index to read. + */ + void ReadSamples( FImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental random access read of 64-bit floating point pixel samples. + * + * This is an overloaded member function for the DImage type; see + * ReadSamples( Image::sample*, int, int, int ) for a full description. + */ + void ReadSamples( DImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental random access read of 32-bit complex pixel samples. + * + * This is an overloaded member function for the ComplexImage type; see + * ReadSamples( Image::sample*, int, int, int ) for a full description. + */ + void ReadSamples( ComplexImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental random access read of 64-bit complex pixel samples. + * + * This is an overloaded member function for the DComplexImage type; see + * ReadSamples( Image::sample*, int, int, int ) for a full description. + */ + void ReadSamples( DComplexImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental random access read of 8-bit unsigned integer pixel samples. + * + * This is an overloaded member function for the UInt8Image type; see + * ReadSamples( Image::sample*, int, int, int ) for a full description. + */ + void ReadSamples( UInt8Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental random access read of 16-bit unsigned integer pixel samples. + * + * This is an overloaded member function for the UInt16Image type; see + * ReadSamples( Image::sample*, int, int, int ) for a full description. + */ + void ReadSamples( UInt16Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental random access read of 32-bit unsigned integer pixel samples. + * + * This is an overloaded member function for the UInt32Image type; see + * ReadSamples( Image::sample*, int, int, int ) for a full description. + */ + void ReadSamples( UInt32Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Extract and parse the %XML header document of an existing monolithic + * %XISF file at the specified \a path, and return it as a dynamically + * allocated instance of XMLDocument. + * + * Ownership of the returned object is transferred to the caller, who is + * responsible for destroying it when appropriate. + * + * This function will throw an Error exception if either the file is not a + * monolithic %XISF unit, or the header is not a well-formed %XML document. + * The header is not verified for validity or correctness as per the %XISF + * format specification; only well-formedness of the XML document is + * checked. + */ + static XMLDocument* ExtractHeader( const String& path, XMLParserOptions options = XMLParserOptions() ); + +private: + + AutoPointer m_engine; + AutoPointer m_logHandler; + XISFOptions m_options; + IsoString m_hints; + + void CheckOpenStream( const char* ) const; + void CheckClosedStream( const char* ) const; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XISFWriter + * \brief %XISF output file stream + * + * %XISFWriter allows you to write properties, images and metadata serialized + * in monolithic %XISF units stored as local files. This class can be used + * without a running PixInsight core application to implement %XISF support in + * external applications. + * + * \ingroup xisf_support + * \sa XISFReader + */ +class PCL_CLASS XISFWriter +{ +public: + + /*! + * Constructs an %XISFWriter object. The stream is created in a default + * closed state. + */ + XISFWriter(); + + /*! + * Destroys an %XISFWriter object. If the stream is open, the destructor + * calls the Close() member function before destroying the object. + */ + virtual ~XISFWriter() noexcept( false ); + + /* + * Copy constructor. This constructor is disabled because %XISF streams are + * unique objects. + */ + XISFWriter( const XISFWriter& ) = delete; + + /* + * Copy assignment. This operator is disabled because %XISF streams are + * unique objects. + */ + XISFWriter& operator =( const XISFWriter& ) = delete; + + /*! + * Define a set of format-specific \a options. + */ + void SetOptions( const pcl::XISFOptions& options ); + + /*! + * Returns the current set of format-specific options. + */ + pcl::XISFOptions Options() const + { + return m_options; + } + + /*! + * Tell the writer which format hints have been specified, for inclusion as + * a reserved metadata property. + */ + void SetHints( const IsoString& ); + + /*! + * Associates a log \a handler with this %XISF output stream. + * + * The specified \a handler object must be allocated dynamically by the + * caller. It will be owned by this %XISFReader instance, which will destroy + * and deallocate it when appropriate. To force destruction of the + * associated log handler (if any), call this function with a null pointer + * as argument. + */ + void SetLogHandler( XISFLogHandler* handler ); + + /*! + * Sets the value of the %XISF:CreatorApplication reserved metadata property + * to be included in newly created %XISF units. + * + * The %XISF:CreatorApplication property is mandatory. If this + * implementation is being used in an installed PixInsight module (such as + * the standard %XISF format support module for example), this property will + * be generated automatically by retrieving version information from the + * running PixInsight core application, and the value set with this function + * will be ignored. If this implementation is used in an external + * application, calling this function with the appropriate application name + * (including version information) is \e mandatory. See the %XISF + * specification for more information on reserved metadata properties. + */ + void SetCreatorApplication( const String& appName ); + + /*! + * Sets the value of the %XISF:CreatorModule reserved metadata property to + * be included in newly created %XISF units. + * + * The %XISF:CreatorModule property is optional. If this implementation is + * being used in an installed PixInsight module (such as the standard %XISF + * format support module for example), this property will be generated + * automatically by retrieving the name and version of the running module, + * and the value set with this function will be ignored. If this + * implementation is being used in an external application, the value set by + * calling this function will be used. If no CreatorModule is defined, the + * corresponding metadata property will not be generated. See the %XISF + * specification for more information on reserved metadata properties. + */ + void SetCreatorModule( const String& modName ); + + /*! + * Returns true iff this stream is currently open for file write operations. + * The stream is open only after a successful call to Create(). + */ + bool IsOpen() const; + + /*! + * Creates a new file for writing at the specified \a path, and prepares to + * write \a count images and their embedded data. + */ + void Create( const String& path, int count ); + + /*! + * If this stream is open, flushes all pending file write operations, closes + * the disk file, and clears all internal data structures. If this stream is + * closed, calling this member function has no effect. + */ + void Close(); + + /*! + * Returns the full path of the output file being accessed through this + * %XISFWriter object, or an empty string if no file has been created. + */ + String FilePath() const; + + /*! + * Defines a new set of format-independent options for the next image + * written by this output stream. + * + * Only options that modify the writing behavior of the stream will be taken + * into account; the rest will be ignored, irrespective of their values. + */ + void SetImageOptions( const ImageOptions& options ); + + /*! + * Sets the identifier of the current image (that is, of the next image that + * will be written) in this input stream. + */ + void SetImageId( const IsoString& id ); + + /*! + * Embeds a set of %FITS header \a keywords in the current image of this + * output stream. + */ + void WriteFITSKeywords( const FITSKeywordArray& keywords ); + + /*! + * Returns the list of %FITS header keywords embedded in the current image. + * This is necessary because the PixInsight core application has an option + * to reload the list of keywords actually embedded after writing a new + * image. Client applications without this requirement can safely ignore + * this member function. + */ + const FITSKeywordArray& FITSKeywords() const; + + /*! + * Embeds an ICC \a profile in the current image of this output stream. + */ + void WriteICCProfile( const ICCProfile& profile ); + + /*! + * Embeds an 8-bit \a thumbnail image in the current image of this output + * stream. + */ + void WriteThumbnail( const UInt8Image& thumbnail ); + + /*! + * Defines RGB working space parameters for the current image of this output + * stream. + */ + void WriteRGBWorkingSpace( const RGBColorSystem& rgbws ); + + /*! + * Defines display function parameters for the current image of this output + * stream. + */ + void WriteDisplayFunction( const DisplayFunction& df ); + + /*! + * Embeds a color filter array (CFA) description for the current image of + * this output stream. + */ + void WriteColorFilterArray( const ColorFilterArray& cfa ); + + /*! + * Associates a property with the specified \a identifier and \a value with + * the current image in this output stream. + */ + void WriteImageProperty( const IsoString& identifier, const Variant& value ); + + /*! + * Associates a set of \a properties with the current image in this output + * stream. + */ + void WriteImageProperties( const PropertyArray& properties ); + + /*! + * Removes a property with the specified \a identifier from the list of + * properties associated with the current image. If no property with the + * specified \a identifier has been defined for the current image, this + * member function takes no action. + */ + void RemoveImageProperty( const IsoString& identifier ); + + /*! + * Associates a property with the specified \a identifier and \a value with + * the %XISF unit being generated by this output stream. + */ + void WriteProperty( const IsoString& identifier, const Variant& value ); + + /*! + * Associates a set of \a properties with the %XISF unit being generated by + * this output stream. + */ + void WriteProperties( const PropertyArray& properties ); + + /*! + * Removes a property with the specified \a identifier from the list of + * properties associated with the %XISF unit. If no property with the + * specified \a identifier has been defined previously, this member function + * takes no action. + */ + void RemoveProperty( const IsoString& identifier ); + + /*! + * Writes a 32-bit floating point image to this output stream. + */ + void WriteImage( const Image& image ); + + /*! + * Writes a 64-bit floating point image to this output stream. + */ + void WriteImage( const DImage& image ); + + /*! + * Writes a 32-bit floating point complex image to this output stream. + */ + void WriteImage( const ComplexImage& image ); + + /*! + * Writes a 64-bit floating point complex image to this output stream. + */ + void WriteImage( const DComplexImage& image ); + + /*! + * Writes an 8-bit unsigned integer image to this output stream. + */ + void WriteImage( const UInt8Image& image ); + + /*! + * Writes a 16-bit unsigned integer image to this output stream. + */ + void WriteImage( const UInt16Image& image ); + + /*! + * Writes a 32-bit unsigned integer image to this output stream. + */ + void WriteImage( const UInt32Image& image ); + + /*! + * Writes the specified \a image to this output stream. + */ + void WriteImage( const ImageVariant& image ); + + /*! + * Creates a new image with the specified geometry and color space, and + * prepare for sequential/random write access. + * + * The data type and other image parameters are defined by the current set + * of format-independent options (see SetImageOptions()). + */ + void CreateImage( const ImageInfo& info ); + + /*! + * Incremental/random write of 32-bit floating point pixel samples. + * + * \param buffer Address of the source pixel sample buffer. + * \param startRow First pixel row to write. + * \param rowCount Number of pixel rows to write. + * \param channel Channel index to write. + */ + void WriteSamples( const FImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental/random write of 64-bit floating point pixel samples. + * + * This is an overloaded member function for the DImage type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full + * description. + */ + void WriteSamples( const DImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental/random write of 32-bit complex pixel samples. + * + * This is an overloaded member function for the ComplexImage type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full + * description. + */ + void WriteSamples( const ComplexImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental/random write of 64-bit complex pixel samples. + * + * This is an overloaded member function for the DComplexImage type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full + * description. + */ + void WriteSamples( const DComplexImage::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental/random write of 8-bit unsigned integer pixel samples. + * + * This is an overloaded member function for the UInt8Image type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full + * description. + */ + void WriteSamples( const UInt8Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental/random write of 16-bit unsigned integer pixel samples. + * + * This is an overloaded member function for the UInt16Image type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full + * description. + */ + void WriteSamples( const UInt16Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Incremental/random write of 32-bit unsigned integer pixel samples. + * + * This is an overloaded member function for the UInt32Image type; see + * WriteSamples( const Image::sample*, int, int, int ) for a full + * description. + */ + void WriteSamples( const UInt32Image::sample* buffer, int startRow, int rowCount, int channel ); + + /*! + * Complete the image created by a previous call to CreateImage() and + * generate it in the output stream. + */ + void CloseImage(); + +private: + + AutoPointer m_engine; + AutoPointer m_logHandler; + XISFOptions m_options; + IsoString m_hints; + String m_creatorApplication; + String m_creatorModule; + + void CheckOpenStream( const char* ) const; + void CheckClosedStream( const char* ) const; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_XISF_h + +// ---------------------------------------------------------------------------- +// EOF pcl/XISF.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/XML.h b/3rdparty/include/pcl/XML.h new file mode 100644 index 0000000..b353873 --- /dev/null +++ b/3rdparty/include/pcl/XML.h @@ -0,0 +1,3038 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/XML.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_XML_h +#define __PCL_XML_h + +/// \file pcl/XML.h + +#include + +#include +#include +#include + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \defgroup xml_parsing_and_generation XML Document Parsing and Generation + */ + +// ---------------------------------------------------------------------------- + +class PCL_CLASS XMLDocument; +class PCL_CLASS XMLElement; + +// ---------------------------------------------------------------------------- + +/*! + * \class XML + * \brief Utility functions and data for %XML document parsing and generation + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XML +{ +public: + + /*! + * Default constructor. This constructor is disabled because %XML is not an + * instantiable class. + */ + XML() = delete; + + /*! + * Copy constructor. This constructor is disabled because %XML is not an + * instantiable class. + */ + XML( const XML& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %XML is not an + * instantiable class. + */ + XML& operator =( const XML& ) = delete; + + /*! + * Destructor. This destructor is disabled because %XML is not an + * instantiable class. + */ + ~XML() = delete; + + /*! + * Returns true iff the specified character \a c is either a white space + * (\#x20) or a tabulator (#9) character. + */ + template + static bool IsWhiteSpaceChar( T c ) + { + return c == 0x20 || c == 9; + } + + /*! + * Returns true iff the specified character \a c is either a line feed + * (\#x0A) or a carriage return (#0D) control character. + */ + template + static bool IsLineBreakChar( T c ) + { + return c == 0x0A || c == 0x0D; + } + + /*! + * Returns true iff the specified character \a c is an %XML space character: + * + * https://www.w3.org/TR/xml11/#NT-S + */ + template + static bool IsSpaceChar( T c ) + { + return IsWhiteSpaceChar( c ) || IsLineBreakChar( c ); + } + + /*! + * Returns true iff the specified character \a c is an %XML NameStartChar: + * + * https://www.w3.org/TR/xml11/#NT-NameStartChar + */ + template + static bool IsNameStartChar( T c ) + { + return c >= T( 'a' ) && c <= T( 'z' ) + || c >= T( 'A' ) && c <= T( 'Z' ) + || c == T( '_' ) + || c == T( ':' ) + || c >= 0xC0 && c <= 0xD6 + || c >= 0xD8 && c <= 0xF6 + || c >= 0xF8 && c <= 0x2FF + || c >= 0x370 && c <= 0x37D + || c >= 0x37F && c <= 0x1FFF + || c >= 0x200C && c <= 0x200D + || c >= 0x2070 && c <= 0x218F + || c >= 0x2C00 && c <= 0x2FEF + || c >= 0x3001 && c <= 0xD7FF + || c >= 0xF900 && c <= 0xFDCF + || c >= 0xFDF0 && c <= 0xFFFD + || uint32( c ) >= 0x10000 && uint32( c ) <= 0xEFFFF; + } + + /*! + * Returns true iff the specified character \a c is an %XML NameChar: + * + * https://www.w3.org/TR/xml11/#NT-NameChar + */ + template + static bool IsNameChar( T c ) + { + return IsNameStartChar( c ) + || c >= T( '0' ) && c <= T( '9' ) + || c == T( '-' ) + || c == T( '.' ) + || c == 0xB7 + || c >= 0x0300 && c <= 0x036F + || c >= 0x203F && c <= 0x2040; + } + + /*! + * Returns true iff the specified character \a c is an %XML RestrictedChar: + * + * https://www.w3.org/TR/xml11/#NT-RestrictedChar + */ + template + static bool IsRestrictedChar( T c ) + { + return c >= 0x00 && c <= 0x08 + || c >= 0x0B && c <= 0x0C + || c >= 0x0E && c <= 0x1F + || c >= 0x7F && c <= 0x84 + || c >= 0x86 && c <= 0x9F; + } + + /*! + * Returns true iff the specified \a name is a valid %XML qualified element + * or attribute name: + * + * https://www.w3.org/TR/xml-names/#ns-qualnames + */ + static bool IsValidName( const String& name ) + { + if ( !name.IsEmpty() ) + if ( IsNameStartChar( *name ) ) + for ( String::const_iterator i = name.Begin(); ; ) + { + if ( ++i == name.End() ) + return true; + if ( !IsNameChar( *i ) ) + break; + } + return false; + } + + /*! + * Returns a copy of the text fragment defined by the range [i,j) of string + * iterators with all leading and trailing space characters removed. + */ + static String TrimmedSpaces( String::const_iterator i, String::const_iterator j ); + + /*! + * Returns a copy of the specified \a text with all leading and trailing + * space characters removed. + */ + static String TrimmedSpaces( const String& text ); + + /*! + * Returns a copy of the text fragment defined by the range [i,j) of string + * iterators with all sequences of one or more space characters replaced + * with single white space characters (\#x20). + */ + static String CollapsedSpaces( String::const_iterator i, String::const_iterator j ); + + /*! + * Returns a copy of the specified \a text with all sequences of one or more + * space characters replaced with single white space characters (\#x20). + */ + static String CollapsedSpaces( const String& text ); + + /*! + * Returns a copy of the text fragment defined by the range [i,j) of string + * iterators with all %XML references replaced by their corresponding UTF-16 + * characters. + * + * Both entity and character references are decoded by this function. For + * entity references, the entire set of %XML reference names is supported: + * + * http://www.w3.org/TR/xml-entity-names/ + * + * Character references are interpreted as defined in the %XML + * specification: + * + * https://www.w3.org/TR/xml11/#NT-CharRef + */ + static String DecodedText( String::const_iterator i, String::const_iterator j ); + + /*! + * Returns a copy of the specified \a text with all %XML references replaced + * by their corresponding UTF-16 characters. + * + * See DecodedText( String::const_iterator, String::const_iterator ) for a + * detailed description. + */ + static String DecodedText( const String& text ); + + /*! + * Returns a copy of the text fragment defined by the range [i,j) of string + * iterators with all occurences of '&', '<', '>' and '"' replaced with the + * entity references "amp", "lt", "gt" and "quot", respectively. If \a apos + * is true, single quotes will also be replaced with "apos" entities. + */ + static String EncodedText( String::const_iterator i, String::const_iterator j, bool apos = true ) + { + return EncodedText( String( i, j ), apos ); + } + + /*! + * Returns a copy of the specified \a text with all occurences of '&', '<', + * '>' and '"' replaced with the entity references "amp", "lt", "gt" and + * "quot", respectively. If \a apos is true, single quotes will also be + * replaced with "apos" entities. + */ + static String EncodedText( const String& text, bool apos = true ); + + /*! + * Returns the Unicode value (encoded as UTF-16) corresponding to an %XML + * reference defined by the range [i,j) of string iterators: + * + * https://www.w3.org/TR/xml11/#NT-Reference + * + * Both entity and character references are decoded by this function. For + * entity references, the entire set of %XML reference names is supported: + * + * http://www.w3.org/TR/xml-entity-names/ + * + * Character references are interpreted as defined in the %XML + * specification: + * + * https://www.w3.org/TR/xml11/#NT-CharRef + */ + static String ReferenceValue( String::const_iterator i, String::const_iterator j ); + + /*! + * Returns the Unicode value (encoded as UTF-16) corresponding to the + * specified %XML \a reference. + * + * See ReferenceValue( String::const_iterator, String::const_iterator ) for + * a detailed description. + */ + static String ReferenceValue( const String& reference ) + { + return ReferenceValue( reference.Begin(), reference.End() ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLComponent + * \brief Root base class of all %XML document components + * + * %XMLComponent supports the hierarchical structure of an %XML document by + * implementing the basic concept of parent element. + * + * \ingroup xml_parsing_and_generation + * \sa XMLNode + */ +class PCL_CLASS XMLComponent +{ +public: + + /*! + * Default constructor. Constructs a default %XMLComment object with no + * parent element. + */ + XMLComponent() = default; + + /*! + * Copy constructor. + */ + XMLComponent( const XMLComponent& ) = default; + + /*! + * Returns a pointer to the parent %XML element of this component, or + * \c nullptr if this object has no parent element. + */ + XMLElement* ParentElement() const + { + return m_parent; + } + + /*! + * Returns true iff this is a top-level component. Top-level document + * components have no parent elements. + */ + bool IsTopLevel() const + { + return m_parent == nullptr; + } + +private: + + XMLElement* m_parent = nullptr; + + friend class XMLElement; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \namespace pcl::XMLNodeType + * \brief %XML document node types + * + * + * + * + * + * + * + * + * + * + * + *
XMLNodeType::Undefined Undefined %XML node type.
XMLNodeType::ChildNode Signals a child %XML document node - for internal use only.
XMLNodeType::Unknown Represents an unsupported %XML node type.
XMLNodeType::Element An %XML element.
XMLNodeType::Text A text block inside an element's contents.
XMLNodeType::CDATA A CDATA section.
XMLNodeType::ProcessingInstructions A processing instructions (PI) section.
XMLNodeType::PI A synonym to ProcessingInstructions.
XMLNodeType::Comment A comment block.
+ * + * \ingroup xml_parsing_and_generation + */ +namespace XMLNodeType +{ + enum mask_type + { + Undefined = 0x00000000, + ChildNode = 0x80000000, + Unknown = 0x10000000, + Element = 0x00000001, + Text = 0x00000002, + CDATA = 0x00000004, + ProcessingInstructions = 0x00000008, + Comment = 0x00000010 + }; + + /*! + * Returns the name of the specified %XML node \a type ("element", "text", + * "comment", etc). + */ + String AsString( mask_type type ); +} + +/*! + * \class pcl::XMLNodeTypes + * \brief A collection of %XML node types + * \ingroup xml_parsing_and_generation + */ +typedef Flags XMLNodeTypes; + +// ---------------------------------------------------------------------------- + +/*! + * \struct XMLNodeLocation + * \brief Source code location of a parsed %XML document node + * \ingroup xml_parsing_and_generation + */ +struct XMLNodeLocation +{ + /*! + * Zero-based text line number where a parsed node has been identified in + * an %XML document, or -1 if text location information is not available. + */ + int64 line = 0; + + /*! + * Zero-based text column number, counted from the starting character of a + * text line, where a parsed node has been identified in an %XML document. + * This member is -1 if text location information is not available. + * + * Note that the value stored in this field is actually a character index, + * not necessarily a valid text column number. It is an actual column number + * only if the corresponding line of text does not contain tabulator + * characters (\#x9). If there are tabulators, there is usually no one-to-one + * correspondence between characters and represented text columns. + */ + int64 column = 0; + + /*! + * Default constructor. Initializes the line and column members to -1, + * signaling an undefined source code location. + */ + XMLNodeLocation() = default; + + /*! + * Constructs an %XMLNodeLocation object with the specified zero-based text + * line and column numbers. + */ + XMLNodeLocation( int line_, int column_ ) + : line( line_ ) + , column( column_ ) + { + } + + /*! + * Copy constructor. + */ + XMLNodeLocation( const XMLNodeLocation& ) = default; + + /*! + * Returns a string representation of this %XMLNodeLocation object in the + * form " (line=n offset=m)", where n and m are, respectively, the one-based + * line number and zero-based text character offset transported by this + * object. This representation is suitable to be included directly in + * warning or error messages generated by parsers. + * + * The line number token won't be generated if the text line number is + * undefined (< 0) in this object. Similarly, the offset token won't be + * generated if the column member is < 0. If no location information is + * available, this member function returns an empty string. + */ + String ToString() const; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLNode + * \brief Abstract base class of all %XML document node classes + * + * %XML document nodes can be elements, text, CDATA sections, processing + * instructions, comments, and unknown special elements. This class extends the + * XMLComponent root base class to implement %XML document node classification + * and serialization. + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLNode : public XMLComponent +{ +public: + + /*! + * Represents the type of an %XML document node. Supported/valid node types + * are defined in the XMLNodeType namespace. + */ + typedef XMLNodeType::mask_type node_type; + + /*! + * Default constructor. Constructs a default %XMLNode object of the + * specified \a type, with no parent element and undefined source code + * location. + */ + XMLNode( node_type type ) + : m_type( type ) + { + } + + /*! + * Copy constructor. + * + * The newly constructed node will be an \e orphan object, that is, it will + * have no parent element even if the source object \a x is a child node. + * This reflects the fact that document nodes are unique objects. + */ + XMLNode( const XMLNode& x ) + : m_type( x.NodeType() ) + , m_location( x.m_location ) + { + } + + /*! + * Virtual destructor. + */ + virtual ~XMLNode() + { + } + + /*! + * Returns true iff this is a child node of an existing %XML element. + */ + bool IsChildNode() const + { + return m_type.IsFlagSet( XMLNodeType::ChildNode ); + } + + /*! + * Returns the type of this %XML document node. + */ + node_type NodeType() const + { + return static_cast( XMLNodeTypes::flag_type( m_type & unsigned( ~XMLNodeType::ChildNode ) ) ); + } + + /*! + * Returns true iff this node is an %XML element. If this member function + * returns true, this node can be statically casted to XMLElement. + */ + bool IsElement() const + { + return NodeType() == XMLNodeType::Element; + } + + /*! + * Returns true iff this node represents an %XML text block. If this member + * function returns true, this node can be statically casted to XMLText. + */ + bool IsText() const + { + return NodeType() == XMLNodeType::Text; + } + + /*! + * Returns true iff this node represents an %XML comment. If this member + * function returns true, this node can be statically casted to XMLComment. + */ + bool IsComment() const + { + return NodeType() == XMLNodeType::Comment; + } + + /*! + * Returns a reference to the (immutable) source code location of this node. + */ + const XMLNodeLocation& Location() const + { + return m_location; + } + + /*! + * Serializes this document node as an %XML fragment encoded in UTF-8. + * + * \param text Reference to an 8-bit string to which the UTF-8 + * encoded serialization of this node must be appended. + * + * \param autoFormat True if line break characters (\#x0A) and + * indentation strings must be used to improve readability of + * the generated %XML code. False if no superfluous white space + * should be generated. + * + * \param indentChar A character used for indentation of generated text + * lines, when \a autoFormat is true. This parameter should be + * either a white space (' ' or \#x20) or a tabulator ('\\t' or + * \#x09) character. + * + * \param indentSize Number of \a indentChar characters used for each + * indentation level, when \a autoFormat is true. + * + * \param level Recursion level. A value greater than zero denotes + * that this function is being called from a parent %XML + * element. The recursion level determines the number of + * \a indentChar characters prepended to each text line + * for indentation, when \a autoFormat is true. + */ + virtual void Serialize( IsoString& text, bool autoFormat, char indentChar, unsigned indentSize, unsigned level ) const = 0; + + /*! + * Returns true iff a new line character (\#x0A) can be inserted before + * serializing this node after the specified \a previous node. + */ + virtual bool NLAfter( const XMLNode& previous ) const; + +private: + + XMLNodeTypes m_type; + XMLNodeLocation m_location; + + friend class XMLDocument; + friend class XMLElement; +}; + +/*! + * \class pcl::XMLNodeList + * \brief Dynamic list of %XML node objects + * + * %XMLNodeList is used as the internal implementation of element child node + * lists and document node lists. In current PCL versions, %XMLNodeList is a + * template instantiation of ReferenceArray<> for the XMLNode class. + * + * \ingroup xml_parsing_and_generation + */ +typedef ReferenceArray XMLNodeList; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLParseError + * \brief %XML parsing error with automatic text location information + * generation + * + * The %XMLParseError is useful to generate warning and error messages during + * document parsing tasks, with automatic generation of text location + * information (when available) and a normalized representation of error + * messages. + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLParseError : public Error +{ +public: + + /*! + * Constructs an %XMLParseError object with a reference to an XMLNode + * instance. + * + * \param node Reference to the XMLNode object that has caused the + * exception. + * + * \param whileDoing Identifies the parsing action that was taking place. + * For example: "Parsing Metadata child Image element". + * + * \param whatHappened Describes the error that has been detected. For + * example: "Missing id attribute". + * + * This constructor inserts node location information, if available, and + * joins the strings appropriately to build an error message. + */ + XMLParseError( const XMLNode& node, const String& whileDoing, const String& whatHappened ) + : Error( whileDoing + node.Location().ToString() + ": " + whatHappened ) + { + } + + /*! + * Constructs an %XMLParseError object with a reference to an + * XMLNodeLocation instance. + * + * \param where Reference to an XMLNodeLocation object to retrieve + * text location information. + * + * \param whileDoing Identifies the parsing action that was taking place. + * For example: "Parsing Metadata child Image element". + * + * \param whatHappened Describes the error that has been detected. For + * example: "Missing id attribute". + * + * This constructor inserts node location information, if available, and + * joins the strings appropriately to build an error message. + */ + XMLParseError( const XMLNodeLocation& where, const String& whileDoing, const String& whatHappened ) + : Error( whileDoing + where.ToString() + ": " + whatHappened ) + { + } + + /*! + * Copy constructor. + */ + XMLParseError( const XMLParseError& ) = default; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLAttribute + * \brief %XML element attribute + * + * The %XMLAttribute class represents an element attribute, as defined by the + * Attribute construct: + * + * https://www.w3.org/TR/xml11/#NT-Attribute + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLAttribute : public XMLComponent +{ +public: + + /*! + * Constructs an empty %XML attribute. An empty attribute is ignored for + * inclusion in element attribute lists. + */ + XMLAttribute() = default; + + /*! + * Constructs a new %XMLAttribute object with the specified qualified + * \a name and \a value. + * + * The specified \a name should be a valid %XML qualified name, as defined + * by the W3C recommendation: + * + * https://www.w3.org/TR/xml-names/#ns-qualnames + * + * However, the \a name is not checked for validity by this constructor, for + * performance reasons. Attribute and element names are verified during the + * document parsing and generation tasks. + */ + XMLAttribute( const String& name, const String& value = String() ) + : m_name( name ) + , m_value( value ) + { + } + + /*! + * Copy constructor. + */ + XMLAttribute( const XMLAttribute& ) = default; + + /*! + * Returns a reference to the (immutable) qualified name of this attribute. + */ + const String& Name() const + { + return m_name; + } + + /*! + * Returns a reference to the (immutable) value of this element attribute. + */ + const String& Value() const + { + return m_value; + } + + /*! + * Sets a new value for this %XML element attribute. + */ + void SetValue( const String& text ) + { + m_value = text; + } + + /*! + * Returns an encoded version of the attribute value. All characters that + * cannot legally occur in an %XML attribute value are replaced by their + * corresponding entity references. + */ + String EncodedValue() const + { + return XML::EncodedText( m_value, false/*apos*/ ); + } + + /*! + * Equality operator. + * + * Two %XML element attributes are considered equal if their qualified names + * are identical. Note that this restricts valid attribute comparisons to a + * particular %XML document. + */ + bool operator ==( const XMLAttribute& x ) const + { + return m_name == x.m_name; + } + + /*! + * Less-than relational operator. + * + * To compare %XML element attributes, only their qualified names are taken + * into account. Note that this restricts valid attribute comparisons to a + * particular %XML document. + */ + bool operator <( const XMLAttribute& x ) const + { + return m_name < x.m_name; + } + +private: + + String m_name; + String m_value; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLAttributeList + * \brief Dynamic list of %XML element attributes + * + * %XMLAttributeList represents a sequence of %XML element attributes in a + * start-tag, as defined in the W3C recommendation: + * + * https://www.w3.org/TR/xml11/#sec-starttags + * + * %XMLAttributeList is internally implemented as a dynamic array of + * XMLAttribute objects. + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLAttributeList +{ +public: + + /*! + * Represents the dynamic container class used internally to implement an + * %XML element attribute list. + */ + typedef Array list_implementation; + + /*! + * Represents a mutable %XML element attribute list iterator. + */ + typedef list_implementation::iterator iterator; + + /*! + * Represents an immutable %XML element attribute list iterator. + */ + typedef list_implementation::const_iterator const_iterator; + + /*! + * Constructs a new %XMLAttributeList object by parsing the specified + * \a text string. + * + * The specified \a text must be a sequence of zero or more Attribute %XML + * definitions pertaining to a start-tag: + * + * https://www.w3.org/TR/xml11/#NT-STag + * + * See the Parse() member function for a more detailed description. + */ + XMLAttributeList( const String& text ) + { + Parse( text ); + } + + /*! + * Default constructor. Constructs an empty %XML attribute list. + */ + XMLAttributeList() = default; + + /*! + * Copy constructor. + */ + XMLAttributeList( const XMLAttributeList& ) = default; + + /*! + * Returns the number of element attributes in this list. + */ + int Length() const + { + return int( m_list.Length() ); + } + + /*! + * Returns true iff this attribute list is empty. + */ + bool IsEmpty() const + { + return m_list.IsEmpty(); + } + + /*! + * Returns a reference to the immutable element attribute at the specified + * zero-based index \a i. No bounds checking is performed: if the specified + * index is invalid this function invokes undefined behavior. + */ + const XMLAttribute& operator []( int i ) const + { + return m_list[i]; + } + + /*! + * Returns an immutable iterator located at the beginning of this element + * attribute list. + */ + const_iterator Begin() const + { + return m_list.Begin(); + } + + /*! + * Returns an immutable iterator located at the end of this element + * attribute list. + */ + const_iterator End() const + { + return m_list.End(); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Returns true iff this list contains an element attribute with the + * specified qualified \a name. + */ + bool HasAttribute( const String& name ) const + { + return m_list.Contains( name ); + } + + /*! + * Returns the value of the element attribute with the specified qualified + * \a name, or an empty string if this list does not contain such an element + * attribute. + */ + String AttributeValue( const String& name ) const + { + const_iterator a = m_list.Search( name ); + return (a != m_list.End()) ? a->Value() : String(); + } + + /*! + * Causes this list to contain an %XML element attribute with the specified + * qualified \a name and \a value. + * + * If an attribute with the same qualified \a name already exists in this + * list, then its value will be changed. Otherwise, a new attribute will be + * appended to this list. + * + * This member function ensures that no %XML element can have two or more + * attributes with the same qualified name. This constraint is part of the + * %XML specification: + * + * https://www.w3.org/TR/xml11/#sec-starttags + * https://www.w3.org/TR/xml-names/#scoping-defaulting + */ + void SetAttribute( const String& name, const String& value ) + { + if ( !name.IsEmpty() ) + { + iterator a = m_list.Search( name ); + if ( a == m_list.End() ) + m_list.Add( XMLAttribute( name, value ) ); + else + a->SetValue( value ); + } + } + + /*! + * Causes this list to contain the specified %XML element \a attribute. + * + * See SetAttribute( const String&, const String& ) for more information. + */ + void SetAttribute( const XMLAttribute& attribute ) + { + if ( !attribute.Name().IsEmpty() ) + { + iterator a = m_list.Search( attribute ); + if ( a == m_list.End() ) + m_list.Add( attribute ); + else + *a = attribute; + } + } + + /*! + * Insertion operator. Returns a reference to this object. + * + * This operator is equivalent to SetAttribute( const XMLAttribute& ). + */ + XMLAttributeList& operator <<( const XMLAttribute& attribute ) + { + SetAttribute( attribute ); + return *this; + } + + /*! + * Causes this list to contain the specified \a list of %XML element + * attributes. + * + * For each attribute in the specified \a list, if an attribute with the + * same qualified \a name already exists in this list, then its value will + * be changed. Otherwise, a new attribute will be appended to this list. + * + * This member function ensures that no %XML element can have two or more + * attributes with the same qualified name. This constraint is part of the + * %XML specification: + * + * https://www.w3.org/TR/xml11/#sec-starttags + * https://www.w3.org/TR/xml-names/#scoping-defaulting + */ + void SetAttributes( const XMLAttributeList& list ) + { + for ( auto a : list ) + SetAttribute( a ); + } + + /*! + * Insertion operator. Returns a reference to this object. + * + * This operator is equivalent to SetAttributes( const XMLAttributeList& ). + */ + XMLAttributeList& operator <<( const XMLAttributeList& list ) + { + SetAttributes( list ); + return *this; + } + + /*! + * Removes the element attribute with the specified qualified \a name, if it + * exists in this list. If no attribute with the specified \a name exists, + * this member function has no effect. + */ + void RemoveAttribute( const String& name ) + { + iterator a = m_list.Search( name ); + if ( a != m_list.End() ) + m_list.Remove( a ); + } + + /*! + * Removes all element attributes in this list, yielding an empty element + * attribute list. + */ + void Clear() + { + m_list.Clear(); + } + + /*! + * Sorts the element attributes in this list in ascending order by comparing + * their qualified names. + */ + void Sort() + { + m_list.Sort(); + } + + /*! + * Parses the specified \a text, encoded as UTF-16, to generate a new list + * of %XML element attributes. + * + * The specified \a text must be a sequence of zero or more Attribute %XML + * definitions pertaining to a start-tag, as described in the W3C + * recommendation: + * + * https://www.w3.org/TR/xml11/#NT-STag + * + * Attribute value normalization is applied to each parsed attribute: + * + * https://www.w3.org/TR/xml11/#AVNormalize + * + * In attribute values, all entity and character references are decoded. See + * the XML::DecodedText() static function for more information on reference + * decoding. Normalization also implies space trimming and compression: all + * leading and trailing space characters are removed, and all sequences of + * one or more space characters are replaced by single white space + * characters (\#x20). + */ + void Parse( const String& text ); + + /*! + * Performs the %XML serialization of this element attribute list and + * appends it to the specified \a text string, encoded in UTF-8. + * + * The generated serialization is a sequence of zero or more Attribute %XML + * definitions pertaining to a start-tag, as described in the W3C + * recommendation: + * + * https://www.w3.org/TR/xml11/#NT-STag + */ + void Serialize( IsoString& text ) const; + +private: + + list_implementation m_list; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLElement + * \brief %XML element + * + * The %XMLElement class represents an %XML document element: + * + * https://www.w3.org/TR/xml11/#dt-element + * + * Elements are the main data holders in the logical design of %XML, following + * a hierarchical tree structure. + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLElement : public XMLNode +{ +public: + + /*! + * Represents a mutable child node list iterator. + */ + typedef XMLNodeList::iterator iterator; + + /*! + * Represents an immutable child node list iterator. + */ + typedef XMLNodeList::const_iterator const_iterator; + + /*! + * A list of child %XML elements. Implemented as a template instantiation of + * ReferenceArray<> for the XMLElement class. + */ + typedef ReferenceArray child_element_list; + + /*! + * Default constructor. Constructs an uninitialized %XMLElement structure. + */ + XMLElement() + : XMLNode( XMLNodeType::Element ) + { + } + + /*! + * Constructs an empty %XMLElement object with the specified qualified + * \a name and \a attributes. + */ + XMLElement( const String& name, const XMLAttributeList& attributes = XMLAttributeList() ) + : XMLNode( XMLNodeType::Element ) + , m_name( name ) + , m_attributes( attributes ) + { + } + + /*! + * Constructs an empty %XMLElement object with the specified qualified + * \a name and \a attributes, as a child node of the specified \a parent + * element. + */ + XMLElement( XMLElement& parent, const String& name, const XMLAttributeList& attributes = XMLAttributeList() ) + : XMLNode( XMLNodeType::Element ) + , m_name( name ) + , m_attributes( attributes ) + { + parent.AddChildNode( this ); + } + + /*! + * Copy constructor. This constructor is disabled because %XMLElement + * represents unique objects. + */ + XMLElement( const XMLElement& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %XMLElement represents + * unique objects. + */ + XMLElement& operator =( const XMLElement& ) = delete; + + /*! + * Virtual destructor. If this element contains child nodes, all of them + * will be destroyed recursively. + */ + virtual ~XMLElement() + { + DestroyChildNodes(); + } + + /*! + * Returns true iff this is a root %XML element. A root %XML element has no + * parent element. + * + * Note that this member function can return true in two different + * situations: when the element has been generated during a document parsing + * process (in which case this is an actual document root element), and if + * this object has not been initialized yet (because it has been newly + * constructed and still has not been associated with an %XML document). + */ + bool IsRootElement() const + { + return ParentElement() == nullptr; + } + + /*! + * Returns a reference to the (immutable) qualified element name. + */ + const String& Name() const + { + return m_name; + } + + /*! + * Returns a copy of the list of %XML element attributes. + */ + XMLAttributeList Attributes() const + { + return m_attributes; + } + + /*! + * Returns true iff this element has one or more attributes defined. + */ + bool HasAttributes() const + { + return !m_attributes.IsEmpty(); + } + + /*! + * Returns true iff this element has an attribute with the specified + * qualified \a name. + */ + bool HasAttribute( const String& name ) const + { + return m_attributes.HasAttribute( name ); + } + + /*! + * Returns the value of the attribute with the specified qualified \a name + * in this element, or an empty string if this element has no such + * attribute. + */ + String AttributeValue( const String& name ) const + { + return m_attributes.AttributeValue( name ); + } + + /*! + * Causes this %XML element to contain an attribute with the specified + * qualified \a name and \a value. + * + * If an attribute with the same qualified \a name already exists in this + * element, then its value will be changed. Otherwise, a new attribute will + * be created in this element. + * + * This member function ensures that no %XML element can have two or more + * attributes with the same qualified name. This constraint is part of the + * %XML specification: + * + * https://www.w3.org/TR/xml11/#sec-starttags + * https://www.w3.org/TR/xml-names/#scoping-defaulting + */ + void SetAttribute( const String& name, const String& value ) + { + XMLAttribute a( name, value ); + a.m_parent = this; + m_attributes.SetAttribute( a ); + } + + /*! + * Causes this %XML element to contain the specified \a attribute. + * + * See SetAttribute( const String&, const String& ) for more information. + */ + void SetAttribute( const XMLAttribute& attribute ) + { + XMLAttribute a( attribute ); + a.m_parent = this; + m_attributes.SetAttribute( a ); + } + + /*! + * Insertion operator. Returns a reference to this object. + * + * This operator is equivalent to SetAttribute( const XMLAttribute& ). + */ + XMLElement& operator <<( const XMLAttribute& attribute ) + { + SetAttribute( attribute ); + return *this; + } + + /*! + * Causes this %XML element to contain the specified \a list of attributes. + * + * For each attribute in the specified \a list, if an attribute with the + * same qualified \a name already exists in this element, then its value + * will be changed. Otherwise, a new attribute will be created in this + * element. + * + * This member function ensures that no %XML element can have two or more + * attributes with the same qualified name. This constraint is part of the + * %XML specification: + * + * https://www.w3.org/TR/xml11/#sec-starttags + * https://www.w3.org/TR/xml-names/#scoping-defaulting + */ + void SetAttributes( const XMLAttributeList& list ) + { + for ( auto a : list ) + SetAttribute( a ); + } + + /*! + * Insertion operator. Returns a reference to this object. + * + * This operator is equivalent to SetAttributes( const XMLAttributeList& ). + */ + XMLElement& operator <<( const XMLAttributeList& list ) + { + SetAttributes( list ); + return *this; + } + + /*! + * Removes the attribute with the specified qualified \a name, if it exists + * in this element. If this element has no attribute with the specified + * \a name, this member function has no effect. + */ + void RemoveAttribute( const String& name ) + { + m_attributes.RemoveAttribute( name ); + } + + /*! + * Removes all existing attributes in this element. + */ + void ClearAttributes() + { + m_attributes.Clear(); + } + + /*! + * Sorts the existing attributes in this element in ascending order by + * comparing their qualified names. + */ + void SortAttributes() + { + m_attributes.Sort(); + } + + /*! + * Sorts the existing attributes in this element in ascending order. + * Ordering of elements is defined such that for any pair a, b of + * XMLAttribute objects in this element, the binary predicate p(a,b) is true + * iff a precedes b. + */ + template + void SortAttributes( BP p ) + { + m_attributes.Sort( p ); + } + + /*! + * Parses the specified \a text, encoded as UTF-16, to generate a new list + * of attributes in this %XML element. The previous list of attributes, if + * any, will be replaced by the newly generated list. + * + * The specified \a text must be a sequence of zero or more Attribute %XML + * definitions pertaining to a start-tag, as described in the W3C + * recommendation: + * + * https://www.w3.org/TR/xml11/#NT-STag + */ + void ParseAttributes( const String& text ) + { + XMLAttributeList list( text ); + ClearAttributes(); + SetAttributes( list ); + } + + /*! + * Performs the %XML serialization of the attribute list in this element and + * appends it to the specified \a text string, encoded in UTF-8. + * + * The generated serialization is a sequence of zero or more Attribute %XML + * definitions pertaining to a start-tag, as described in the W3C + * recommendation: + * + * https://www.w3.org/TR/xml11/#NT-STag + */ + void SerializeAttributes( IsoString& text ) const + { + m_attributes.Serialize( text ); + } + + /*! + * Returns the number of child nodes in this %XML element. + */ + int ChildCount() const + { + return int( m_childNodes.Length() ); + } + + /*! + * Returns true iff this is an empty %XML element. An empty element has no + * child nodes. + */ + bool IsEmpty() const + { + return m_childNodes.IsEmpty(); + } + + /*! + * Returns a reference to the immutable child node at the specified + * zero-based index \a i. No bounds checking is performed: if the specified + * index is invalid this function invokes undefined behavior. + */ + const XMLNode& operator []( int i ) const + { + return m_childNodes[i]; + } + + /*! + * Returns a reference to the immutable first child node in this element. No + * bounds checking is performed: if this element is empty, this function + * invokes undefined behavior. + */ + const XMLNode& First() const + { + return m_childNodes.First(); + } + + /*! + * Returns a reference to the immutable last child node in this element. No + * bounds checking is performed: if this element is empty, this function + * invokes undefined behavior. + */ + const XMLNode& Last() const + { + return m_childNodes.Last(); + } + + /*! + * Returns an immutable iterator located at the beginning of the list of + * child nodes of this %XML element. + */ + const_iterator Begin() const + { + return m_childNodes.Begin(); + } + + /*! + * Returns an immutable iterator located at the end of the list of child + * nodes of this %XML element. + */ + const_iterator End() const + { + return m_childNodes.End(); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + +#ifndef __PCL_NO_MUTABLE_XML_ELEMENT_ITERATORS + + /*! + * Returns a mutable iterator located at the beginning of the list of child + * nodes of this %XML element. + */ + iterator Begin() + { + return m_childNodes.Begin(); + } + + /*! + * Returns a mutable iterator located at the end of the list of child nodes + * of this %XML element. + */ + iterator End() + { + return m_childNodes.End(); + } + + /*! + * Returns an immutable iterator located at the beginning of the list of + * child nodes of this %XML element. + */ + const_iterator ConstBegin() const + { + return m_childNodes.ConstBegin(); + } + + /*! + * Returns an immutable iterator located at the end of the list of child + * nodes of this %XML element. + */ + const_iterator ConstEnd() const + { + return m_childNodes.ConstEnd(); + } + +# ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin(). + */ + iterator begin() + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End(). + */ + iterator end() + { + return End(); + } +# endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + +#endif // !__PCL_NO_MUTABLE_XML_ELEMENT_ITERATORS + + /*! + * Returns true iff this element contains one or more child %XML elements. + */ + bool HasElements() const + { + return m_childTypes.IsFlagSet( XMLNodeType::Element ); + } + + /*! + * Returns true iff this element contains one or more child text blocks. + */ + bool HasText() const + { + return m_childTypes.IsFlagSet( XMLNodeType::Text ); + } + + /*! + * Returns true iff this element contains one or more child CDATA sections. + */ + bool HasCDATA() const + { + return m_childTypes.IsFlagSet( XMLNodeType::CDATA ); + } + + /*! + * Returns true iff this element contains one or more child processing + * instructions. + */ + bool HasProcessingInstructions() const + { + return m_childTypes.IsFlagSet( XMLNodeType::ProcessingInstructions ); + } + + /*! + * Returns true iff this element contains one or more child comment + * sections. + */ + bool HasComments() const + { + return m_childTypes.IsFlagSet( XMLNodeType::Comment ); + } + + /*! + * Returns the text contents of this element, or an empty string if this + * element has no text child nodes. + * + * If this element has two or more text child nodes, the returned value is + * the concatenation of all child text nodes. + */ + String Text() const; + + /*! + * \internal + */ + void GetChildElements( child_element_list& list, bool recursive ) const + { + for ( const XMLNode& node : m_childNodes ) + if ( node.IsElement() ) + { + const XMLElement& element = static_cast( node ); + list << &element; + if ( recursive ) + element.GetChildElements( list, recursive ); + } + } + + /*! + * Returns a list with all child elements of this element. + * + * if \a recursive is \c true, this member function performs a recursive + * search across the entire tree structure rooted at this element. Otherwise + * only the direct descendant elements will be returned. + */ + child_element_list ChildElements( bool recursive = false ) const + { + child_element_list list; + GetChildElements( list, recursive ); + return list; + } + + /*! + * \internal + */ + void GetChildElementsByName( child_element_list& list, const String& name, bool recursive ) const + { + for ( const XMLNode& node : m_childNodes ) + if ( node.IsElement() ) + { + const XMLElement& element = static_cast( node ); + if ( element.Name() == name ) + { + list << &element; + if ( recursive ) + element.GetChildElementsByName( list, name, recursive ); + } + } + } + + /*! + * Returns a list with all child elements of this element with the specified + * \a name. + * + * if \a recursive is \c true, this member function performs a recursive + * search across the entire tree structure rooted at this element. Otherwise + * only the direct descendant elements will be returned. + */ + child_element_list ChildElementsByName( const String& name, bool recursive = false ) const + { + child_element_list list; + GetChildElementsByName( list, name, recursive ); + return list; + } + + /*! + * \internal + */ + void GetChildNodesByType( XMLNodeList& list, XMLNodeTypes types, bool recursive ) const + { + for ( const XMLNode& node : m_childNodes ) + if ( types.IsFlagSet( node.NodeType() ) ) + { + list << &node; + if ( recursive ) + if ( node.IsElement() ) + static_cast( node ).GetChildNodesByType( list, types, recursive ); + } + } + + /*! + * Returns a list with all child nodes of this element of the specified + * \a types. The \a types argument can be an ORed combination of XMLNodeType + * enumerated mask values. + * + * if \a recursive is \c true, this member function performs a recursive + * search across the entire tree structure rooted at this element. Otherwise + * only the direct descendant nodes will be returned. + */ + XMLNodeList ChildNodesByType( XMLNodeTypes types, bool recursive = false ) const + { + XMLNodeList list; + GetChildNodesByType( list, types, recursive ); + return list; + } + + /*! + * \internal + */ + template + void GetChildNodesThat( XMLNodeList& list, UP u, bool recursive ) const + { + for ( const XMLNode& node : m_childNodes ) + if ( u( node ) ) + { + list << &node; + if ( recursive ) + if ( node.IsElement() ) + static_cast( node ).GetChildNodesThat( list, u, recursive ); + } + } + + /*! + * Returns a list with all child nodes of this element that satisfy the + * specified unary predicate \a u. + * + * For each child node n in this element, n will be included in the returned + * list iff u( n ) returns true. + * + * if \a recursive is \c true, this member function performs a recursive + * search across the entire tree structure rooted at this element. Otherwise + * only the direct descendant nodes will be returned. + */ + template + XMLNodeList ChildNodesThat( UP u, bool recursive = false ) const + { + XMLNodeList list; + GetChildNodesThat( list, u, recursive ); + return list; + } + + /*! + * Appends a child \a node to this %XML element. + * + * The specified \a node will be owned by this element, which will destroy + * it automatically (and recursively) upon destruction. + */ + void AddChildNode( XMLNode* node ) + { + m_childNodes << node; + node->m_parent = this; + node->m_type.SetFlag( XMLNodeType::ChildNode ); + m_childTypes.SetFlag( node->NodeType() ); + } + + /*! + * Insertion operator: Appends a child \a node to this %XML element. Returns + * a reference to this object. + * + * This operator does the same as AddChildNode( node ). + */ + XMLElement& operator <<( XMLNode* node ) + { + AddChildNode( node ); + return *this; + } + + /*! + * Appends an ordered sequence of child \a nodes to this %XML element. + * + * After calling this function, all existing \a nodes in the specified list + * will be owned by this element, which will destroy them automatically (and + * recursively) upon destruction. + */ + void AddChildNodes( XMLNodeList& nodes ) + { + for ( XMLNode& node : nodes ) + AddChildNode( &node ); + } + + /*! + * Insertion operator: Appends an ordered sequence of child \a nodes to this + * %XML element. Returns a reference to this object. + * + * This operator does the same as AddChildNodes( nodes ). + */ + XMLElement& operator <<( XMLNodeList& nodes ) + { + AddChildNodes( nodes ); + return *this; + } + + /*! + * \internal + * Appends a new child \a node to this %XML element. + * + * The specified \a node will be owned by this element, which will destroy + * it automatically (and recursively) upon destruction. + */ + void AddChildNode( XMLNode* node, const XMLNodeLocation& location ) + { + node->m_location = location; + AddChildNode( node ); + } + + /*! + * Recursively destroys all existing child nodes in this %XML element, + * yielding an empty element. + */ + void DestroyChildNodes() + { + m_childNodes.Destroy(); + m_childTypes = XMLNodeType::Undefined; + } + + /*! + * Releases the child nodes of this %XML element. + * + * This function returns the (possibly empty) list of child nodes in this + * element and causes this object to forget them. The caller will be + * responsible for destroying and deallocating all of the returned nodes as + * appropriate. After calling this member function, this %XML element will + * be empty. + */ + XMLNodeList ReleaseChildNodes() + { + XMLNodeList nodes = m_childNodes; + m_childNodes.Clear(); + m_childTypes = XMLNodeType::Undefined; + return nodes; + } + + /*! + * Recursively serializes this %XML element and its contents. Appends the + * generated %XML source code to the specified 8-bit \a text string, encoded + * in UTF-8. + * + * See XMLNode::Serialize() for information on function parameters. + */ + void Serialize( IsoString& text, bool autoFormat, char indentChar, unsigned indentSize, unsigned level ) const override; + +private: + + String m_name; + XMLAttributeList m_attributes; + XMLNodeList m_childNodes; + XMLNodeTypes m_childTypes = XMLNodeType::Undefined; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class pcl::XMLElementList + * \brief Dynamic list of %XML elements + * + * %XMLElementList is a template instantiation of ReferenceArray<> for the + * XMLElement class. It is used to transport ordered sequences of child element + * nodes. See for example XMLElement::ChildElements(). + * + * \ingroup xml_parsing_and_generation + */ +typedef XMLElement::child_element_list XMLElementList; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLText + * \brief %XML text block + * + * This %XMLText class represents a text entity in an %XML document: + * + * https://www.w3.org/TR/xml11/#dt-text + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLText : public XMLNode +{ +public: + + /*! + * Constructs a new %XMLText object. + * + * \param text The Unicode text block contents encoded as UTF-16. + * + * \param preserveSpaces If false, the text block will be transformed by + * trimming and collapsing spaces: All leading and trailing + * space characters will be removed, and all sequences of one + * or more space characters will be replaced by single white + * space characters (\#x20). If true, the specified \a text + * string will be stored intact. + * + * \param verbatim If true, the text block will be serialized unencoded, + * that is, exactly as is being specified, in the XML + * document. No codification of illegal characers such as + * quotes and '<' or '>' will be performed. This is useful to + * generate special code blocks that must be included + * literally, such as <style> or <script> tags in + * HTML and SVG documents. + * + * Besides text contents transformation, space preservation also has an + * impact in the way text blocks are serialized as %XML: New line characters + * (\#x0A) are never used to separate text blocks from their parent or + * sibling nodes when space preservation is enabled. + */ + XMLText( const String& text, bool preserveSpaces = true, bool verbatim = false ) + : XMLNode( XMLNodeType::Text ) + , m_text( preserveSpaces ? text : XML::CollapsedSpaces( XML::TrimmedSpaces( text ) ) ) + , m_preserveSpaces( preserveSpaces ) + , m_verbatim( verbatim ) + { + } + + /*! + * Copy constructor. + */ + XMLText( const XMLText& ) = default; + + /*! + * Returns a reference to the (immutable) text string contained by this %XML + * text block. The returned string is encoded in UTF-16. + */ + const String& Text() const + { + return m_text; + } + + /*! + * Returns true iff this text block preserves space characters for + * serialization. See the class constructor for more information. + */ + bool IsPreserveSpaces() const + { + return m_preserveSpaces; + } + + /*! + * Returns an encoded version of this text block. All characters that cannot + * legally occur in an %XML text block are replaced by their corresponding + * entity references. + */ + String EncodedText() const + { + return XML::EncodedText( m_text ); + } + + /*! + * Returns a space-transformed version of this text block. + * + * \param collapse Replace all sequences of one or more space characters + * with single white space characters (\#x20). + * + * \param trim Remove all leading and trailing space characters. + */ + String SpaceTransformedText( bool collapse, bool trim ) const + { + String text = m_text; + if ( trim ) + text = XML::TrimmedSpaces( text ); + if ( collapse ) + text = XML::CollapsedSpaces( text ); + return text; + } + + /*! + * Serializes this %XML text block with UTF-8 encoding. + * + * See XMLNode::Serialize() for information on function parameters. See also + * the class constructor for information on space preservation options in + * %XML text blocks. + */ + void Serialize( IsoString& text, bool autoFormat, char indentChar, unsigned indentSize, unsigned level ) const override; + + /*! + * Returns true iff a new line character (\#x0A) can be inserted before + * serializing this node after the specified \a previous node. + * + * In the case of a text block, a new line character can only be inserted + * if the block does not preserve space characters. If space preservation is + * enabled, new line characters are forbidden at the beginning and end of + * the text block serialization. + */ + bool NLAfter( const XMLNode& previous ) const override + { + return !m_preserveSpaces; + } + +private: + + String m_text; // N.B.: This is plain, that is, decoded, text. + bool m_preserveSpaces = true; + bool m_verbatim = false; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLCDATA + * \brief %XML CDATA section + * + * The %XMLCDATA class represents a CDATA section in an %XML document: + * + * https://www.w3.org/TR/xml11/#sec-cdata-sect + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLCDATA : public XMLNode +{ +public: + + /*! + * Constructs a new %XMLCDATA object with the specified character \a data + * encoded in UTF-16. + * + * The specified \a data must not contain the sequence "]]>". Any occurrence + * of this forbidden sequence will be removed for serialization. + */ + XMLCDATA( const String& data = String() ) + : XMLNode( XMLNodeType::CDATA ) + , m_cdata( data ) + { + } + + /*! + * Copy constructor. + */ + XMLCDATA( const XMLCDATA& ) = default; + + /*! + * Returns a reference to the (immutable) character data string, encoded as + * UTF-16, contained by this CDATA section. + */ + const String& CData() const + { + return m_cdata; + } + + /*! + * Serializes this %XML CDATA section with UTF-8 encoding. + * + * See XMLNode::Serialize() for information on function parameters. + */ + void Serialize( IsoString& text, bool autoFormat, char indentChar, unsigned indentSize, unsigned level ) const override; + +private: + + String m_cdata; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLProcessingInstructions + * \brief %XML processing instructions + * + * The %XMLProcessingInstructions class represents a processing instructions + * (PI) tag in an %XML document: + * + * https://www.w3.org/TR/xml11/#sec-pi + * + * \ingroup xml_parsing_and_generation + */ +class XMLProcessingInstructions : public XMLNode +{ +public: + + /*! + * Constructs a new %XMLProcessingInstructions object with the specified + * \a target name and \a instructions string, both encoded in UTF-16. + * + * The specified \a instructions string must not contain the sequence "?>". + * Any occurrence of this forbidden sequence will be removed for + * serialization. + */ + XMLProcessingInstructions( const String& target, const String& instructions ) + : XMLNode( XMLNodeType::ProcessingInstructions ) + , m_target( target ) + , m_instructions( instructions ) + { + } + + /*! + * Copy constructor. + */ + XMLProcessingInstructions( const XMLProcessingInstructions& ) = default; + + /*! + * Returns a reference to the (immutable) instructions target name. + */ + const String& Target() const + { + return m_target; + } + + /*! + * Returns a reference to the (immutable) instructions string. + */ + const String& Instructions() const + { + return m_instructions; + } + + /*! + * Serializes this %XML PI section with UTF-8 encoding. + * + * See XMLNode::Serialize() for information on function parameters. + */ + void Serialize( IsoString& text, bool autoFormat, char indentChar, unsigned indentSize, unsigned level ) const override; + +private: + + String m_target; + String m_instructions; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLComment + * \brief %XML comment section + * + * The %XMLComment class represents a comment in an %XML document: + * + * https://www.w3.org/TR/xml11/#sec-comments + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLComment : public XMLNode +{ +public: + + /*! + * Constructs a new %XMLComment object with the specified \a comment string + * encoded in UTF-16. + * + * The specified \a comment must not contain the sequence "--" or end with + * a '-' character. Any occurrence of these forbidden sequences will be + * removed for serialization. + */ + XMLComment( const String& comment ) + : XMLNode( XMLNodeType::Comment ) + , m_comment( comment ) + { + } + + /*! + * Copy constructor. + */ + XMLComment( const XMLComment& ) = default; + + /*! + * Returns a reference to the (immutable) comment string. + */ + const String& Comment() const + { + return m_comment; + } + + /*! + * Serializes this %XML comment section with UTF-8 encoding. + * + * See XMLNode::Serialize() for information on function parameters. + */ + void Serialize( IsoString& text, bool autoFormat, char indentChar, unsigned indentSize, unsigned level ) const override; + +private: + + String m_comment; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLUnknownElement + * \brief Unsupported or invalid %XML element + * + * %XMLUnknownElement represents an invalid or unrecognized %XML element + * retrieved while parsing an %XML document. In the current PCL implementation, + * an %XMLUnknownElement object is generated if the parser finds an element + * whose start-tag begins with the " + * XMLParserOption::IgnoreComments Do not add comment nodes to the DOM. + * XMLParserOption::IgnoreUnknownElements Do not add unknown/invalid elements to the DOM. + * XMLParserOption::IgnoreStrayCharacters Be tolerant of non-space characters outside markup. + * XMLParserOption::NormalizeTextSpaces Trim and collapse spaces in all child text nodes. + * + * + * \ingroup xml_parsing_and_generation + */ +namespace XMLParserOption +{ + enum mask_type + { + IgnoreComments = 0x00000001, + IgnoreUnknownElements = 0x00000002, + IgnoreStrayCharacters = 0x00000004, + NormalizeTextSpaces = 0x00000008 + }; +} + +/*! + * \class pcl::XMLParserOptions + * \brief A collection of %XML document parsing options + * \ingroup xml_parsing_and_generation + */ +typedef Flags XMLParserOptions; + +// ---------------------------------------------------------------------------- + +/*! + * \class XMLDocument + * \brief %XML document parsing and generation + * + * %XMLDocument implements parsing and generation of well-formed %XML + * documents. + * + * The Parse() member function reads and interprets a Unicode text string to + * generate a read-only document object model (DOM) that represents the data + * entities defined by a well-formed %XML document. The DOM can be inspected + * with several member functions of the %XMLDocument class. All %XML nodes and + * elements in a document can be visited recursively with specialized accessor + * functions and iterators. See the Begin() and End() functions (and their + * STL-compatible equivalents, begin() and end()), as well as XML(), DocType(), + * RootElement(), and operator []( int ), among others. + * + * For generation of %XML documents, the Serialize() member function builds a + * new document as a Unicode string encoded in UTF-8. The document's root node + * and several nodes and critical components must be defined before document + * generation - see the SetXML(), SetDocType(), AddNode() and SetRootElement() + * member functions. + * + * For general information on %XML, the authoritative sources are the W3C + * recommendations: + * + * https://www.w3.org/TR/xml/ + * https://www.w3.org/TR/xml11/ + * https://www.w3.org/TR/xml-names/ + * + * The following example shows how an existing document can be parsed as a new + * %XMLDocument object, and then a new %XML document can be generated and + * written to a disk file, all in just three source code lines: + * + * \code + * XMLDocument xml; + * xml.Parse( File::ReadTextFile( "/path/to/file.xml" ).UTF8ToUTF16() ); + * File::WriteTextFile( "/tmp/test.xml", xml.Serialize() ); + * \endcode + * + * In this case the new document is generated without superfluous space + * characters. To enable automatic indentation of text lines, see the + * EnableAutoFormatting(), SetIndentSize() and EnableIndentTabs() member + * functions. + * + * The following example: + * + * \code + * XMLElement* e1 = new XMLElement( "Foo", XMLAttributeList() << XMLAttribute( "version", "1.0" ) ); + * + * XMLElement* e2 = new XMLElement( "Bar" ); + * *e2 << new XMLElement( "bar_child_1" ) + * << new XMLElement( "bar_child_2" ); + * + * XMLElement* e3 = new XMLElement( "FooBar" ); + * *e3 << new XMLText( "This is FooBar." ); + * + * *e1 << e2 << e3; + * + * XMLDocument xml; + * xml.SetXML( "1.0" ); + * xml.SetRootElement( e1 ); + * xml.EnableAutoFormatting(); + * xml.SerializeToFile( "/tmp/foobar.xml" ); + * \endcode + * + * generates this %XML file in /tmp/foobar.xml: + * + * \code + * + * + * + * + * + * + * This is FooBar. + * + * \endcode + * + * \ingroup xml_parsing_and_generation + */ +class PCL_CLASS XMLDocument +{ +public: + + /*! + * Represents a mutable child node list iterator. + */ + typedef XMLNodeList::iterator iterator; + + /*! + * Represents an immutable child node list iterator. + */ + typedef XMLNodeList::const_iterator const_iterator; + + /*! + * Represents an option to control the %XML parser behavior. Valid options + * are defined in the XMLParserOption namespace. + */ + typedef XMLParserOption::mask_type parser_option; + + /*! + * Default constructor. Constructs an empty %XML document. + * + * For serialization of XML documents, this constructor defines the + * following default settings: + * + * \li Auto-formatting disabled. + * \li Use space characters (\#x20) for indentation. + * \li Indentation size = 3 spaces. + */ + XMLDocument() = default; + + /*! + * Virtual destructor. Recursively destroys all %XML elements, declarations + * and auxiliary data associated with this object. + */ + virtual ~XMLDocument() + { + m_nodes.Destroy(); + m_root = nullptr; + RemoveElementFilter(); + } + + /*! + * Copy constructor. This constructor is disabled because %XMLDocument + * represents unique objects. + */ + XMLDocument( const XMLDocument& ) = delete; + + /*! + * Copy assignment. This operator is disabled because %XMLDocument + * represents unique objects. + */ + XMLDocument& operator =( const XMLDocument& ) = delete; + + /*! + * Returns a reference to the (immutable) %XML declaration object associated + * with this document. + */ + const XMLDeclaration& XML() const + { + return m_xml; + } + + /*! + * Defines an %XML declaration in this %XML document. + */ + void SetXML( const XMLDeclaration& xml ) + { + m_xml = xml; + } + + /*! + * Defines an %XML declaration in this %XML document with the specified + * \a version, \a encoding and \a standalone attributes. + */ + void SetXML( const String& version = "1.0", const String& encoding = "UTF-8", bool standalone = false ) + { + SetXML( XMLDeclaration( version, encoding, standalone ) ); + } + + /*! + * Returns a reference to the (immutable) %XML document type declaration + * object associated with this document. + */ + const XMLDocTypeDeclaration& DocType() const + { + return m_docType; + } + + /*! + * Associates a new %XML document type declaration object with this %XML + * document. + */ + void SetDocType( const XMLDocTypeDeclaration& docType ) + { + m_docType = docType; + } + + /*! + * Returns a pointer to the (immutable) root element of this %XML document. + * If there is no root element, for example when this is an uninitialized + * %XMLDocument instance, this function returns \c nullptr. + * + * \sa ReleaseRootElement(), SetRootElement() + */ + const XMLElement* RootElement() const + { + return m_root; + } + + /*! + * Releases the root element of this %XML document. + * + * This function returns the root element and causes this object to forget + * it. The caller will be responsible for destroying and deallocating the + * returned XMLElement instance as appropriate. This function performs an + * implicit call to Clear(), so the document will be empty after calling it. + * + * If there is no root element, for example when this is an uninitialized + * %XMLDocument instance, this function returns \c nullptr. + * + * \sa RootElement(), SetRootElement() + */ + XMLElement* ReleaseRootElement() + { + XMLElement* root = m_root; + m_nodes.RemovePointer( m_root ); + Clear(); + return root; + } + + /*! + * Returns the number of nodes in this %XML document, or zero if this is an + * empty or uninitialized %XMLDocument object. + */ + int NodeCount() const + { + return int( m_nodes.Length() ); + } + + /*! + * Returns true iff this is an empty %XML document. An empty document has no + * %XML nodes. + */ + bool IsEmpty() const + { + return m_nodes.IsEmpty(); + } + + /*! + * Returns a reference to the (immutable) document node at the specified + * zero-based index \a i. No bounds checking is performed: if the specified + * index is invalid, this function invokes undefined behavior. + */ + const XMLNode& operator []( int i ) const + { + return m_nodes[i]; + } + + /*! + * Returns an immutable iterator located at the beginning of the list of + * nodes of this %XML document. + */ + const_iterator Begin() const + { + return m_nodes.Begin(); + } + + /*! + * Returns an immutable iterator located at the end of the list of + * nodes of this %XML document. + */ + const_iterator End() const + { + return m_nodes.End(); + } + +#ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS + /*! + * STL-compatible iteration. Equivalent to Begin() const. + */ + const_iterator begin() const + { + return Begin(); + } + + /*! + * STL-compatible iteration. Equivalent to End() const. + */ + const_iterator end() const + { + return End(); + } +#endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS + + /*! + * Appends a new top-level %XML node to this document. + * + * If the specified \a node already belongs to an %XMLDocument object, or if + * a null pointer is specified, this member function will throw an Error + * exception. + * + * The specified \a node will be appended to the current list of document + * nodes. If there is a root element in this document, the new \a node will + * be appended after the root element. + * + * The \a node will be owned by this document object, which will destroy and + * deallocate it automatically when appropriate. + */ + void AddNode( XMLNode* node ); + + /*! + * Insertion operator. Returns a reference to this %XMLDocument object. + * + * This operator is equivalent to AddNode( XMLNode* ). + */ + XMLDocument& operator <<( XMLNode* node ) + { + AddNode( node ); + return *this; + } + + /*! + * Sets the root element of this %XML document. + * + * If the specified \a element already belongs to an %XMLDocument object, if + * a null pointer is specified, or if a root node has already been defined + * for this document, this member function will throw an Error exception. + * + * The specified \a element will be appended to the current list of document + * nodes. The \a element will be owned by this document object, which will + * destroy and deallocate it automatically when appropriate. + * + * \sa RootElement(), ReleaseRootElement() + */ + void SetRootElement( XMLElement* element ); + + /*! + * Destroys and deallocates all nodes and elements in this %XML document + * object, and initializes all internal structures to a default state, + * yielding an uninitialized object. + * + * If there is an element filter or a set of parser options defined for this + * object, they are preserved by this function. See RemoveElementFilter() to + * remove a filter set by a previous call to SetElementFilter(). See also + * ClearParserOptions() to reset parser options set by previous calls to + * SetParserOption(). + */ + void Clear(); + + /*! + * Sets a new element filter for this object. The specified object will be + * owned by this %XMLDocument instance, which will destroy and deallocate it + * when appropriate. + * + * See XMLElementFilter for a complete description of the element filtering + * functionality. See RemoveElementFilter() to remove the element filter + * set by this function. + */ + void SetElementFilter( XMLElementFilter* filter ) + { + delete m_filter, m_filter = filter; + } + + /*! + * Removes an element filter set by a previous call to SetElementFilter(). + * If no filter has been defined for this object, this function has no + * effect. + */ + void RemoveElementFilter() + { + SetElementFilter( nullptr ); + } + + /*! + * Enables or disables an %XML document parser option for this object. Valid + * options are defined in the XMLParserOption namespace. See + * ClearParserOptions() to reset all parser options to a default state. + */ + void SetParserOption( parser_option option, bool on = true ) + { + m_parserOptions.SetFlag( option, on ); + } + + /*! + * Sets the specified parser \a options. Valid options are defined in the + * XMLParserOption namespace. See ClearParserOptions() to reset all parser + * options to a default state. + */ + void SetParserOptions( XMLParserOptions options ) + { + m_parserOptions = options; + } + + /*! + * Resets all parser options defined for this object by a previous call to + * SetParserOption() or SetParserOptions(). + */ + void ClearParserOptions() + { + m_parserOptions.Clear(); + } + + /*! + * %XML document parser. Reads and interprets the specified Unicode \a text + * string, which must be encoded in UTF-16, as a well-formed %XML document. + * + * This member function generates a document object model (DOM) to represent + * the data entities defined by the source %XML document. The DOM can then + * be inspected with several member functions of the %XMLDocument class. All + * %XML nodes and elements can be visited recursively with specialized + * iterators. See the Begin() and End() functions (and their STL-compatible + * equivalents, begin() and end()), as well as XML(), DocType(), + * RootElement() and operator []( int ), among others. + */ + void Parse( const String& text ); + + /*! + * Returns true iff the auto-formatting feature is enabled for %XML + * serialization with this %XMLDocument object. + * + * When auto-formatting is enabled, ignorable line breaks (\#x0A) and white + * space characters (either spaces (\#x20) or tabulators (\#x09)) are used + * to separate %XML nodes and to indent text lines, respectively, improving + * readability of generated %XML code. When auto-formatting is disabled, no + * superfluous white space characters are generated. The only exception is + * XMLText child nodes with space preservation enabled, which always ignore + * all indentation and formatting settings in order to reproduce their text + * contents without modification. + * + * The auto-formatting feature is always disabled by default for newly + * constructed %XMLDocument objects. This is because the main purpose and + * utility of %XMLDocument is parsing and generation of %XML documents + * intended for automated data management, without direct user intervention. + * Auto-formatting is only useful for human readability of %XML source code. + */ + bool IsAutoFormatting() const + { + return m_autoFormatting; + } + + /*! + * Enables the auto-formatting feature for generation of %XML code. See + * IsAutoFormatting() for more information. + */ + void EnableAutoFormatting( bool enable = true ) + { + m_autoFormatting = enable; + } + + /*! + * Disables the auto-formatting feature for generation of %XML code. See + * IsAutoFormatting() for more information. + */ + void DisableAutoFormatting( bool disable = true ) + { + EnableAutoFormatting( !disable ); + } + + /*! + * Returns the number of space characters (\#x20) used for each indentation + * level of text lines, when the auto-formatting feature is enabled and + * space characters are used for indentation. + * + * When tabulator characters (\#x09) are used for indentation, this setting + * is ignored and a single tabulator is always used for each indentation + * level. See IsAutoFormatting() and SetIndentSize() for more information. + */ + int IndentSize() const + { + return m_indentSize; + } + + /*! + * Sets the number of indentation space characters. + * + * \param indentSize Number of space characters (\#x20) used for a level + * of indentation of text lines in generated %XML code, + * when the auto-formatting feature is enabled and + * space characters are used for indentation. The valid + * range of values is from zero (for no indentation) to + * 8 characters. + * + * When the indentation size is zero and auto-formatting is enabled, each + * document node is generated in a separate line without any indentation. + * XMLText child nodes with space preservation enabled will always ignore + * all indentation and formatting settings, in order to reproduce their text + * contents without modification. + * + * When tabulator characters (\#x09) are used for indentation, this setting + * is ignored and a single tabulator character is always used for each + * indentation level. + * + * The default indentation size is 3 for newly constructed %XMLDocument + * objects. + */ + void SetIndentSize( int indentSize ) + { + m_indentSize = Range( indentSize, 0, 8 ); + } + + /*! + * Returns true if tabulator characters (\#x09) are used for indentation of + * text lines, when the auto-formatting feature is enabled. Returns false if + * space characters (\#x20) are used for indentation. + * + * By default, text indentation is always performed using space characters + * by newly constructed %XMLDocument objects. + */ + bool IsIndentTabs() const + { + return m_indentTabs; + } + + /*! + * Enables the use of tabulator characters (\#x09) for indentation. See + * IsIndentTabs() for more information. + */ + void EnableIndentTabs( bool enable = true ) + { + m_indentTabs = enable; + } + + /*! + * Disables the use of tabulator characters (\#x09) for indentation. See + * IsIndentTabs() for more information. + */ + void DisableIndentTabs( bool disable = true ) + { + EnableIndentTabs( !disable ); + } + + /*! + * Serializes this %XML document. Returns the generated serialization as a + * Unicode string encoded in UTF-8. + * + * To serialize a well-formed %XML document, this object must be initialized + * first by defining a root element (see SetRootElement()) and other + * document nodes, as necessary (see SetXML(), SetDocType(), and AddNode()). + * + * For formatting and indentation settings, see IsAutoFormatting(), + * IndentSize() and IsIndentTabs(). + */ + IsoString Serialize() const; + + /*! + * Serializes this %XML document and writes the result to a file at the + * specified \a path with UTF-8 encoding. + * + * See Serialize() for more information. + * + * \warning If a file already exists at the specified path, its previous + * contents will be lost after calling this function. + */ + void SerializeToFile( const String& path ) const; + +private: + + XMLDeclaration m_xml; + XMLDocTypeDeclaration m_docType; + XMLNodeList m_nodes; + XMLElement* m_root = nullptr; + XMLElementFilter* m_filter = nullptr; + XMLParserOptions m_parserOptions; + XMLNodeLocation m_location; + bool m_autoFormatting = false; + bool m_indentTabs = false; + int m_indentSize = 3; +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_XML_h + +// ---------------------------------------------------------------------------- +// EOF pcl/XML.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/include/pcl/ZenithalProjections.h b/3rdparty/include/pcl/ZenithalProjections.h new file mode 100644 index 0000000..d2573ed --- /dev/null +++ b/3rdparty/include/pcl/ZenithalProjections.h @@ -0,0 +1,281 @@ +// ____ ______ __ +// / __ \ / ____// / +// / /_/ // / / / +// / ____// /___ / /___ PixInsight Class Library +// /_/ \____//_____/ PCL 2.4.23 +// ---------------------------------------------------------------------------- +// pcl/ZenithalProjections.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_ZenithalProjections_h +#define __PCL_ZenithalProjections_h + +/// \file pcl/ZenithalProjections.h + +#include + +#include + +/* + * Based on original work contributed by Andrés del Pozo. + */ + +namespace pcl +{ + +// ---------------------------------------------------------------------------- + +/*! + * \class ZenithalProjectionBase + * \brief Base class of zenithal projection systems + * + * \ingroup astrometry_support + */ +class PCL_CLASS ZenithalProjectionBase : public ProjectionBase +{ +protected: + + /*! + * Default constructor. + */ + ZenithalProjectionBase() + { + m_theta0 = 90; + } + + /*! + * Copy constructor. + */ + ZenithalProjectionBase( const ZenithalProjectionBase& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + virtual ProjectionBase* Clone() const override = 0; + + /*! + * Returns the WCS projection identifier for this projection system. + */ + virtual IsoString ProjCode() const override = 0; + + /*! + * Returns the readable name of this projection system. + */ + virtual IsoString Name() const override = 0; + +protected: + + /*! + * Transforms from world coordinates to native spherical coordinates. + */ + bool Project( DPoint& pW, const DPoint& pN ) const noexcept override + { + double rTheta = GetRTheta( pN ); + double sinTheta, cosTheta; + SinCos( Rad( pN.x ), sinTheta, cosTheta ); + pW.x = rTheta * sinTheta; + pW.y = -rTheta * cosTheta; + return true; + } + + /*! + * Transforms from native spherical coordinates to world coordinates. + */ + bool Unproject( DPoint& pN, const DPoint& pW ) const noexcept override + { + pN.x = Deg( ArcTan( pW.x, -pW.y ) ); + pN.y = GetTheta( Sqrt( pW.x*pW.x + pW.y*pW.y ) ); + return true; + } + + virtual double GetRTheta( const DPoint& np ) const = 0; + virtual double GetTheta( double rTheta ) const = 0; +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class ZenithalEqualAreaProjection + * \brief Zenithal equal-area projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS ZenithalEqualAreaProjection: public ZenithalProjectionBase +{ +public: + + /*! + * Default constructor. + */ + ZenithalEqualAreaProjection() = default; + + /*! + * Copy constructor. + */ + ZenithalEqualAreaProjection( const ZenithalEqualAreaProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new ZenithalEqualAreaProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "ZEA"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Zenithal Equal Area"; + } + + /*! + * + */ + bool CheckBrokenLine( const DPoint& cp1, const DPoint& cp2 ) const noexcept override + { + DPoint np1 = m_sph.CelestialToNative( cp1 ); + DPoint np2 = m_sph.CelestialToNative( cp2 ); + return Min( Mod( Abs( np1.x - np2.x - 360 ), 360.0 ), + Mod( Abs( np1.x - np2.x + 360 ), 360.0 ) ) < 180*Sin( Rad( 45 + (np1.y + np2.y)/2/2 ) ); + } + +private: + + double GetRTheta( const DPoint& np ) const override + { + return 2 * Deg( Sin( Rad( (90 - np.y)/2 ) ) ); + } + + double GetTheta( double rTheta ) const override + { + return 90 - 2*Deg( ArcSin( Rad( rTheta )/2 ) ); + } +}; + +// ---------------------------------------------------------------------------- + +/*! + * \class StereographicProjection + * \brief Stereographic projection system + * + * \ingroup astrometry_support + */ +class PCL_CLASS StereographicProjection: public ZenithalProjectionBase +{ +public: + + /*! + * Default constructor. + */ + StereographicProjection() = default; + + /*! + * Copy constructor. + */ + StereographicProjection( const StereographicProjection& ) = default; + + /*! + * Returns a dynamically allocated duplicate of this object. + */ + ProjectionBase* Clone() const override + { + return new StereographicProjection( *this ); + } + + /*! + * Returns the WCS projection identifier for this projection system. + */ + IsoString ProjCode() const override + { + return "STG"; + } + + /*! + * Returns the readable name of this projection system. + */ + IsoString Name() const override + { + return "Stereographic"; + } + + /*! + * + */ + bool CheckBrokenLine(const DPoint& cp1, const DPoint& cp2) const noexcept override + { + return true; + } + +private: + + double GetRTheta( const DPoint& np ) const override + { + return 2 * Deg( Tan( Rad( (90 - np.y)/2 ) ) ); + } + + double GetTheta( double rTheta ) const override + { + return 90 - 2*Deg( ArcTan( Rad( rTheta )/2 ) ); + } +}; + +// ---------------------------------------------------------------------------- + +} // pcl + +#endif // __PCL_ZenithalProjections_h + +// ---------------------------------------------------------------------------- +// EOF pcl/ZenithalProjections.h - Released 2022-03-12T18:59:29Z diff --git a/3rdparty/lib/Linux/libPCL.a b/3rdparty/lib/Linux/libPCL.a new file mode 100644 index 0000000..04b5fb3 Binary files /dev/null and b/3rdparty/lib/Linux/libPCL.a differ diff --git a/3rdparty/lib/Linux/libRFC6234.a b/3rdparty/lib/Linux/libRFC6234.a new file mode 100644 index 0000000..4c3be51 Binary files /dev/null and b/3rdparty/lib/Linux/libRFC6234.a differ diff --git a/3rdparty/lib/Linux/liblcms.a b/3rdparty/lib/Linux/liblcms.a new file mode 100644 index 0000000..dd1355b Binary files /dev/null and b/3rdparty/lib/Linux/liblcms.a differ diff --git a/3rdparty/lib/Linux/liblz4.a b/3rdparty/lib/Linux/liblz4.a new file mode 100644 index 0000000..5fc501e Binary files /dev/null and b/3rdparty/lib/Linux/liblz4.a differ diff --git a/3rdparty/lib/Linux/libzlib.a b/3rdparty/lib/Linux/libzlib.a new file mode 100644 index 0000000..8967b10 Binary files /dev/null and b/3rdparty/lib/Linux/libzlib.a differ diff --git a/3rdparty/lib/Windows/libPCL.a b/3rdparty/lib/Windows/libPCL.a new file mode 100755 index 0000000..588afe3 Binary files /dev/null and b/3rdparty/lib/Windows/libPCL.a differ diff --git a/3rdparty/lib/Windows/libRFC6234.a b/3rdparty/lib/Windows/libRFC6234.a new file mode 100755 index 0000000..6b0c870 Binary files /dev/null and b/3rdparty/lib/Windows/libRFC6234.a differ diff --git a/3rdparty/lib/Windows/liblcms.a b/3rdparty/lib/Windows/liblcms.a new file mode 100755 index 0000000..9e5b560 Binary files /dev/null and b/3rdparty/lib/Windows/liblcms.a differ diff --git a/3rdparty/lib/Windows/liblz4.a b/3rdparty/lib/Windows/liblz4.a new file mode 100755 index 0000000..60448b3 Binary files /dev/null and b/3rdparty/lib/Windows/liblz4.a differ diff --git a/3rdparty/lib/Windows/libzlib.a b/3rdparty/lib/Windows/libzlib.a new file mode 100755 index 0000000..9c7f0e2 Binary files /dev/null and b/3rdparty/lib/Windows/libzlib.a differ diff --git a/CMakeLists.txt b/CMakeLists.txt index be90b0c..1c79f3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.15) project(Tenmon) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) @@ -39,15 +39,22 @@ set(TENMON_SRC qt5_add_resources(TENMON_SRC resources.qrc) if(WIN32) list(APPEND TENMON_SRC icon.rc) + add_compile_definitions("__PCL_WINDOWS") endif(WIN32) +if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux") + add_compile_definitions("__PCL_LINUX") +endif() add_executable(tenmon ${TENMON_SRC}) find_path(FITS_INCLUDE fitsio2.h PATH_SUFFIXES cfitsio REQUIRED) -target_include_directories(tenmon PRIVATE ${OpenCV_INCLUDE_DIRS} ${FITS_INCLUDE}) +target_include_directories(tenmon PRIVATE ${OpenCV_INCLUDE_DIRS} ${FITS_INCLUDE} 3rdparty/include) target_link_libraries(tenmon Qt5::Widgets Qt5::Sql Qt5::OpenGL ${OpenCV_LIBS} ${GSL_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB}) +target_link_directories(tenmon PRIVATE 3rdparty/lib/${CMAKE_HOST_SYSTEM_NAME}) +target_link_libraries(tenmon PCL lcms lz4 RFC6234 zlib) + install(TARGETS tenmon) if(UNIX) install(SCRIPT install.cmake) diff --git a/imageringlist.cpp b/imageringlist.cpp index 4d0f724..23ee944 100644 --- a/imageringlist.cpp +++ b/imageringlist.cpp @@ -91,7 +91,7 @@ bool ImageRingList::setDir(const QString path, const QString ¤tFile) if(dir.exists()) { QStringList nameFilter; - nameFilter << "*.jpg" << "*.jpeg" << "*.png" << "*.cr2" << "*.fit" << "*.fits"; + nameFilter << "*.jpg" << "*.jpeg" << "*.png" << "*.cr2" << "*.fit" << "*.fits" << "*.xisf"; QStringList list = dir.entryList(nameFilter, QDir::Files | QDir::Readable, m_liveMode ? QDir::Time : QDir::Name); QStringList absolutePaths; diff --git a/loadrunable.cpp b/loadrunable.cpp index a20b079..5e18283 100644 --- a/loadrunable.cpp +++ b/loadrunable.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "rawimage.h" #include "starfit.h" @@ -75,7 +76,7 @@ void printStarModel(int radius, const std::vector &data, const Star &sta std::cout << m.toStdString() << std::endl << std::endl; } -bool loadRAW(QString path, ImageInfoData &info, RawImage **image) +bool loadRAW(const QString path, ImageInfoData &info, RawImage **image) { if(!image) return false; @@ -167,7 +168,7 @@ int loadFITSHeader(fitsfile *file, ImageInfoData &info) return status; } -bool loadFITS(QString path, ImageInfoData &info, RawImage **image) +bool loadFITS(const QString path, ImageInfoData &info, RawImage **image) { if(!image) return false; @@ -210,6 +211,10 @@ bool loadFITS(QString path, ImageInfoData &info, RawImage **image) cvtype = CV_32F; fitstype = TFLOAT; break; + default: + info.info.append({QObject::tr("Error"), QObject::tr("Unsupported sample format")}); + goto noload; + break; } size_t size = naxes[0]*naxes[1]; @@ -241,7 +246,7 @@ bool loadFITS(QString path, ImageInfoData &info, RawImage **image) } } } - + noload: loadFITSHeader(file, info); fits_close_file(file, &status); @@ -256,6 +261,77 @@ bool loadFITS(QString path, ImageInfoData &info, RawImage **image) return true; } +template +bool loadPCLImage(pcl::XISFReader &xisf, RawImage **image) +{ + PCLtype pclImage; + xisf.ReadImage(pclImage); + + int numChannels = pclImage.NumberOfChannels(); + cv::Mat cvImg[numChannels]; + for(int i=0; i(xisf, image); + if(!complex && !signedInt) + { + switch(bps) + { + case 8: + return loadPCLImage(xisf, image); + case 16: + return loadPCLImage(xisf, image); + } + + } + } + catch (pcl::Error err) + { + info.info.append(QPair("Error", err.FormatInfo().ToUTF8().c_str())); + qDebug() << err.FormatInfo().ToUTF8().c_str(); + } + info.info.append({QObject::tr("Error"), QObject::tr("Unsupported sample format")}); + return false; +} + void LoadRunable::run() { if(!m_receiver->isCurrent()) @@ -280,6 +356,10 @@ void LoadRunable::run() { loadFITS(m_file, info, &rawImage); } + else if(m_file.endsWith(".XISF", Qt::CaseInsensitive)) + { + loadXISF(m_file, info, &rawImage); + } else { QImage img(m_file); diff --git a/mainwindow.cpp b/mainwindow.cpp index 433f718..7d9d9b1 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -252,7 +252,7 @@ void MainWindow::pixmapLoaded(Image *image) void MainWindow::loadFile() { - QString file = QFileDialog::getOpenFileName(this, tr("Open file"), _lastDir, tr("Images (*.jpg *.jpeg *.png *.cr2 *.fit *.fits *.JPG *.JPEG *.PNG *.CR2 *.FIT *.FITS)")); + QString file = QFileDialog::getOpenFileName(this, tr("Open file"), _lastDir, tr("Images (*.jpg *.jpeg *.png *.cr2 *.fit *.fits *.xisf *.JPG *.JPEG *.PNG *.CR2 *.FIT *.FITS *.XISF)")); loadFile(file); }