PCL
LanczosInterpolation.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.4.0
6 // ----------------------------------------------------------------------------
7 // pcl/LanczosInterpolation.h - Released 2020-07-31T19:33:04Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2020 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (http://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_LanczosInterpolation_h
53 #define __PCL_LanczosInterpolation_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
61 #include <pcl/Math.h>
62 #include <pcl/Utility.h>
63 #include <pcl/Vector.h>
64 
65 namespace pcl
66 {
67 
68 // ----------------------------------------------------------------------------
69 
70 #define m_width this->m_width
71 #define m_height this->m_height
72 #define m_fillBorder this->m_fillBorder
73 #define m_fillValue this->m_fillValue
74 #define m_data this->m_data
75 
76 // ----------------------------------------------------------------------------
77 
78 /*
79  * Default clamping threshold for Lanczos interpolation. This value has been
80  * selected as the best trade-off for a large set of test linear images.
81  */
82 #ifndef __PCL_LANCZOS_CLAMPING_THRESHOLD
83 #define __PCL_LANCZOS_CLAMPING_THRESHOLD 0.3F
84 #endif
85 
86 // ----------------------------------------------------------------------------
87 
88 /*
89  * Floating point and integer LUT-based interpolations for 3rd, 4th and 5th
90  * order Lanczos functions. LUTs are initialized automatically on-demand by
91  * thread-safe internal routines.
92  *
93  * Real Lanczos LUTs are accurate to +/- 1e-7 DN
94  * Integer Lanczos LUTs are accurate to +/- 1 16-bit DN
95  */
96 #define __PCL_LANCZOS_LUT_REAL_RESOLUTION 4096
97 const double** PCL_FUNC PCL_InitializeLanczosRealLUT( int );
98 #define __PCL_LANCZOS_LUT_INT_RESOLUTION 65535
99 const float* PCL_FUNC PCL_InitializeLanczosIntLUT( int );
100 
101 // ----------------------------------------------------------------------------
102 
103 #define PCL_LANCZOS_ACC() \
104  if ( s < 0 ) \
105  sn -= s, wn -= L; \
106  else \
107  sp += s, wp += L;
108 
148 template <typename T>
150 {
151 private:
152 
153  struct Default
154  {
155  template <typename _T> static bool UseLUT( _T* ) { return false; }
156  static bool UseLUT( uint8* ) { return true; }
157  static bool UseLUT( int8* ) { return true; }
158  static bool UseLUT( uint16* ) { return true; }
159  static bool UseLUT( int16* ) { return true; }
160  static bool UseLUT( float* ) { return true; }
161  };
162 
163 public:
164 
197  LanczosInterpolation( int n = 3, float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD, bool useLUT = Default::UseLUT( (T*)0 ) )
198  : m_n( Max( 1, n ) )
199  , m_lut( useLUT ? PCL_InitializeLanczosRealLUT( m_n ) : nullptr )
200  , m_Lx( 2*m_n )
201  , m_clampTh( Range( clamp, 0.0F, 1.0F ) )
202  , m_clampThInv( 1 - m_clampTh )
203  , m_clamp( clamp >= 0 )
204  {
205  PCL_PRECONDITION( n >= 1 )
206  PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 )
207  }
208 
212  LanczosInterpolation( const LanczosInterpolation& ) = default;
213 
218  {
219  }
220 
227  double operator()( double x, double y ) const override
228  {
229  PCL_PRECONDITION( m_data != nullptr )
230  PCL_PRECONDITION( m_width > 0 && m_height > 0 )
231  PCL_PRECONDITION( x >= 0 && x < m_width )
232  PCL_PRECONDITION( y >= 0 && y < m_height )
233  PCL_CHECK( m_n >= 1 )
234 
235  // Central grid coordinates
236  int x0 = Range( TruncInt( x ), 0, m_width-1 );
237  int y0 = Range( TruncInt( y ), 0, m_height-1 );
238 
239  double sp = 0; // positive filter values
240  double sn = 0; // negative filter values
241  double wp = 0; // positive filter weight
242  double wn = 0; // negative filter weight
243  int i; // row index
244 
245  if ( m_lut != nullptr )
246  {
247  // Discrete interpolation increments
248  int dx = TruncInt( __PCL_LANCZOS_LUT_REAL_RESOLUTION*(x - x0) );
249  int dy = TruncInt( __PCL_LANCZOS_LUT_REAL_RESOLUTION*(y - y0) );
250 
251  // Precalculate horizontal filter values
252  for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
253  m_Lx[k] = m_lut[k][dx];
254 
255  int k; // LUT node index
256 
257  // Clipped rows at top
258  for ( i = -m_n + 1, k = 0; i <= m_n; ++i, ++k )
259  {
260  int y = y0 + i;
261  if ( y >= 0 )
262  break;
263  if ( m_fillBorder )
264  FillRow( sp, sn, wp, wn, m_lut[k][dy] );
265  else
266  InterpolateRow( sp, sn, wp, wn, m_data - 2*int64( y )*m_width, x0, m_lut[k][dy] );
267  }
268 
269  // Unclipped rows
270  for ( ; i <= m_n; ++i, ++k )
271  {
272  int y = y0 + i;
273  if ( y == m_height )
274  break;
275  InterpolateRow( sp, sn, wp, wn, m_data + int64( y )*m_width, x0, m_lut[k][dy] );
276  }
277 
278  // Clipped rows at bottom
279  for ( ; i <= m_n; ++i, ++k )
280  {
281  if ( m_fillBorder )
282  FillRow( sp, sn, wp, wn, m_lut[k][dy] );
283  else
284  InterpolateRow( sp, sn, wp, wn, m_data + int64( 2*m_height - 2 - y0 - i )*m_width, x0, m_lut[k][dy] );
285  }
286  }
287  else
288  {
289  // Interpolation increments
290  double dx = x - x0;
291  double dy = y - y0;
292 
293  // Precalculate horizontal filter values
294  for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
295  m_Lx[k] = Lanczos( j - dx );
296 
297  // Clipped rows at top
298  for ( i = -m_n + 1; i <= m_n; ++i )
299  {
300  int y = y0 + i;
301  if ( y >= 0 )
302  break;
303  if ( m_fillBorder )
304  FillRow( sp, sn, wp, wn, Lanczos( i - dy ) );
305  else
306  InterpolateRow( sp, sn, wp, wn, m_data - 2*int64( y )*m_width, x0, Lanczos( i - dy ) );
307  }
308 
309  // Unclipped rows
310  for ( ; i <= m_n; ++i )
311  {
312  int y = y0 + i;
313  if ( y == m_height )
314  break;
315  InterpolateRow( sp, sn, wp, wn, m_data + int64( y )*m_width, x0, Lanczos( i - dy ) );
316  }
317 
318  // Clipped rows at bottom
319  for ( ; i <= m_n; ++i )
320  {
321  if ( m_fillBorder )
322  FillRow( sp, sn, wp, wn, Lanczos( i - dy ) );
323  else
324  InterpolateRow( sp, sn, wp, wn, m_data + int64( 2*m_height - 2 - y0 - i )*m_width, x0, Lanczos( i - dy ) );
325  }
326  }
327 
328  // Clamping
329  if ( m_clamp )
330  {
331  // Empty data?
332  if ( sp == 0 )
333  return 0;
334 
335  // Clamping ratio: s-/s+
336  double r = sn/sp;
337 
338  // Clamp for s- >= s+
339  if ( r >= 1 )
340  return sp/wp;
341 
342  // Clamp for c < s- < s+
343  if ( r > m_clampTh )
344  {
345  r = (r - m_clampTh)/m_clampThInv;
346  double c = 1 - r*r;
347  sn *= c, wn *= c;
348  }
349  }
350 
351  // Weighted convolution
352  return (sp - sn)/(wp - wn);
353  }
354 
361  bool IsClampingEnabled() const
362  {
363  return m_clamp;
364  }
365 
371  void EnableClamping( bool enable = true )
372  {
373  m_clamp = enable;
374  }
375 
381  void DisableClamping( bool disable = true )
382  {
383  EnableClamping( !disable );
384  }
385 
394  float ClampingThreshold() const
395  {
396  return m_clampTh;
397  }
398 
419  void SetClampingThreshold( float clamp )
420  {
421  PCL_PRECONDITION( 0 <= clamp && clamp <= 1 )
422  m_clampTh = Range( clamp, 0.0F, 1.0F );
423  }
424 
425 private:
426 
427  int m_n; // filter order
428  const double** m_lut; // precomputed function values
429  mutable DVector m_Lx; // precalculated row of function values
430  double m_clampTh; // clamping threshold in [0,1]
431  double m_clampThInv; // 1 - m_clampTh
432  bool m_clamp; // clamping enabled ?
433 
434  /*
435  * Sinc function for x > 0
436  */
437  static double Sinc( double x )
438  {
439  x *= Const<double>::pi();
440  return (x > 1.0e-07) ? Sin( x )/x : 1.0;
441  }
442 
443  /*
444  * Evaluate Lanczos function at x.
445  */
446  double Lanczos( double x ) const
447  {
448  if ( x < 0 )
449  x = -x;
450  if ( x < m_n )
451  return Sinc( x ) * Sinc( x/m_n );
452  return 0;
453  }
454 
455  /*
456  * Interpolate a row of pixels.
457  * Can be either an unclipped row or a mirrored border row.
458  */
459  void InterpolateRow( double& sp, double& sn, double& wp, double& wn, const T* f, int x0, double Ly ) const
460  {
461  int j, k;
462 
463  // Clipped pixels at the left border
464  for ( j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
465  {
466  int x = x0 + j;
467  if ( x >= 0 )
468  break;
469  double L = m_Lx[k] * Ly;
470  double s = (m_fillBorder ? m_fillValue : double( f[-x] )) * L;
471  PCL_LANCZOS_ACC()
472  }
473 
474  // Unclipped pixels
475  for ( ; j <= m_n; ++j, ++k )
476  {
477  int x = x0 + j;
478  if ( x == m_width )
479  break;
480  double L = m_Lx[k] * Ly;
481  double s = f[x] * L;
482  PCL_LANCZOS_ACC()
483  }
484 
485  // Clipped pixels at the right border
486  for ( ; j <= m_n; ++j, ++k )
487  {
488  int x = x0 + j;
489  double L = m_Lx[k] * Ly;
490  double s = (m_fillBorder ? m_fillValue : double( f[2*m_width - 2 - x] )) * L;
491  PCL_LANCZOS_ACC()
492  }
493  }
494 
495  /*
496  * Interpolate a clipped pixel row with border filling.
497  */
498  void FillRow( double& sp, double& sn, double& wp, double& wn, double Ly ) const
499  {
500  for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
501  {
502  double L = m_Lx[k] * Ly;
503  double s = m_fillValue * L;
504  PCL_LANCZOS_ACC()
505  }
506  }
507 };
508 
509 // ----------------------------------------------------------------------------
510 
530 template <typename T, int m_n>
531 class PCL_CLASS LanczosLUTInterpolationBase : public BidimensionalInterpolation<T>
532 {
533 public:
534 
547  LanczosLUTInterpolationBase( float clamp )
548  : m_lut( PCL_InitializeLanczosIntLUT( m_n ) )
549  , m_Lx( 2*m_n )
550  , m_Ly( 2*m_n )
551  , m_clampTh( Range( clamp, 0.0F, 1.0F ) )
552  , m_clampThInv( 1 - m_clampTh )
553  , m_clamp( clamp >= 0 )
554  {
555  PCL_PRECONDITION( m_n >= 1 )
556  PCL_PRECONDITION( clamp < 0 || 0 <= clamp && clamp <= 1 )
557  PCL_CHECK( m_lut != nullptr )
558  }
559 
563  LanczosLUTInterpolationBase( const LanczosLUTInterpolationBase& ) = default;
564 
568  virtual ~LanczosLUTInterpolationBase()
569  {
570  }
571 
578  double operator()( double x, double y ) const override
579  {
580  PCL_PRECONDITION( m_data != nullptr )
581  PCL_PRECONDITION( m_width > 0 && m_height > 0 )
582  PCL_PRECONDITION( x >= 0 && x < m_width )
583  PCL_PRECONDITION( y >= 0 && y < m_height )
584 
585  // Central grid coordinates
586  int x0 = Range( TruncInt( x ), 0, m_width-1 );
587  int y0 = Range( TruncInt( y ), 0, m_height-1 );
588 
589  // Precalculate function values
590  int dx = RoundInt( (x - x0)*__PCL_LANCZOS_LUT_INT_RESOLUTION );
591  int dy = RoundInt( (y - y0)*__PCL_LANCZOS_LUT_INT_RESOLUTION );
592  for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
593  {
594  int d0 = j*__PCL_LANCZOS_LUT_INT_RESOLUTION;
595  m_Lx[k] = m_lut[Abs( d0 - dx )];
596  m_Ly[k] = m_lut[Abs( d0 - dy )];
597  }
598 
599  double sp = 0; // positive filter values
600  double sn = 0; // negative filter values
601  double wp = 0; // positive filter weight
602  double wn = 0; // negative filter weight
603  int i, k; // row and coefficient indices
604 
605  // Clipped rows at top
606  for ( i = -m_n + 1, k = 0; i <= m_n; ++i, ++k )
607  {
608  int y = y0 + i;
609  if ( y >= 0 )
610  break;
611  if ( m_fillBorder )
612  FillRow( sp, sn, wp, wn, m_Ly[k] );
613  else
614  InterpolateRow( sp, sn, wp, wn, m_data - 2*int64( y )*m_width, x0, m_Ly[k] );
615  }
616 
617  // Unclipped rows
618  for ( ; i <= m_n; ++i, ++k )
619  {
620  int y = y0 + i;
621  if ( y == m_height )
622  break;
623  InterpolateRow( sp, sn, wp, wn, m_data + int64( y )*m_width, x0, m_Ly[k] );
624  }
625 
626  // Clipped rows at bottom
627  for ( ; i <= m_n; ++i, ++k )
628  {
629  if ( m_fillBorder )
630  FillRow( sp, sn, wp, wn, m_Ly[k] );
631  else
632  InterpolateRow( sp, sn, wp, wn, m_data + int64( 2*m_height - 2 - y0 - i )*m_width, x0, m_Ly[k] );
633  }
634 
635  // Clamping
636  if ( m_clamp )
637  {
638  // Empty data?
639  if ( sp == 0 )
640  return 0;
641 
642  // Clamping ratio: s-/s+
643  double r = sn/sp;
644 
645  // Clamp for s- >= s+
646  if ( r >= 1 )
647  return sp/wp;
648 
649  // Clamp for c < s- < s+
650  if ( r > m_clampTh )
651  {
652  r = (r - m_clampTh)/m_clampThInv;
653  double c = 1 - r*r;
654  sn *= c, wn *= c;
655  }
656  }
657 
658  // Weighted convolution
659  return (sp - sn)/(wp - wn);
660  }
661 
668  bool IsClampingEnabled() const
669  {
670  return m_clamp;
671  }
672 
678  void EnableClamping( bool enable = true )
679  {
680  m_clamp = enable;
681  }
682 
688  void DisableClamping( bool disable = true )
689  {
690  EnableClamping( !disable );
691  }
692 
701  float ClampingThreshold() const
702  {
703  return m_clampTh;
704  }
705 
726  void SetClampingThreshold( float clamp )
727  {
728  PCL_PRECONDITION( 0 <= clamp && clamp <= 1 )
729  m_clampTh = Range( clamp, 0.0F, 1.0F );
730  }
731 
732 private:
733 
734  const float* m_lut; // filter LUT
735  mutable FVector m_Lx, m_Ly; // precalculated function values
736  double m_clampTh; // clamping threshold in [0,1]
737  double m_clampThInv; // 1 - m_clampTh
738  bool m_clamp; // clamping enabled ?
739 
740  /*
741  * Interpolate a row of pixels.
742  * Can be either an unclipped row or a mirrored border row.
743  */
744  void InterpolateRow( double& sp, double& sn, double& wp, double& wn, const T* f, int x0, float Ly ) const
745  {
746  int j, k;
747 
748  // Clipped pixels at the left border
749  for ( j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
750  {
751  int x = x0 + j;
752  if ( x >= 0 )
753  break;
754  double L = m_Lx[k] * Ly;
755  double s = (m_fillBorder ? m_fillValue : double( f[-x] )) * L;
756  PCL_LANCZOS_ACC()
757  }
758 
759  // Unclipped pixels
760  for ( ; j <= m_n; ++j, ++k )
761  {
762  int x = x0 + j;
763  if ( x == m_width )
764  break;
765  double L = m_Lx[k] * Ly;
766  double s = f[x] * L;
767  PCL_LANCZOS_ACC()
768  }
769 
770  // Clipped pixels at the right border
771  for ( ; j <= m_n; ++j, ++k )
772  {
773  int x = x0 + j;
774  double L = m_Lx[k] * Ly;
775  double s = (m_fillBorder ? m_fillValue : double( f[2*m_width - 2 - x] )) * L;
776  PCL_LANCZOS_ACC()
777  }
778  }
779 
780  /*
781  * Interpolate a clipped pixel row with border filling.
782  */
783  void FillRow( double& sp, double& sn, double& wp, double& wn, float Ly ) const
784  {
785  for ( int j = -m_n + 1, k = 0; j <= m_n; ++j, ++k )
786  {
787  double L = m_Lx[k] * Ly;
788  double s = m_fillValue * L;
789  PCL_LANCZOS_ACC()
790  }
791  }
792 };
793 
794 // ----------------------------------------------------------------------------
795 
813 template <typename T>
814 class PCL_CLASS Lanczos3LUTInterpolation : public LanczosLUTInterpolationBase<T,3>
815 {
816 public:
817 
830  Lanczos3LUTInterpolation( float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD )
831  : LanczosLUTInterpolationBase<T,3>( clamp )
832  {
833  PCL_PRECONDITION( 0 <= clamp && clamp <= 1 )
834  }
835 
840 
845  {
846  }
847 };
848 
849 // ----------------------------------------------------------------------------
850 
868 template <typename T>
869 class PCL_CLASS Lanczos4LUTInterpolation : public LanczosLUTInterpolationBase<T,4>
870 {
871 public:
872 
885  Lanczos4LUTInterpolation( float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD )
886  : LanczosLUTInterpolationBase<T,4>( clamp )
887  {
888  PCL_PRECONDITION( 0 <= clamp && clamp <= 1 )
889  }
890 
895 
900  {
901  }
902 };
903 
904 // ----------------------------------------------------------------------------
905 
923 template <typename T>
924 class PCL_CLASS Lanczos5LUTInterpolation : public LanczosLUTInterpolationBase<T,5>
925 {
926 public:
927 
940  Lanczos5LUTInterpolation( float clamp = __PCL_LANCZOS_CLAMPING_THRESHOLD )
941  : LanczosLUTInterpolationBase<T,5>( clamp )
942  {
943  PCL_PRECONDITION( 0 <= clamp && clamp <= 1 )
944  }
945 
950 
955  {
956  }
957 };
958 
959 // ----------------------------------------------------------------------------
960 
961 #undef PCL_LANCZOS_ACC
962 
963 #undef m_width
964 #undef m_height
965 #undef m_fillBorder
966 #undef m_fillValue
967 #undef m_data
968 
969 // ----------------------------------------------------------------------------
970 
971 } // pcl
972 
973 #endif // __PCL_LanczosInterpolation_h
974 
975 // ----------------------------------------------------------------------------
976 // EOF pcl/LanczosInterpolation.h - Released 2020-07-31T19:33:04Z
unsigned char uint8
Definition: Defs.h:576
Lanczos5LUTInterpolation(float clamp=__PCL_LANCZOS_CLAMPING_THRESHOLD)
static constexpr T pi()
Definition: Constants.h:94
int RoundInt(T x)
Definition: Math.h:1458
Two dimensional LUT-based 3rd-order Lanczos interpolation algorithm.
signed short int16
Definition: Defs.h:582
PCL root namespace.
Definition: AbstractImage.h:76
A generic interface to two-dimensional interpolation algorithms.
Two dimensional Lanczos interpolation algorithm.
Lanczos4LUTInterpolation(float clamp=__PCL_LANCZOS_CLAMPING_THRESHOLD)
constexpr const T & Range(const T &x, const T &a, const T &b)
Definition: Utility.h:190
T Abs(const Complex< T > &c)
Definition: Complex.h:431
Two dimensional LUT-based 4th-order Lanczos interpolation algorithm.
signed char int8
Definition: Defs.h:570
constexpr const T & Max(const T &a, const T &b)
Definition: Utility.h:119
64-bit floating point real vector.
unsigned short uint16
Definition: Defs.h:588
int TruncInt(T x)
Definition: Math.h:1091
Two dimensional LUT-based 5th-order Lanczos interpolation algorithm.
void EnableClamping(bool enable=true)
LanczosInterpolation(int n=3, float clamp=__PCL_LANCZOS_CLAMPING_THRESHOLD, bool useLUT=Default::UseLUT((T *) 0))
double operator()(double x, double y) const override
Complex< T > Sin(const Complex< T > &c)
Definition: Complex.h:797
void DisableClamping(bool disable=true)
void SetClampingThreshold(float clamp)
32-bit floating point real vector.
signed long long int64
Definition: Defs.h:610
Lanczos3LUTInterpolation(float clamp=__PCL_LANCZOS_CLAMPING_THRESHOLD)