Skip to content

Package: ColorMatrix

ColorMatrix

nameinstructionbranchcomplexitylinemethod
ColorMatrix(double[])
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
compute(int, short[], int)
M: 82 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
inverse()
M: 274 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 23 C: 0
0%
M: 1 C: 0
0%
normalizeRows()
M: 118 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 13 C: 0
0%
M: 1 C: 0
0%
process(short[], int)
M: 37 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
product(ColorMatrix)
M: 296 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 51 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
toString()
M: 36 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * *********************************************************************************************************************
3: *
4: * Mistral: open source imaging engine
5: * http://tidalwave.it/projects/mistral
6: *
7: * Copyright (C) 2003 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/mistral-src
23: * git clone https://github.com/tidalwave-it/mistral-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.image;
28:
29: import java.text.DecimalFormat;
30: import lombok.extern.slf4j.Slf4j;
31:
32: /***********************************************************************************************************************
33: *
34: * @author Fabrizio Giudici
35: *
36: **********************************************************************************************************************/
37: @Slf4j
38: public class ColorMatrix
39: {
40: private static final DecimalFormat FORMAT = new DecimalFormat("+0.0000;-0.0000");
41: private static final long SHORT_MASK = 0xffff;
42: public static final ColorMatrix XYZ_TO_RGB = new ColorMatrix(new double[]
43: {
44: 0.412453,
45: 0.357580,
46: 0.180423,
47: 0.212671,
48: 0.715160,
49: 0.072169,
50: 0.019334,
51: 0.119193,
52: 0.950227
53: });
54: private final double[] c;
55:
56: /*******************************************************************************************************************
57: *
58: * @param coefficients
59: *
60: ******************************************************************************************************************/
61: public ColorMatrix (final double[] coefficients)
62: {
63: this.c = coefficients;
64: }
65:
66: /*******************************************************************************************************************
67: *
68: * FIXME: move to EditableImage
69: *
70: * @param data
71: * @param index
72: *
73: ******************************************************************************************************************/
74: public final void process (final short[] data, final int index)
75: {
76: final var d0 = compute(0, data, index);
77: final var d1 = compute(1, data, index);
78: final var d2 = compute(2, data, index);
79: data[index + 0] = d0;
80: data[index + 1] = d1;
81: data[index + 2] = d2;
82: }
83:
84: /*******************************************************************************************************************
85: *
86: * @param m
87: * @return
88: *
89: * 012
90: * 345
91: * 678
92: *
93: ******************************************************************************************************************/
94: public final ColorMatrix product (final ColorMatrix m)
95: {
96: final var r = new double[9];
97:
98: r[2] = (c[0] * m.c[2]) + (c[1] * m.c[5]) + (c[2] * m.c[8]);
99: r[5] = (c[3] * m.c[2]) + (c[4] * m.c[5]) + (c[5] * m.c[8]);
100: r[8] = (c[6] * m.c[2]) + (c[7] * m.c[5]) + (c[8] * m.c[8]);
101:
102: r[1] = (c[0] * m.c[1]) + (c[1] * m.c[4]) + (c[2] * m.c[7]);
103: r[4] = (c[3] * m.c[1]) + (c[4] * m.c[4]) + (c[5] * m.c[7]);
104: r[7] = (c[6] * m.c[1]) + (c[7] * m.c[4]) + (c[8] * m.c[7]);
105:
106: r[0] = (c[0] * m.c[0]) + (c[1] * m.c[3]) + (c[2] * m.c[6]);
107: r[3] = (c[3] * m.c[0]) + (c[4] * m.c[3]) + (c[5] * m.c[6]);
108: r[6] = (c[6] * m.c[0]) + (c[7] * m.c[3]) + (c[8] * m.c[6]);
109:
110: return new ColorMatrix(r);
111: }
112:
113: /*******************************************************************************************************************
114: *
115: *
116: *
117: ******************************************************************************************************************/
118: public final void normalizeRows()
119: {
120: var sum = c[0] + c[1] + c[2];
121: c[0] /= sum;
122: c[1] /= sum;
123: c[2] /= sum;
124: sum = c[3] + c[4] + c[5];
125: c[3] /= sum;
126: c[4] /= sum;
127: c[5] /= sum;
128: sum = c[6] + c[7] + c[8];
129: c[6] /= sum;
130: c[7] /= sum;
131: c[8] /= sum;
132: }
133:
134: /*******************************************************************************************************************
135: *
136: * @return
137: *
138: ******************************************************************************************************************/
139: public final ColorMatrix inverse()
140: {
141: final var cof0 = +((c[4] * c[8]) - (c[7] * c[5]));
142: final var cof1 = -((c[3] * c[8]) - (c[6] * c[5]));
143: final var cof2 = +((c[3] * c[7]) - (c[6] * c[4]));
144: final var cof3 = -((c[1] * c[8]) - (c[7] * c[2]));
145: final var cof4 = +((c[0] * c[8]) - (c[6] * c[2]));
146: final var cof5 = -((c[0] * c[7]) - (c[6] * c[1]));
147: final var cof6 = +((c[1] * c[5]) - (c[4] * c[2]));
148: final var cof7 = -((c[0] * c[5]) - (c[3] * c[2]));
149: final var cof8 = +((c[0] * c[4]) - (c[3] * c[1]));
150:
151: final var det = (c[0] * cof0) + (c[1] * cof1) + (c[2] * cof2);
152:
153: final var nc = new double[9];
154: nc[0] = cof0 / det;
155: nc[1] = cof3 / det;
156: nc[2] = cof6 / det;
157: nc[3] = cof1 / det;
158: nc[4] = cof4 / det;
159: nc[5] = cof7 / det;
160: nc[6] = cof2 / det;
161: nc[7] = cof5 / det;
162: nc[8] = cof8 / det;
163:
164: final var result = new ColorMatrix(nc);
165:
166: log.trace("inverse(" + this + ") = " + result);
167:
168: // logger.finest(">>>> det = " + det);
169: return result;
170: }
171:
172: /*******************************************************************************************************************
173: *
174: * {@inheritDoc}
175: *
176: ******************************************************************************************************************/
177: @Override
178: public final String toString()
179: {
180: final var buffer = new StringBuilder("[");
181:
182:• for (var i = 0; i < c.length; i++)
183: {
184:• if (i > 0)
185: {
186: buffer.append(",");
187: }
188:
189: buffer.append(FORMAT.format(c[i]));
190: }
191:
192: buffer.append("]");
193:
194: return buffer.toString();
195: }
196:
197: /*******************************************************************************************************************
198: *
199: * @param data
200: * @return
201: *
202: ******************************************************************************************************************/
203: private short compute (final int channel, final short[] data, final int index)
204: {
205: final var c0 = c[(channel * 3) + 0];
206: final var c1 = c[(channel * 3) + 1];
207: final var c2 = c[(channel * 3) + 2];
208:
209: final var f = (c0 * (data[index + 0] & SHORT_MASK)) + (c1 * (data[index + 1] & SHORT_MASK))
210: + (c2 * (data[index + 2] & SHORT_MASK));
211: final var x = (int)f;
212:
213:• if (x < 0)
214: {
215: return 0;
216: }
217:
218:• return (short)((x <= SHORT_MASK) ? x : SHORT_MASK);
219: }
220: }