Codebase list colord / 9aba3df
libcolord: Add cd_icc_utils_get_adaptation_matrix Window systems such as gnome-shell can use this to calculate a color transform matrix (CTM) to plug into typical desktop display hardware. Aaron Plattner authored 4 years ago Richard Hughes committed 4 years ago
2 changed file(s) with 129 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
171171 *coverage = coverage_tmp;
172172 return TRUE;
173173 }
174
175 /**
176 * cd_icc_utils_get_chroma_matrix:
177 * @icc: The profile to use.
178 * @mat: (out): The returned matrix containing the primaries from @icc.
179 *
180 * Fills a 3x3 matrix with the XYZ red, green, and blue primary values from an
181 * ICC profile as columns.
182 */
183 static void
184 cd_icc_utils_get_chroma_matrix (CdIcc *icc, CdMat3x3 *mat)
185 {
186 const CdColorXYZ *red = cd_icc_get_red (icc);
187 const CdColorXYZ *green = cd_icc_get_green (icc);
188 const CdColorXYZ *blue = cd_icc_get_blue (icc);
189 CdMat3x3 matrix = {
190 red->X, green->X, blue->X,
191 red->Y, green->Y, blue->Y,
192 red->Z, green->Z, blue->Z };
193
194 *mat = matrix;
195 }
196
197 /**
198 * cd_bradford_transform:
199 * @reference: The white point to use as a reference.
200 * @measured: The white point measurement for the target device.
201 * @mat: (out): The returned Bradford color adaptation matrix.
202 */
203 static void
204 cd_bradford_transform (const CdColorXYZ *reference,
205 const CdColorXYZ *measured,
206 CdMat3x3 *mat)
207 {
208 /* see https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781119021780.app3 */
209 const CdMat3x3 bradford_response_matrix = {
210 0.8951, 0.2664, -0.1614,
211 -0.7502, 1.7135, 0.0367,
212 0.0389, -0.0685, 1.0296 };
213 CdMat3x3 bradford_inv;
214 CdMat3x3 ratio;
215 CdMat3x3 tmp;
216 CdVec3 ref_xyz = { reference->X / reference->Y,
217 1.0,
218 reference->Z / reference->Y };
219 CdVec3 meas_xyz = { measured->X / measured->Y,
220 1.0,
221 measured->Z / measured->Y };
222 CdVec3 ref_rgb;
223 CdVec3 meas_rgb;
224
225 /* convert XYZ white point values to RGB */
226 cd_mat33_vector_multiply (&bradford_response_matrix,
227 &ref_xyz,
228 &ref_rgb);
229 cd_mat33_vector_multiply (&bradford_response_matrix,
230 &meas_xyz,
231 &meas_rgb);
232
233 /* construct a diagonal matrix D of the ratios between the RGB values */
234 cd_mat33_clear (&ratio);
235 ratio.m00 = meas_rgb.v0 / ref_rgb.v0;
236 ratio.m11 = meas_rgb.v1 / ref_rgb.v1;
237 ratio.m22 = meas_rgb.v2 / ref_rgb.v2;
238
239 /* transform is inv(B) * D * B */
240 cd_mat33_reciprocal (&bradford_response_matrix, &bradford_inv);
241 cd_mat33_matrix_multiply (&bradford_inv, &ratio, &tmp);
242 cd_mat33_matrix_multiply (&tmp, &bradford_response_matrix, mat);
243 }
244
245 /**
246 * cd_icc_utils_get_adaptation_matrix:
247 * @icc: The measured ICC profile for the target device.
248 * @icc_reference: The ICC profile to use as a reference (typically sRGB).
249 * @mat: (out): The returned adaptation matrix.
250 * @error: (out): A #GError, or %NULL
251 *
252 * Computes a correction matrix suitable for adjusting colors in a reference
253 * color space @icc_reference (typically sRGB) to the color space of a target
254 * device described by @icc.
255 *
256 * This function is designed to be used by desktop window systems to program the
257 * color transform matrix (CTM) property of the display hardware.
258 *
259 * Return value: %TRUE for success
260 *
261 * Since: 1.4.5
262 */
263 gboolean
264 cd_icc_utils_get_adaptation_matrix (CdIcc *icc,
265 CdIcc *icc_reference,
266 CdMat3x3 *mat,
267 GError **error)
268 {
269 CdMat3x3 reference;
270 CdMat3x3 measured_chroma;
271 CdMat3x3 measured;
272 CdMat3x3 measured_inv;
273 CdMat3x3 bradford;
274
275 cd_icc_utils_get_chroma_matrix (icc_reference, &reference);
276 cd_icc_utils_get_chroma_matrix (icc, &measured_chroma);
277
278 /* compute a Bradford color adaptation transform from the measured white
279 * point to the reference white point */
280 cd_bradford_transform (cd_icc_get_white (icc_reference),
281 cd_icc_get_white (icc),
282 &bradford);
283
284 /* use the Bradford transform to adjust the measured chroma values to
285 * match the reference luminance */
286 cd_mat33_matrix_multiply (&bradford, &measured_chroma, &measured);
287
288 /* invert the adjusted measured chroma matrix and multiply by the
289 * reference colors to compute the resulting CSC matrix */
290 cd_mat33_reciprocal (&measured, &measured_inv);
291 cd_mat33_matrix_multiply (&measured_inv,
292 &reference,
293 mat);
294
295 return cd_mat33_is_finite (mat, error);
296 }
2828 #include <glib-object.h>
2929
3030 #include "cd-icc.h"
31 #include "cd-math.h"
3132
3233 G_BEGIN_DECLS
3334
3637 gdouble *coverage,
3738 GError **error);
3839
40 gboolean cd_icc_utils_get_adaptation_matrix (CdIcc *icc,
41 CdIcc *icc_reference,
42 CdMat3x3 *out,
43 GError **error);
44
3945 G_END_DECLS
4046
4147 #endif /* __CD_ICC_UTILS_H__ */