From fbf026653b117f8363f9b49ce0d803669c45d026 Mon Sep 17 00:00:00 2001
From: Pekka Paalanen <pekka.paalanen@collabora.com>
Date: Thu, 13 Mar 2025 16:43:52 +0200
Subject: [PATCH] color-lcms: cmsMAT3 is row-major after all

Found out in https://github.com/mm2/Little-CMS/issues/483

This should be a complete no-op change, but there is one difference.
Previously matrix_inf_norm() summed over rows. Now it sums over columns
as it should be. This shouldn't hurt because it is only used to identify
identity matrices. The bug was actually in is_identity_matrix_stage()
because it deliberately passed what was assumed to be a transpose of the
matrix.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
---
 libweston/color-lcms/color-transform.c | 18 +++++-------------
 tests/color_util.h                     |  3 +++
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/libweston/color-lcms/color-transform.c b/libweston/color-lcms/color-transform.c
index 643186a97e..3da96958b3 100644
--- a/libweston/color-lcms/color-transform.c
+++ b/libweston/color-lcms/color-transform.c
@@ -192,7 +192,7 @@ matrix_inf_norm(const cmsMAT3 *mat)
 		double sum = 0.0;
 
 		for (col = 0; col < 3; col++)
-			sum += fabs(mat->v[col].n[row]);
+			sum += fabs(mat->v[row].n[col]);
 
 		if (infnorm < sum)
 			infnorm = sum;
@@ -222,9 +222,9 @@ matrix_is_identity(const cmsMAT3 *mat, int bits_precision)
 }
 
 static const cmsMAT3 *
-stage_matrix_transpose(const _cmsStageMatrixData *smd)
+stage_matrix(const _cmsStageMatrixData *smd)
 {
-	/* smd is row-major, cmsMAT3 is column-major */
+	/* Both are row-major. */
 	return (const cmsMAT3 *)smd->Double;
 }
 
@@ -259,7 +259,7 @@ is_identity_matrix_stage(const cmsStage *stage)
 		return false;
 
 	data = cmsStageData(stage);
-	return matrix_is_identity(stage_matrix_transpose(data),
+	return matrix_is_identity(stage_matrix(data),
 				  MATRIX_PRECISION_BITS);
 }
 
@@ -274,15 +274,7 @@ multiply_matrix_stages(cmsContext context_id, cmsStage *next, cmsStage *prev)
 	prev_ = cmsStageData(prev);
 	next_ = cmsStageData(next);
 
-	/* res = prev^T * next^T */
-	_cmsMAT3per(&res, stage_matrix_transpose(next_),
-		    stage_matrix_transpose(prev_));
-
-	/*
-	 * res is column-major while Alloc function takes row-major;
-	 * the cast effectively transposes the matrix.
-	 * We return (prev^T * next^T)^T = next * prev.
-	 */
+	_cmsMAT3per(&res, stage_matrix(next_), stage_matrix(prev_));
 	ret = cmsStageAllocMatrix(context_id, 3, 3,
 				  (const cmsFloat64Number*)&res, NULL);
 	abort_oom_if_null(ret);
diff --git a/tests/color_util.h b/tests/color_util.h
index 46817dfc13..52a765c3fc 100644
--- a/tests/color_util.h
+++ b/tests/color_util.h
@@ -53,6 +53,9 @@ struct lcmsVEC3 {
 	float n[3];
 };
 
+/*
+ * While LittleCMS' cmsMAT3 is row-major, this here is colum-major.
+ */
 struct lcmsMAT3 {
 	/* array of columns */
 	struct lcmsVEC3 v[3];
-- 
GitLab