29template<
class fptype,
class fptypesimd >
31 public CImageResizerFilterStep< fptype, fptype >
34 using CImageResizerFilterStep< fptype, fptype >
:: IsUpsample;
36 using CImageResizerFilterStep< fptype, fptype >
:: Flt;
37 using CImageResizerFilterStep< fptype, fptype >
:: FltOrig;
38 using CImageResizerFilterStep< fptype, fptype >
:: FltLatency;
39 using CImageResizerFilterStep< fptype, fptype >
:: Vars;
40 using CImageResizerFilterStep< fptype, fptype >
:: InLen;
41 using CImageResizerFilterStep< fptype, fptype >
:: InPrefix;
42 using CImageResizerFilterStep< fptype, fptype >
:: InSuffix;
43 using CImageResizerFilterStep< fptype, fptype >
:: InElIncr;
44 using CImageResizerFilterStep< fptype, fptype >
:: OutLen;
45 using CImageResizerFilterStep< fptype, fptype >
:: OutPrefix;
46 using CImageResizerFilterStep< fptype, fptype >
:: OutSuffix;
47 using CImageResizerFilterStep< fptype, fptype >
:: OutElIncr;
48 using CImageResizerFilterStep< fptype, fptype >
:: PrefixDC;
49 using CImageResizerFilterStep< fptype, fptype >
:: SuffixDC;
50 using CImageResizerFilterStep< fptype, fptype >
:: RPosBuf;
51 using CImageResizerFilterStep< fptype, fptype >
:: FltBank;
68 const int ElCount =
Vars -> ElCount;
71 if( !
Vars -> UseSRGBGamma )
73 for( j = 0; j < ElCount; j++ )
75 const Tin* ip = ip0 + j;
76 fptype*
const op = op0 + j *
InElIncr;
79 for( i = 0; i < l; i++ )
81 op[ i ] = (fptype) *ip;
88 const int AlphaIndex =
Vars -> AlphaIndex;
89 const fptype gm = (fptype)
Vars -> InGammaMult;
91 for( j = 0; j < ElCount; j++ )
93 const Tin* ip = ip0 + j;
94 fptype*
const op = op0 + j *
InElIncr;
97 if( ElCount == 4 && j == AlphaIndex )
99 for( i = 0; i < l; i++ )
101 op[ i ] = (fptype) *ip * gm;
107 for( i = 0; i < l; i++ )
129 const int ElCount = Vars0.
ElCount;
134 for( j = 0; j < ElCount; j++ )
136 fptype*
const p = p0 + j * l;
139 if( ElCount == 4 && j == AlphaIndex )
141 for( i = 0; i < l; i++ )
148 for( i = 0; i < l; i++ )
174 const int SrcIncr )
const
176 const int ElCount =
Vars -> ElCount;
177 const int SrcElIncr = SrcIncr / ElCount;
178 const int ips1 = SrcElIncr;
179 const int ips2 = SrcElIncr * 2;
180 const int ips3 = SrcElIncr * 3;
188 for( j = 0; j < SrcLen; j++ )
198 for( j = 0; j < SrcLen; j++ )
201 op[ ops1 ] = ip[ ips1 ];
202 op[ ops2 ] = ip[ ips2 ];
203 op[ ops3 ] = ip[ ips3 ];
211 for( j = 0; j < SrcLen; j++ )
214 op[ ops1 ] = ip[ ips1 ];
215 op[ ops2 ] = ip[ ips2 ];
223 for( j = 0; j < SrcLen; j++ )
226 op[ ops1 ] = ip[ ips1 ];
248 template<
class Tout >
252 const int ElCount = Vars0.
ElCount;
255 for( j = 0; j < ElCount; j++ )
257 const fptype*
const ip = ip0 + j * l;
261 for( i = 0; i < l; i++ )
263 *op = (Tout) ip[ i ];
288 for( j = 0; j <
Vars -> ElCount; j++ )
291 fptype*
const Src2 = Src +
InLen - 1;
307 const int elalign =
Vars -> elalign;
309 const fptype*
const f =
Flt;
310 const int flen =
Flt.getCapacity();
315 for( j = 0; j <
Vars -> ElCount; j++ )
317 const fptype* ip = Src;
322 if(
FltOrig.getCapacity() > 0 )
361 fptypesimd ipv = (fptypesimd) ip[ 0 ];
365 for( i = 0; i < flen; i += elalign )
367 fptypesimd :: addu( op0 + i,
368 fptypesimd :: load( f + i ) * ipv );
379 ipv = (fptypesimd) ip[ 0 ];
381 for( i = 0; i < flen; i += elalign )
383 fptypesimd :: addu( op0 + i,
384 fptypesimd :: load( f + i ) * ipv );
393 ipv = (fptypesimd) ip[ 0 ];
397 for( i = 0; i < flen; i += elalign )
399 fptypesimd :: addu( op0 + i,
400 fptypesimd :: load( f + i ) * ipv );
410 for( i = 0; i < l; i += elalign )
412 fptypesimd :: addu( op0 + i,
413 fptypesimd :: load( dc + i ) * ipv );
416 ipv = (fptypesimd) Src[ 0 ];
421 for( i = 0; i < l; i += elalign )
423 fptypesimd :: addu( op0 + i,
424 fptypesimd :: load( dc + i ) * ipv );
444 void doFilter(
const fptype*
const Src, fptype* Dst,
445 const int DstIncr )
const
447 const int ElCount =
Vars -> ElCount;
448 const int elalign =
Vars -> elalign;
449 const fptype*
const f = &
Flt[ 0 ];
450 const int flen =
Flt.getCapacity();
463 fptypesimd s = fptypesimd :: load( f ) *
464 fptypesimd :: loadu( ip );
466 for( i = elalign; i < flen; i += elalign )
468 s += fptypesimd :: load( f + i ) *
469 fptypesimd :: loadu( ip + i );
481 for( j = 0; j < ElCount; j++ )
491 fptypesimd s = fptypesimd :: load( f ) *
492 fptypesimd :: loadu( ip );
494 for( i = elalign; i < flen; i += elalign )
496 s += fptypesimd :: load( f + i ) *
497 fptypesimd :: loadu( ip + i );
515 const fptype* ip = ip0;
518 for( j = 0; j < ElCount; j++ )
520 fptypesimd s = fptypesimd :: load( f ) *
521 fptypesimd :: loadu( ip );
523 for( i = elalign; i < flen; i += elalign )
525 s += fptypesimd :: load( f + i ) *
526 fptypesimd :: loadu( ip + i );
559 void doResize(
const fptype* SrcLine, fptype* DstLine,
560 int DstLineIncr, fptype*
const xx )
const
562 const int IntFltLen =
FltBank -> getFilterLen();
563 const int ElCount =
Vars -> ElCount;
564 const int elalign =
Vars -> elalign;
566 CResizePos* rpos = &(*RPosBuf)[ 0 ];
572#define AVIR_RESIZE_PART1 \
573 while( DstLineLen > 0 ) \
575 const fptypesimd x = (fptypesimd) rpos -> x; \
576 const fptype* ftp = rpos -> ftp; \
577 const fptype* ftp2 = rpos -> ftp + IntFltLen; \
578 const fptype* Src = SrcLine + rpos -> SrcOffs;
580#define AVIR_RESIZE_PART1nx \
581 while( DstLineLen > 0 ) \
583 const fptype* ftp = rpos -> ftp; \
584 const fptype* Src = SrcLine + rpos -> SrcOffs;
586#define AVIR_RESIZE_PART2 \
587 DstLine += DstLineIncr; \
594 if(
FltBank -> getOrder() == 1 )
598 fptypesimd sum = ( fptypesimd :: load( ftp ) +
599 fptypesimd :: load( ftp2 ) * x ) *
600 fptypesimd :: loadu( Src );
602 for( i = elalign; i < IntFltLen; i += elalign )
604 sum += ( fptypesimd :: load( ftp + i ) +
605 fptypesimd :: load( ftp2 + i ) * x ) *
606 fptypesimd :: loadu( Src + i );
609 DstLine[ 0 ] = sum.hadd();
617 fptypesimd sum = fptypesimd :: load( ftp ) *
618 fptypesimd :: loadu( Src );
620 for( i = elalign; i < IntFltLen; i += elalign )
622 sum += fptypesimd :: load( ftp + i ) *
623 fptypesimd :: loadu( Src + i );
626 DstLine[ 0 ] = sum.hadd();
632 if( DstLineIncr == 1 )
637 const int DstLineElIncr =
OutElIncr - DstLineIncr * DstLineLen;
639 if(
FltBank -> getOrder() == 1 )
641 for( j = 0; j < ElCount; j++ )
645 fptypesimd sum = 0.0;
647 for( i = 0; i < IntFltLen; i += elalign )
649 sum += ( fptypesimd :: load( ftp + i ) +
650 fptypesimd :: load( ftp2 + i ) * x ) *
651 fptypesimd :: loadu( Src + i );
654 DstLine[ 0 ] = sum.hadd();
658 DstLine += DstLineElIncr;
661 rpos = &(*RPosBuf)[ 0 ];
666 for( j = 0; j < ElCount; j++ )
670 fptypesimd sum = fptypesimd :: load( ftp ) *
671 fptypesimd :: loadu( Src );
673 for( i = elalign; i < IntFltLen; i += elalign )
675 sum += fptypesimd :: load( ftp + i ) *
676 fptypesimd :: loadu( Src + i );
679 DstLine[ 0 ] = sum.hadd();
683 DstLine += DstLineElIncr;
686 rpos = &(*RPosBuf)[ 0 ];
694 DstLineIncr -= DstLineElIncr * ElCount;
696 if(
FltBank -> getOrder() == 1 )
700 for( i = 0; i < IntFltLen; i += elalign )
702 ( fptypesimd :: load( ftp + i ) +
703 fptypesimd :: load( ftp2 + i ) * x ).store( xx + i );
706 for( j = 0; j < ElCount; j++ )
708 fptypesimd sum = fptypesimd :: load( xx ) *
709 fptypesimd :: loadu( Src );
711 for( i = elalign; i < IntFltLen; i += elalign )
713 sum += fptypesimd :: load( xx + i ) *
714 fptypesimd :: loadu( Src + i );
717 DstLine[ 0 ] = sum.hadd();
718 DstLine += DstLineElIncr;
728 for( j = 0; j < ElCount; j++ )
730 fptypesimd sum = fptypesimd :: load( ftp ) *
731 fptypesimd :: loadu( Src );
733 for( i = elalign; i < IntFltLen; i += elalign )
735 sum += fptypesimd :: load( ftp + i ) *
736 fptypesimd :: loadu( Src + i );
739 DstLine[ 0 ] = sum.hadd();
740 DstLine += DstLineElIncr;
748#undef AVIR_RESIZE_PART2
749#undef AVIR_RESIZE_PART1nx
750#undef AVIR_RESIZE_PART1
758 int DstLineIncr, fptype*
const xx )
const
760 doResize( SrcLine, DstLine, DstLineIncr, xx );
778template<
class fptype,
class fptypesimd >
793 const double aTrMul,
const double aPkOut )
815 void dither( fptype*
const ResScanline )
const
817 const int elalign =
Vars -> elalign;
818 const fptypesimd c0 = 0.0;
819 const fptypesimd PkOut = (fptypesimd)
PkOut0;
826 for( j = 0; j <
LenE - elalign; j += elalign )
828 const fptypesimd z0 =
round(
829 fptypesimd :: loadu( ResScanline + j ));
831 clamp( z0, c0, PkOut ).storeu( ResScanline + j );
834 const int lim =
LenE - j;
835 const fptypesimd z0 =
round(
836 fptypesimd :: loadu( ResScanline + j, lim ));
838 clamp( z0, c0, PkOut ).storeu( ResScanline + j, lim );
842 const fptypesimd TrMul = (fptypesimd)
TrMul0;
843 const fptypesimd TrMulI = (fptypesimd) ( 1.0 /
TrMul0 );
845 for( j = 0; j <
LenE - elalign; j += elalign )
847 const fptypesimd z0 =
round(
848 fptypesimd :: loadu( ResScanline + j ) * TrMulI ) * TrMul;
850 clamp( z0, c0, PkOut ).storeu( ResScanline + j );
853 const int lim =
LenE - j;
854 const fptypesimd z0 =
round( fptypesimd :: loadu(
855 ResScanline + j, lim ) * TrMulI ) * TrMul;
857 clamp( z0, c0, PkOut ).storeu( ResScanline + j, lim );
881template<
class fptype,
class fptypesimd >
896 const double aTrMul,
const double aPkOut )
908 for( i = 0; i <
LenE +
Vars -> ElCount; i++ )
929 const int ea =
Vars -> elalign;
930 const fptypesimd c0 = 0;
931 const fptypesimd TrMul = (fptypesimd)
TrMul0;
932 const fptypesimd TrMulI = (fptypesimd) ( 1.0 /
TrMul0 );
933 const fptypesimd PkOut = (fptypesimd)
PkOut0;
936 for( j = 0; j <
LenE - ea; j += ea )
938 fptypesimd :: addu( ResScanline + j,
945 fptypesimd :: addu( ResScanline + j,
950 const int Len1 =
Len - 1;
951 fptype* rs = ResScanline;
955 for( i = 0; i <
Vars -> ElCount; i++ )
957 for( j = 0; j < Len1; j++ )
961 fptype*
const rsj = rs + j;
962 const fptype z0 =
round( rsj[ 0 ] * TrMulI ) * TrMul;
963 const fptype Noise = rsj[ 0 ] - z0;
964 rsj[ 0 ] =
clamp( z0, (fptype) 0, PkOut );
966 fptype*
const rsdj = rsd + j;
967 const fptype NoiseM1 = Noise * (fptype) 0.364842;
969 rsdj[ -1 ] += Noise * (fptype) 0.207305;
970 rsdj[ 0 ] += NoiseM1;
971 rsdj[ 1 ] += Noise * (fptype) 0.063011;
976 const fptype z1 =
round( rs[ Len1 ] * TrMulI ) * TrMul;
977 const fptype Noise2 = rs[ Len1 ] - z1;
978 rs[ Len1 ] =
clamp( z1, c0, PkOut );
980 rsd[ Len1 - 1 ] += Noise2 * (fptype) 0.207305;
981 rsd[ Len1 ] += Noise2 * (fptype) 0.364842;
1014template<
class afptype,
class afptypesimd,
1028 static const int elalign =
sizeof( afptypesimd ) /
sizeof( afptype );
T clamp(const T &Value, const T minv, const T maxv)
"Clamps" (clips) the specified value so that it is not lesser than minv, and not greater than maxv.
Definition avir.h:149
T convertLin2SRGB(const T s)
Approximately de-linearizes the linear gamma value.
Definition avir.h:300
void replicateArray(const T1 *const ip, const int ipl, T2 *op, int l, const int opinc)
Replicates a set of adjacent elements several times in a row.
Definition avir.h:378
T round(const T d)
Rounding function, based on the (int) typecast. Biased result. Not suitable for numbers greater than ...
Definition avir.h:131
T convertSRGB2Lin(const Tin &s0, const T m)
Approximately linearizes the sRGB gamma value.
Definition avir.h:209
double OutGammaMult
Output gamma multiplier, used to convert data to [0; 255/65535] range. 0.0, if no gamma is in use.
Definition avir.h:2504
int ElCount
The number of fptype elements used to store 1 pixel.
Definition avir.h:2476
Image resizing variables.
Definition avir.h:2517
int AlphaIndex
Alpha-channel index, for 4-channel input. Default -1 applies gamma correction to all channels....
Definition avir.h:2527
int OutLen
Definition avir.h:2606
int ResampleFactor
Definition avir.h:2577
int InElIncr
Definition avir.h:2603
bool IsUpsample
Definition avir.h:2574
int OutPrefix
Definition avir.h:2608
CBuffer< fptype > SuffixDC
Definition avir.h:2620
int OutElIncr
Definition avir.h:2614
int EdgePixelCount
Definition avir.h:2623
int InPrefix
Definition avir.h:2593
int InLen
Definition avir.h:2591
CFltBuffer FltOrig
Definition avir.h:2581
int FltLatency
Definition avir.h:2589
CBuffer< fptype > Flt
Definition avir.h:2580
const CDSPFracFilterBankLin< fptype > * FltBank
Definition avir.h:2719
int OutSuffix
Definition avir.h:2611
const CImageResizerVars * Vars
Definition avir.h:2590
CRPosBuf * RPosBuf
Definition avir.h:2717
int InSuffix
Definition avir.h:2598
CBuffer< fptype > PrefixDC
Definition avir.h:2617
De-interleaved filtering steps implementation class.
Definition avir_dil.h:32
void doFilter(const fptype *const Src, fptype *Dst, const int DstIncr) const
Performs scanline filtering with optional downsampling.
Definition avir_dil.h:444
void convertVtoH(const fptype *ip, fptype *op, const int SrcLen, const int SrcIncr) const
Converts vertical scanline to horizontal scanline.
Definition avir_dil.h:173
void packScanline(const Tin *const ip0, fptype *const op0, const int l) const
Performs "packing" (de-interleaving) of a scanline, and type conversion. If required,...
Definition avir_dil.h:65
void doResize(const fptype *SrcLine, fptype *DstLine, int DstLineIncr, fptype *const xx) const
Performs resizing of a single scanline.
Definition avir_dil.h:559
void prepareInBuf(fptype *Src) const
Prepares input scanline buffer for this filtering step.
Definition avir_dil.h:279
static void applySRGBGamma(fptype *const p0, const int l, const CImageResizerVars &Vars0)
Applies Linear to sRGB gamma correction to the specified scanline, in-place.
Definition avir_dil.h:126
void doResize2(const fptype *SrcLine, fptype *DstLine, int DstLineIncr, fptype *const xx) const
Performs resizing of a single scanline.
Definition avir_dil.h:757
static void unpackScanline(const fptype *const ip0, Tout *const op0, const int l, const CImageResizerVars &Vars0)
Performs "unpacking" of a scanline, and type conversion.
Definition avir_dil.h:249
void doUpsample(const fptype *Src, fptype *Dst) const
Peforms scanline upsampling with filtering.
Definition avir_dil.h:305
Image resizer's default de-interleaved dithering class.
Definition avir_dil.h:780
void dither(fptype *const ResScanline) const
Performs rounding and clipping operations, in-place.
Definition avir_dil.h:815
double PkOut0
Peak output value allowed.
Definition avir_dil.h:866
int LenE
= LenE * ElCount.
Definition avir_dil.h:864
double TrMul0
Bit-depth truncation multiplier.
Definition avir_dil.h:865
const CImageResizerVars * Vars
Image resizing-related variables.
Definition avir_dil.h:863
static bool isRecursive()
Returns true, if dithering is recursive relative to scanlines, meaning multi-threaded execution is no...
Definition avir_dil.h:806
void init(const int aLen, const CImageResizerVars &aVars, const double aTrMul, const double aPkOut)
Initializes the ditherer object.
Definition avir_dil.h:792
int Len
Scanline's length in pixels.
Definition avir_dil.h:862
Image resizer's error-diffusion dithering class, de-interleaved mode.
Definition avir_dil.h:883
int LenE
= LenE * ElCount.
Definition avir_dil.h:991
const CImageResizerVars * Vars
Image resizing-related variables.
Definition avir_dil.h:990
void init(const int aLen, const CImageResizerVars &aVars, const double aTrMul, const double aPkOut)
Definition avir_dil.h:895
double PkOut0
Peak output value allowed.
Definition avir_dil.h:993
fptype * ResScanlineDith
Error propagation buffer pointer which skips the first ElCount elements.
Definition avir_dil.h:996
void dither(fptype *const ResScanline)
Performs rounding and clipping operations, in-place.
Definition avir_dil.h:927
static bool isRecursive()
Returns true, if dithering is recursive relative to scanlines, meaning multi-threaded execution is no...
Definition avir_dil.h:918
double TrMul0
Bit-depth truncation multiplier.
Definition avir_dil.h:992
CBuffer< fptype > ResScanlineDith0
Error propagation buffer for dithering, first pixel unused.
Definition avir_dil.h:994
int Len
Scanline's length in pixels.
Definition avir_dil.h:989
Floating-point processing definition and abstraction class for de-interleaved processing.
Definition avir_dil.h:1017
static const int elalign
Definition avir_dil.h:1028
static const int packmode
Definition avir_dil.h:1033
afptype fptypeatom
Atomic type fptype consists of.
Definition avir_dil.h:1020
static const int fpalign
Definition avir_dil.h:1023
afptype fptype
Floating-point type to use during processing.
Definition avir_dil.h:1019
static const int fppack
Definition avir_dil.h:1021
adith CDitherer
Ditherer class to use during processing.
Definition avir_dil.h:1037
CImageResizerFilterStepDIL< fptype, afptypesimd > CFilterStep
Filtering step class to use during processing.
Definition avir_dil.h:1035