support f16norm in skcms
Change-Id: Ic1699f8d4180b23e9b2f3aa336991207cc175894
Reviewed-on: https://skia-review.googlesource.com/c/skcms/+/199978
Commit-Queue: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/skcms.cc b/skcms.cc
index b965c56..874b55d 100644
--- a/skcms.cc
+++ b/skcms.cc
@@ -1984,6 +1984,8 @@
case skcms_PixelFormat_RGBA_16161616LE >> 1: return 8;
case skcms_PixelFormat_RGB_161616BE >> 1: return 6;
case skcms_PixelFormat_RGBA_16161616BE >> 1: return 8;
+ case skcms_PixelFormat_RGB_hhh_Norm >> 1: return 6;
+ case skcms_PixelFormat_RGBA_hhhh_Norm >> 1: return 8;
case skcms_PixelFormat_RGB_hhh >> 1: return 6;
case skcms_PixelFormat_RGBA_hhhh >> 1: return 8;
case skcms_PixelFormat_RGB_fff >> 1: return 12;
@@ -2083,6 +2085,8 @@
case skcms_PixelFormat_RGBA_16161616LE >> 1: *ops++ = Op_load_16161616LE; break;
case skcms_PixelFormat_RGB_161616BE >> 1: *ops++ = Op_load_161616BE; break;
case skcms_PixelFormat_RGBA_16161616BE >> 1: *ops++ = Op_load_16161616BE; break;
+ case skcms_PixelFormat_RGB_hhh_Norm >> 1: *ops++ = Op_load_hhh; break;
+ case skcms_PixelFormat_RGBA_hhhh_Norm >> 1: *ops++ = Op_load_hhhh; break;
case skcms_PixelFormat_RGB_hhh >> 1: *ops++ = Op_load_hhh; break;
case skcms_PixelFormat_RGBA_hhhh >> 1: *ops++ = Op_load_hhhh; break;
case skcms_PixelFormat_RGB_fff >> 1: *ops++ = Op_load_fff; break;
@@ -2092,6 +2096,10 @@
*args++ = palette;
break;
}
+ if (srcFmt == skcms_PixelFormat_RGB_hhh_Norm ||
+ srcFmt == skcms_PixelFormat_RGBA_hhhh_Norm) {
+ *ops++ = Op_clamp;
+ }
if (srcFmt & 1) {
*ops++ = Op_swap_rb;
}
@@ -2213,8 +2221,8 @@
if (!is_identity_tf(&inv_dst_tf_b)) { *ops++ = Op_tf_b; *args++ = &inv_dst_tf_b; }
}
- // Clamp here before premul to make sure we're clamping to fixed-point values _and_ gamut,
- // not just to values that fit in the fixed point representation.
+ // Clamp here before premul to make sure we're clamping to normalized values _and_ gamut,
+ // not just to values that fit in [0,1].
//
// E.g. r = 1.1, a = 0.5 would fit fine in fixed point after premul (ra=0.55,a=0.5),
// but would be carrying r > 1, which is really unexpected for downstream consumers.
@@ -2242,6 +2250,8 @@
case skcms_PixelFormat_RGBA_16161616LE >> 1: *ops++ = Op_store_16161616LE; break;
case skcms_PixelFormat_RGB_161616BE >> 1: *ops++ = Op_store_161616BE; break;
case skcms_PixelFormat_RGBA_16161616BE >> 1: *ops++ = Op_store_16161616BE; break;
+ case skcms_PixelFormat_RGB_hhh_Norm >> 1: *ops++ = Op_store_hhh; break;
+ case skcms_PixelFormat_RGBA_hhhh_Norm >> 1: *ops++ = Op_store_hhhh; break;
case skcms_PixelFormat_RGB_hhh >> 1: *ops++ = Op_store_hhh; break;
case skcms_PixelFormat_RGBA_hhhh >> 1: *ops++ = Op_store_hhhh; break;
case skcms_PixelFormat_RGB_fff >> 1: *ops++ = Op_store_fff; break;
diff --git a/skcms.h b/skcms.h
index d924f34..6ca8236 100644
--- a/skcms.h
+++ b/skcms.h
@@ -208,6 +208,11 @@
skcms_PixelFormat_RGBA_16161616 = skcms_PixelFormat_RGBA_16161616BE,
skcms_PixelFormat_BGRA_16161616 = skcms_PixelFormat_BGRA_16161616BE,
+ skcms_PixelFormat_RGB_hhh_Norm, // 1-5-10 half-precision float in [0,1]
+ skcms_PixelFormat_BGR_hhh_Norm, // Pointers must be 16-bit aligned.
+ skcms_PixelFormat_RGBA_hhhh_Norm,
+ skcms_PixelFormat_BGRA_hhhh_Norm,
+
skcms_PixelFormat_RGB_hhh, // 1-5-10 half-precision float.
skcms_PixelFormat_BGR_hhh, // Pointers must be 16-bit aligned.
skcms_PixelFormat_RGBA_hhhh,
diff --git a/tests.c b/tests.c
index 9e217a8..2f7ade4 100644
--- a/tests.c
+++ b/tests.c
@@ -434,6 +434,42 @@
expect(back[5] == src[6] || back[5] == 0x0000);
}
+static void test_FormatConversions_half_norm() {
+ const uint16_t src[] = {
+ 0x3800, // 0.5
+ 0x3c00, // 1.0
+ 0xbc00, // -1.0
+ 0x4000, // 2.0
+ };
+ uint16_t dst[ARRAY_COUNT(src)];
+
+ const skcms_AlphaFormat upm = skcms_AlphaFormat_Unpremul;
+
+ // No-op, no clamp, should preserve all values.
+ expect(skcms_Transform(&src, skcms_PixelFormat_RGBA_hhhh, upm, NULL,
+ &dst, skcms_PixelFormat_RGBA_hhhh, upm, NULL, 1));
+ expect(dst[0] == src[0]);
+ expect(dst[1] == src[1]);
+ expect(dst[2] == src[2]);
+ expect(dst[3] == src[3]);
+
+ // Clamp on read.
+ expect(skcms_Transform(&src, skcms_PixelFormat_RGBA_hhhh_Norm, upm, NULL,
+ &dst, skcms_PixelFormat_RGBA_hhhh , upm, NULL, 1));
+ expect(dst[0] == src[0]);
+ expect(dst[1] == src[1]);
+ expect(dst[2] == 0x0000);
+ expect(dst[3] == src[1]);
+
+ // Clamp on write.
+ expect(skcms_Transform(&src, skcms_PixelFormat_RGBA_hhhh , upm, NULL,
+ &dst, skcms_PixelFormat_RGBA_hhhh_Norm, upm, NULL, 1));
+ expect(dst[0] == src[0]);
+ expect(dst[1] == src[1]);
+ expect(dst[2] == 0x0000);
+ expect(dst[3] == src[1]);
+}
+
static void test_FormatConversions_float() {
float src[] = { 1.0f, 0.5f, 1/255.0f, 1/512.0f };
@@ -1305,6 +1341,7 @@
test_FormatConversions_161616BE();
test_FormatConversions_101010();
test_FormatConversions_half();
+ test_FormatConversions_half_norm();
test_FormatConversions_float();
test_Parse(regenTestData);
test_ApproximateCurve_clamped();