2727
2828template <typename T>
2929inline T CubicBSpline (T t) {
30- T absX = std:: abs (t);
30+ T absX = abs (t);
3131 if (absX <= 1.0 ) {
32- return (2.0 / 3.0 ) - (absX * absX) + (0.5 * absX * absX * absX);
32+ return T (2.0 / 3.0 ) - (absX * absX) + (T ( 0.5 ) * absX * absX * absX);
3333 } else if (absX <= 2.0 ) {
34- return ((2.0 - absX) * (2.0 - absX) * (2.0 - absX)) / 6.0 ;
34+ return ((T ( 2.0 ) - absX) * (T ( 2.0 ) - absX) * (T ( 2.0 ) - absX)) / T ( 6.0 ) ;
3535 } else {
36- return 0.0 ;
36+ return T ( 0.0 ) ;
3737 }
3838}
3939
40- inline half FilterMitchell (half t) {
41- half x = abs (t);
40+ template <typename T>
41+ inline T FilterMitchell (T t) {
42+ T x = abs (t);
4243
4344 if (x < 1 .0f )
44- return (half (16 ) + x*x*(half (21 ) * x - half (36 )))/half (18 );
45+ return (T (16 ) + x*x*(T (21 ) * x - T (36 )))/T (18 );
4546 else if (x < 2 .0f )
46- return (half (32 ) + x*(half (-60 ) + x*(half (36 ) - half (7 )*x)))/half (18 );
47+ return (T (32 ) + x*(T (-60 ) + x*(T (36 ) - T (7 )*x)))/T (18 );
4748
48- return half (0 .0f );
49+ return T (0 .0f );
4950}
5051
51- inline half CubicBSpline (half t) {
52- half absX = abs (t);
53- if (absX <= 1.0 ) {
54- return half (2.0 / 3.0 ) - (absX * absX) + (half (0.5 ) * absX * absX * absX);
55- } else if (absX <= 2.0 ) {
56- return ((half (2.0 ) - absX) * (half (2.0 ) - absX) * (half (2.0 ) - absX)) / half (6.0 );
52+ template <typename T>
53+ T sinc (T x) {
54+ if (x == 0.0 ) {
55+ return T (1.0 );
5756 } else {
58- return half ( 0.0 );
57+ return sin ( T (M_PI) * x) / ( T (M_PI) * x );
5958 }
6059}
6160
61+ template <typename T>
62+ inline T lanczosWindow (T x, T a) {
63+ if (x == 0.0 ) {
64+ return T (1.0 );
65+ }
66+ if (abs (x) < a) {
67+ return a * sin (T (M_PI) * x) * sin (T (M_PI) * x / a) / (T (M_PI) * T (M_PI) * x * x);
68+ }
69+ return T (0.0 );
70+ }
71+
6272void scaleImageFloat16 (uint16_t * input,
6373 int srcStride,
6474 int inputWidth, int inputHeight,
@@ -153,6 +163,32 @@ void scaleImageFloat16(uint16_t* input,
153163 }
154164 }
155165
166+ for (int c = 0 ; c < components; ++c) {
167+ dst16[x*components + c] = rgb[c].data_ ;
168+ }
169+ } else if (option == lanczos) {
170+ half rgb[components];
171+
172+ int a = 3 ;
173+ float lanczosFA = float (3 .0f );
174+
175+ for (int j = -a + 1 ; j <= a; j++) {
176+ for (int i = -a + 1 ; i <= a; i++) {
177+ int xi = x1 + i;
178+ int yj = y1 + j;
179+
180+ if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
181+ float weight = lanczosWindow (float (srcX - xi), (float )lanczosFA) * lanczosWindow (float (srcY - yj), (float )lanczosFA);
182+
183+ for (int c = 0 ; c < components; ++c) {
184+ half clrf = castU16 (reinterpret_cast <const uint16_t *>(src8 + yj * srcStride)[xi*components + c]);
185+ half clr = half ((float )clrf * weight);
186+ rgb[c] += clr;
187+ }
188+ }
189+ }
190+ }
191+
156192 for (int c = 0 ; c < components; ++c) {
157193 dst16[x*components + c] = rgb[c].data_ ;
158194 }
@@ -253,9 +289,6 @@ void scaleImageU16(uint16_t* input,
253289 dst16[x*components + c] = static_cast <uint16_t >(f);
254290 }
255291 } else if (option == mitchell) {
256- half dx = half (srcX - x);
257- half dy = half (srcY - y);
258-
259292 half rgb[components];
260293
261294 for (int j = -1 ; j <= 2 ; j++) {
@@ -268,7 +301,7 @@ void scaleImageU16(uint16_t* input,
268301
269302 for (int c = 0 ; c < components; ++c) {
270303 uint16_t p = reinterpret_cast <const uint16_t *>(src8 + yj * srcStride)[xi*components + c];
271- half clrf (p / maxColors);
304+ half clrf (( float ) p / maxColors);
272305 half clr = clrf * weight;
273306 rgb[c] += clr;
274307 }
@@ -282,7 +315,36 @@ void scaleImageU16(uint16_t* input,
282315 f = std::clamp (f, 0 .0f , maxColors);
283316 dst16[x*components + c] = static_cast <uint16_t >(f);
284317 }
285- } else {
318+ } else if (option == lanczos) {
319+ half rgb[components];
320+
321+ int a = 3 ;
322+ float lanczosKernel = 3.0 ;
323+
324+ for (int j = -a + 1 ; j <= a; j++) {
325+ for (int i = -a + 1 ; i <= a; i++) {
326+ int xi = x1 + i;
327+ int yj = y1 + j;
328+
329+ if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
330+ float weight = lanczosWindow (float (srcX - xi), lanczosKernel) * lanczosWindow (float (srcY - yj), lanczosKernel);
331+
332+ for (int c = 0 ; c < components; ++c) {
333+ uint16_t p = reinterpret_cast <const uint16_t *>(src8 + yj * srcStride)[xi*components + c];
334+ half clrf ((float )p / maxColors * weight);
335+ rgb[c] += clrf;
336+ }
337+ }
338+ }
339+ }
340+
341+ for (int c = 0 ; c < components; ++c) {
342+ float cc = rgb[c];
343+ float f = cc * maxColors;
344+ f = std::clamp (f, 0 .0f , maxColors);
345+ dst16[x*components + c] = static_cast <uint16_t >(f);
346+ }
347+ } else {
286348 for (int c = 0 ; c < components; ++c) {
287349 dst16[x*components + c] = reinterpret_cast <const uint16_t *>(src8 + y1 * srcStride)[x1*components + c];
288350 }
@@ -345,9 +407,6 @@ void scaleImageU8(uint8_t* input,
345407
346408 }
347409 } else if (option == cubic) {
348- half dx = half (srcX - x);
349- half dy = half (srcY - y);
350-
351410 half rgb[components];
352411
353412 for (int j = -1 ; j <= 2 ; j++) {
@@ -375,9 +434,6 @@ void scaleImageU8(uint8_t* input,
375434 dst[x*components + c] = static_cast <uint16_t >(f);
376435 }
377436 } else if (option == mitchell) {
378- half dx = half (srcX - x);
379- half dy = half (srcY - y);
380-
381437 half rgb[components];
382438
383439 for (int j = -1 ; j <= 2 ; j++) {
@@ -390,14 +446,44 @@ void scaleImageU8(uint8_t* input,
390446
391447 for (int c = 0 ; c < components; ++c) {
392448 uint8_t p = reinterpret_cast <const uint8_t *>(src8 + yj * srcStride)[xi*components + c];
393- half clrf (p / maxColors);
449+ half clrf (( float ) p / maxColors);
394450 half clr = clrf * weight;
395451 rgb[c] += clr;
396452 }
397453 }
398454 }
399455 }
400456
457+ for (int c = 0 ; c < components; ++c) {
458+ float cc = rgb[c];
459+ float f = cc * maxColors;
460+ f = std::clamp (f, 0 .0f , maxColors);
461+ dst[x*components + c] = static_cast <uint16_t >(f);
462+ }
463+ } else if (option == lanczos) {
464+ half rgb[components];
465+
466+ float lanczosFA = float (3 .0f );
467+
468+ int a = 3 ;
469+
470+ for (int j = -a + 1 ; j <= a; j++) {
471+ for (int i = -a + 1 ; i <= a; i++) {
472+ int xi = x1 + i;
473+ int yj = y1 + j;
474+
475+ if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
476+ float weight = lanczosWindow (float (srcX - xi), lanczosFA) * lanczosWindow (float (srcY - yj), lanczosFA);
477+
478+ for (int c = 0 ; c < components; ++c) {
479+ uint8_t p = reinterpret_cast <const uint8_t *>(src8 + yj * srcStride)[xi*components + c];
480+ half clrf ((float )p / maxColors * weight);
481+ rgb[c] += clrf;
482+ }
483+ }
484+ }
485+ }
486+
401487 for (int c = 0 ; c < components; ++c) {
402488 float cc = rgb[c];
403489 float f = cc * maxColors;
0 commit comments