1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/qcms/matrix.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,136 @@ 1.4 +/* vim: set ts=8 sw=8 noexpandtab: */ 1.5 +// qcms 1.6 +// Copyright (C) 2009 Mozilla Foundation 1.7 +// Copyright (C) 1998-2007 Marti Maria 1.8 +// 1.9 +// Permission is hereby granted, free of charge, to any person obtaining 1.10 +// a copy of this software and associated documentation files (the "Software"), 1.11 +// to deal in the Software without restriction, including without limitation 1.12 +// the rights to use, copy, modify, merge, publish, distribute, sublicense, 1.13 +// and/or sell copies of the Software, and to permit persons to whom the Software 1.14 +// is furnished to do so, subject to the following conditions: 1.15 +// 1.16 +// The above copyright notice and this permission notice shall be included in 1.17 +// all copies or substantial portions of the Software. 1.18 +// 1.19 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1.20 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 1.21 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1.22 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 1.23 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 1.24 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 1.25 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1.26 + 1.27 +#include <stdlib.h> 1.28 +#include "qcmsint.h" 1.29 +#include "matrix.h" 1.30 + 1.31 +struct vector matrix_eval(struct matrix mat, struct vector v) 1.32 +{ 1.33 + struct vector result; 1.34 + result.v[0] = mat.m[0][0]*v.v[0] + mat.m[0][1]*v.v[1] + mat.m[0][2]*v.v[2]; 1.35 + result.v[1] = mat.m[1][0]*v.v[0] + mat.m[1][1]*v.v[1] + mat.m[1][2]*v.v[2]; 1.36 + result.v[2] = mat.m[2][0]*v.v[0] + mat.m[2][1]*v.v[1] + mat.m[2][2]*v.v[2]; 1.37 + return result; 1.38 +} 1.39 + 1.40 +//XXX: should probably pass by reference and we could 1.41 +//probably reuse this computation in matrix_invert 1.42 +float matrix_det(struct matrix mat) 1.43 +{ 1.44 + float det; 1.45 + det = mat.m[0][0]*mat.m[1][1]*mat.m[2][2] + 1.46 + mat.m[0][1]*mat.m[1][2]*mat.m[2][0] + 1.47 + mat.m[0][2]*mat.m[1][0]*mat.m[2][1] - 1.48 + mat.m[0][0]*mat.m[1][2]*mat.m[2][1] - 1.49 + mat.m[0][1]*mat.m[1][0]*mat.m[2][2] - 1.50 + mat.m[0][2]*mat.m[1][1]*mat.m[2][0]; 1.51 + return det; 1.52 +} 1.53 + 1.54 +/* from pixman and cairo and Mathematics for Game Programmers */ 1.55 +/* lcms uses gauss-jordan elimination with partial pivoting which is 1.56 + * less efficient and not as numerically stable. See Mathematics for 1.57 + * Game Programmers. */ 1.58 +struct matrix matrix_invert(struct matrix mat) 1.59 +{ 1.60 + struct matrix dest_mat; 1.61 + int i,j; 1.62 + static int a[3] = { 2, 2, 1 }; 1.63 + static int b[3] = { 1, 0, 0 }; 1.64 + 1.65 + /* inv (A) = 1/det (A) * adj (A) */ 1.66 + float det = matrix_det(mat); 1.67 + 1.68 + if (det == 0) { 1.69 + dest_mat.invalid = true; 1.70 + } else { 1.71 + dest_mat.invalid = false; 1.72 + } 1.73 + 1.74 + det = 1/det; 1.75 + 1.76 + for (j = 0; j < 3; j++) { 1.77 + for (i = 0; i < 3; i++) { 1.78 + double p; 1.79 + int ai = a[i]; 1.80 + int aj = a[j]; 1.81 + int bi = b[i]; 1.82 + int bj = b[j]; 1.83 + 1.84 + p = mat.m[ai][aj] * mat.m[bi][bj] - 1.85 + mat.m[ai][bj] * mat.m[bi][aj]; 1.86 + if (((i + j) & 1) != 0) 1.87 + p = -p; 1.88 + 1.89 + dest_mat.m[j][i] = det * p; 1.90 + } 1.91 + } 1.92 + return dest_mat; 1.93 +} 1.94 + 1.95 +struct matrix matrix_identity(void) 1.96 +{ 1.97 + struct matrix i; 1.98 + i.m[0][0] = 1; 1.99 + i.m[0][1] = 0; 1.100 + i.m[0][2] = 0; 1.101 + i.m[1][0] = 0; 1.102 + i.m[1][1] = 1; 1.103 + i.m[1][2] = 0; 1.104 + i.m[2][0] = 0; 1.105 + i.m[2][1] = 0; 1.106 + i.m[2][2] = 1; 1.107 + i.invalid = false; 1.108 + return i; 1.109 +} 1.110 + 1.111 +struct matrix matrix_invalid(void) 1.112 +{ 1.113 + struct matrix inv = matrix_identity(); 1.114 + inv.invalid = true; 1.115 + return inv; 1.116 +} 1.117 + 1.118 + 1.119 +/* from pixman */ 1.120 +/* MAT3per... */ 1.121 +struct matrix matrix_multiply(struct matrix a, struct matrix b) 1.122 +{ 1.123 + struct matrix result; 1.124 + int dx, dy; 1.125 + int o; 1.126 + for (dy = 0; dy < 3; dy++) { 1.127 + for (dx = 0; dx < 3; dx++) { 1.128 + double v = 0; 1.129 + for (o = 0; o < 3; o++) { 1.130 + v += a.m[dy][o] * b.m[o][dx]; 1.131 + } 1.132 + result.m[dy][dx] = v; 1.133 + } 1.134 + } 1.135 + result.invalid = a.invalid || b.invalid; 1.136 + return result; 1.137 +} 1.138 + 1.139 +