AVIR
High-quality pro image resizing library
 
Loading...
Searching...
No Matches
avir_dil.h
Go to the documentation of this file.
1
15
16namespace avir {
17
28
29template< class fptype, class fptypesimd >
31 public CImageResizerFilterStep< fptype, fptype >
32{
33public:
34 using CImageResizerFilterStep< fptype, fptype > :: IsUpsample;
35 using CImageResizerFilterStep< fptype, fptype > :: ResampleFactor;
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;
52 using CImageResizerFilterStep< fptype, fptype > :: EdgePixelCount;
53
63
64 template< class Tin >
65 void packScanline( const Tin* const ip0, fptype* const op0,
66 const int l ) const
67 {
68 const int ElCount = Vars -> ElCount;
69 int j;
70
71 if( !Vars -> UseSRGBGamma )
72 {
73 for( j = 0; j < ElCount; j++ )
74 {
75 const Tin* ip = ip0 + j;
76 fptype* const op = op0 + j * InElIncr;
77 int i;
78
79 for( i = 0; i < l; i++ )
80 {
81 op[ i ] = (fptype) *ip;
82 ip += ElCount;
83 }
84 }
85 }
86 else
87 {
88 const int AlphaIndex = Vars -> AlphaIndex;
89 const fptype gm = (fptype) Vars -> InGammaMult;
90
91 for( j = 0; j < ElCount; j++ )
92 {
93 const Tin* ip = ip0 + j;
94 fptype* const op = op0 + j * InElIncr;
95 int i;
96
97 if( ElCount == 4 && j == AlphaIndex )
98 {
99 for( i = 0; i < l; i++ )
100 {
101 op[ i ] = (fptype) *ip * gm;
102 ip += ElCount;
103 }
104 }
105 else
106 {
107 for( i = 0; i < l; i++ )
108 {
109 op[ i ] = convertSRGB2Lin( *ip, gm );
110 ip += ElCount;
111 }
112 }
113 }
114 }
115 }
116
125
126 static void applySRGBGamma( fptype* const p0, const int l,
127 const CImageResizerVars& Vars0 )
128 {
129 const int ElCount = Vars0.ElCount;
130 const int AlphaIndex = Vars0.AlphaIndex;
131 const fptype gm = (fptype) Vars0.OutGammaMult;
132 int j;
133
134 for( j = 0; j < ElCount; j++ )
135 {
136 fptype* const p = p0 + j * l;
137 int i;
138
139 if( ElCount == 4 && j == AlphaIndex )
140 {
141 for( i = 0; i < l; i++ )
142 {
143 p[ i ] *= gm;
144 }
145 }
146 else
147 {
148 for( i = 0; i < l; i++ )
149 {
150 p[ i ] = convertLin2SRGB( p[ i ]) * gm;
151 }
152 }
153 }
154 }
155
172
173 void convertVtoH( const fptype* ip, fptype* op, const int SrcLen,
174 const int SrcIncr ) const
175 {
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;
181 const int ops1 = InElIncr;
182 const int ops2 = InElIncr * 2;
183 const int ops3 = InElIncr * 3;
184 int j;
185
186 if( ElCount == 1 )
187 {
188 for( j = 0; j < SrcLen; j++ )
189 {
190 op[ 0 ] = ip[ 0 ];
191 ip += SrcIncr;
192 op++;
193 }
194 }
195 else
196 if( ElCount == 4 )
197 {
198 for( j = 0; j < SrcLen; j++ )
199 {
200 op[ 0 ] = ip[ 0 ];
201 op[ ops1 ] = ip[ ips1 ];
202 op[ ops2 ] = ip[ ips2 ];
203 op[ ops3 ] = ip[ ips3 ];
204 ip += SrcIncr;
205 op++;
206 }
207 }
208 else
209 if( ElCount == 3 )
210 {
211 for( j = 0; j < SrcLen; j++ )
212 {
213 op[ 0 ] = ip[ 0 ];
214 op[ ops1 ] = ip[ ips1 ];
215 op[ ops2 ] = ip[ ips2 ];
216 ip += SrcIncr;
217 op++;
218 }
219 }
220 else
221 if( ElCount == 2 )
222 {
223 for( j = 0; j < SrcLen; j++ )
224 {
225 op[ 0 ] = ip[ 0 ];
226 op[ ops1 ] = ip[ ips1 ];
227 ip += SrcIncr;
228 op++;
229 }
230 }
231 }
232
247
248 template< class Tout >
249 static void unpackScanline( const fptype* const ip0, Tout* const op0,
250 const int l, const CImageResizerVars& Vars0 )
251 {
252 const int ElCount = Vars0.ElCount;
253 int j;
254
255 for( j = 0; j < ElCount; j++ )
256 {
257 const fptype* const ip = ip0 + j * l;
258 Tout* op = op0 + j;
259 int i;
260
261 for( i = 0; i < l; i++ )
262 {
263 *op = (Tout) ip[ i ];
264 op += ElCount;
265 }
266 }
267 }
268
278
279 void prepareInBuf( fptype* Src ) const
280 {
281 if( IsUpsample || InPrefix + InSuffix == 0 )
282 {
283 return;
284 }
285
286 int j;
287
288 for( j = 0; j < Vars -> ElCount; j++ )
289 {
290 replicateArray( Src, 1, Src - InPrefix, InPrefix, 1 );
291 fptype* const Src2 = Src + InLen - 1;
292 replicateArray( Src2, 1, Src2 + 1, InSuffix, 1 );
293 Src += InElIncr;
294 }
295 }
296
304
305 void doUpsample( const fptype* Src, fptype* Dst ) const
306 {
307 const int elalign = Vars -> elalign;
308 const int opstep = ResampleFactor;
309 const fptype* const f = Flt;
310 const int flen = Flt.getCapacity();
311 int l;
312 int i;
313 int j;
314
315 for( j = 0; j < Vars -> ElCount; j++ )
316 {
317 const fptype* ip = Src;
318 fptype* op0 = &Dst[ -OutPrefix ];
319 memset( op0, 0, (size_t) ( OutPrefix + OutLen + OutSuffix ) *
320 sizeof( fptype ));
321
322 if( FltOrig.getCapacity() > 0 )
323 {
324 // Do not perform filtering, only upsample.
325
326 op0 += OutPrefix % ResampleFactor;
328
329 while( l > 0 )
330 {
331 op0[ 0 ] = ip[ 0 ];
332 op0 += opstep;
333 l--;
334 }
335
336 l = InLen - 1;
337
338 while( l > 0 )
339 {
340 op0[ 0 ] = ip[ 0 ];
341 op0 += opstep;
342 ip++;
343 l--;
344 }
345
347
348 while( l >= 0 )
349 {
350 op0[ 0 ] = ip[ 0 ];
351 op0 += opstep;
352 l--;
353 }
354
355 Src += InElIncr;
356 Dst += OutElIncr;
357 continue;
358 }
359
360 l = InPrefix;
361 fptypesimd ipv = (fptypesimd) ip[ 0 ];
362
363 while( l > 0 )
364 {
365 for( i = 0; i < flen; i += elalign )
366 {
367 fptypesimd :: addu( op0 + i,
368 fptypesimd :: load( f + i ) * ipv );
369 }
370
371 op0 += opstep;
372 l--;
373 }
374
375 l = InLen - 1;
376
377 while( l > 0 )
378 {
379 ipv = (fptypesimd) ip[ 0 ];
380
381 for( i = 0; i < flen; i += elalign )
382 {
383 fptypesimd :: addu( op0 + i,
384 fptypesimd :: load( f + i ) * ipv );
385 }
386
387 ip++;
388 op0 += opstep;
389 l--;
390 }
391
392 l = InSuffix;
393 ipv = (fptypesimd) ip[ 0 ];
394
395 while( l >= 0 )
396 {
397 for( i = 0; i < flen; i += elalign )
398 {
399 fptypesimd :: addu( op0 + i,
400 fptypesimd :: load( f + i ) * ipv );
401 }
402
403 op0 += opstep;
404 l--;
405 }
406
407 const fptype* dc = SuffixDC;
408 l = SuffixDC.getCapacity();
409
410 for( i = 0; i < l; i += elalign )
411 {
412 fptypesimd :: addu( op0 + i,
413 fptypesimd :: load( dc + i ) * ipv );
414 }
415
416 ipv = (fptypesimd) Src[ 0 ];
417 op0 = Dst - InPrefix * opstep;
418 dc = PrefixDC;
419 l = PrefixDC.getCapacity();
420
421 for( i = 0; i < l; i += elalign )
422 {
423 fptypesimd :: addu( op0 + i,
424 fptypesimd :: load( dc + i ) * ipv );
425 }
426
427 Src += InElIncr;
428 Dst += OutElIncr;
429 }
430 }
431
443
444 void doFilter( const fptype* const Src, fptype* Dst,
445 const int DstIncr ) const
446 {
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();
451 const int ipstep = ResampleFactor;
452 int i;
453 int j;
454
455 if( ElCount == 1 )
456 {
457 const fptype* ip = Src - EdgePixelCount * ipstep - FltLatency;
458 fptype* op = Dst;
459 int l = OutLen;
460
461 while( l > 0 )
462 {
463 fptypesimd s = fptypesimd :: load( f ) *
464 fptypesimd :: loadu( ip );
465
466 for( i = elalign; i < flen; i += elalign )
467 {
468 s += fptypesimd :: load( f + i ) *
469 fptypesimd :: loadu( ip + i );
470 }
471
472 op[ 0 ] = s.hadd();
473 op += DstIncr;
474 ip += ipstep;
475 l--;
476 }
477 }
478 else
479 if( DstIncr == 1 )
480 {
481 for( j = 0; j < ElCount; j++ )
482 {
483 const fptype* ip = Src - EdgePixelCount * ipstep -
484 FltLatency + j * InElIncr;
485
486 fptype* op = Dst + j * OutElIncr;
487 int l = OutLen;
488
489 while( l > 0 )
490 {
491 fptypesimd s = fptypesimd :: load( f ) *
492 fptypesimd :: loadu( ip );
493
494 for( i = elalign; i < flen; i += elalign )
495 {
496 s += fptypesimd :: load( f + i ) *
497 fptypesimd :: loadu( ip + i );
498 }
499
500 op[ 0 ] = s.hadd();
501 op += DstIncr;
502 ip += ipstep;
503 l--;
504 }
505 }
506 }
507 else
508 {
509 const fptype* ip0 = Src - EdgePixelCount * ipstep - FltLatency;
510 fptype* op0 = Dst;
511 int l = OutLen;
512
513 while( l > 0 )
514 {
515 const fptype* ip = ip0;
516 fptype* op = op0;
517
518 for( j = 0; j < ElCount; j++ )
519 {
520 fptypesimd s = fptypesimd :: load( f ) *
521 fptypesimd :: loadu( ip );
522
523 for( i = elalign; i < flen; i += elalign )
524 {
525 s += fptypesimd :: load( f + i ) *
526 fptypesimd :: loadu( ip + i );
527 }
528
529 op[ 0 ] = s.hadd();
530 ip += InElIncr;
531 op += OutElIncr;
532 }
533
534 ip0 += ipstep;
535 op0 += DstIncr;
536 l--;
537 }
538 }
539 }
540
558
559 void doResize( const fptype* SrcLine, fptype* DstLine,
560 int DstLineIncr, fptype* const xx ) const
561 {
562 const int IntFltLen = FltBank -> getFilterLen();
563 const int ElCount = Vars -> ElCount;
564 const int elalign = Vars -> elalign;
566 CResizePos* rpos = &(*RPosBuf)[ 0 ];
567
568 int DstLineLen = OutLen;
569 int i;
570 int j;
571
572#define AVIR_RESIZE_PART1 \
573 while( DstLineLen > 0 ) \
574 { \
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;
579
580#define AVIR_RESIZE_PART1nx \
581 while( DstLineLen > 0 ) \
582 { \
583 const fptype* ftp = rpos -> ftp; \
584 const fptype* Src = SrcLine + rpos -> SrcOffs;
585
586#define AVIR_RESIZE_PART2 \
587 DstLine += DstLineIncr; \
588 rpos++; \
589 DstLineLen--; \
590 }
591
592 if( ElCount == 1 )
593 {
594 if( FltBank -> getOrder() == 1 )
595 {
596 AVIR_RESIZE_PART1
597
598 fptypesimd sum = ( fptypesimd :: load( ftp ) +
599 fptypesimd :: load( ftp2 ) * x ) *
600 fptypesimd :: loadu( Src );
601
602 for( i = elalign; i < IntFltLen; i += elalign )
603 {
604 sum += ( fptypesimd :: load( ftp + i ) +
605 fptypesimd :: load( ftp2 + i ) * x ) *
606 fptypesimd :: loadu( Src + i );
607 }
608
609 DstLine[ 0 ] = sum.hadd();
610
611 AVIR_RESIZE_PART2
612 }
613 else
614 {
615 AVIR_RESIZE_PART1nx
616
617 fptypesimd sum = fptypesimd :: load( ftp ) *
618 fptypesimd :: loadu( Src );
619
620 for( i = elalign; i < IntFltLen; i += elalign )
621 {
622 sum += fptypesimd :: load( ftp + i ) *
623 fptypesimd :: loadu( Src + i );
624 }
625
626 DstLine[ 0 ] = sum.hadd();
627
628 AVIR_RESIZE_PART2
629 }
630 }
631 else
632 if( DstLineIncr == 1 )
633 {
634 // Horizontal-oriented processing, element loop is outer.
635
636 const int SrcIncr = InElIncr;
637 const int DstLineElIncr = OutElIncr - DstLineIncr * DstLineLen;
638
639 if( FltBank -> getOrder() == 1 )
640 {
641 for( j = 0; j < ElCount; j++ )
642 {
643 AVIR_RESIZE_PART1
644
645 fptypesimd sum = 0.0;
646
647 for( i = 0; i < IntFltLen; i += elalign )
648 {
649 sum += ( fptypesimd :: load( ftp + i ) +
650 fptypesimd :: load( ftp2 + i ) * x ) *
651 fptypesimd :: loadu( Src + i );
652 }
653
654 DstLine[ 0 ] = sum.hadd();
655
656 AVIR_RESIZE_PART2
657
658 DstLine += DstLineElIncr;
659 SrcLine += SrcIncr;
660 DstLineLen = OutLen;
661 rpos = &(*RPosBuf)[ 0 ];
662 }
663 }
664 else
665 {
666 for( j = 0; j < ElCount; j++ )
667 {
668 AVIR_RESIZE_PART1nx
669
670 fptypesimd sum = fptypesimd :: load( ftp ) *
671 fptypesimd :: loadu( Src );
672
673 for( i = elalign; i < IntFltLen; i += elalign )
674 {
675 sum += fptypesimd :: load( ftp + i ) *
676 fptypesimd :: loadu( Src + i );
677 }
678
679 DstLine[ 0 ] = sum.hadd();
680
681 AVIR_RESIZE_PART2
682
683 DstLine += DstLineElIncr;
684 SrcLine += SrcIncr;
685 DstLineLen = OutLen;
686 rpos = &(*RPosBuf)[ 0 ];
687 }
688 }
689 }
690 else
691 {
692 const int SrcIncr = InElIncr;
693 const int DstLineElIncr = OutElIncr;
694 DstLineIncr -= DstLineElIncr * ElCount;
695
696 if( FltBank -> getOrder() == 1 )
697 {
698 AVIR_RESIZE_PART1
699
700 for( i = 0; i < IntFltLen; i += elalign )
701 {
702 ( fptypesimd :: load( ftp + i ) +
703 fptypesimd :: load( ftp2 + i ) * x ).store( xx + i );
704 }
705
706 for( j = 0; j < ElCount; j++ )
707 {
708 fptypesimd sum = fptypesimd :: load( xx ) *
709 fptypesimd :: loadu( Src );
710
711 for( i = elalign; i < IntFltLen; i += elalign )
712 {
713 sum += fptypesimd :: load( xx + i ) *
714 fptypesimd :: loadu( Src + i );
715 }
716
717 DstLine[ 0 ] = sum.hadd();
718 DstLine += DstLineElIncr;
719 Src += SrcIncr;
720 }
721
722 AVIR_RESIZE_PART2
723 }
724 else
725 {
726 AVIR_RESIZE_PART1nx
727
728 for( j = 0; j < ElCount; j++ )
729 {
730 fptypesimd sum = fptypesimd :: load( ftp ) *
731 fptypesimd :: loadu( Src );
732
733 for( i = elalign; i < IntFltLen; i += elalign )
734 {
735 sum += fptypesimd :: load( ftp + i ) *
736 fptypesimd :: loadu( Src + i );
737 }
738
739 DstLine[ 0 ] = sum.hadd();
740 DstLine += DstLineElIncr;
741 Src += SrcIncr;
742 }
743
744 AVIR_RESIZE_PART2
745 }
746 }
747
748#undef AVIR_RESIZE_PART2
749#undef AVIR_RESIZE_PART1nx
750#undef AVIR_RESIZE_PART1
751 }
752
756
757 void doResize2( const fptype* SrcLine, fptype* DstLine,
758 int DstLineIncr, fptype* const xx ) const
759 {
760 doResize( SrcLine, DstLine, DstLineIncr, xx );
761 }
762};
763
777
778template< class fptype, class fptypesimd >
780{
781public:
791
792 void init( const int aLen, const CImageResizerVars& aVars,
793 const double aTrMul, const double aPkOut )
794 {
795 Len = aLen;
796 Vars = &aVars;
797 LenE = aLen * Vars -> ElCount;
798 TrMul0 = aTrMul;
799 PkOut0 = aPkOut;
800 }
801
805
806 static bool isRecursive()
807 {
808 return( false );
809 }
810
814
815 void dither( fptype* const ResScanline ) const
816 {
817 const int elalign = Vars -> elalign;
818 const fptypesimd c0 = 0.0;
819 const fptypesimd PkOut = (fptypesimd) PkOut0;
820 int j;
821
822 if( TrMul0 == 1.0 )
823 {
824 // Optimization - do not perform bit truncation.
825
826 for( j = 0; j < LenE - elalign; j += elalign )
827 {
828 const fptypesimd z0 = round(
829 fptypesimd :: loadu( ResScanline + j ));
830
831 clamp( z0, c0, PkOut ).storeu( ResScanline + j );
832 }
833
834 const int lim = LenE - j;
835 const fptypesimd z0 = round(
836 fptypesimd :: loadu( ResScanline + j, lim ));
837
838 clamp( z0, c0, PkOut ).storeu( ResScanline + j, lim );
839 }
840 else
841 {
842 const fptypesimd TrMul = (fptypesimd) TrMul0;
843 const fptypesimd TrMulI = (fptypesimd) ( 1.0 / TrMul0 );
844
845 for( j = 0; j < LenE - elalign; j += elalign )
846 {
847 const fptypesimd z0 = round(
848 fptypesimd :: loadu( ResScanline + j ) * TrMulI ) * TrMul;
849
850 clamp( z0, c0, PkOut ).storeu( ResScanline + j );
851 }
852
853 const int lim = LenE - j;
854 const fptypesimd z0 = round( fptypesimd :: loadu(
855 ResScanline + j, lim ) * TrMulI ) * TrMul;
856
857 clamp( z0, c0, PkOut ).storeu( ResScanline + j, lim );
858 }
859 }
860
861protected:
862 int Len;
864 int LenE;
865 double TrMul0;
866 double PkOut0;
867};
868
880
881template< class fptype, class fptypesimd >
883{
884public:
894
895 void init( const int aLen, const CImageResizerVars& aVars,
896 const double aTrMul, const double aPkOut )
897 {
898 Len = aLen;
899 Vars = &aVars;
900 LenE = aLen * Vars -> ElCount;
901 TrMul0 = aTrMul;
902 PkOut0 = aPkOut;
903
904 ResScanlineDith0.alloc( LenE + Vars -> ElCount, sizeof( fptype ));
906 int i;
907
908 for( i = 0; i < LenE + Vars -> ElCount; i++ )
909 {
910 ResScanlineDith0[ i ] = 0.0;
911 }
912 }
913
917
918 static bool isRecursive()
919 {
920 return( true );
921 }
922
926
927 void dither( fptype* const ResScanline )
928 {
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;
934 int j;
935
936 for( j = 0; j < LenE - ea; j += ea )
937 {
938 fptypesimd :: addu( ResScanline + j,
939 fptypesimd :: loadu( ResScanlineDith + j ));
940
941 c0.storeu( ResScanlineDith + j );
942 }
943
944 int lim = LenE - j;
945 fptypesimd :: addu( ResScanline + j,
946 fptypesimd :: loadu( ResScanlineDith + j, lim ), lim );
947
948 c0.storeu( ResScanlineDith + j, lim );
949
950 const int Len1 = Len - 1;
951 fptype* rs = ResScanline;
952 fptype* rsd = ResScanlineDith;
953 int i;
954
955 for( i = 0; i < Vars -> ElCount; i++ )
956 {
957 for( j = 0; j < Len1; j++ )
958 {
959 // Perform rounding, noise estimation and saturation.
960
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 );
965
966 fptype* const rsdj = rsd + j;
967 const fptype NoiseM1 = Noise * (fptype) 0.364842;
968 rsj[ 1 ] += NoiseM1;
969 rsdj[ -1 ] += Noise * (fptype) 0.207305;
970 rsdj[ 0 ] += NoiseM1;
971 rsdj[ 1 ] += Noise * (fptype) 0.063011;
972 }
973
974 // Process the last pixel element in scanline.
975
976 const fptype z1 = round( rs[ Len1 ] * TrMulI ) * TrMul;
977 const fptype Noise2 = rs[ Len1 ] - z1;
978 rs[ Len1 ] = clamp( z1, c0, PkOut );
979
980 rsd[ Len1 - 1 ] += Noise2 * (fptype) 0.207305;
981 rsd[ Len1 ] += Noise2 * (fptype) 0.364842;
982
983 rs += Len;
984 rsd += Len;
985 }
986 }
987
988protected:
989 int Len;
991 int LenE;
992 double TrMul0;
993 double PkOut0;
998};
999
1013
1014template< class afptype, class afptypesimd,
1017{
1018public:
1019 typedef afptype fptype;
1020 typedef afptype fptypeatom;
1021 static const int fppack = 1;
1023 static const int fpalign = sizeof( afptypesimd );
1028 static const int elalign = sizeof( afptypesimd ) / sizeof( afptype );
1033 static const int packmode = 1;
1037 typedef adith CDitherer;
1038};
1039
1040} // namespace avir
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
CBuffer< fptype > SuffixDC
Definition avir.h:2620
CFltBuffer FltOrig
Definition avir.h:2581
CBuffer< fptype > Flt
Definition avir.h:2580
const CDSPFracFilterBankLin< fptype > * FltBank
Definition avir.h:2719
const CImageResizerVars * Vars
Definition avir.h:2590
CRPosBuf * RPosBuf
Definition avir.h:2717
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