1212#include < algorithm>
1313
1414using namespace half_float ;
15+ using namespace std ;
1516
1617inline half_float::half castU16 (uint16_t t) {
1718 half_float::half result;
@@ -69,6 +70,18 @@ inline T lanczosWindow(T x, T a) {
6970 return T (0.0 );
7071}
7172
73+ template <typename T>
74+ inline T CatmullRom (T x) {
75+ x = (float )fabs (x);
76+
77+ if (x < 1 .0f )
78+ return T (1 ) - x*x*(T (2 .5f ) - T (1 .5f )*x);
79+ else if (x < 2 .0f )
80+ return T (2 ) - x*(T (4 ) + x*(T (0 .5f )*x - T (2 .5f )));
81+
82+ return T (0 .0f );
83+ }
84+
7285void scaleImageFloat16 (uint16_t * input,
7386 int srcStride,
7487 int inputWidth, int inputHeight,
@@ -163,6 +176,33 @@ void scaleImageFloat16(uint16_t* input,
163176 }
164177 }
165178
179+ for (int c = 0 ; c < components; ++c) {
180+ dst16[x*components + c] = rgb[c].data_ ;
181+ }
182+ } else if (option == catmullRom) {
183+
184+ half rgb[components];
185+
186+ float kx1 = floor (srcX);
187+ float ky1 = floor (srcY);
188+
189+ for (int j = -1 ; j <= 2 ; j++) {
190+ for (int i = -1 ; i <= 2 ; i++) {
191+ int xi = kx1 + i;
192+ int yj = ky1 + j;
193+
194+ if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
195+ half weight = CatmullRom (half (srcX - xi)) * CatmullRom (half (srcY - yj));
196+
197+ for (int c = 0 ; c < components; ++c) {
198+ half clrf = castU16 (reinterpret_cast <const uint16_t *>(src8 + yj * srcStride)[xi*components + c]);
199+ half clr = clrf * weight;
200+ rgb[c] += clr;
201+ }
202+ }
203+ }
204+ }
205+
166206 for (int c = 0 ; c < components; ++c) {
167207 dst16[x*components + c] = rgb[c].data_ ;
168208 }
@@ -172,10 +212,13 @@ void scaleImageFloat16(uint16_t* input,
172212 int a = 3 ;
173213 float lanczosFA = float (3 .0f );
174214
215+ float kx1 = floor (srcX);
216+ float ky1 = floor (srcY);
217+
175218 for (int j = -a + 1 ; j <= a; j++) {
176219 for (int i = -a + 1 ; i <= a; i++) {
177- int xi = x1 + i;
178- int yj = y1 + j;
220+ int xi = kx1 + i;
221+ int yj = ky1 + j;
179222
180223 if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
181224 float weight = lanczosWindow (float (srcX - xi), (float )lanczosFA) * lanczosWindow (float (srcY - yj), (float )lanczosFA);
@@ -254,7 +297,7 @@ void scaleImageU16(uint16_t* input,
254297
255298 half result = (c1 + c2 + c3 + c4);
256299 float f = result * maxColors;
257- f = std:: clamp (f, 0 .0f , maxColors);
300+ f = clamp (f, 0 .0f , maxColors);
258301 dst16[x*components + c] = static_cast <uint16_t >(f);
259302 }
260303
@@ -285,7 +328,7 @@ void scaleImageU16(uint16_t* input,
285328 for (int c = 0 ; c < components; ++c) {
286329 float cc = rgb[c];
287330 float f = cc * maxColors;
288- f = std:: clamp (f, 0 .0f , maxColors);
331+ f = clamp (f, 0 .0f , maxColors);
289332 dst16[x*components + c] = static_cast <uint16_t >(f);
290333 }
291334 } else if (option == mitchell) {
@@ -312,7 +355,37 @@ void scaleImageU16(uint16_t* input,
312355 for (int c = 0 ; c < components; ++c) {
313356 float cc = rgb[c];
314357 float f = cc * maxColors;
315- f = std::clamp (f, 0 .0f , maxColors);
358+ f = clamp (f, 0 .0f , maxColors);
359+ dst16[x*components + c] = static_cast <uint16_t >(f);
360+ }
361+ } else if (option == catmullRom) {
362+ half rgb[components];
363+
364+ float kx1 = floor (srcX);
365+ float ky1 = floor (srcY);
366+
367+ for (int j = -1 ; j <= 2 ; j++) {
368+ for (int i = -1 ; i <= 2 ; i++) {
369+ int xi = kx1 + i;
370+ int yj = ky1 + j;
371+
372+ if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
373+ half weight = CatmullRom (half (srcX - xi)) * CatmullRom (half (srcY - yj));
374+
375+ for (int c = 0 ; c < components; ++c) {
376+ uint16_t p = reinterpret_cast <const uint16_t *>(src8 + yj * srcStride)[xi*components + c];
377+ half clrf ((float )p / maxColors);
378+ half clr = clrf * weight;
379+ rgb[c] += clr;
380+ }
381+ }
382+ }
383+ }
384+
385+ for (int c = 0 ; c < components; ++c) {
386+ float cc = rgb[c];
387+ float f = cc * maxColors;
388+ f = clamp (f, 0 .0f , maxColors);
316389 dst16[x*components + c] = static_cast <uint16_t >(f);
317390 }
318391 } else if (option == lanczos) {
@@ -341,7 +414,7 @@ void scaleImageU16(uint16_t* input,
341414 for (int c = 0 ; c < components; ++c) {
342415 float cc = rgb[c];
343416 float f = cc * maxColors;
344- f = std:: clamp (f, 0 .0f , maxColors);
417+ f = clamp (f, 0 .0f , maxColors);
345418 dst16[x*components + c] = static_cast <uint16_t >(f);
346419 }
347420 } else {
@@ -402,7 +475,7 @@ void scaleImageU8(uint8_t* input,
402475
403476 half result = (c1 + c2 + c3 + c4);
404477 float f = result * maxColors;
405- f = std:: clamp (f, 0 .0f , maxColors);
478+ f = clamp (f, 0 .0f , maxColors);
406479 dst[x*components + c] = static_cast <uint8_t >(f);
407480
408481 }
@@ -460,17 +533,50 @@ void scaleImageU8(uint8_t* input,
460533 f = std::clamp (f, 0 .0f , maxColors);
461534 dst[x*components + c] = static_cast <uint16_t >(f);
462535 }
536+ } else if (option == catmullRom) {
537+ half rgb[components];
538+
539+ float kx1 = floor (srcX);
540+ float ky1 = floor (srcY);
541+
542+ for (int j = -1 ; j <= 2 ; j++) {
543+ for (int i = -1 ; i <= 2 ; i++) {
544+ int xi = kx1 + i;
545+ int yj = ky1 + j;
546+
547+ if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
548+ half weight = CatmullRom (half (srcX - xi)) * CatmullRom (half (srcY - yj));
549+
550+ for (int c = 0 ; c < components; ++c) {
551+ uint8_t p = reinterpret_cast <const uint8_t *>(src8 + yj * srcStride)[xi*components + c];
552+ half clrf ((float )p / maxColors);
553+ half clr = clrf * weight;
554+ rgb[c] += clr;
555+ }
556+ }
557+ }
558+ }
559+
560+ for (int c = 0 ; c < components; ++c) {
561+ float cc = rgb[c];
562+ float f = cc * maxColors;
563+ f = clamp (f, 0 .0f , maxColors);
564+ dst[x*components + c] = static_cast <uint16_t >(f);
565+ }
463566 } else if (option == lanczos) {
464567 half rgb[components];
465568
466569 float lanczosFA = float (3 .0f );
467570
468571 int a = 3 ;
469572
573+ float kx1 = floor (srcX);
574+ float ky1 = floor (srcY);
575+
470576 for (int j = -a + 1 ; j <= a; j++) {
471577 for (int i = -a + 1 ; i <= a; i++) {
472- int xi = x1 + i;
473- int yj = y1 + j;
578+ int xi = kx1 + i;
579+ int yj = ky1 + j;
474580
475581 if (xi >= 0 && xi < inputWidth && yj >= 0 && yj < inputHeight) {
476582 float weight = lanczosWindow (float (srcX - xi), lanczosFA) * lanczosWindow (float (srcY - yj), lanczosFA);
@@ -487,7 +593,7 @@ void scaleImageU8(uint8_t* input,
487593 for (int c = 0 ; c < components; ++c) {
488594 float cc = rgb[c];
489595 float f = cc * maxColors;
490- f = std:: clamp (f, 0 .0f , maxColors);
596+ f = clamp (f, 0 .0f , maxColors);
491597 dst[x*components + c] = static_cast <uint16_t >(f);
492598 }
493599 } else {
0 commit comments