54 #ifndef AVIR_CIMAGERESIZER_INCLUDED
55 #define AVIR_CIMAGERESIZER_INCLUDED
68 #define AVIR_VERSION "3.0"
75 #define AVIR_PI 3.1415926535897932
82 #define AVIR_PId2 1.5707963267948966
90 #define AVIR_NOCTOR( ClassName ) \
92 ClassName( const ClassName& ) { } \
93 ClassName& operator = ( const ClassName& ) { return( *this ); }
104 inline T round(
const T d )
106 return( d < (T) 0 ? -(T) (
int) ( (T) 0.5 - d ) :
107 (T) (
int) ( d + (T) 0.5 ));
121 inline T clamp(
const T& Value,
const T minv,
const T maxv )
146 inline T pow24_sRGB(
const T x )
148 const double x2 = (double) x * x;
149 const double x3 = x2 * x;
150 const double x4 = x2 * x2;
152 return( (T) ( 0.0985766365536824 + 0.839474952656502 * x2 +
153 0.363287814061725 * x3 - 0.0125559718896615 /
154 ( 0.12758338921578 + 0.290283465468235 * x ) -
155 0.231757513261358 * x - 0.0395365717969074 * x4 ));
166 inline T pow24i_sRGB(
const T x )
168 const double sx = sqrt( (
double) x );
169 const double ssx = sqrt( sx );
170 const double sssx = sqrt( ssx );
172 return( (T) ( 0.000213364515060263 + 0.0149409239419218 * x +
173 0.433973412731747 * sx + ssx * ( 0.659628181609715 * sssx -
174 0.0380957908841466 - 0.0706476137208521 * sx )));
185 inline T convertSRGB2Lin(
const T s )
187 const T a = (T) 0.055;
189 if( s <= (T) 0.04045 )
191 return( s / (T) 12.92 );
194 return( pow24_sRGB(( s + a ) / ( (T) 1 + a )));
205 inline T convertLin2SRGB(
const T s )
207 const T a = (T) 0.055;
209 if( s <= (T) 0.0031308 )
211 return( (T) 12.92 * s );
214 return(( (T) 1 + a ) * pow24i_sRGB( s ) - a );
230 template<
class T1,
class T2 >
231 inline void copyArray(
const T1* ip, T2* op,
int l,
232 const int ipinc = 1,
const int opinc = 1 )
253 template<
class T1,
class T2 >
254 inline void addArray(
const T1* ip, T2* op,
int l,
255 const int ipinc = 1,
const int opinc = 1 )
280 template<
class T1,
class T2 >
281 inline void replicateArray(
const T1*
const ip,
const int ipl, T2* op,
int l,
288 op[ 0 ] = (T2) ip[ 0 ];
298 op[ 0 ] = (T2) ip[ 0 ];
299 op[ 1 ] = (T2) ip[ 1 ];
300 op[ 2 ] = (T2) ip[ 2 ];
301 op[ 3 ] = (T2) ip[ 3 ];
311 op[ 0 ] = (T2) ip[ 0 ];
312 op[ 1 ] = (T2) ip[ 1 ];
313 op[ 2 ] = (T2) ip[ 2 ];
323 op[ 0 ] = (T2) ip[ 0 ];
324 op[ 1 ] = (T2) ip[ 1 ];
335 for( i = 0; i < ipl; i++ )
337 op[ i ] = (T2) ip[ i ];
361 inline void calcFIRFilterResponse(
const T* flt,
int fltlen,
362 const double th,
double& re0,
double& im0,
const int fltlat = 0 )
364 const double sincr = 2.0 * cos( th );
375 cvalue1 = cos( -fltlat * th );
376 svalue1 = sin( -fltlat * th );
379 double cvalue2 = cos( -( fltlat + 1 ) * th );
380 double svalue2 = sin( -( fltlat + 1 ) * th );
387 re += cvalue1 * flt[ 0 ];
388 im += svalue1 * flt[ 0 ];
392 double tmp = cvalue1;
393 cvalue1 = sincr * cvalue1 - cvalue2;
397 svalue1 = sincr * svalue1 - svalue2;
416 inline void normalizeFIRFilter( T*
const p,
const int l,
const double DCGain,
417 const int pstep = 1 )
436 *pp = (T) ( *pp * s );
461 template<
class T,
typename cap
int =
int >
467 , DataAligned( NULL )
481 CBuffer(
const capint aCapacity,
const int aAlignment = 0 )
483 allocinit( aCapacity, aAlignment );
488 allocinit( Source.Capacity, Source.Alignment );
492 memcpy( DataAligned, Source.DataAligned, Capacity *
sizeof( T ));
501 CBuffer& operator = (
const CBuffer& Source )
503 alloc( Source.Capacity, Source.Alignment );
507 memcpy( DataAligned, Source.DataAligned, Capacity *
sizeof( T ));
522 void alloc(
const capint aCapacity,
const int aAlignment = 0 )
525 allocinit( aCapacity, aAlignment );
562 Capacity = NewCapacity;
575 const bool DoDataCopy =
true )
577 if( NewCapacity < Capacity )
584 const capint PrevCapacity = Capacity;
585 T*
const PrevData = Data;
586 T*
const PrevDataAligned = DataAligned;
588 allocinit( NewCapacity, Alignment );
590 if( PrevCapacity > 0 )
592 memcpy( DataAligned, PrevDataAligned,
593 PrevCapacity *
sizeof( T ));
601 allocinit( NewCapacity, Alignment );
614 if( NewCapacity >= Capacity )
619 Capacity = NewCapacity;
633 if( ReqCapacity <= Capacity )
638 capint NewCapacity = Capacity;
640 while( NewCapacity < ReqCapacity )
642 NewCapacity += NewCapacity / 3 + 1;
650 return( DataAligned );
673 void allocinit(
const capint aCapacity,
const int aAlignment )
675 if( aAlignment == 0 )
677 Data = (T*) :: malloc( aCapacity *
sizeof( T ));
683 Data = (T*) :: malloc( aCapacity *
sizeof( T ) + aAlignment );
684 DataAligned = alignptr( Data, aAlignment );
685 Alignment = aAlignment;
688 Capacity = aCapacity;
712 inline Tp alignptr(
const Tp ptr,
const uintptr_t align )
714 return( (Tp) ( (uintptr_t) ptr + align -
715 ( (uintptr_t) ptr & ( align - 1 ))) );
746 Items[ ItemCount ] =
new T( Source[ ItemCount ]);
760 const int NewCount = Source.ItemCount;
763 while( ItemCount < NewCount )
765 Items[ ItemCount ] =
new T( Source[ ItemCount ]);
772 T& operator [](
const int Index )
774 return( *Items[ Index ]);
777 const T& operator [](
const int Index )
const
779 return( *Items[ Index ]);
796 Items[ ItemCount ] =
new T();
799 return( (*
this)[ ItemCount - 1 ]);
812 if( NewCount > ItemCount )
816 while( ItemCount < NewCount )
818 Items[ ItemCount ] =
new T();
824 while( ItemCount > NewCount )
827 delete Items[ ItemCount ];
838 while( ItemCount > 0 )
841 delete Items[ ItemCount ];
881 : svalue1( sin( ph ))
882 , svalue2( sin( ph - si ))
883 , sincr( 2.0 * cos( si ))
893 const double res = svalue1;
895 svalue1 = sincr * res - svalue2;
936 , Len2i( 1.0 / aLen2 )
948 const double h = pow( wn * Len2i, Alpha );
951 return( w1.
generate() * ( 1.0 - h ));
1008 void init(
const double SampleRate,
const double aFilterLength,
1009 const int aBandCount,
const double MinFreq,
const double MaxFreq,
1010 const bool IsLogBands,
const double WFAlpha )
1012 FilterLength = aFilterLength;
1013 BandCount = aBandCount;
1015 CenterFreqs.
alloc( BandCount );
1017 z = (int) ceil( FilterLength * 0.5 );
1022 initOscBuf( oscbuf );
1025 initWinBuf( winbuf, WFAlpha );
1027 UseFirstVirtBand = ( MinFreq > 0.0 );
1028 const int k = zi * ( BandCount + ( UseFirstVirtBand ? 1 : 0 ));
1029 Kernels1.
alloc( k );
1030 Kernels2.
alloc( k );
1037 m = exp( log( MaxFreq / MinFreq ) / ( BandCount - 1 ));
1043 mo = ( MaxFreq - MinFreq ) / ( BandCount - 1 );
1051 if( UseFirstVirtBand )
1058 CenterFreqs[ 0 ] = 0.0;
1062 double* kernbuf1 = &Kernels1[ 0 ];
1063 double* kernbuf2 = &Kernels2[ 0 ];
1066 for( i = si; i < BandCount; i++ )
1068 x2 = f * 2.0 / SampleRate;
1069 CenterFreqs[ i ] = x2;
1071 fillBandKernel( x1, x2, kernbuf1, kernbuf2, oscbuf, winbuf );
1081 UseLastVirtBand =
true;
1082 fillBandKernel( x1, 1.0, kernbuf1, kernbuf2, oscbuf, winbuf );
1086 UseLastVirtBand =
false;
1117 void buildFilter(
const double*
const BandGains,
double*
const Filter )
1119 const double* kernbuf1 = &Kernels1[ 0 ];
1120 const double* kernbuf2 = &Kernels2[ 0 ];
1122 double y1 = BandGains[ 0 ];
1129 if( UseFirstVirtBand )
1132 x2 = CenterFreqs[ 0 ];
1138 x2 = CenterFreqs[ 1 ];
1139 y2 = BandGains[ 1 ];
1142 copyBandKernel( Filter, kernbuf1, kernbuf2, y1 - y2,
1143 x1 * y2 - x2 * y1 );
1150 for( i = si; i < BandCount; i++ )
1152 x2 = CenterFreqs[ i ];
1153 y2 = BandGains[ i ];
1155 addBandKernel( Filter, kernbuf1, kernbuf2, y1 - y2,
1156 x1 * y2 - x2 * y1 );
1164 if( UseLastVirtBand )
1166 addBandKernel( Filter, kernbuf1, kernbuf2, y1 - y2,
1170 for( i = 0; i < z - 1; i++ )
1172 Filter[ z + i ] = Filter[ z - 2 - i ];
1188 const int l = (int) ceil( aFilterLength * 0.5 );
1191 return( l * 2 - 1 );
1195 double FilterLength;
1214 bool UseFirstVirtBand;
1217 bool UseLastVirtBand;
1232 void initOscBuf(
double* oscbuf )
const
1253 void initWinBuf(
double* winbuf,
const double Alpha )
const
1255 CDSPWindowGenPeakedCosine wf( Alpha, FilterLength * 0.5 );
1258 for( i = 1; i <= z; i++ )
1260 winbuf[ z - i ] = wf.generate();
1280 void fillBandKernel(
const double x1,
const double x2,
double* kernbuf1,
1281 double* kernbuf2,
double* oscbuf,
const double*
const winbuf )
1283 const double s2_incr =
AVIR_PI * x2;
1284 const double s2_coeff = 2.0 * cos( s2_incr );
1286 double s2_value1 = sin( s2_incr * ( -z + 1 ));
1287 double c2_value1 = sin( s2_incr * ( -z + 1 ) +
AVIR_PI * 0.5 );
1288 oscbuf[ 0 ] = sin( s2_incr * -z );
1289 oscbuf[ 1 ] = sin( s2_incr * -z +
AVIR_PI * 0.5 );
1293 for( ks = 1; ks < z; ks++ )
1295 const int ks2 = ks * 2;
1296 const double s1_value1 = oscbuf[ ks2 ];
1297 const double c1_value1 = oscbuf[ ks2 + 1 ];
1298 oscbuf[ ks2 ] = s2_value1;
1299 oscbuf[ ks2 + 1 ] = c2_value1;
1301 const double x =
AVIR_PI * ( ks - z );
1302 const double v0 = winbuf[ ks - 1 ] / (( x1 - x2 ) * x );
1304 kernbuf1[ ks - 1 ] = ( x2 * s2_value1 - x1 * s1_value1 +
1305 ( c2_value1 - c1_value1 ) / x ) * v0;
1307 kernbuf2[ ks - 1 ] = ( s2_value1 - s1_value1 ) * v0;
1309 s2_value1 = s2_coeff * s2_value1 - oscbuf[ ks2 - 2 ];
1310 c2_value1 = s2_coeff * c2_value1 - oscbuf[ ks2 - 1 ];
1313 kernbuf1[ z - 1 ] = ( x2 * x2 - x1 * x1 ) / ( x1 - x2 ) * 0.5;
1314 kernbuf2[ z - 1 ] = -1.0;
1327 void copyBandKernel(
double* outbuf,
const double*
const kernbuf1,
1328 const double*
const kernbuf2,
const double c,
const double d )
const
1332 for( ks = 0; ks < z; ks++ )
1334 outbuf[ ks ] = c * kernbuf1[ ks ] + d * kernbuf2[ ks ];
1348 void addBandKernel(
double* outbuf,
const double*
const kernbuf1,
1349 const double*
const kernbuf2,
const double c,
const double d )
const
1353 for( ks = 0; ks < z; ks++ )
1355 outbuf[ ks ] += c * kernbuf1[ ks ] + d * kernbuf2[ ks ];
1387 const double aAlpha )
1388 :
fl2( (int) ceil( aLen2 ) - 1 )
1420 *op = (T) ( Freq2 * wf.
generate() );
1439 *op2 = (T) ( *op2 * s );
1448 *op = (T) ( Freq2 * wf.
generate() );
1531 template<
class fptype >
1555 WFAlpha = s.WFAlpha;
1556 FracCount = s.FracCount;
1558 Alignment = s.Alignment;
1559 SrcFilterLen = s.SrcFilterLen;
1560 FilterLen = s.FilterLen;
1561 FilterSize = s.FilterSize;
1562 IsSrcTableBuilt =
false;
1563 ExtFilter = s.ExtFilter;
1570 for( i = 0; i < TableFillFlags.
getCapacity(); i++ )
1572 TableFillFlags[ i ] = (uint8_t) ( s.TableFillFlags[ i ] << 2 );
1587 return( Order == s.Order && WFLen2 == s.WFLen2 &&
1588 WFFreq == s.WFFreq && WFAlpha == s.WFAlpha &&
1589 FracCount == s.FracCount && ExtFilter == s.ExtFilter );
1613 void init(
const int ReqFracCount,
const int ReqOrder,
1614 const double BaseLen,
const double Cutoff,
const double aWFAlpha,
1615 const CFltBuffer& aExtFilter,
const int aAlignment = 0,
1616 const int FltLenAlign = 1 )
1618 double NewWFLen2 = 0.5 * BaseLen * ReqFracCount;
1619 double NewWFFreq =
AVIR_PI * Cutoff / ReqFracCount;
1620 double NewWFAlpha = aWFAlpha;
1622 if( ReqOrder == Order && NewWFLen2 == WFLen2 && NewWFFreq == WFFreq &&
1623 NewWFAlpha == WFAlpha && ReqFracCount == FracCount &&
1624 aExtFilter == ExtFilter )
1626 IsInitRequired =
false;
1632 WFAlpha = NewWFAlpha;
1633 FracCount = ReqFracCount;
1635 Alignment = aAlignment;
1636 ExtFilter = aExtFilter;
1639 SrcFilterLen = ( p.
fl2 / ReqFracCount + 1 ) * 2;
1641 const int ElementSize = ReqOrder + 1;
1642 FilterLen = SrcFilterLen;
1649 FilterLen = ( FilterLen + FltLenAlign - 1 ) & ~( FltLenAlign - 1 );
1650 FilterSize = FilterLen * ElementSize;
1651 IsSrcTableBuilt =
false;
1652 IsInitRequired =
true;
1662 return( FilterLen );
1671 return( FracCount );
1696 if( !IsSrcTableBuilt )
1701 fptype*
const Res = &Table[ i * FilterSize ];
1703 if(( TableFillFlags[ i ] & 2 ) == 0 )
1706 TableFillFlags[ i ] |= 2;
1710 createFilter( i + 1 );
1711 const fptype*
const Res2 = Res + FilterSize;
1712 fptype*
const op = Res + FilterLen;
1718 for( j = 0; j < FilterLen; j++ )
1720 op[ j ] = Res2[ j ] - Res[ j ];
1736 for( i = 0; i < FracCount; i++ )
1757 const int FltInitCost = 65;
1759 const int FltUseCost = FilterLen * Order +
1762 const int ucb[ 2 ] = { 0, FltUseCost };
1766 if( IsInitRequired )
1768 ic = FracCount * SrcFilterLen * FltInitCost;
1770 for( i = 0; i < FracCount; i++ )
1772 ic += ucb[ FracUseMap[ i ]];
1779 for( i = 0; i < FracCount; i++ )
1781 if( FracUseMap[ i ] != 0 )
1783 ic += ucb[ TableFillFlags[ i ] == 0 ? 1 : 0 ];
1792 static const int InterpPoints = 2;
1815 bool IsInitRequired;
1835 bool IsSrcTableBuilt;
1846 void buildSrcTable()
1848 IsSrcTableBuilt =
true;
1849 IsInitRequired =
false;
1853 const int BufLen = SrcFilterLen * FracCount + InterpPoints - 1;
1854 const int BufOffs = InterpPoints / 2 - 1;
1855 const int BufCenter = SrcFilterLen * FracCount / 2 + BufOffs;
1858 memset( Buf, 0, ( BufCenter - p.fl2 ) *
sizeof(
double ));
1859 int i = BufLen - BufCenter - p.fl2 - 1;
1860 memset( &Buf[ BufLen - i ], 0, i *
sizeof(
double ));
1862 p.generateLPF( &Buf[ BufCenter - p.fl2 ], 0.0 );
1864 SrcTable.
alloc(( FracCount + 1 ) * SrcFilterLen );
1865 TableFillFlags.
alloc( FracCount + 1 );
1867 double* op0 = SrcTable;
1869 for( i = FracCount; i >= 0; i-- )
1871 TableFillFlags[ i ] = 0;
1872 double* p = Buf + BufOffs + i;
1874 for( j = 0; j < SrcFilterLen; j++ )
1881 normalizeFIRFilter( op0 - SrcFilterLen, SrcFilterLen, 1.0 );
1884 Table.
alloc(( FracCount + 1 ) * FilterSize, Alignment );
1896 void createFilter(
const int k )
1898 if( TableFillFlags[ k ] != 0 )
1903 TableFillFlags[ k ] |= 1;
1904 const int ExtFilterLatency = ExtFilter.
getCapacity() / 2;
1905 const int ResLatency = ExtFilterLatency + SrcFilterLen / 2;
1906 int ResLen = SrcFilterLen;
1913 const int ResOffs = FilterLen / 2 - ResLatency;
1914 fptype* op = &Table[ k * FilterSize ];
1917 for( i = 0; i < ResOffs; i++ )
1919 op[ i ] = (fptype) 0;
1922 for( i = ResOffs + ResLen; i < FilterLen; i++ )
1924 op[ i ] = (fptype) 0;
1928 const double*
const srcflt = &SrcTable[ k * SrcFilterLen ];
1932 for( i = 0; i < ResLen; i++ )
1934 op[ i ] = (fptype) srcflt[ i ];
1942 const double*
const extflt = &ExtFilter[ 0 ];
1945 for( j = 0; j < ResLen; j++ )
1957 if( r > SrcFilterLen )
1962 const double*
const extfltb = extflt + k;
1963 const double*
const srcfltb = srcflt + l;
1967 for( i = 0; i < l; i++ )
1969 s += extfltb[ i ] * srcfltb[ i ];
1972 op[ j ] = (fptype) s;
2447 template<
class fptype,
class fptypeatom >
2600 const int FracCount )
2608 if( Buf.
k == k && Buf.
o == o && Buf.
FracCount == FracCount )
2646 template<
class fptype,
class fptypeatom >
2680 template<
class Tin >
2683 const int ElCount =
Vars -> ElCount;
2684 const int ElCountIO =
Vars -> ElCountIO;
2688 if( !
Vars -> UseSRGBGamma )
2690 if( ElCountIO == 1 )
2694 fptypeatom* v = (fptypeatom*) op;
2695 v[ 0 ] = (fptypeatom) ip[ 0 ];
2702 if( ElCountIO == 4 )
2706 fptypeatom* v = (fptypeatom*) op;
2707 v[ 0 ] = (fptypeatom) ip[ 0 ];
2708 v[ 1 ] = (fptypeatom) ip[ 1 ];
2709 v[ 2 ] = (fptypeatom) ip[ 2 ];
2710 v[ 3 ] = (fptypeatom) ip[ 3 ];
2717 if( ElCountIO == 3 )
2721 fptypeatom* v = (fptypeatom*) op;
2722 v[ 0 ] = (fptypeatom) ip[ 0 ];
2723 v[ 1 ] = (fptypeatom) ip[ 1 ];
2724 v[ 2 ] = (fptypeatom) ip[ 2 ];
2731 if( ElCountIO == 2 )
2735 fptypeatom* v = (fptypeatom*) op;
2736 v[ 0 ] = (fptypeatom) ip[ 0 ];
2737 v[ 1 ] = (fptypeatom) ip[ 1 ];
2746 const fptypeatom gm = (fptypeatom)
Vars -> InGammaMult;
2748 if( ElCountIO == 1 )
2752 fptypeatom* v = (fptypeatom*) op;
2753 v[ 0 ] = convertSRGB2Lin( (fptypeatom) ip[ 0 ] * gm );
2760 if( ElCountIO == 4 )
2764 fptypeatom* v = (fptypeatom*) op;
2765 v[ 0 ] = convertSRGB2Lin( (fptypeatom) ip[ 0 ] * gm );
2766 v[ 1 ] = convertSRGB2Lin( (fptypeatom) ip[ 1 ] * gm );
2767 v[ 2 ] = convertSRGB2Lin( (fptypeatom) ip[ 2 ] * gm );
2768 v[ 3 ] = convertSRGB2Lin( (fptypeatom) ip[ 3 ] * gm );
2775 if( ElCountIO == 3 )
2779 fptypeatom* v = (fptypeatom*) op;
2780 v[ 0 ] = convertSRGB2Lin( (fptypeatom) ip[ 0 ] * gm );
2781 v[ 1 ] = convertSRGB2Lin( (fptypeatom) ip[ 1 ] * gm );
2782 v[ 2 ] = convertSRGB2Lin( (fptypeatom) ip[ 2 ] * gm );
2789 if( ElCountIO == 2 )
2793 fptypeatom* v = (fptypeatom*) op;
2794 v[ 0 ] = convertSRGB2Lin( (fptypeatom) ip[ 0 ] * gm );
2795 v[ 1 ] = convertSRGB2Lin( (fptypeatom) ip[ 1 ] * gm );
2803 const int ZeroCount = ElCount *
Vars -> fppack - ElCountIO;
2804 op = (fptype*) ( (fptypeatom*) op0 + ElCountIO );
2807 if( ZeroCount == 1 )
2811 fptypeatom* v = (fptypeatom*) op;
2812 v[ 0 ] = (fptypeatom) 0;
2818 if( ZeroCount == 2 )
2822 fptypeatom* v = (fptypeatom*) op;
2823 v[ 0 ] = (fptypeatom) 0;
2824 v[ 1 ] = (fptypeatom) 0;
2830 if( ZeroCount == 3 )
2834 fptypeatom* v = (fptypeatom*) op;
2835 v[ 0 ] = (fptypeatom) 0;
2836 v[ 1 ] = (fptypeatom) 0;
2837 v[ 2 ] = (fptypeatom) 0;
2856 const int ElCount = Vars0.
ElCount;
2860 if( ElCountIO == 1 )
2864 fptypeatom* v = (fptypeatom*) p;
2865 v[ 0 ] = convertLin2SRGB( v[ 0 ]) * gm;
2871 if( ElCountIO == 4 )
2875 fptypeatom* v = (fptypeatom*) p;
2876 v[ 0 ] = convertLin2SRGB( v[ 0 ]) * gm;
2877 v[ 1 ] = convertLin2SRGB( v[ 1 ]) * gm;
2878 v[ 2 ] = convertLin2SRGB( v[ 2 ]) * gm;
2879 v[ 3 ] = convertLin2SRGB( v[ 3 ]) * gm;
2885 if( ElCountIO == 3 )
2889 fptypeatom* v = (fptypeatom*) p;
2890 v[ 0 ] = convertLin2SRGB( v[ 0 ]) * gm;
2891 v[ 1 ] = convertLin2SRGB( v[ 1 ]) * gm;
2892 v[ 2 ] = convertLin2SRGB( v[ 2 ]) * gm;
2898 if( ElCountIO == 2 )
2902 fptypeatom* v = (fptypeatom*) p;
2903 v[ 0 ] = convertLin2SRGB( v[ 0 ]) * gm;
2904 v[ 1 ] = convertLin2SRGB( v[ 1 ]) * gm;
2926 const int SrcIncr )
const
2928 const int ElCount =
Vars -> ElCount;
2933 for( j = 0; j < SrcLen; j++ )
2943 for( j = 0; j < SrcLen; j++ )
2956 for( j = 0; j < SrcLen; j++ )
2968 for( j = 0; j < SrcLen; j++ )
2992 template<
class Tout >
2996 const int ElCount = Vars0.
ElCount;
2999 if( ElCountIO == 1 )
3003 const fptypeatom* v = (
const fptypeatom*) ip;
3004 op[ 0 ] = (Tout) v[ 0 ];
3011 if( ElCountIO == 4 )
3015 const fptypeatom* v = (
const fptypeatom*) ip;
3016 op[ 0 ] = (Tout) v[ 0 ];
3017 op[ 1 ] = (Tout) v[ 1 ];
3018 op[ 2 ] = (Tout) v[ 2 ];
3019 op[ 3 ] = (Tout) v[ 3 ];
3026 if( ElCountIO == 3 )
3030 const fptypeatom* v = (
const fptypeatom*) ip;
3031 op[ 0 ] = (Tout) v[ 0 ];
3032 op[ 1 ] = (Tout) v[ 1 ];
3033 op[ 2 ] = (Tout) v[ 2 ];
3040 if( ElCountIO == 2 )
3044 const fptypeatom* v = (
const fptypeatom*) ip;
3045 op[ 0 ] = (Tout) v[ 0 ];
3046 op[ 1 ] = (Tout) v[ 1 ];
3064 fptype*
const ElBiases )
const
3066 const int ElCount =
Vars -> ElCount;
3071 fptype b0 = (fptype) 0;
3080 ElBiases[ 0 ] = b0 / (fptype) SrcLen;
3085 fptype b0 = (fptype) 0;
3086 fptype b1 = (fptype) 0;
3087 fptype b2 = (fptype) 0;
3088 fptype b3 = (fptype) 0;
3100 ElBiases[ 0 ] = b0 / (fptype) SrcLen;
3101 ElBiases[ 1 ] = b1 / (fptype) SrcLen;
3102 ElBiases[ 2 ] = b2 / (fptype) SrcLen;
3103 ElBiases[ 3 ] = b3 / (fptype) SrcLen;
3108 fptype b0 = (fptype) 0;
3109 fptype b1 = (fptype) 0;
3110 fptype b2 = (fptype) 0;
3121 ElBiases[ 0 ] = b0 / (fptype) SrcLen;
3122 ElBiases[ 1 ] = b1 / (fptype) SrcLen;
3123 ElBiases[ 2 ] = b2 / (fptype) SrcLen;
3128 fptype b0 = (fptype) 0;
3129 fptype b1 = (fptype) 0;
3139 ElBiases[ 0 ] = b0 / (fptype) SrcLen;
3140 ElBiases[ 1 ] = b1 / (fptype) SrcLen;
3154 const fptype*
const ElBiases )
const
3156 const int ElCount =
Vars -> ElCount;
3160 const fptype b0 = ElBiases[ 0 ];
3172 const fptype b0 = ElBiases[ 0 ];
3173 const fptype b1 = ElBiases[ 1 ];
3174 const fptype b2 = ElBiases[ 2 ];
3175 const fptype b3 = ElBiases[ 3 ];
3190 const fptype b0 = ElBiases[ 0 ];
3191 const fptype b1 = ElBiases[ 1 ];
3192 const fptype b2 = ElBiases[ 2 ];
3206 const fptype b0 = ElBiases[ 0 ];
3207 const fptype b1 = ElBiases[ 1 ];
3235 const int ElCount =
Vars -> ElCount;
3236 replicateArray( Src, ElCount, Src - ElCount,
InPrefix, -ElCount );
3238 Src += (
InLen - 1 ) * ElCount;
3239 replicateArray( Src, ElCount, Src + ElCount,
InSuffix, ElCount );
3250 void doUpsample(
const fptype*
const Src, fptype*
const Dst )
const
3252 const int ElCount =
Vars -> ElCount;
3253 fptype* op0 = &Dst[ -
OutPrefix * ElCount ];
3257 const fptype* ip = Src;
3405 const fptype*
const f =
Flt;
3418 for( i = 0; i < flen; i++ )
3420 op[ i ] += f[ i ] * ip[ 0 ];
3433 for( i = 0; i < flen; i++ )
3435 op[ i ] += f[ i ] * ip[ 0 ];
3449 for( i = 0; i < flen; i++ )
3451 op[ i ] += f[ i ] * ip[ 0 ];
3467 for( i = 0; i < flen; i++ )
3469 op[ 0 ] += f[ i ] * ip[ 0 ];
3470 op[ 1 ] += f[ i ] * ip[ 1 ];
3471 op[ 2 ] += f[ i ] * ip[ 2 ];
3472 op[ 3 ] += f[ i ] * ip[ 3 ];
3486 for( i = 0; i < flen; i++ )
3488 op[ 0 ] += f[ i ] * ip[ 0 ];
3489 op[ 1 ] += f[ i ] * ip[ 1 ];
3490 op[ 2 ] += f[ i ] * ip[ 2 ];
3491 op[ 3 ] += f[ i ] * ip[ 3 ];
3506 for( i = 0; i < flen; i++ )
3508 op[ 0 ] += f[ i ] * ip[ 0 ];
3509 op[ 1 ] += f[ i ] * ip[ 1 ];
3510 op[ 2 ] += f[ i ] * ip[ 2 ];
3511 op[ 3 ] += f[ i ] * ip[ 3 ];
3528 for( i = 0; i < flen; i++ )
3530 op[ 0 ] += f[ i ] * ip[ 0 ];
3531 op[ 1 ] += f[ i ] * ip[ 1 ];
3532 op[ 2 ] += f[ i ] * ip[ 2 ];
3546 for( i = 0; i < flen; i++ )
3548 op[ 0 ] += f[ i ] * ip[ 0 ];
3549 op[ 1 ] += f[ i ] * ip[ 1 ];
3550 op[ 2 ] += f[ i ] * ip[ 2 ];
3565 for( i = 0; i < flen; i++ )
3567 op[ 0 ] += f[ i ] * ip[ 0 ];
3568 op[ 1 ] += f[ i ] * ip[ 1 ];
3569 op[ 2 ] += f[ i ] * ip[ 2 ];
3586 for( i = 0; i < flen; i++ )
3588 op[ 0 ] += f[ i ] * ip[ 0 ];
3589 op[ 1 ] += f[ i ] * ip[ 1 ];
3603 for( i = 0; i < flen; i++ )
3605 op[ 0 ] += f[ i ] * ip[ 0 ];
3606 op[ 1 ] += f[ i ] * ip[ 1 ];
3621 for( i = 0; i < flen; i++ )
3623 op[ 0 ] += f[ i ] * ip[ 0 ];
3624 op[ 1 ] += f[ i ] * ip[ 1 ];
3639 for( i = 0; i < l; i++ )
3641 op[ i ] += ip[ 0 ] * dc[ i ];
3649 op[ 0 ] += ip[ 0 ] * dc[ 0 ];
3650 op[ 1 ] += ip[ 1 ] * dc[ 0 ];
3651 op[ 2 ] += ip[ 2 ] * dc[ 0 ];
3652 op[ 3 ] += ip[ 3 ] * dc[ 0 ];
3663 op[ 0 ] += ip[ 0 ] * dc[ 0 ];
3664 op[ 1 ] += ip[ 1 ] * dc[ 0 ];
3665 op[ 2 ] += ip[ 2 ] * dc[ 0 ];
3676 op[ 0 ] += ip[ 0 ] * dc[ 0 ];
3677 op[ 1 ] += ip[ 1 ] * dc[ 0 ];
3691 for( i = 0; i < l; i++ )
3693 op[ i ] += ip[ 0 ] * dc[ i ];
3701 op[ 0 ] += ip[ 0 ] * dc[ 0 ];
3702 op[ 1 ] += ip[ 1 ] * dc[ 0 ];
3703 op[ 2 ] += ip[ 2 ] * dc[ 0 ];
3704 op[ 3 ] += ip[ 3 ] * dc[ 0 ];
3715 op[ 0 ] += ip[ 0 ] * dc[ 0 ];
3716 op[ 1 ] += ip[ 1 ] * dc[ 0 ];
3717 op[ 2 ] += ip[ 2 ] * dc[ 0 ];
3728 op[ 0 ] += ip[ 0 ] * dc[ 0 ];
3729 op[ 1 ] += ip[ 1 ] * dc[ 0 ];
3749 const int DstIncr )
const
3751 const int ElCount =
Vars -> ElCount;
3765 fptype s = f[ 0 ] * ip[ 0 ];
3769 for( i = 1; i < flen; i++ )
3773 s += f[ i ] * ( ip1[ 0 ] + ip2[ 0 ]);
3787 fptype s1 = f[ 0 ] * ip[ 0 ];
3788 fptype s2 = f[ 0 ] * ip[ 1 ];
3789 fptype s3 = f[ 0 ] * ip[ 2 ];
3790 fptype s4 = f[ 0 ] * ip[ 3 ];
3794 for( i = 1; i < flen; i++ )
3798 s1 += f[ i ] * ( ip1[ 0 ] + ip2[ 0 ]);
3799 s2 += f[ i ] * ( ip1[ 1 ] + ip2[ 1 ]);
3800 s3 += f[ i ] * ( ip1[ 2 ] + ip2[ 2 ]);
3801 s4 += f[ i ] * ( ip1[ 3 ] + ip2[ 3 ]);
3818 fptype s1 = f[ 0 ] * ip[ 0 ];
3819 fptype s2 = f[ 0 ] * ip[ 1 ];
3820 fptype s3 = f[ 0 ] * ip[ 2 ];
3824 for( i = 1; i < flen; i++ )
3828 s1 += f[ i ] * ( ip1[ 0 ] + ip2[ 0 ]);
3829 s2 += f[ i ] * ( ip1[ 1 ] + ip2[ 1 ]);
3830 s3 += f[ i ] * ( ip1[ 2 ] + ip2[ 2 ]);
3846 fptype s1 = f[ 0 ] * ip[ 0 ];
3847 fptype s2 = f[ 0 ] * ip[ 1 ];
3851 for( i = 1; i < flen; i++ )
3855 s1 += f[ i ] * ( ip1[ 0 ] + ip2[ 0 ]);
3856 s2 += f[ i ] * ( ip1[ 1 ] + ip2[ 1 ]);
3886 const int DstLineIncr,
const fptype*
const ElBiases,
3887 fptype*
const )
const
3889 const int IntFltLen =
FltBank -> getFilterLen();
3890 const int ElCount =
Vars -> ElCount;
3897 #define AVIR_RESIZE_PART1 \
3898 while( rpos < rpose ) \
3900 const fptype x = (fptype) rpos -> x; \
3901 const fptype* const ftp = rpos -> ftp; \
3902 const fptype* const ftp2 = ftp + IntFltLen; \
3903 const fptype* Src = SrcLine + rpos -> SrcOffs; \
3906 #define AVIR_RESIZE_PART1nx \
3907 while( rpos < rpose ) \
3909 const fptype* const ftp = rpos -> ftp; \
3910 const fptype* Src = SrcLine + rpos -> SrcOffs; \
3913 #define AVIR_RESIZE_PART2 \
3914 DstLine += DstLineIncr; \
3918 if(
FltBank -> getOrder() == 1 )
3924 fptype sum0 = ElBiases[ 0 ];
3926 for( i = 0; i < IntFltLen; i++ )
3928 sum0 += ( ftp[ i ] + ftp2[ i ] * x ) * Src[ i ];
3931 DstLine[ 0 ] = sum0;
3940 fptype sum0 = ElBiases[ 0 ];
3941 fptype sum1 = ElBiases[ 1 ];
3942 fptype sum2 = ElBiases[ 2 ];
3943 fptype sum3 = ElBiases[ 3 ];
3945 for( i = 0; i < IntFltLen; i++ )
3947 const fptype xx = ftp[ i ] + ftp2[ i ] * x;
3948 sum0 += xx * Src[ 0 ];
3949 sum1 += xx * Src[ 1 ];
3950 sum2 += xx * Src[ 2 ];
3951 sum3 += xx * Src[ 3 ];
3955 DstLine[ 0 ] = sum0;
3956 DstLine[ 1 ] = sum1;
3957 DstLine[ 2 ] = sum2;
3958 DstLine[ 3 ] = sum3;
3967 fptype sum0 = ElBiases[ 0 ];
3968 fptype sum1 = ElBiases[ 1 ];
3969 fptype sum2 = ElBiases[ 2 ];
3971 for( i = 0; i < IntFltLen; i++ )
3973 const fptype xx = ftp[ i ] + ftp2[ i ] * x;
3974 sum0 += xx * Src[ 0 ];
3975 sum1 += xx * Src[ 1 ];
3976 sum2 += xx * Src[ 2 ];
3980 DstLine[ 0 ] = sum0;
3981 DstLine[ 1 ] = sum1;
3982 DstLine[ 2 ] = sum2;
3991 fptype sum0 = ElBiases[ 0 ];
3992 fptype sum1 = ElBiases[ 1 ];
3994 for( i = 0; i < IntFltLen; i++ )
3996 const fptype xx = ftp[ i ] + ftp2[ i ] * x;
3997 sum0 += xx * Src[ 0 ];
3998 sum1 += xx * Src[ 1 ];
4002 DstLine[ 0 ] = sum0;
4003 DstLine[ 1 ] = sum1;
4014 fptype sum0 = ElBiases[ 0 ];
4016 for( i = 0; i < IntFltLen; i++ )
4018 sum0 += ftp[ i ] * Src[ i ];
4021 DstLine[ 0 ] = sum0;
4030 fptype sum0 = ElBiases[ 0 ];
4031 fptype sum1 = ElBiases[ 1 ];
4032 fptype sum2 = ElBiases[ 2 ];
4033 fptype sum3 = ElBiases[ 3 ];
4035 for( i = 0; i < IntFltLen; i++ )
4037 const fptype xx = ftp[ i ];
4038 sum0 += xx * Src[ 0 ];
4039 sum1 += xx * Src[ 1 ];
4040 sum2 += xx * Src[ 2 ];
4041 sum3 += xx * Src[ 3 ];
4045 DstLine[ 0 ] = sum0;
4046 DstLine[ 1 ] = sum1;
4047 DstLine[ 2 ] = sum2;
4048 DstLine[ 3 ] = sum3;
4057 fptype sum0 = ElBiases[ 0 ];
4058 fptype sum1 = ElBiases[ 1 ];
4059 fptype sum2 = ElBiases[ 2 ];
4061 for( i = 0; i < IntFltLen; i++ )
4063 const fptype xx = ftp[ i ];
4064 sum0 += xx * Src[ 0 ];
4065 sum1 += xx * Src[ 1 ];
4066 sum2 += xx * Src[ 2 ];
4070 DstLine[ 0 ] = sum0;
4071 DstLine[ 1 ] = sum1;
4072 DstLine[ 2 ] = sum2;
4081 fptype sum0 = ElBiases[ 0 ];
4082 fptype sum1 = ElBiases[ 1 ];
4084 for( i = 0; i < IntFltLen; i++ )
4086 const fptype xx = ftp[ i ];
4087 sum0 += xx * Src[ 0 ];
4088 sum1 += xx * Src[ 1 ];
4092 DstLine[ 0 ] = sum0;
4093 DstLine[ 1 ] = sum1;
4099 #undef AVIR_RESIZE_PART2
4100 #undef AVIR_RESIZE_PART1nx
4101 #undef AVIR_RESIZE_PART1
4118 const int DstLineIncr,
const fptype*
const ElBiases,
4119 fptype*
const )
const
4121 const int IntFltLen0 =
FltBank -> getFilterLen();
4122 const int ElCount =
Vars -> ElCount;
4129 #define AVIR_RESIZE_PART1 \
4130 while( rpos < rpose ) \
4132 const fptype x = (fptype) rpos -> x; \
4133 const fptype* const ftp = rpos -> ftp; \
4134 const fptype* const ftp2 = ftp + IntFltLen0; \
4135 const fptype* Src = SrcLine + rpos -> SrcOffs; \
4136 const int IntFltLen = rpos -> fl; \
4139 #define AVIR_RESIZE_PART1nx \
4140 while( rpos < rpose ) \
4142 const fptype* const ftp = rpos -> ftp; \
4143 const fptype* Src = SrcLine + rpos -> SrcOffs; \
4144 const int IntFltLen = rpos -> fl; \
4147 #define AVIR_RESIZE_PART2 \
4148 DstLine += DstLineIncr; \
4152 if(
FltBank -> getOrder() == 1 )
4158 fptype sum0 = ElBiases[ 0 ];
4160 for( i = 0; i < IntFltLen; i += 2 )
4162 sum0 += ( ftp[ i ] + ftp2[ i ] * x ) * Src[ i ];
4165 DstLine[ 0 ] = sum0;
4174 fptype sum0 = ElBiases[ 0 ];
4175 fptype sum1 = ElBiases[ 1 ];
4176 fptype sum2 = ElBiases[ 2 ];
4177 fptype sum3 = ElBiases[ 3 ];
4179 for( i = 0; i < IntFltLen; i += 2 )
4181 const fptype xx = ftp[ i ] + ftp2[ i ] * x;
4182 sum0 += xx * Src[ 0 ];
4183 sum1 += xx * Src[ 1 ];
4184 sum2 += xx * Src[ 2 ];
4185 sum3 += xx * Src[ 3 ];
4189 DstLine[ 0 ] = sum0;
4190 DstLine[ 1 ] = sum1;
4191 DstLine[ 2 ] = sum2;
4192 DstLine[ 3 ] = sum3;
4201 fptype sum0 = ElBiases[ 0 ];
4202 fptype sum1 = ElBiases[ 1 ];
4203 fptype sum2 = ElBiases[ 2 ];
4205 for( i = 0; i < IntFltLen; i += 2 )
4207 const fptype xx = ftp[ i ] + ftp2[ i ] * x;
4208 sum0 += xx * Src[ 0 ];
4209 sum1 += xx * Src[ 1 ];
4210 sum2 += xx * Src[ 2 ];
4214 DstLine[ 0 ] = sum0;
4215 DstLine[ 1 ] = sum1;
4216 DstLine[ 2 ] = sum2;
4225 fptype sum0 = ElBiases[ 0 ];
4226 fptype sum1 = ElBiases[ 1 ];
4228 for( i = 0; i < IntFltLen; i += 2 )
4230 const fptype xx = ftp[ i ] + ftp2[ i ] * x;
4231 sum0 += xx * Src[ 0 ];
4232 sum1 += xx * Src[ 1 ];
4236 DstLine[ 0 ] = sum0;
4237 DstLine[ 1 ] = sum1;
4248 fptype sum0 = ElBiases[ 0 ];
4250 for( i = 0; i < IntFltLen; i += 2 )
4252 sum0 += ftp[ i ] * Src[ i ];
4255 DstLine[ 0 ] = sum0;
4264 fptype sum0 = ElBiases[ 0 ];
4265 fptype sum1 = ElBiases[ 1 ];
4266 fptype sum2 = ElBiases[ 2 ];
4267 fptype sum3 = ElBiases[ 3 ];
4269 for( i = 0; i < IntFltLen; i += 2 )
4271 const fptype xx = ftp[ i ];
4272 sum0 += xx * Src[ 0 ];
4273 sum1 += xx * Src[ 1 ];
4274 sum2 += xx * Src[ 2 ];
4275 sum3 += xx * Src[ 3 ];
4279 DstLine[ 0 ] = sum0;
4280 DstLine[ 1 ] = sum1;
4281 DstLine[ 2 ] = sum2;
4282 DstLine[ 3 ] = sum3;
4291 fptype sum0 = ElBiases[ 0 ];
4292 fptype sum1 = ElBiases[ 1 ];
4293 fptype sum2 = ElBiases[ 2 ];
4295 for( i = 0; i < IntFltLen; i += 2 )
4297 const fptype xx = ftp[ i ];
4298 sum0 += xx * Src[ 0 ];
4299 sum1 += xx * Src[ 1 ];
4300 sum2 += xx * Src[ 2 ];
4304 DstLine[ 0 ] = sum0;
4305 DstLine[ 1 ] = sum1;
4306 DstLine[ 2 ] = sum2;
4315 fptype sum0 = ElBiases[ 0 ];
4316 fptype sum1 = ElBiases[ 1 ];
4318 for( i = 0; i < IntFltLen; i += 2 )
4320 const fptype xx = ftp[ i ];
4321 sum0 += xx * Src[ 0 ];
4322 sum1 += xx * Src[ 1 ];
4326 DstLine[ 0 ] = sum0;
4327 DstLine[ 1 ] = sum1;
4333 #undef AVIR_RESIZE_PART2
4334 #undef AVIR_RESIZE_PART1nx
4335 #undef AVIR_RESIZE_PART1
4355 template<
class fptype >
4370 const double aTrMul,
const double aPkOut )
4395 void dither( fptype*
const ResScanline )
const
4397 const fptype c0 = (fptype) 0;
4398 const fptype PkOut = (fptype)
PkOut0;
4405 for( j = 0; j <
LenE; j++ )
4407 ResScanline[ j ] = clamp( round( ResScanline[ j ]), c0,
4413 const fptype TrMul = (fptype)
TrMul0;
4415 for( j = 0; j <
LenE; j++ )
4417 const fptype z0 = round( ResScanline[ j ] / TrMul ) * TrMul;
4418 ResScanline[ j ] = clamp( z0, c0, PkOut );
4448 template<
class fptype >
4464 const double aTrMul,
const double aPkOut )
4473 for( i = 0; i <
LenE +
Vars -> ElCount; i++ )
4479 static bool isRecursive()
4484 void dither( fptype*
const ResScanline )
4486 const int ElCount =
Vars -> ElCount;
4487 const fptype c0 = (fptype) 0;
4488 const fptype TrMul = (fptype)
TrMul0;
4489 const fptype PkOut = (fptype)
PkOut0;
4492 for( j = 0; j <
LenE; j++ )
4498 for( j = 0; j < LenE - ElCount; j++ )
4502 const fptype z0 = round( ResScanline[ j ] / TrMul ) * TrMul;
4503 const fptype Noise = ResScanline[ j ] - z0;
4504 ResScanline[ j ] = clamp( z0, c0, PkOut );
4506 ResScanline[ j + ElCount ] += Noise * (fptype) 0.364842;
4508 ResScanlineDith[ j ] += Noise * (fptype) 0.364842;
4509 ResScanlineDith[ j + ElCount ] += Noise * (fptype) 0.063011;
4514 const fptype z0 = round( ResScanline[ j ] / TrMul ) * TrMul;
4515 const fptype Noise = ResScanline[ j ] - z0;
4516 ResScanline[ j ] = clamp( z0, c0, PkOut );
4525 using CImageResizerDithererDefINL< fptype >
:: Len;
4526 using CImageResizerDithererDefINL< fptype >
:: Vars;
4527 using CImageResizerDithererDefINL< fptype >
:: LenE;
4528 using CImageResizerDithererDefINL< fptype >
:: TrMul0;
4529 using CImageResizerDithererDefINL< fptype >
:: PkOut0;
4568 template<
class afptype,
class afptypeatom = afptype,
4616 template<
class fp
class = fp
class_def<
float > >
4640 , ResBitDepth( aResBitDepth )
4642 SrcBitDepth = ( aSrcBitDepth == 0 ? ResBitDepth : aSrcBitDepth );
4644 initFilterBank( FixedFilterBank, 1.0,
false,
CFltBuffer() );
4645 FixedFilterBank.createAllFilters();
4687 template<
class Tin,
class Tout >
4689 const int SrcHeight,
int SrcScanlineSize, Tout*
const NewBuf,
4690 const int NewWidth,
const int NewHeight,
const int ElCountIO,
4693 if( SrcWidth == 0 || SrcHeight == 0 )
4695 memset( NewBuf, 0, (
size_t) NewWidth * NewHeight *
4701 if( NewWidth == 0 || NewHeight == 0 )
4718 double ox = Vars.
ox;
4719 double oy = Vars.
oy;
4723 kx = (double) SrcWidth / NewWidth;
4724 ox += ( kx - 1.0 ) * 0.5;
4726 ky = (double) SrcHeight / NewHeight;
4727 oy += ( ky - 1.0 ) * 0.5;
4735 const double ko = ( k - 1.0 ) * 0.5;
4747 const bool IsInFloat = ( (Tin) 0.25 != 0 );
4748 const bool IsOutFloat = ( (Tout) 0.25 != 0 );
4760 1.0 / (
sizeof( Tin ) == 1 ? 255.0 : 65535.0 );
4769 Vars.
OutGammaMult = (
sizeof( Tout ) == 1 ? 255.0 : 65535.0 );
4782 OutMul = (
sizeof( Tout ) == 1 ? 255.0 : 65535.0 );
4787 OutMul /= (
sizeof( Tin ) == 1 ? 255.0 : 65535.0 );
4793 const int ElCount = ( ElCountIO + fpclass :: fppack - 1 ) /
4796 const int NewWidthE = NewWidth * ElCount;
4798 if( SrcScanlineSize < 1 )
4800 SrcScanlineSize = SrcWidth * ElCountIO;
4805 Vars.
fppack = fpclass :: fppack;
4806 Vars.
fpalign = fpclass :: fpalign;
4807 Vars.
elalign = fpclass :: elalign;
4808 Vars.
packmode = fpclass :: packmode;
4814 typename CFilterStep :: CRPosBufArray RPosBufArray;
4820 int UseBuildMode = 1;
4821 const int BuildModeCount =
4822 ( FixedFilterBank.getOrder() == 0 ? 4 : 2 );
4832 int BestScore = 0x7FFFFFFF;
4834 for( m = 0; m < BuildModeCount; m++ )
4840 buildFilterSteps( TmpSteps, Vars, TmpBank, OutMul, m,
true );
4841 updateFilterStepBuffers( TmpSteps, Vars, RPosBufArray,
4842 SrcWidth, NewWidth );
4844 fillUsedFracMap( TmpSteps[ Vars.
ResizeStep ], UsedFracMap );
4845 const int c = calcComplexity( TmpSteps, Vars, UsedFracMap,
4860 buildFilterSteps( FltSteps, Vars, FltBank, OutMul, UseBuildMode,
4863 updateFilterStepBuffers( FltSteps, Vars, RPosBufArray, SrcWidth,
4866 updateBufLenAndRPosPtrs( FltSteps, Vars, NewWidth );
4875 for( i = 0; i < ThreadCount; i++ )
4882 td[ i ].init( i, ThreadCount, FltSteps, Vars );
4884 td[ i ].initScanlineQueue( td[ i ].sopResizeH, SrcHeight,
4889 fpclass :: fpalign );
4892 for( i = 0; i < SrcHeight; i++ )
4894 td[ i % ThreadCount ].addScanlineToQueue(
4895 (
void*) &SrcBuf[ (
size_t) i * SrcScanlineSize ],
4896 &FltBuf[ (
size_t) i * NewWidthE ]);
4900 td[ 0 ].processScanlineQueue();
4906 const int PrevUseBuildMode = UseBuildMode;
4915 int BestScore = 0x7FFFFFFF;
4917 for( m = 0; m < BuildModeCount; m++ )
4924 buildFilterSteps( TmpSteps, TmpVars, TmpBank, 1.0, m,
true );
4925 updateFilterStepBuffers( TmpSteps, TmpVars, RPosBufArray,
4926 SrcHeight, NewHeight );
4928 fillUsedFracMap( TmpSteps[ TmpVars.
ResizeStep ],
4931 const int c = calcComplexity( TmpSteps, TmpVars, UsedFracMap,
4945 if( UseBuildMode == PrevUseBuildMode && ky == kx )
4949 modifyCorrFilterDCGain( FltSteps, 1.0 / OutMul );
4954 buildFilterSteps( FltSteps, Vars, FltBank, 1.0, UseBuildMode,
4958 updateFilterStepBuffers( FltSteps, Vars, RPosBufArray, SrcHeight,
4961 updateBufLenAndRPosPtrs( FltSteps, Vars, NewWidth );
4963 if( IsOutFloat &&
sizeof( FltBuf[ 0 ]) ==
sizeof( Tout ) &&
4964 fpclass :: packmode == 0 )
4968 for( i = 0; i < ThreadCount; i++ )
4970 td[ i ].initScanlineQueue( td[ i ].sopResizeV, NewWidth,
4971 SrcHeight, NewWidthE, NewWidthE );
4974 for( i = 0; i < NewWidth; i++ )
4976 td[ i % ThreadCount ].addScanlineToQueue(
4977 &FltBuf[ (
size_t) i * ElCount ],
4978 (fptype*) &NewBuf[ (
size_t) i * ElCount ]);
4982 td[ 0 ].processScanlineQueue();
4990 fpclass :: fpalign );
4992 for( i = 0; i < ThreadCount; i++ )
4994 td[ i ].initScanlineQueue( td[ i ].sopResizeV, NewWidth,
4995 SrcHeight, NewWidthE, NewWidthE );
4998 const int im = ( fpclass :: packmode == 0 ? ElCount : 1 );
5000 for( i = 0; i < NewWidth; i++ )
5002 td[ i % ThreadCount ].addScanlineToQueue(
5003 &FltBuf[ (
size_t) i * im ], &ResBuf[ (
size_t) i * im ]);
5007 td[ 0 ].processScanlineQueue();
5014 for( i = 0; i < ThreadCount; i++ )
5016 td[ i ].initScanlineQueue( td[ i ].sopUnpackH,
5017 NewHeight, NewWidth );
5020 for( i = 0; i < NewHeight; i++ )
5022 td[ i % ThreadCount ].addScanlineToQueue(
5023 &ResBuf[ (
size_t) i * NewWidthE ],
5024 &NewBuf[ (
size_t) i * NewWidth * ElCountIO ]);
5028 td[ 0 ].processScanlineQueue();
5040 if(
sizeof( Tout ) == 1 )
5042 TruncBits = 8 - ResBitDepth;
5047 TruncBits = 16 - ResBitDepth;
5051 const double PkOut = OutRange;
5052 const double TrMul = ( TruncBits > 0 ?
5053 PkOut / ( OutRange >> TruncBits ) : 1.0 );
5055 if( CDitherer :: isRecursive() )
5057 td[ 0 ].getDitherer().init( NewWidth, Vars, TrMul, PkOut );
5061 for( i = 0; i < NewHeight; i++ )
5063 fptype*
const ResScanline =
5064 &ResBuf[ (size_t) i * NewWidthE ];
5066 CFilterStep :: applySRGBGamma( ResScanline, NewWidth,
5069 td[ 0 ].getDitherer().dither( ResScanline );
5071 CFilterStep :: unpackScanline( ResScanline,
5072 &NewBuf[ (
size_t) i * NewWidth * ElCountIO ],
5078 for( i = 0; i < NewHeight; i++ )
5080 fptype*
const ResScanline =
5081 &ResBuf[ (size_t) i * NewWidthE ];
5083 td[ 0 ].getDitherer().dither( ResScanline );
5085 CFilterStep :: unpackScanline( ResScanline,
5086 &NewBuf[ (
size_t) i * NewWidth * ElCountIO ],
5093 for( i = 0; i < ThreadCount; i++ )
5095 td[ i ].initScanlineQueue( td[ i ].sopDitherAndUnpackH,
5096 NewHeight, NewWidth );
5098 td[ i ].getDitherer().init( NewWidth, Vars, TrMul, PkOut );
5101 for( i = 0; i < NewHeight; i++ )
5103 td[ i % ThreadCount ].addScanlineToQueue(
5104 &ResBuf[ (
size_t) i * NewWidthE ],
5105 &NewBuf[ (
size_t) i * NewWidth * ElCountIO ]);
5109 td[ 0 ].processScanlineQueue();
5117 typedef typename fpclass :: fptype fptype;
5118 typedef typename fpclass :: CFilterStep CFilterStep;
5121 typedef typename fpclass :: CDitherer CDitherer;
5158 const double CutoffMult,
const bool ForceHiOrder,
5161 const int IntBitDepth = ( ResBitDepth > SrcBitDepth ? ResBitDepth :
5164 const double SNR = -6.02 * ( IntBitDepth + 3 );
5173 if( ForceHiOrder || IntBitDepth > 8 )
5176 FracCount = (int) ceil( 0.23134052 * exp( -0.058062929 * SNR ));
5181 FracCount = (int) ceil( 0.33287686 * exp( -0.11334583 * SNR ));
5189 FltBank.
init( FracCount, UseOrder, Params.
IntFltLen / CutoffMult,
5191 fpclass :: fpalign, fpclass :: elalign );
5208 const bool IsModel =
false,
int*
const FltExt = NULL )
5210 int UseCapacity = ( ReqCapacity + fpclass :: elalign - 1 ) &
5211 ~( fpclass :: elalign - 1 );
5213 int Ext = UseCapacity - ReqCapacity;
5215 if( FltExt != NULL )
5226 Flt.
alloc( UseCapacity, fpclass :: fpalign );
5231 Flt[ ReqCapacity + Ext ] = (fptype) 0;
5256 void assignFilterParams( CFilterStep& fs,
const bool IsUpsample,
5257 const int ResampleFactor,
const double FltCutoff,
const double DCGain,
5258 const bool UseFltOrig,
const bool IsModel )
const
5264 if( FltCutoff == 0.0 )
5266 const double m = 2.0 / ResampleFactor;
5280 Len2 *= ResampleFactor;
5281 Freq /= ResampleFactor;
5282 fs.DCGain = DCGain * ResampleFactor;
5289 fs.FltOrig.Len2 = Len2;
5290 fs.FltOrig.Freq = Freq;
5291 fs.FltOrig.Alpha = FltAlpha;
5292 fs.FltOrig.DCGain = fs.DCGain;
5294 CDSPPeakedCosineLPF w( Len2, Freq, FltAlpha );
5296 fs.IsUpsample = IsUpsample;
5297 fs.ResampleFactor = ResampleFactor;
5298 fs.FltLatency = w.fl2;
5304 allocFilter( fs.Flt, w.FilterLen,
true, &FltExt );
5311 fs.FltOrig.alloc( w.FilterLen );
5312 memset( &fs.FltOrig[ 0 ], 0,
5313 w.FilterLen *
sizeof( fs.FltOrig[ 0 ]));
5318 fs.FltOrig.alloc( w.FilterLen );
5320 w.generateLPF( &fs.FltOrig[ 0 ], fs.DCGain );
5322 allocFilter( fs.Flt, fs.FltOrig.getCapacity(),
false, &FltExt );
5323 copyArray( &fs.FltOrig[ 0 ], &fs.Flt[ 0 ],
5324 fs.FltOrig.getCapacity() );
5334 int l = fs.Flt.getCapacity() - fs.FltLatency - ResampleFactor -
5337 allocFilter( fs.PrefixDC, l, IsModel );
5338 allocFilter( fs.SuffixDC, fs.FltLatency, IsModel );
5347 const fptype* ip = &fs.Flt[ fs.FltLatency + ResampleFactor ];
5348 copyArray( ip, &fs.PrefixDC[ 0 ], l );
5352 ip += ResampleFactor;
5353 l -= ResampleFactor;
5360 addArray( ip, &fs.PrefixDC[ 0 ], l );
5364 fptype* op = &fs.SuffixDC[ 0 ];
5365 copyArray( &fs.Flt[ 0 ], op, l );
5369 op += ResampleFactor;
5370 l -= ResampleFactor;
5377 addArray( &fs.Flt[ 0 ], op, l );
5383 fs.EdgePixelCount = fs.EdgePixelCountDef;
5408 void addCorrectionFilter( CFilterSteps& Steps,
const double bw,
5409 const bool IsPreCorrection,
const bool IsModel )
const
5411 CFilterStep& fs = ( IsPreCorrection ? Steps[ 0 ] : Steps.add() );
5412 fs.IsUpsample =
false;
5413 fs.ResampleFactor = 1;
5415 fs.EdgePixelCount = ( IsPreCorrection ? fs.EdgePixelCountDef : 0 );
5425 const int BinCount = 65;
5426 const int BinCount1 = BinCount - 1;
5436 for( j = 0; j < BinCount; j++ )
5441 const int si = ( IsPreCorrection ? 1 : 0 );
5443 for( i = si; i < Steps.getItemCount() - ( si ^ 1 ); i++ )
5445 const CFilterStep& fs = Steps[ i ];
5449 curbw *= fs.ResampleFactor;
5451 if( fs.FltOrig.getCapacity() > 0 )
5460 if( fs.ResampleFactor == 0 )
5462 Flt = fs.FltBank -> getFilter( 0 );
5463 FltLen = fs.FltBank -> getFilterLen();
5468 FltLen = fs.Flt.getCapacity();
5475 const double thm =
AVIR_PI * bw / ( curbw * BinCount1 );
5477 for( j = 0; j < BinCount; j++ )
5479 calcFIRFilterResponse( Flt, FltLen, j * thm, re, im );
5481 Bins[ j ] *= fs.DCGain / sqrt( re * re + im * im );
5484 if( !fs.IsUpsample && fs.ResampleFactor > 1 )
5486 curbw /= fs.ResampleFactor;
5493 EQ.init( bw * 2.0, Params.
CorrFltLen, BinCount, 0.0, bw,
false,
5496 fs.FltLatency = EQ.getFilterLatency();
5499 EQ.buildFilter( Bins, &Filter[ 0 ]);
5500 normalizeFIRFilter( &Filter[ 0 ], Filter.getCapacity(), 1.0 );
5502 allocFilter( fs.Flt, Filter.getCapacity() );
5503 copyArray( &Filter[ 0 ], &fs.Flt[ 0 ], Filter.getCapacity() );
5541 static void addSharpenTest( CFilterSteps& Steps,
const double bw,
5542 const bool IsModel )
5549 const double FltLen = 10.0 * bw;
5551 CFilterStep& fs = Steps.add();
5552 fs.IsUpsample =
false;
5553 fs.ResampleFactor = 1;
5555 fs.EdgePixelCount = 0;
5560 fs.FltLatency ),
true );
5565 const int BinCount = 200;
5567 int Thresh = (int) round( BinCount / bw * 1.75 );
5569 if( Thresh > BinCount )
5576 for( j = 0; j < Thresh; j++ )
5581 for( j = Thresh; j < BinCount; j++ )
5587 EQ.init( bw * 2.0, FltLen, BinCount, 0.0, bw,
false, 1.7 );
5589 fs.FltLatency = EQ.getFilterLatency();
5592 EQ.buildFilter( Bins, &Filter[ 0 ]);
5593 normalizeFIRFilter( &Filter[ 0 ], Filter.getCapacity(), 1.0 );
5595 allocFilter( fs.Flt, Filter.getCapacity() );
5596 copyArray( &Filter[ 0 ], &fs.Flt[ 0 ], Filter.getCapacity() );
5629 void buildFilterSteps( CFilterSteps& Steps, CImageResizerVars& Vars,
5630 CDSPFracFilterBankLin< fptype >& FltBank,
const double DCGain,
5631 const int ModeFlags,
const bool IsModel )
const
5635 const bool DoFltAndIntCombo = (( ModeFlags & 1 ) != 0 );
5637 const bool ForceHiOrderInt = (( ModeFlags & 2 ) != 0 );
5639 const bool UseHalfband = (( ModeFlags & 4 ) != 0 );
5642 const double bw = 1.0 / Vars.k;
5643 const int UpsampleFactor = ( (int) floor( Vars.k ) < 2 ? 2 : 1 );
5644 double IntCutoffMult;
5645 CFilterStep* ReuseStep;
5647 CFilterStep* ExtFltStep;
5649 bool IsPreCorrection;
5656 IsPreCorrection =
true;
5663 IsPreCorrection =
false;
5670 if( UpsampleFactor > 1 )
5672 CFilterStep& fs = Steps.add();
5673 assignFilterParams( fs,
true, UpsampleFactor, FltCutoff, DCGain,
5674 DoFltAndIntCombo, IsModel );
5676 IntCutoffMult = FltCutoff * 2.0 / UpsampleFactor;
5678 ExtFltStep = ( DoFltAndIntCombo ? &fs : NULL );
5682 int DownsampleFactor;
5686 DownsampleFactor = (int) floor( 0.5 / FltCutoff );
5687 bool DoHBFltAdd = ( UseHalfband && DownsampleFactor > 1 );
5691 assignFilterParams( Steps.add(),
false, DownsampleFactor,
5692 0.0, 1.0,
false, IsModel );
5694 FltCutoff *= DownsampleFactor;
5698 if( DownsampleFactor < 1 )
5700 DownsampleFactor = 1;
5707 CFilterStep& fs = Steps.add();
5708 assignFilterParams( fs,
false, DownsampleFactor, FltCutoff,
5709 DCGain, DoFltAndIntCombo, IsModel );
5711 IntCutoffMult = FltCutoff / 0.5;
5713 if( DoFltAndIntCombo )
5720 IntCutoffMult *= DownsampleFactor;
5728 CFilterStep& fs = ( ReuseStep == NULL ? Steps.add() : *ReuseStep );
5730 Vars.ResizeStep = Steps.getItemCount() - 1;
5731 fs.IsUpsample =
false;
5732 fs.ResampleFactor = 0;
5733 fs.DCGain = ( ExtFltStep == NULL ? 1.0 : ExtFltStep -> DCGain );
5735 initFilterBank( FltBank, IntCutoffMult, ForceHiOrderInt,
5736 ( ExtFltStep == NULL ? fs.FltOrig : ExtFltStep -> FltOrig ));
5738 if( FltBank == FixedFilterBank )
5740 fs.FltBank = (CDSPFracFilterBankLin< fptype >*) &FixedFilterBank;
5744 fs.FltBank = &FltBank;
5747 addCorrectionFilter( Steps, corrbw, IsPreCorrection, IsModel );
5762 static void extendUpsample( CFilterStep& fs, CFilterStep& NextStep )
5764 fs.InPrefix = ( NextStep.InPrefix + fs.ResampleFactor - 1 ) /
5767 fs.OutPrefix += fs.InPrefix * fs.ResampleFactor;
5768 NextStep.InPrefix = 0;
5770 fs.InSuffix = ( NextStep.InSuffix + fs.ResampleFactor - 1 ) /
5773 fs.OutSuffix += fs.InSuffix * fs.ResampleFactor;
5774 NextStep.InSuffix = 0;
5791 static void fillRPosBuf( CFilterStep& fs,
const CImageResizerVars& Vars )
5793 const int PrevLen = fs.RPosBuf -> getCapacity();
5795 if( fs.OutLen > PrevLen )
5797 fs.RPosBuf -> increaseCapacity( fs.OutLen );
5800 typename CFilterStep :: CResizePos* rpos = &(*fs.RPosBuf)[ PrevLen ];
5801 const int FracCount = fs.FltBank -> getFracCount();
5802 const double o = Vars.o;
5803 const double k = Vars.k;
5806 for( i = PrevLen; i < fs.OutLen; i++ )
5808 const double SrcPos = o + k * i;
5809 const int SrcPosInt = (int) floor( SrcPos );
5810 const double x = ( SrcPos - SrcPosInt ) * FracCount;
5811 const int fti = (int) x;
5812 rpos -> x = (
typename fpclass :: fptypeatom) ( x - fti );
5814 rpos -> SrcPosInt = SrcPosInt;
5835 static void updateFilterStepBuffers( CFilterSteps& Steps,
5836 CImageResizerVars& Vars,
5837 typename CFilterStep :: CRPosBufArray& RPosBufArray,
int SrcLen,
5844 for( i = 0; i < Steps.getItemCount(); i++ )
5846 CFilterStep& fs = Steps[ i ];
5851 fs.OutBuf = ( InBuf + 1 ) & 1;
5856 Vars.k *= fs.ResampleFactor;
5857 Vars.o *= fs.ResampleFactor;
5860 fs.OutLen = fs.InLen * fs.ResampleFactor;
5861 fs.OutPrefix = fs.FltLatency;
5862 fs.OutSuffix = fs.Flt.getCapacity() - fs.FltLatency -
5865 int l0 = fs.OutPrefix + fs.OutLen + fs.OutSuffix;
5866 int l = fs.InLen * fs.ResampleFactor +
5867 fs.SuffixDC.getCapacity();
5871 fs.OutSuffix += l - l0;
5874 l0 = fs.OutLen + fs.OutSuffix;
5876 if( fs.PrefixDC.getCapacity() > l0 )
5878 fs.OutSuffix += fs.PrefixDC.getCapacity() - l0;
5882 if( fs.ResampleFactor == 0 )
5884 const int FilterLenD2 = fs.FltBank -> getFilterLen() / 2;
5885 const int FilterLenD21 = FilterLenD2 - 1;
5887 const int ResizeLPix = (int) floor( Vars.o ) - FilterLenD21;
5888 fs.InPrefix = ( ResizeLPix < 0 ? -ResizeLPix : 0 );
5889 const int ResizeRPix = (int) floor( Vars.o +
5890 ( NewLen - 1 ) * Vars.k ) + FilterLenD2 + 1;
5892 fs.InSuffix = ( ResizeRPix > fs.InLen ?
5893 ResizeRPix - fs.InLen : 0 );
5896 fs.RPosBuf = &RPosBufArray.getRPosBuf( Vars.k, Vars.o,
5897 fs.FltBank -> getFracCount() );
5899 fillRPosBuf( fs, Vars );
5903 Vars.k /= fs.ResampleFactor;
5904 Vars.o /= fs.ResampleFactor;
5905 Vars.o += fs.EdgePixelCount;
5907 fs.InPrefix = fs.FltLatency;
5908 fs.InSuffix = fs.Flt.getCapacity() - fs.FltLatency - 1;
5913 fs.OutLen = ( fs.InLen + fs.ResampleFactor - 1 ) /
5914 fs.ResampleFactor + fs.EdgePixelCount;
5916 fs.InSuffix += ( fs.OutLen - 1 ) * fs.ResampleFactor + 1 -
5919 fs.InPrefix += fs.EdgePixelCount * fs.ResampleFactor;
5920 fs.OutLen += fs.EdgePixelCount;
5927 Steps[ Steps.getItemCount() - 1 ].OutBuf = 2;
5928 Vars.IsResize2 =
false;
5932 extendUpsample( Steps[ upstep ], Steps[ upstep + 1 ]);
5934 if( Steps[ upstep ].ResampleFactor == 2 &&
5935 Vars.ResizeStep == upstep + 1 &&
5936 fpclass :: packmode == 0 &&
5937 Steps[ upstep ].FltOrig.getCapacity() > 0 )
5942 Vars.IsResize2 =
true;
5963 static void updateBufLenAndRPosPtrs( CFilterSteps& Steps,
5964 CImageResizerVars& Vars,
const int ResElIncr )
5966 int MaxPrefix[ 2 ] = { 0, 0 };
5967 int MaxLen[ 2 ] = { 0, 0 };
5970 for( i = 0; i < Steps.getItemCount(); i++ )
5972 CFilterStep& fs = Steps[ i ];
5973 const int ib = fs.InBuf;
5975 if( fs.InPrefix > MaxPrefix[ ib ])
5977 MaxPrefix[ ib ] = fs.InPrefix;
5980 int l = fs.InLen + fs.InSuffix;
5982 if( l > MaxLen[ ib ])
5987 fs.InElIncr = fs.InPrefix + l;
5989 if( fs.OutBuf == 2 )
5994 const int ob = fs.OutBuf;
5998 if( fs.OutPrefix > MaxPrefix[ ob ])
6000 MaxPrefix[ ob ] = fs.OutPrefix;
6003 l = fs.OutLen + fs.OutSuffix;
6005 if( l > MaxLen[ ob ])
6012 if( fs.OutLen > MaxLen[ ob ])
6014 MaxLen[ ob ] = fs.OutLen;
6021 for( i = 0; i < Steps.getItemCount(); i++ )
6023 CFilterStep& fs = Steps[ i ];
6025 if( fs.OutBuf == 2 )
6027 fs.OutElIncr = ResElIncr;
6031 CFilterStep& fs2 = Steps[ i + 1 ];
6035 fs.OutElIncr = fs.OutPrefix + fs.OutLen + fs.OutSuffix;
6037 if( fs.OutElIncr > fs2.InElIncr )
6039 fs2.InElIncr = fs.OutElIncr;
6043 fs.OutElIncr = fs2.InElIncr;
6048 fs.OutElIncr = fs2.InElIncr;
6054 for( i = 0; i < 2; i++ )
6056 Vars.BufLen[ i ] = MaxPrefix[ i ] + MaxLen[ i ];
6057 Vars.BufOffs[ i ] = MaxPrefix[ i ];
6059 if( Vars.packmode == 0 )
6061 Vars.BufOffs[ i ] *= Vars.ElCount;
6064 Vars.BufLen[ i ] *= Vars.ElCount;
6069 CFilterStep& fs = Steps[ Vars.ResizeStep ];
6070 typename CFilterStep :: CResizePos* rpos = &(*fs.RPosBuf)[ 0 ];
6071 const int em = ( fpclass :: packmode == 0 ? Vars.ElCount : 1 );
6072 const int fl = fs.FltBank -> getFilterLen();
6073 const int FilterLenD21 = fl / 2 - 1;
6075 if( Vars.IsResize2 )
6077 for( i = 0; i < fs.OutLen; i++ )
6079 const int p = rpos -> SrcPosInt - FilterLenD21;
6080 const int fo = p & 1;
6081 rpos -> SrcOffs = ( p + fo ) * em;
6082 rpos -> ftp = fs.FltBank -> getFilter( rpos -> fti ) + fo;
6083 rpos -> fl = fl - fo;
6089 for( i = 0; i < fs.OutLen; i++ )
6091 rpos -> SrcOffs = ( rpos -> SrcPosInt - FilterLenD21 ) * em;
6092 rpos -> ftp = fs.FltBank -> getFilter( rpos -> fti );
6106 void modifyCorrFilterDCGain( CFilterSteps& Steps,
const double m )
const
6109 const int z = Steps.getItemCount() - 1;
6111 if( !Steps[ z ].IsUpsample && Steps[ z ].ResampleFactor == 1 )
6113 Flt = &Steps[ z ].Flt;
6117 Flt = &Steps[ 0 ].Flt;
6122 for( i = 0; i < Flt -> getCapacity(); i++ )
6124 (*Flt)[ i ] = (fptype) ( (
double) (*Flt)[ i ] * m );
6136 static void fillUsedFracMap(
const CFilterStep& fs,
6139 const int FracCount = fs.FltBank -> getFracCount();
6141 memset( &UsedFracMap[ 0 ], 0, FracCount *
sizeof( UsedFracMap[ 0 ]));
6143 typename CFilterStep :: CResizePos* rpos = &(*fs.RPosBuf)[ 0 ];
6146 for( i = 0; i < fs.OutLen; i++ )
6148 UsedFracMap[ rpos -> fti ] |= 1;
6173 static int calcComplexity(
const CFilterSteps& Steps,
6175 const int ScanlineCount )
6180 if( Vars.packmode != 0 )
6198 for( i = 0; i < Steps.getItemCount(); i++ )
6200 const CFilterStep& fs = Steps[ i ];
6202 s2 += 65 * fs.Flt.getCapacity();
6206 if( fs.FltOrig.getCapacity() > 0 )
6211 s += ( fs.Flt.getCapacity() *
6212 ( fs.InPrefix + fs.InLen + fs.InSuffix ) +
6213 fs.SuffixDC.getCapacity() + fs.PrefixDC.getCapacity() ) *
6217 if( fs.ResampleFactor == 0 )
6219 s += fs.FltBank -> getFilterLen() *
6220 ( fs.FltBank -> getOrder() + Vars.ElCount ) * fs.OutLen;
6222 if( i == Vars.ResizeStep && Vars.IsResize2 )
6227 s2 += fs.FltBank -> calcInitComplexity( UsedFracMap );
6231 s += fs.Flt.getCapacity() * Vars.ElCount * fs.OutLen *
6236 return( s + s2 / ScanlineCount );
6251 template<
class Tin,
class Tout >
6252 class CThreadData :
public CImageResizerThreadPool :: CWorkload
6255 virtual void process()
6257 processScanlineQueue();
6264 enum EScanlineOperation
6269 sopDitherAndUnpackH,
6286 void init(
const int aThreadIndex,
const int aThreadCount,
6287 const CFilterSteps& aSteps,
const CImageResizerVars& aVars )
6289 ThreadIndex = aThreadIndex;
6290 ThreadCount = aThreadCount;
6309 void initScanlineQueue(
const EScanlineOperation aOp,
6310 const int TotalLines,
const int aSrcLen,
const int aSrcIncr = 0,
6311 const int aResIncr = 0 )
6313 const int l = Vars -> BufLen[ 0 ] + Vars -> BufLen[ 1 ];
6315 if( Bufs.getCapacity() < l )
6317 Bufs.alloc( l, fpclass :: fpalign );
6320 BufPtrs[ 0 ] = Bufs + Vars -> BufOffs[ 0 ];
6321 BufPtrs[ 1 ] = Bufs + Vars -> BufLen[ 0 ] + Vars -> BufOffs[ 1 ];
6326 for( j = 0; j < Steps -> getItemCount(); j++ )
6328 const CFilterStep& fs = (*Steps)[ j ];
6330 if( fs.ResampleFactor == 0 &&
6331 ml < fs.FltBank -> getFilterLen() )
6333 ml = fs.FltBank -> getFilterLen();
6337 TmpFltBuf.alloc( ml, fpclass :: fpalign );
6343 Queue.increaseCapacity(( TotalLines + ThreadCount - 1 ) /
6344 ThreadCount,
false );
6357 void addScanlineToQueue(
void*
const SrcBuf,
void*
const ResBuf )
6359 Queue[ QueueLen ].SrcBuf = SrcBuf;
6360 Queue[ QueueLen ].ResBuf = ResBuf;
6368 void processScanlineQueue()
6372 switch( ScanlineOp )
6376 for( i = 0; i < QueueLen; i++ )
6378 resizeScanlineH( (Tin*) Queue[ i ].SrcBuf,
6379 (fptype*) Queue[ i ].ResBuf );
6387 for( i = 0; i < QueueLen; i++ )
6389 resizeScanlineV( (fptype*) Queue[ i ].SrcBuf,
6390 (fptype*) Queue[ i ].ResBuf );
6396 case sopDitherAndUnpackH:
6398 if( Vars -> UseSRGBGamma )
6400 for( i = 0; i < QueueLen; i++ )
6402 CFilterStep :: applySRGBGamma(
6403 (fptype*) Queue[ i ].SrcBuf, SrcLen, *Vars );
6405 Ditherer.dither( (fptype*) Queue[ i ].SrcBuf );
6407 CFilterStep :: unpackScanline(
6408 (fptype*) Queue[ i ].SrcBuf,
6409 (Tout*) Queue[ i ].ResBuf, SrcLen, *Vars );
6414 for( i = 0; i < QueueLen; i++ )
6416 Ditherer.dither( (fptype*) Queue[ i ].SrcBuf );
6418 CFilterStep :: unpackScanline(
6419 (fptype*) Queue[ i ].SrcBuf,
6420 (Tout*) Queue[ i ].ResBuf, SrcLen, *Vars );
6429 if( Vars -> UseSRGBGamma )
6431 for( i = 0; i < QueueLen; i++ )
6433 CFilterStep :: applySRGBGamma(
6434 (fptype*) Queue[ i ].SrcBuf, SrcLen, *Vars );
6436 CFilterStep :: unpackScanline(
6437 (fptype*) Queue[ i ].SrcBuf,
6438 (Tout*) Queue[ i ].ResBuf, SrcLen, *Vars );
6443 for( i = 0; i < QueueLen; i++ )
6445 CFilterStep :: unpackScanline(
6446 (fptype*) Queue[ i ].SrcBuf,
6447 (Tout*) Queue[ i ].ResBuf, SrcLen, *Vars );
6461 CDitherer& getDitherer()
6470 const CFilterSteps* Steps;
6472 const CImageResizerVars* Vars;
6476 fptype* BufPtrs[ 3 ];
6481 EScanlineOperation ScanlineOp;
6525 void resizeScanlineH(
const Tin*
const SrcBuf, fptype*
const ResBuf )
6527 const CFilterStep& fs0 = (*Steps)[ 0 ];
6529 fs0.packScanline( SrcBuf, BufPtrs[ 0 ], SrcLen );
6530 BufPtrs[ 2 ] = ResBuf;
6532 fptype ElBiases[ 4 ];
6533 fs0.calcScanlineBias( BufPtrs[ 0 ], SrcLen, ElBiases );
6534 fs0.unbiasScanline( BufPtrs[ 0 ], SrcLen, ElBiases );
6538 for( j = 0; j < Steps -> getItemCount(); j++ )
6540 const CFilterStep& fs = (*Steps)[ j ];
6541 fs.prepareInBuf( BufPtrs[ fs.InBuf ]);
6543 ( Vars -> packmode == 0 ? Vars -> ElCount : 1 );
6545 if( fs.ResampleFactor != 0 )
6549 fs.doUpsample( BufPtrs[ fs.InBuf ],
6550 BufPtrs[ fs.OutBuf ]);
6554 fs.doFilter( BufPtrs[ fs.InBuf ],
6555 BufPtrs[ fs.OutBuf ], DstIncr );
6560 if( Vars -> IsResize2 )
6562 fs.doResize2( BufPtrs[ fs.InBuf ],
6563 BufPtrs[ fs.OutBuf ], DstIncr, ElBiases,
6568 fs.doResize( BufPtrs[ fs.InBuf ],
6569 BufPtrs[ fs.OutBuf ], DstIncr, ElBiases,
6584 void resizeScanlineV(
const fptype*
const SrcBuf,
6585 fptype*
const ResBuf )
6587 const CFilterStep& fs0 = (*Steps)[ 0 ];
6589 fs0.convertVtoH( SrcBuf, BufPtrs[ 0 ], SrcLen, SrcIncr );
6590 BufPtrs[ 2 ] = ResBuf;
6592 fptype ElBiases[ 4 ];
6593 fs0.calcScanlineBias( BufPtrs[ 0 ], SrcLen, ElBiases );
6594 fs0.unbiasScanline( BufPtrs[ 0 ], SrcLen, ElBiases );
6598 for( j = 0; j < Steps -> getItemCount(); j++ )
6600 const CFilterStep& fs = (*Steps)[ j ];
6601 fs.prepareInBuf( BufPtrs[ fs.InBuf ]);
6602 const int DstIncr = ( fs.OutBuf == 2 ? ResIncr :
6603 ( Vars -> packmode == 0 ? Vars -> ElCount : 1 ));
6605 if( fs.ResampleFactor != 0 )
6609 fs.doUpsample( BufPtrs[ fs.InBuf ],
6610 BufPtrs[ fs.OutBuf ]);
6614 fs.doFilter( BufPtrs[ fs.InBuf ],
6615 BufPtrs[ fs.OutBuf ], DstIncr );
6620 if( Vars -> IsResize2 )
6622 fs.doResize2( BufPtrs[ fs.InBuf ],
6623 BufPtrs[ fs.OutBuf ], DstIncr, ElBiases,
6628 fs.doResize( BufPtrs[ fs.InBuf ],
6629 BufPtrs[ fs.OutBuf ], DstIncr, ElBiases,
6644 #endif // AVIR_CIMAGERESIZER_INCLUDED
#define AVIR_PI
Definition: avir.h:75
int ElCountIO
Definition: avir.h:2354
double CorrFltAlpha
Definition: avir.h:2126
double ox
Definition: avir.h:2396
Thread pool for multi-threaded image resizing operation.
Definition: avir.h:1991
void packScanline(const Tin *ip, fptype *const op0, const int l0) const
Definition: avir.h:2681
fptypeatom x
Definition: avir.h:2547
double OutGammaMult
Definition: avir.h:2392
void prepareInBuf(fptype *Src) const
Definition: avir.h:3228
double LPFltBaseLen
Definition: avir.h:2154
void updateCapacity(const capint ReqCapacity)
Definition: avir.h:631
double k
Definition: avir.h:2565
Resizing position structure.
Definition: avir.h:2539
double Alpha
Definition: avir.h:1489
static const int fpalign
Definition: avir.h:4580
void init(const int aLen, const CImageResizerVars &aVars, const double aTrMul, const double aPkOut)
Definition: avir.h:4463
void init(const double SampleRate, const double aFilterLength, const int aBandCount, const double MinFreq, const double MaxFreq, const bool IsLogBands, const double WFAlpha)
Definition: avir.h:1008
int getItemCount() const
Definition: avir.h:849
int fl2
Definition: avir.h:1371
static int calcFilterLength(const double aFilterLength, int &Latency)
Definition: avir.h:1186
bool IsResize2
Definition: avir.h:2387
CBuffer(const capint aCapacity, const int aAlignment=0)
Definition: avir.h:481
static void applySRGBGamma(fptype *p, int l, const CImageResizerVars &Vars0)
Definition: avir.h:2853
int getOrder() const
Definition: avir.h:1678
Resizing algorithm parameters structure.
Definition: avir.h:2124
int BuildMode
Definition: avir.h:2408
void createAllFilters()
Definition: avir.h:1732
Sinc function-based fractional delay filter bank.
Definition: avir.h:1532
CBuffer< fptype > Flt
Definition: avir.h:2460
double k
Definition: avir.h:2378
void doResize2(const fptype *SrcLine, fptype *DstLine, const int DstLineIncr, const fptype *const ElBiases, fptype *const ) const
Definition: avir.h:4117
void free()
Definition: avir.h:532
Resizing positions buffer array class.
Definition: avir.h:2582
Memory buffer class for element array storage, with capacity tracking.
Definition: avir.h:462
int fpalign
Definition: avir.h:2360
adith CDitherer
Definition: avir.h:4597
static const int elalign
Definition: avir.h:4586
void increaseCapacity(const capint NewCapacity, const bool DoDataCopy=true)
Definition: avir.h:574
void doFilter(const fptype *const Src, fptype *Dst, const int DstIncr) const
Definition: avir.h:3748
CImageResizer(const int aResBitDepth=8, const int aSrcBitDepth=0, const CImageResizerParams &aParams=CImageResizerParamsDef())
Definition: avir.h:4637
CBuffer< fptype > ResScanlineDith0
Definition: avir.h:4531
int FracCount
Definition: avir.h:2569
int getFilterLength() const
Definition: avir.h:1094
int EdgePixelCount
Definition: avir.h:2520
bool IsUpsample
Definition: avir.h:2453
int RndSeed
Definition: avir.h:2412
Image resizing variables class.
Definition: avir.h:2349
int packmode
Definition: avir.h:2370
double DCGain
Definition: avir.h:2469
CDSPWindowGenPeakedCosine(const double aAlpha, const double aLen2)
Definition: avir.h:933
Set of resizing algorithm parameters for ultra low-aliasing resizing (13.68/1.79/1.000(521792.07)/0.000026).
Definition: avir.h:2324
int FilterLen
Definition: avir.h:1374
bool operator==(const CDSPFracFilterBankLin &s) const
Definition: avir.h:1585
double Len2
Definition: avir.h:1484
int ResizeStep
Definition: avir.h:2384
double o
Definition: avir.h:2567
double DCGain
Definition: avir.h:1491
int OutSuffix
Definition: avir.h:2504
double generate()
Definition: avir.h:946
static const int fppack
Definition: avir.h:4577
CSineGen(const double si, const double ph)
Definition: avir.h:880
CDSPPeakedCosineLPF(const double aLen2, const double aFreq2, const double aAlpha)
Definition: avir.h:1386
int getFilterLen() const
Definition: avir.h:1660
Set of resizing algorithm parameters for lower-ringing performance (9.21/1.91/1.040(391960.71)/0.000023).
Definition: avir.h:2274
int InElIncr
Definition: avir.h:2492
int FltLatency
Definition: avir.h:2472
void init(const int ReqFracCount, const int ReqOrder, const double BaseLen, const double Cutoff, const double aWFAlpha, const CFltBuffer &aExtFilter, const int aAlignment=0, const int FltLenAlign=1)
Definition: avir.h:1613
Buffer class for parametrized low-pass filter.
Definition: avir.h:1481
double HBFltAlpha
Definition: avir.h:2177
void calcScanlineBias(const fptype *p, const int SrcLen, fptype *const ElBiases) const
Definition: avir.h:3063
const CImageResizerVars * Vars
Definition: avir.h:2474
static const int EdgePixelCountDef
Definition: avir.h:2527
static bool isRecursive()
Definition: avir.h:4384
virtual int getSuggestedWorkloadCount() const
Definition: avir.h:2031
void truncateCapacity(const capint NewCapacity)
Definition: avir.h:612
double oy
Definition: avir.h:2399
Image resizer's default dithering class.
Definition: avir.h:4356
void copyInitParams(const CDSPFracFilterBankLin &s)
Definition: avir.h:1551
virtual void waitAllWorkloadsToFinish()
Definition: avir.h:2074
bool UseSRGBGamma
Definition: avir.h:2406
int SrcOffs
Definition: avir.h:2549
virtual void addWorkload(CWorkload *const Workload)
Definition: avir.h:2054
int InBuf
Definition: avir.h:2478
#define AVIR_PId2
Definition: avir.h:82
Interleaved filtering steps implementation class.
Definition: avir.h:2647
virtual void startAllWorkloads()
Definition: avir.h:2066
CBuffer< fptype > PrefixDC
Definition: avir.h:2512
double LPFltCutoffMult
Definition: avir.h:2159
Image resizer's filtering step class.
Definition: avir.h:2448
int calcInitComplexity(const CBuffer< uint8_t > &FracUseMap) const
Definition: avir.h:1755
T & add()
Definition: avir.h:789
void clear()
Definition: avir.h:836
int fl
Definition: avir.h:2551
Resizing positions buffer class.
Definition: avir.h:2562
static void unpackScanline(const fptype *ip, Tout *op, int l, const CImageResizerVars &Vars0)
Definition: avir.h:2993
int getFilterLatency() const
Definition: avir.h:1103
Set of resizing algorithm parameters for low-aliasing resizing (11.59/1.84/1.015(73054.59)/0.000159).
Definition: avir.h:2299
void forceCapacity(const capint NewCapacity)
Definition: avir.h:560
int ResampleFactor
Definition: avir.h:2457
Thread pool's workload object class.
Definition: avir.h:2009
const fptype * getFilter(const int i)
Definition: avir.h:1694
Peaked Cosine window function generator class.
Definition: avir.h:922
int fti
Definition: avir.h:2543
CRPosBuf & getRPosBuf(const double k, const double o, const int FracCount)
Definition: avir.h:2599
double o
Definition: avir.h:2381
int ElCount
Definition: avir.h:2352
int OutPrefix
Definition: avir.h:2500
virtual void removeAllWorkloads()
Definition: avir.h:2084
double HBFltLen
Definition: avir.h:2182
Set of resizing algorithm parameters for ultra-low-ringing performance (7.50/2.01/1.083(11568559.86)/0.000001).
Definition: avir.h:2226
CImageResizerFilterStepINL< fptype, fptypeatom > CFilterStep
Definition: avir.h:4594
void convertVtoH(const fptype *ip, fptype *op, const int SrcLen, const int SrcIncr) const
Definition: avir.h:2925
void init(const int aLen, const CImageResizerVars &aVars, const double aTrMul, const double aPkOut)
Definition: avir.h:4369
CDSPFracFilterBankLin< fptype > * FltBank
Definition: avir.h:2626
double IntFltCutoff
Definition: avir.h:2139
Floating-point processing definition and abstraction class.
Definition: avir.h:4570
int OutBuf
Definition: avir.h:2498
void doUpsample(const fptype *const Src, fptype *const Dst) const
Definition: avir.h:3250
void resizeImage(const Tin *const SrcBuf, const int SrcWidth, const int SrcHeight, int SrcScanlineSize, Tout *const NewBuf, const int NewWidth, const int NewHeight, const int ElCountIO, const double k, CImageResizerVars *const aVars=NULL) const
Definition: avir.h:4688
double LPFltAlpha
Definition: avir.h:2150
int InSuffix
Definition: avir.h:2486
double IntFltAlpha
Definition: avir.h:2135
int LenE
Definition: avir.h:4428
int Len
Definition: avir.h:4424
int InPrefix
Definition: avir.h:2480
afptype fptype
Definition: avir.h:4573
Image resizer's error-diffusion dithering class, interleaved mode.
Definition: avir.h:4449
const CImageResizerVars * Vars
Definition: avir.h:4426
double CorrFltLen
Definition: avir.h:2130
int OutLen
Definition: avir.h:2496
double Freq
Definition: avir.h:1487
void buildFilter(const double *const BandGains, double *const Filter)
Definition: avir.h:1117
double generate()
Definition: avir.h:891
Array of structured objects.
Definition: avir.h:732
void generateLPF(T *op, const double DCGain)
Definition: avir.h:1407
Sine signal generator class.
Definition: avir.h:869
void unbiasScanline(fptype *p, int l, const fptype *const ElBiases) const
Definition: avir.h:3153
int getFracCount() const
Definition: avir.h:1669
void setItemCount(const int NewCount)
Definition: avir.h:810
double TrMul0
Definition: avir.h:4430
int OutElIncr
Definition: avir.h:2508
void alloc(const capint aCapacity, const int aAlignment=0)
Definition: avir.h:522
CRPosBuf * RPosBuf
Definition: avir.h:2623
int InLen
Definition: avir.h:2476
CBuffer< fptype > SuffixDC
Definition: avir.h:2516
The default set of resizing algorithm parameters (10.06/1.88/1.029(256064.90)/0.000039).
Definition: avir.h:2201
const fptype * ftp
Definition: avir.h:2545
Low-pass filter windowed by Peaked Cosine window function.
Definition: avir.h:1368
double InGammaMult
Definition: avir.h:2389
int elalign
Definition: avir.h:2365
bool operator==(const CFltBuffer &b2) const
Definition: avir.h:1508
double HBFltCutoff
Definition: avir.h:2179
CImageResizerThreadPool * ThreadPool
Definition: avir.h:2402
FIR filter-based equalizer generator.
Definition: avir.h:989
CFltBuffer FltOrig
Definition: avir.h:2462
void doResize(const fptype *SrcLine, fptype *DstLine, const int DstLineIncr, const fptype *const ElBiases, fptype *const ) const
Definition: avir.h:3885
capint getCapacity() const
Definition: avir.h:545
afptypeatom fptypeatom
Definition: avir.h:4575
int fppack
Definition: avir.h:2357
double IntFltLen
Definition: avir.h:2142
fptype * ResScanlineDith
Definition: avir.h:4533
Set of resizing algorithm parameters for low-ringing performance (7.91/1.96/1.065(1980857.66)/0.000004).
Definition: avir.h:2250
int SrcPosInt
Definition: avir.h:2541
void dither(fptype *const ResScanline) const
Definition: avir.h:4395
static const int packmode
Definition: avir.h:4591
double PkOut0
Definition: avir.h:4432
Image resizer class.
Definition: avir.h:4617