You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
3.2 KiB
76 lines
3.2 KiB
diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
|
|
index 5ea1b4c85..8a1171820 100644
|
|
--- a/third_party/lcms/src/cmsopt.c
|
|
+++ b/third_party/lcms/src/cmsopt.c
|
|
@@ -104,6 +104,39 @@ typedef struct {
|
|
// Simple optimizations ----------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
+// Clamp a fixed point integer to signed 28 bits to avoid overflow in
|
|
+// calculations. Clamp is intended for use with colorants, requiring one bit
|
|
+// for a colorant and another two bits to avoid overflow when combining the
|
|
+// colors.
|
|
+cmsINLINE cmsS1Fixed14Number _FixedClamp(cmsS1Fixed14Number n) {
|
|
+ const cmsS1Fixed14Number max_positive = 268435455; // 0x0FFFFFFF;
|
|
+ const cmsS1Fixed14Number max_negative = -268435456; // 0xF0000000;
|
|
+ // Normally expect the provided number to be in the range [0..1] (but in
|
|
+ // fixed 1.14 format), so can perform a quick check for this typical case
|
|
+ // to reduce number of compares.
|
|
+ const cmsS1Fixed14Number typical_range_mask = 0xFFFF8000;
|
|
+
|
|
+ if (!(n & typical_range_mask))
|
|
+ return n;
|
|
+ if (n < max_negative)
|
|
+ return max_negative;
|
|
+ if (n > max_positive)
|
|
+ return max_positive;
|
|
+ return n;
|
|
+}
|
|
+
|
|
+// Perform one row of matrix multiply with translation for MatShaperEval16().
|
|
+cmsINLINE cmsInt64Number _MatShaperEvaluateRow(cmsS1Fixed14Number* mat,
|
|
+ cmsS1Fixed14Number off,
|
|
+ cmsS1Fixed14Number r,
|
|
+ cmsS1Fixed14Number g,
|
|
+ cmsS1Fixed14Number b) {
|
|
+ return ((cmsInt64Number)mat[0] * r +
|
|
+ (cmsInt64Number)mat[1] * g +
|
|
+ (cmsInt64Number)mat[2] * b +
|
|
+ off + 0x2000) >> 14;
|
|
+}
|
|
+
|
|
// Remove an element in linked chain
|
|
static
|
|
void _RemoveElement(cmsStage** head)
|
|
@@ -1527,7 +1560,8 @@ void MatShaperEval16(register const cmsUInt16Number In[],
|
|
register const void* D)
|
|
{
|
|
MatShaper8Data* p = (MatShaper8Data*) D;
|
|
- cmsS1Fixed14Number l1, l2, l3, r, g, b;
|
|
+ cmsS1Fixed14Number r, g, b;
|
|
+ cmsInt64Number l1, l2, l3;
|
|
cmsUInt32Number ri, gi, bi;
|
|
|
|
// In this case (and only in this case!) we can use this simplification since
|
|
@@ -1537,14 +1571,14 @@ void MatShaperEval16(register const cmsUInt16Number In[],
|
|
bi = In[2] & 0xFFU;
|
|
|
|
// Across first shaper, which also converts to 1.14 fixed point
|
|
- r = p->Shaper1R[ri];
|
|
- g = p->Shaper1G[gi];
|
|
- b = p->Shaper1B[bi];
|
|
+ r = _FixedClamp(p->Shaper1R[ri]);
|
|
+ g = _FixedClamp(p->Shaper1G[gi]);
|
|
+ b = _FixedClamp(p->Shaper1B[bi]);
|
|
|
|
// Evaluate the matrix in 1.14 fixed point
|
|
- l1 = (p->Mat[0][0] * r + p->Mat[0][1] * g + p->Mat[0][2] * b + p->Off[0] + 0x2000) >> 14;
|
|
- l2 = (p->Mat[1][0] * r + p->Mat[1][1] * g + p->Mat[1][2] * b + p->Off[1] + 0x2000) >> 14;
|
|
- l3 = (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14;
|
|
+ l1 = _MatShaperEvaluateRow(p->Mat[0], p->Off[0], r, g, b);
|
|
+ l2 = _MatShaperEvaluateRow(p->Mat[1], p->Off[1], r, g, b);
|
|
+ l3 = _MatShaperEvaluateRow(p->Mat[2], p->Off[2], r, g, b);
|
|
|
|
// Now we have to clip to 0..1.0 range
|
|
ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384U : (cmsUInt32Number) l1);
|