AVIR
High-quality pro image resizing library
 All Classes Files Functions Variables Typedefs Macros
lancir.h
Go to the documentation of this file.
1 //$ nobt
2 //$ nocpp
3 
45 #ifndef AVIR_CLANCIR_INCLUDED
46 #define AVIR_CLANCIR_INCLUDED
47 
48 #include <string.h>
49 #include <math.h>
50 
51 namespace avir {
52 
58 #define LANCIR_PI 3.1415926535897932
59 
77 class CLancIR
78 {
79 private:
80  CLancIR( const CLancIR& )
81  {
82  // Unsupported.
83  }
84 
85  CLancIR& operator = ( const CLancIR& )
86  {
87  // Unsupported.
88  return( *this );
89  }
90 
91 public:
92  CLancIR()
93  : FltBuf( NULL )
94  , FltBufLen( 0 )
95  , spv( NULL )
96  , spvlen( 0 )
97  {
98  }
99 
100  ~CLancIR()
101  {
102  delete[] FltBuf;
103  delete[] spv;
104  }
105 
138  template< class T >
139  void resizeImage( const T* const SrcBuf, const int SrcWidth,
140  const int SrcHeight, int SrcScanlineSize, T* const NewBuf,
141  const int NewWidth, const int NewHeight, const int ElCount,
142  const double kx0 = 0.0, const double ky0 = 0.0, double ox = 0.0,
143  double oy = 0.0 )
144  {
145  if( NewWidth <= 0 || NewHeight <= 0 )
146  {
147  return;
148  }
149 
150  if( SrcWidth <= 0 || SrcHeight <= 0 )
151  {
152  memset( NewBuf, 0, (size_t) NewWidth * NewHeight * ElCount *
153  sizeof( T ));
154 
155  return;
156  }
157 
158  const double la = 3.0; // Lanczos "a".
159  double kx;
160  double ky;
161 
162  if( kx0 == 0.0 )
163  {
164  kx = (double) SrcWidth / NewWidth;
165  ox += ( kx - 1.0 ) * 0.5;
166  }
167  else
168  if( kx0 > 0.0 )
169  {
170  kx = kx0;
171  ox += ( kx0 - 1.0 ) * 0.5;
172  }
173  else
174  {
175  kx = -kx0;
176  }
177 
178  if( ky0 == 0.0 )
179  {
180  ky = (double) SrcHeight / NewHeight;
181  oy += ( ky - 1.0 ) * 0.5;
182  }
183  else
184  if( ky0 > 0.0 )
185  {
186  ky = ky0;
187  oy += ( ky0 - 1.0 ) * 0.5;
188  }
189  else
190  {
191  ky = -ky0;
192  }
193 
194  if( rfh.update( la, kx ))
195  {
196  rsh.reset();
197  rsv.reset();
198  }
199 
200  CResizeFilters* rfv; // Pointer to resizing filters for vertical
201  // resizing, may equal to "rfh" if the same stepping is in use.
202 
203  if( ky == kx )
204  {
205  rfv = &rfh;
206  }
207  else
208  {
209  rfv = &rfv0;
210 
211  if( rfv0.update( la, ky ))
212  {
213  rsv.reset();
214  }
215  }
216 
217  rsh.update( kx, ox, ElCount, SrcWidth, NewWidth, rfh );
218  rsv.update( ky, oy, ElCount, SrcHeight, NewHeight, *rfv );
219 
220  const int NewWidthE = NewWidth * ElCount;
221 
222  if( SrcScanlineSize < 1 )
223  {
224  SrcScanlineSize = SrcWidth * ElCount;
225  }
226 
227  // Allocate/resize temporary buffer.
228 
229  const size_t FltBufLenNew = (size_t) NewWidthE * (size_t) SrcHeight;
230 
231  if( FltBufLenNew > FltBufLen )
232  {
233  delete[] FltBuf;
234  FltBufLen = FltBufLenNew;
235  FltBuf = new float[ FltBufLen ];
236  }
237 
238  // Perform horizontal resizing.
239 
240  const T* ips = SrcBuf;
241  float* op = FltBuf;
242  int i;
243 
244  if( ElCount == 3 )
245  {
246  for( i = 0; i < SrcHeight; i++ )
247  {
248  copyScanline3h( ips, rsh, SrcWidth );
249  resize3( op, NewWidth, rsh.pos, rfh.KernelLen );
250  ips += SrcScanlineSize;
251  op += NewWidthE;
252  }
253  }
254  else
255  if( ElCount == 1 )
256  {
257  for( i = 0; i < SrcHeight; i++ )
258  {
259  copyScanline1h( ips, rsh, SrcWidth );
260  resize1( op, NewWidth, rsh.pos, rfh.KernelLen );
261  ips += SrcScanlineSize;
262  op += NewWidthE;
263  }
264  }
265  else
266  if( ElCount == 4 )
267  {
268  for( i = 0; i < SrcHeight; i++ )
269  {
270  copyScanline4h( ips, rsh, SrcWidth );
271  resize4( op, NewWidth, rsh.pos, rfh.KernelLen );
272  ips += SrcScanlineSize;
273  op += NewWidthE;
274  }
275  }
276  else
277  if( ElCount == 2 )
278  {
279  for( i = 0; i < SrcHeight; i++ )
280  {
281  copyScanline2h( ips, rsh, SrcWidth );
282  resize2( op, NewWidth, rsh.pos, rfh.KernelLen );
283  ips += SrcScanlineSize;
284  op += NewWidthE;
285  }
286  }
287 
288  // Perform vertical resizing.
289 
290  const int spvlennew = NewHeight * ElCount;
291 
292  if( spvlennew > spvlen )
293  {
294  delete[] spv;
295  spvlen = spvlennew;
296  spv = new float[ spvlen ];
297  }
298 
299  const bool IsIOFloat = ( (T) 0.25 != 0 );
300  const int Clamp = ( sizeof( T ) == 1 ? 255 : 65535 );
301  const float* ip = FltBuf;
302  T* opd = NewBuf;
303 
304  if( ElCount == 3 )
305  {
306  for( i = 0; i < NewWidth; i++ )
307  {
308  copyScanline3v( ip, rsv, SrcHeight, NewWidthE );
309  resize3( spv, NewHeight, rsv.pos, rfv -> KernelLen );
310  copyOutput3( spv, opd, NewHeight, NewWidthE, IsIOFloat,
311  Clamp );
312 
313  ip += 3;
314  opd += 3;
315  }
316  }
317  else
318  if( ElCount == 1 )
319  {
320  for( i = 0; i < NewWidth; i++ )
321  {
322  copyScanline1v( ip, rsv, SrcHeight, NewWidthE );
323  resize1( spv, NewHeight, rsv.pos, rfv -> KernelLen );
324  copyOutput1( spv, opd, NewHeight, NewWidthE, IsIOFloat,
325  Clamp );
326 
327  ip++;
328  opd++;
329  }
330  }
331  else
332  if( ElCount == 4 )
333  {
334  for( i = 0; i < NewWidth; i++ )
335  {
336  copyScanline4v( ip, rsv, SrcHeight, NewWidthE );
337  resize4( spv, NewHeight, rsv.pos, rfv -> KernelLen );
338  copyOutput4( spv, opd, NewHeight, NewWidthE, IsIOFloat,
339  Clamp );
340 
341  ip += 4;
342  opd += 4;
343  }
344  }
345  else
346  if( ElCount == 2 )
347  {
348  for( i = 0; i < NewWidth; i++ )
349  {
350  copyScanline2v( ip, rsv, SrcHeight, NewWidthE );
351  resize2( spv, NewHeight, rsv.pos, rfv -> KernelLen );
352  copyOutput2( spv, opd, NewHeight, NewWidthE, IsIOFloat,
353  Clamp );
354 
355  ip += 2;
356  opd += 2;
357  }
358  }
359  }
360 
361 protected:
362  float* FltBuf;
363  size_t FltBufLen;
365  float* spv;
367  int spvlen;
369 
378  static int roundclamp( const float v, const int Clamp )
379  {
380  if( v <= 0.0f )
381  {
382  return( 0 );
383  }
384 
385  const int vr = (int) ( v + 0.5f );
386 
387  if( vr > Clamp )
388  {
389  return( Clamp );
390  }
391 
392  return( vr );
393  }
394 
407  template< class T >
408  static void copyOutput1( const float* ip, T* op, int l, const int opinc,
409  const bool IsIOFloat, const int Clamp )
410  {
411  if( IsIOFloat )
412  {
413  while( l > 0 )
414  {
415  op[ 0 ] = (T) ip[ 0 ];
416  ip++;
417  op += opinc;
418  l--;
419  }
420  }
421  else
422  {
423  while( l > 0 )
424  {
425  op[ 0 ] = (T) roundclamp( ip[ 0 ], Clamp );
426  ip++;
427  op += opinc;
428  l--;
429  }
430  }
431  }
432 
433  template< class T >
434  static void copyOutput2( const float* ip, T* op, int l, const int opinc,
435  const bool IsIOFloat, const int Clamp )
436  {
437  if( IsIOFloat )
438  {
439  while( l > 0 )
440  {
441  op[ 0 ] = (T) ip[ 0 ];
442  op[ 1 ] = (T) ip[ 1 ];
443  ip += 2;
444  op += opinc;
445  l--;
446  }
447  }
448  else
449  {
450  while( l > 0 )
451  {
452  op[ 0 ] = (T) roundclamp( ip[ 0 ], Clamp );
453  op[ 1 ] = (T) roundclamp( ip[ 1 ], Clamp );
454  ip += 2;
455  op += opinc;
456  l--;
457  }
458  }
459  }
460 
461  template< class T >
462  static void copyOutput3( const float* ip, T* op, int l, const int opinc,
463  const bool IsIOFloat, const int Clamp )
464  {
465  if( IsIOFloat )
466  {
467  while( l > 0 )
468  {
469  op[ 0 ] = (T) ip[ 0 ];
470  op[ 1 ] = (T) ip[ 1 ];
471  op[ 2 ] = (T) ip[ 2 ];
472  ip += 3;
473  op += opinc;
474  l--;
475  }
476  }
477  else
478  {
479  while( l > 0 )
480  {
481  op[ 0 ] = (T) roundclamp( ip[ 0 ], Clamp );
482  op[ 1 ] = (T) roundclamp( ip[ 1 ], Clamp );
483  op[ 2 ] = (T) roundclamp( ip[ 2 ], Clamp );
484  ip += 3;
485  op += opinc;
486  l--;
487  }
488  }
489  }
490 
491  template< class T >
492  static void copyOutput4( const float* ip, T* op, int l, const int opinc,
493  const bool IsIOFloat, const int Clamp )
494  {
495  if( IsIOFloat )
496  {
497  while( l > 0 )
498  {
499  op[ 0 ] = (T) ip[ 0 ];
500  op[ 1 ] = (T) ip[ 1 ];
501  op[ 2 ] = (T) ip[ 2 ];
502  op[ 3 ] = (T) ip[ 3 ];
503  ip += 4;
504  op += opinc;
505  l--;
506  }
507  }
508  else
509  {
510  while( l > 0 )
511  {
512  op[ 0 ] = (T) roundclamp( ip[ 0 ], Clamp );
513  op[ 1 ] = (T) roundclamp( ip[ 1 ], Clamp );
514  op[ 2 ] = (T) roundclamp( ip[ 2 ], Clamp );
515  op[ 3 ] = (T) roundclamp( ip[ 3 ], Clamp );
516  ip += 4;
517  op += opinc;
518  l--;
519  }
520  }
521  }
522 
523  class CResizeScanline;
524 
530  {
531  friend class CResizeScanline;
532 
533  public:
534  int KernelLen;
535 
539  : FilterBuf( NULL )
540  , Filters( NULL )
541  , Prevla( -1.0 )
542  , Prevk( -1.0 )
543  , FilterBufLen( 0 )
544  , FiltersLen( 0 )
545  {
546  }
547 
548  ~CResizeFilters()
549  {
550  delete[] FilterBuf;
551  delete[] Filters;
552  }
553 
563  bool update( const double la, const double k )
564  {
565  if( la == Prevla && k == Prevk )
566  {
567  return( false );
568  }
569 
570  Prevla = la;
571  Prevk = k;
572 
573  NormFreq = ( k <= 1.0 ? 1.0 : 1.0 / k );
574  Freq = LANCIR_PI * NormFreq;
575  FreqA = LANCIR_PI * NormFreq / la;
576 
577  Len2 = la / NormFreq;
578  fl2 = (int) ceil( Len2 );
579  KernelLen = fl2 + fl2;
580 
581  FracCount = 607; // For 8-bit precision.
582  FracFill = 0;
583 
584  const int FilterBufLenNew = ( FracCount + 1 ) * KernelLen;
585  // Add +1 to cover rare cases of fractional delay == 1.
586 
587  if( FilterBufLenNew > FilterBufLen )
588  {
589  delete[] FilterBuf;
590  FilterBufLen = FilterBufLenNew;
591  FilterBuf = new float[ FilterBufLen ];
592  }
593 
594  if( FracCount > FiltersLen )
595  {
596  delete[] Filters;
598  Filters = new float*[ FiltersLen + 1 ];
599  }
600 
601  memset( Filters, 0, ( FiltersLen + 1 ) * sizeof( float* ));
602 
603  return( true );
604  }
605 
614  float* getFilter( const double x )
615  {
616  const int Frac = (int) floor( x * FracCount );
617 
618  if( Filters[ Frac ] == NULL )
619  {
620  Filters[ Frac ] = FilterBuf + FracFill * KernelLen;
621  FracFill++;
622  makeFilter( 1.0 - (double) Frac / FracCount, Filters[ Frac ]);
623  normalizeFilter( Filters[ Frac ]);
624  }
625 
626  return( Filters[ Frac ]);
627  }
628 
629  protected:
630  double NormFreq;
631  double Freq;
633  double FreqA;
635  double Len2;
637  int fl2;
639  int FracCount;
641  int FracFill;
644  float* FilterBuf;
647  float** Filters;
649  double Prevla;
652  double Prevk;
654  int FilterBufLen;
656  int FiltersLen;
658 
668  class CSinGen
669  {
670  public:
680  CSinGen( const double si, const double ph, const double g = 1.0 )
681  : svalue1( sin( ph ) * g )
682  , svalue2( sin( ph - si ) * g )
683  , sincr( 2.0 * cos( si ))
684  {
685  }
686 
691  double generate()
692  {
693  const double res = svalue1;
694 
695  svalue1 = sincr * res - svalue2;
696  svalue2 = res;
697 
698  return( res );
699  }
700 
701  private:
702  double svalue1;
703  double svalue2;
705  double sincr;
707  };
709 
721  template< class T >
722  void makeFilter( const double FracDelay, T* op ) const
723  {
724  CSinGen f( Freq, Freq * ( FracDelay - fl2 ));
725  CSinGen fw( FreqA, FreqA * ( FracDelay - fl2 ), Len2 );
726 
727  int t = -fl2;
728 
729  if( t + FracDelay < -Len2 )
730  {
731  f.generate();
732  fw.generate();
733  *op = (T) 0.0;
734  op++;
735  t++;
736  }
737 
738  int mt = ( FracDelay >= 1.0 - 1e-13 && FracDelay <= 1.0 + 1e-13 ?
739  -1 : 0 );
740 
741  while( t < mt )
742  {
743  double ut = t + FracDelay;
744  *op = (T) ( f.generate() * fw.generate() / ( ut * ut ));
745  op++;
746  t++;
747  }
748 
749  double ut = t + FracDelay;
750 
751  if( fabs( ut ) <= 1e-13 )
752  {
753  *op = (T) ( NormFreq * ( LANCIR_PI * LANCIR_PI ));
754  f.generate();
755  fw.generate();
756  }
757  else
758  {
759  *op = (T) ( f.generate() * fw.generate() / ( ut * ut ));
760  }
761 
762  mt = fl2 - 2;
763 
764  while( t < mt )
765  {
766  op++;
767  t++;
768  ut = t + FracDelay;
769  *op = (T) ( f.generate() * fw.generate() / ( ut * ut ));
770  }
771 
772  op++;
773  t++;
774  ut = t + FracDelay;
775 
776  if( ut > Len2 )
777  {
778  *op = (T) 0.0;
779  }
780  else
781  {
782  *op = (T) ( f.generate() * fw.generate() / ( ut * ut ));
783  }
784  }
785 
794  template< class T >
795  void normalizeFilter( T* const p ) const
796  {
797  double s = 0.0;
798  int i;
799 
800  for( i = 0; i < KernelLen; i++ )
801  {
802  s += p[ i ];
803  }
804 
805  s = 1.0 / s;
806 
807  for( i = 0; i < KernelLen; i++ )
808  {
809  p[ i ] = (T) ( p[ i ] * s );
810  }
811  }
812  };
813 
819  struct CResizePos
820  {
821  const float* ip;
822  float* flt;
824  };
826 
833  {
834  public:
835  int padl;
836  int padr;
839  float* sp;
842  CResizePos* pos;
845 
850  : sp( NULL )
851  , pos( NULL )
852  , PrevSrcLen( -1 )
853  , PrevDstLen( -1 )
854  , Prevk( 0.0 )
855  , Prevo( 0.0 )
856  , PrevElCount( 0 )
857  , splen( 0 )
858  , poslen( 0 )
859  {
860  }
861 
862  ~CResizeScanline()
863  {
864  delete[] sp;
865  delete[] pos;
866  }
867 
874  void reset()
875  {
876  PrevSrcLen = -1;
877  }
878 
891  void update( const double k, const double o0, const int ElCount,
892  const int SrcLen, const int DstLen, CResizeFilters& rf )
893  {
894  if( SrcLen == PrevSrcLen && DstLen == PrevDstLen &&
895  k == Prevk && o0 == Prevo && ElCount == PrevElCount )
896  {
897  return;
898  }
899 
900  PrevSrcLen = SrcLen;
901  PrevDstLen = DstLen;
902  Prevk = k;
903  Prevo = o0;
904  PrevElCount = ElCount;
905 
906  const int fl2m1 = rf.fl2 - 1;
907  padl = fl2m1 - (int) floor( o0 );
908 
909  if( padl < 0 )
910  {
911  padl = 0;
912  }
913 
914  padr = (int) floor( o0 + k * ( DstLen - 1 )) + rf.fl2 + 1 -
915  SrcLen;
916 
917  if( padr < 0 )
918  {
919  padr = 0;
920  }
921 
922  const int splennew = ( padl + SrcLen + padr ) * ElCount;
923 
924  if( splennew > splen )
925  {
926  delete[] sp;
927  splen = splennew;
928  sp = new float[ splen ];
929  }
930 
931  if( DstLen > poslen )
932  {
933  delete[] pos;
934  poslen = DstLen;
935  pos = new CResizePos[ poslen ];
936  }
937 
938  const float* const spo = sp + ( padl - fl2m1 ) * ElCount;
939  int i;
940 
941  for( i = 0; i < DstLen; i++ )
942  {
943  const double o = o0 + k * i;
944  const int ix = (int) floor( o );
945  pos[ i ].ip = spo + ix * ElCount;
946  pos[ i ].flt = rf.getFilter( o - ix );
947  }
948  }
949 
950  protected:
952  int PrevDstLen;
954  double Prevk;
956  double Prevo;
958  int PrevElCount;
960  int splen;
962  int poslen;
964  };
966 
975 
988  template< class T >
989  static void copyScanline1h( const T* ip, CResizeScanline& rs, const int l )
990  {
991  float* op = rs.sp;
992  int i;
993 
994  for( i = 0; i < rs.padl; i++ )
995  {
996  op[ 0 ] = ip[ 0 ];
997  op++;
998  }
999 
1000  for( i = 0; i < l - 1; i++ )
1001  {
1002  op[ 0 ] = ip[ 0 ];
1003  ip++;
1004  op++;
1005  }
1006 
1007  for( i = 0; i <= rs.padr; i++ )
1008  {
1009  op[ 0 ] = ip[ 0 ];
1010  op++;
1011  }
1012  }
1013 
1014  template< class T >
1015  static void copyScanline2h( const T* ip, CResizeScanline& rs, const int l )
1016  {
1017  float* op = rs.sp;
1018  int i;
1019 
1020  for( i = 0; i < rs.padl; i++ )
1021  {
1022  op[ 0 ] = ip[ 0 ];
1023  op[ 1 ] = ip[ 1 ];
1024  op += 2;
1025  }
1026 
1027  for( i = 0; i < l - 1; i++ )
1028  {
1029  op[ 0 ] = ip[ 0 ];
1030  op[ 1 ] = ip[ 1 ];
1031  ip += 2;
1032  op += 2;
1033  }
1034 
1035  for( i = 0; i <= rs.padr; i++ )
1036  {
1037  op[ 0 ] = ip[ 0 ];
1038  op[ 1 ] = ip[ 1 ];
1039  op += 2;
1040  }
1041  }
1042 
1043  template< class T >
1044  static void copyScanline3h( const T* ip, CResizeScanline& rs, const int l )
1045  {
1046  float* op = rs.sp;
1047  int i;
1048 
1049  for( i = 0; i < rs.padl; i++ )
1050  {
1051  op[ 0 ] = ip[ 0 ];
1052  op[ 1 ] = ip[ 1 ];
1053  op[ 2 ] = ip[ 2 ];
1054  op += 3;
1055  }
1056 
1057  for( i = 0; i < l - 1; i++ )
1058  {
1059  op[ 0 ] = ip[ 0 ];
1060  op[ 1 ] = ip[ 1 ];
1061  op[ 2 ] = ip[ 2 ];
1062  ip += 3;
1063  op += 3;
1064  }
1065 
1066  for( i = 0; i <= rs.padr; i++ )
1067  {
1068  op[ 0 ] = ip[ 0 ];
1069  op[ 1 ] = ip[ 1 ];
1070  op[ 2 ] = ip[ 2 ];
1071  op += 3;
1072  }
1073  }
1074 
1075  template< class T >
1076  static void copyScanline4h( const T* ip, CResizeScanline& rs, const int l )
1077  {
1078  float* op = rs.sp;
1079  int i;
1080 
1081  for( i = 0; i < rs.padl; i++ )
1082  {
1083  op[ 0 ] = ip[ 0 ];
1084  op[ 1 ] = ip[ 1 ];
1085  op[ 2 ] = ip[ 2 ];
1086  op[ 3 ] = ip[ 3 ];
1087  op += 4;
1088  }
1089 
1090  for( i = 0; i < l - 1; i++ )
1091  {
1092  op[ 0 ] = ip[ 0 ];
1093  op[ 1 ] = ip[ 1 ];
1094  op[ 2 ] = ip[ 2 ];
1095  op[ 3 ] = ip[ 3 ];
1096  ip += 4;
1097  op += 4;
1098  }
1099 
1100  for( i = 0; i <= rs.padr; i++ )
1101  {
1102  op[ 0 ] = ip[ 0 ];
1103  op[ 1 ] = ip[ 1 ];
1104  op[ 2 ] = ip[ 2 ];
1105  op[ 3 ] = ip[ 3 ];
1106  op += 4;
1107  }
1108  }
1109 
1121  template< class T >
1122  static void copyScanline1v( const T* ip, CResizeScanline& rs, const int l,
1123  const int ipinc )
1124  {
1125  float* op = rs.sp;
1126  int i;
1127 
1128  for( i = 0; i < rs.padl; i++ )
1129  {
1130  op[ 0 ] = ip[ 0 ];
1131  op++;
1132  }
1133 
1134  for( i = 0; i < l - 1; i++ )
1135  {
1136  op[ 0 ] = ip[ 0 ];
1137  ip += ipinc;
1138  op++;
1139  }
1140 
1141  for( i = 0; i <= rs.padr; i++ )
1142  {
1143  op[ 0 ] = ip[ 0 ];
1144  op++;
1145  }
1146  }
1147 
1148  template< class T >
1149  static void copyScanline2v( const T* ip, CResizeScanline& rs, const int l,
1150  const int ipinc )
1151  {
1152  float* op = rs.sp;
1153  int i;
1154 
1155  for( i = 0; i < rs.padl; i++ )
1156  {
1157  op[ 0 ] = ip[ 0 ];
1158  op[ 1 ] = ip[ 1 ];
1159  op += 2;
1160  }
1161 
1162  for( i = 0; i < l - 1; i++ )
1163  {
1164  op[ 0 ] = ip[ 0 ];
1165  op[ 1 ] = ip[ 1 ];
1166  ip += ipinc;
1167  op += 2;
1168  }
1169 
1170  for( i = 0; i <= rs.padr; i++ )
1171  {
1172  op[ 0 ] = ip[ 0 ];
1173  op[ 1 ] = ip[ 1 ];
1174  op += 2;
1175  }
1176  }
1177 
1178  template< class T >
1179  static void copyScanline3v( const T* ip, CResizeScanline& rs, const int l,
1180  const int ipinc )
1181  {
1182  float* op = rs.sp;
1183  int i;
1184 
1185  for( i = 0; i < rs.padl; i++ )
1186  {
1187  op[ 0 ] = ip[ 0 ];
1188  op[ 1 ] = ip[ 1 ];
1189  op[ 2 ] = ip[ 2 ];
1190  op += 3;
1191  }
1192 
1193  for( i = 0; i < l - 1; i++ )
1194  {
1195  op[ 0 ] = ip[ 0 ];
1196  op[ 1 ] = ip[ 1 ];
1197  op[ 2 ] = ip[ 2 ];
1198  ip += ipinc;
1199  op += 3;
1200  }
1201 
1202  for( i = 0; i <= rs.padr; i++ )
1203  {
1204  op[ 0 ] = ip[ 0 ];
1205  op[ 1 ] = ip[ 1 ];
1206  op[ 2 ] = ip[ 2 ];
1207  op += 3;
1208  }
1209  }
1210 
1211  template< class T >
1212  static void copyScanline4v( const T* ip, CResizeScanline& rs, const int l,
1213  const int ipinc )
1214  {
1215  float* op = rs.sp;
1216  int i;
1217 
1218  for( i = 0; i < rs.padl; i++ )
1219  {
1220  op[ 0 ] = ip[ 0 ];
1221  op[ 1 ] = ip[ 1 ];
1222  op[ 2 ] = ip[ 2 ];
1223  op[ 3 ] = ip[ 3 ];
1224  op += 4;
1225  }
1226 
1227  for( i = 0; i < l - 1; i++ )
1228  {
1229  op[ 0 ] = ip[ 0 ];
1230  op[ 1 ] = ip[ 1 ];
1231  op[ 2 ] = ip[ 2 ];
1232  op[ 3 ] = ip[ 3 ];
1233  ip += ipinc;
1234  op += 4;
1235  }
1236 
1237  for( i = 0; i <= rs.padr; i++ )
1238  {
1239  op[ 0 ] = ip[ 0 ];
1240  op[ 1 ] = ip[ 1 ];
1241  op[ 2 ] = ip[ 2 ];
1242  op[ 3 ] = ip[ 3 ];
1243  op += 4;
1244  }
1245  }
1246 
1247  #define LANCIR_LF_PRE \
1248  CResizePos* const rpe = rp + DstLen; \
1249  while( rp < rpe ) \
1250  { \
1251  const float* ip = rp -> ip; \
1252  const float* const flt = rp -> flt;
1253 
1254  #define LANCIR_LF_POST \
1255  rp++; \
1256  }
1257 
1268  static void resize1( float* op, int DstLen, CResizePos* rp, const int kl )
1269  {
1270  if( kl == 6 )
1271  {
1272  LANCIR_LF_PRE
1273  op[ 0 ] =
1274  flt[ 0 ] * ip[ 0 ] +
1275  flt[ 1 ] * ip[ 1 ] +
1276  flt[ 2 ] * ip[ 2 ] +
1277  flt[ 3 ] * ip[ 3 ] +
1278  flt[ 4 ] * ip[ 4 ] +
1279  flt[ 5 ] * ip[ 5 ];
1280 
1281  op++;
1282  LANCIR_LF_POST
1283  }
1284  else
1285  {
1286  LANCIR_LF_PRE
1287  float sum = 0.0;
1288  int i;
1289 
1290  for( i = 0; i < kl; i++ )
1291  {
1292  sum += flt[ i ] * ip[ i ];
1293  }
1294 
1295  op[ 0 ] = sum;
1296  op++;
1297  LANCIR_LF_POST
1298  }
1299  }
1300 
1301  static void resize2( float* op, int DstLen, CResizePos* rp, const int kl )
1302  {
1303  if( kl == 6 )
1304  {
1305  LANCIR_LF_PRE
1306  op[ 0 ] =
1307  flt[ 0 ] * ip[ 0 ] +
1308  flt[ 1 ] * ip[ 2 ] +
1309  flt[ 2 ] * ip[ 4 ] +
1310  flt[ 3 ] * ip[ 6 ] +
1311  flt[ 4 ] * ip[ 8 ] +
1312  flt[ 5 ] * ip[ 10 ];
1313 
1314  op[ 1 ] =
1315  flt[ 0 ] * ip[ 1 ] +
1316  flt[ 1 ] * ip[ 3 ] +
1317  flt[ 2 ] * ip[ 5 ] +
1318  flt[ 3 ] * ip[ 7 ] +
1319  flt[ 4 ] * ip[ 9 ] +
1320  flt[ 5 ] * ip[ 11 ];
1321 
1322  op += 2;
1323  LANCIR_LF_POST
1324  }
1325  else
1326  {
1327  LANCIR_LF_PRE
1328  float sum[ 2 ];
1329  sum[ 0 ] = 0.0;
1330  sum[ 1 ] = 0.0;
1331  int i;
1332 
1333  for( i = 0; i < kl; i++ )
1334  {
1335  const float xx = flt[ i ];
1336  sum[ 0 ] += xx * ip[ 0 ];
1337  sum[ 1 ] += xx * ip[ 1 ];
1338  ip += 2;
1339  }
1340 
1341  op[ 0 ] = sum[ 0 ];
1342  op[ 1 ] = sum[ 1 ];
1343  op += 2;
1344  LANCIR_LF_POST
1345  }
1346  }
1347 
1348  static void resize3( float* op, int DstLen, CResizePos* rp, const int kl )
1349  {
1350  if( kl == 6 )
1351  {
1352  LANCIR_LF_PRE
1353  op[ 0 ] =
1354  flt[ 0 ] * ip[ 0 ] +
1355  flt[ 1 ] * ip[ 3 ] +
1356  flt[ 2 ] * ip[ 6 ] +
1357  flt[ 3 ] * ip[ 9 ] +
1358  flt[ 4 ] * ip[ 12 ] +
1359  flt[ 5 ] * ip[ 15 ];
1360 
1361  op[ 1 ] =
1362  flt[ 0 ] * ip[ 1 ] +
1363  flt[ 1 ] * ip[ 4 ] +
1364  flt[ 2 ] * ip[ 7 ] +
1365  flt[ 3 ] * ip[ 10 ] +
1366  flt[ 4 ] * ip[ 13 ] +
1367  flt[ 5 ] * ip[ 16 ];
1368 
1369  op[ 2 ] =
1370  flt[ 0 ] * ip[ 2 ] +
1371  flt[ 1 ] * ip[ 5 ] +
1372  flt[ 2 ] * ip[ 8 ] +
1373  flt[ 3 ] * ip[ 11 ] +
1374  flt[ 4 ] * ip[ 14 ] +
1375  flt[ 5 ] * ip[ 17 ];
1376 
1377  op += 3;
1378  LANCIR_LF_POST
1379  }
1380  else
1381  {
1382  LANCIR_LF_PRE
1383  float sum[ 3 ];
1384  sum[ 0 ] = 0.0;
1385  sum[ 1 ] = 0.0;
1386  sum[ 2 ] = 0.0;
1387  int i;
1388 
1389  for( i = 0; i < kl; i++ )
1390  {
1391  const float xx = flt[ i ];
1392  sum[ 0 ] += xx * ip[ 0 ];
1393  sum[ 1 ] += xx * ip[ 1 ];
1394  sum[ 2 ] += xx * ip[ 2 ];
1395  ip += 3;
1396  }
1397 
1398  op[ 0 ] = sum[ 0 ];
1399  op[ 1 ] = sum[ 1 ];
1400  op[ 2 ] = sum[ 2 ];
1401  op += 3;
1402  LANCIR_LF_POST
1403  }
1404  }
1405 
1406  static void resize4( float* op, int DstLen, CResizePos* rp, const int kl )
1407  {
1408  LANCIR_LF_PRE
1409  float sum[ 4 ];
1410  sum[ 0 ] = 0.0;
1411  sum[ 1 ] = 0.0;
1412  sum[ 2 ] = 0.0;
1413  sum[ 3 ] = 0.0;
1414  int i;
1415 
1416  for( i = 0; i < kl; i++ )
1417  {
1418  const float xx = flt[ i ];
1419  sum[ 0 ] += xx * ip[ 0 ];
1420  sum[ 1 ] += xx * ip[ 1 ];
1421  sum[ 2 ] += xx * ip[ 2 ];
1422  sum[ 3 ] += xx * ip[ 3 ];
1423  ip += 4;
1424  }
1425 
1426  op[ 0 ] = sum[ 0 ];
1427  op[ 1 ] = sum[ 1 ];
1428  op[ 2 ] = sum[ 2 ];
1429  op[ 3 ] = sum[ 3 ];
1430  op += 4;
1431  LANCIR_LF_POST
1432  }
1433 
1434  #undef LANCIR_LF_PRE
1435  #undef LANCIR_LF_POST
1436 };
1437 
1438 #undef LANCIR_PI
1439 
1440 } // namespace avir
1441 
1442 #endif // AVIR_CLANCIR_INCLUDED
LANCIR image resizer class.
Definition: lancir.h:77
static void resize1(float *op, int DstLen, CResizePos *rp, const int kl)
Definition: lancir.h:1268
CResizeScanline rsh
Definition: lancir.h:972
#define LANCIR_PI
Definition: lancir.h:58
static int roundclamp(const float v, const int Clamp)
Definition: lancir.h:378
float * FltBuf
Definition: lancir.h:362
double Prevk
Definition: lancir.h:955
const float * ip
Definition: lancir.h:821
int splen
Definition: lancir.h:961
int spvlen
Definition: lancir.h:368
double FreqA
Definition: lancir.h:634
void makeFilter(const double FracDelay, T *op) const
Definition: lancir.h:722
int FilterBufLen
Definition: lancir.h:655
CSinGen(const double si, const double ph, const double g=1.0)
Definition: lancir.h:680
static void copyOutput1(const float *ip, T *op, int l, const int opinc, const bool IsIOFloat, const int Clamp)
Definition: lancir.h:408
int PrevElCount
Definition: lancir.h:959
double generate()
Definition: lancir.h:691
CResizeScanline rsv
Definition: lancir.h:974
float * FilterBuf
Definition: lancir.h:646
Definition: lancir.h:819
void normalizeFilter(T *const p) const
Definition: lancir.h:795
double Freq
Definition: lancir.h:632
int PrevSrcLen
Definition: lancir.h:951
int KernelLen
Definition: lancir.h:534
int poslen
Definition: lancir.h:963
int FiltersLen
Definition: lancir.h:657
Sine signal generator class.
Definition: lancir.h:668
CResizeFilters rfh
Definition: lancir.h:967
float * getFilter(const double x)
Definition: lancir.h:614
size_t FltBufLen
Definition: lancir.h:364
double Prevo
Definition: lancir.h:957
int FracCount
Definition: lancir.h:640
static void copyScanline1v(const T *ip, CResizeScanline &rs, const int l, const int ipinc)
Definition: lancir.h:1122
float * flt
Definition: lancir.h:823
Definition: lancir.h:529
float ** Filters
Definition: lancir.h:648
static void copyScanline1h(const T *ip, CResizeScanline &rs, const int l)
Definition: lancir.h:989
double Len2
Definition: lancir.h:636
void resizeImage(const T *const SrcBuf, const int SrcWidth, const int SrcHeight, int SrcScanlineSize, T *const NewBuf, const int NewWidth, const int NewHeight, const int ElCount, const double kx0=0.0, const double ky0=0.0, double ox=0.0, double oy=0.0)
Definition: lancir.h:139
void reset()
Definition: lancir.h:874
int PrevDstLen
Definition: lancir.h:953
double Prevla
Definition: lancir.h:651
CResizePos * pos
Definition: lancir.h:844
int FracFill
Definition: lancir.h:643
float * sp
Definition: lancir.h:841
double Prevk
Definition: lancir.h:653
int padr
Definition: lancir.h:838
Definition: lancir.h:832
int fl2
Definition: lancir.h:638
float * spv
Definition: lancir.h:366
bool update(const double la, const double k)
Definition: lancir.h:563
int padl
Definition: lancir.h:835
void update(const double k, const double o0, const int ElCount, const int SrcLen, const int DstLen, CResizeFilters &rf)
Definition: lancir.h:891
CResizeFilters rfv0
Definition: lancir.h:969
double NormFreq
Definition: lancir.h:630