AJA NTV2 SDK  17.1.1.1245
NTV2 SDK 17.1.1.1245
ntv2cscmatrix.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2cscmatrix.h"
9 #include <math.h>
10 
11 static const double kPi(3.1415926536);
12 
13 
15 {
16  InitMatrix (inPreset);
17 }
18 
19 
21 {
22  switch (inPreset)
23  {
24  case NTV2_Unity_Matrix:
25  default:
26  mA0 = 1.0;
27  mA1 = 0.0;
28  mA2 = 0.0;
29  mB0 = 0.0;
30  mB1 = 1.0;
31  mB2 = 0.0;
32  mC0 = 0.0;
33  mC1 = 0.0;
34  mC2 = 1.0;
35 
36  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset;
37  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
38  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
39 
40  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset;
41  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
42  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
43  break;
44 
46  mA0 = 1.0;
47  mA1 = 0.0;
48  mA2 = 0.0;
49  mB0 = 0.0;
50  mB1 = 1.0;
51  mB2 = 0.0;
52  mC0 = 0.0;
53  mC1 = 0.0;
54  mC2 = 1.0;
55 
56  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
57  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
58  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
59 
60  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
61  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
62  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
63  break;
64 
65  // RGB full range -> YCbCr Rec 709 (HD)
67  mA0 = 0.612427; // G -> Y
68  mA1 = 0.061829; // B -> Y
69  mA2 = 0.182068; // R -> Y
70  mB0 = -0.337585; // G -> Cb
71  mB1 = 0.437927; // B -> Cb
72  mB2 = -0.100342; // R -> Cb
73  mC0 = -0.397766; // G -> Cr
74  mC1 = -0.040161; // B -> Cr
75  mC2 = 0.437927; // R -> Cr
76 
77  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset; // full-range RGB: no offset
78  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
79  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
80 
81  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset; // YCbCr: "SMPTE" offsets
82  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
83  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
84  break;
85 
86  // RGB full range -> YCbCr Rec 2020
88  mA0 = 0.58057; // G -> Y
89  mA1 = 0.05078; // B -> Y
90  mA2 = 0.22495; // R -> Y
91  mB0 = -0.31563; // G -> Cb
92  mB1 = 0.43793; // B -> Cb
93  mB2 = -0.12230; // R -> Cb
94  mC0 = -0.40271; // G -> Cr
95  mC1 = -0.03522; // B -> Cr
96  mC2 = 0.43793; // R -> Cr
97 
98  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset; // full-range RGB: no offset
99  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
100  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
101 
102  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset; // YCbCr: "SMPTE" offsets
103  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
104  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
105  break;
106 
107  // RGB full range -> YCbCr Rec 601 (SD)
109  mA0 = 0.502655; // G -> Y
110  mA1 = 0.097626; // B -> Y
111  mA2 = 0.256042; // R -> Y
112  mB0 = -0.290131; // G -> Cb
113  mB1 = 0.437927; // B -> Cb
114  mB2 = -0.147797; // R -> Cb
115  mC0 = -0.366699; // G -> Cr
116  mC1 = -0.071228; // B -> Cr
117  mC2 = 0.437927; // R -> Cr
118 
119  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset;
120  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
121  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
122 
123  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
124  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
125  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
126  break;
127 
128  // RGB SMPTE range -> YCbCr Rec 709 (HD)
130  mA0 = 0.715210; // G -> Y
131  mA1 = 0.072205; // B -> Y
132  mA2 = 0.212585; // R -> Y
133  mB0 = -0.394226; // G -> Cb
134  mB1 = 0.511414; // B -> Cb
135  mB2 = -0.117188; // R -> Cb
136  mC0 = -0.464508; // G -> Cr
137  mC1 = -0.046906; // B -> Cr
138  mC2 = 0.511414; // R -> Cr
139 
140  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
141  mPreOffset1 = NTV2_CSCMatrix_SMPTEYOffset;
142  mPreOffset2 = NTV2_CSCMatrix_SMPTEYOffset;
143 
144  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
145  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
146  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
147  break;
148 
149 
150  // RGB SMPTE range -> YCbCr Rec 2020
152  mA0 = 0.678009; // G -> Y
153  mA1 = 0.059296; // B -> Y
154  mA2 = 0.262695; // R -> Y
155  mB0 = -0.368591; // G -> Cb
156  mB1 = 0.511414; // B -> Cb
157  mB2 = -0.142822; // R -> Cb
158  mC0 = -0.470276; // G -> Cr
159  mC1 = -0.041138; // B -> Cr
160  mC2 = 0.511414; // R -> Cr
161 
162 
163  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
164  mPreOffset1 = NTV2_CSCMatrix_SMPTEYOffset;
165  mPreOffset2 = NTV2_CSCMatrix_SMPTEYOffset;
166 
167  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
168  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
169  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
170  break;
171 
172  // RGB SMPTE range -> YCbCr Rec 601 (SD)
174  mA0 = 0.587006; // G -> Y
175  mA1 = 0.113983; // B -> Y
176  mA2 = 0.299011; // R -> Y
177  mB0 = -0.338837; // G -> Cb
178  mB1 = 0.511414; // B -> Cb
179  mB2 = -0.172577; // R -> Cb
180  mC0 = -0.428253; // G -> Cr
181  mC1 = -0.083160; // B -> Cr
182  mC2 = 0.511414; // R -> Cr
183 
184  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
185  mPreOffset1 = NTV2_CSCMatrix_SMPTEYOffset;
186  mPreOffset2 = NTV2_CSCMatrix_SMPTEYOffset;
187 
188  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
189  mPostOffsetB = NTV2_CSCMatrix_SMPTECOffset;
190  mPostOffsetC = NTV2_CSCMatrix_SMPTECOffset;
191  break;
192 
193 
194 
195  // YCbCr -> RGB full range Rec 709 (HD)
197  mA0 = 1.167786; // Y -> G
198  mA1 = -0.213898; // Cb -> G
199  mA2 = -0.534515; // Cr -> G
200  mB0 = 1.167786; // Y -> B
201  mB1 = 2.118591; // Cb -> B
202  mB2 = 0.000000; // Cr -> B
203  mC0 = 1.167786; // Y -> R
204  mC1 = 0.000000; // Cb -> R
205  mC2 = 1.797974; // Cr -> R
206 
207  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset; // YCbCr: "SMPTE" offsets
208  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
209  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
210 
211  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset; // full-range RGB: no offset
212  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
213  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
214  break;
215 
216  // YCbCr -> RGB full range Rec 2020
218  mA0 = 1.167786; // Y -> G
219  mA1 = -0.187877; // Cb -> G
220  mA2 = -0.652337; // Cr -> G
221  mB0 = 1.167786; // Y -> B
222  mB1 = 2.148061; // Cb -> B
223  mB2 = 0.000000; // Cr -> B
224  mC0 = 1.167786; // Y -> R
225  mC1 = 0.000000; // Cb -> R
226  mC2 = 1.683611; // Cr -> R
227 
228  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset; // YCbCr: "SMPTE" offsets
229  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
230  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
231 
232  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset; // full-range RGB: no offset
233  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
234  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
235  break;
236 
237  // YCbCr -> RGB full range Rec 601 (SD)
239  mA0 = 1.167786; // Y -> G
240  mA1 = -0.392944; // Cb -> G
241  mA2 = -0.815399; // Cr -> G
242  mB0 = 1.167786; // Y -> B
243  mB1 = 2.023163; // Cb -> B
244  mB2 = 0.000000; // Cr -> B
245  mC0 = 1.167786; // Y -> R
246  mC1 = 0.000000; // Cb -> R
247  mC2 = 1.600708; // Cr -> R
248 
249  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
250  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
251  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
252 
253  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset;
254  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
255  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
256  break;
257 
258  // YCbCr -> RGB SMPTE range Rec 709 (HD)
260  mA0 = 1.000000; // Y -> G
261  mA1 = -0.183167; // Cb -> G
262  mA2 = -0.457642; // Cr -> G
263  mB0 = 1.000000; // Y -> B
264  mB1 = 1.814148; // Cb -> B
265  mB2 = 0.000000; // Cr -> B
266  mC0 = 1.000000; // Y -> R
267  mC1 = 0.000000; // Cb -> R
268  mC2 = 1.539673; // Cr -> R
269 
270  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
271  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
272  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
273 
274  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
275  mPostOffsetB = NTV2_CSCMatrix_SMPTEYOffset;
276  mPostOffsetC = NTV2_CSCMatrix_SMPTEYOffset;
277  break;
278 
279  // YCbCr -> RGB SMPTE range Rec 2020
281  mA0 = 1.000000; // Y -> G
282  mA1 = -0.160889; // Cb -> G
283  mA2 = -0.558594; // Cr -> G
284  mB0 = 1.000000; // Y -> B
285  mB1 = 1.839386; // Cb -> B
286  mB2 = 0.000000; // Cr -> B
287  mC0 = 1.000000; // Y -> R
288  mC1 = 0.000000; // Cb -> R
289  mC2 = 1.441681; // Cr -> R
290 
291 
292  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
293  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
294  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
295 
296  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
297  mPostOffsetB = NTV2_CSCMatrix_SMPTEYOffset;
298  mPostOffsetC = NTV2_CSCMatrix_SMPTEYOffset;
299  break;
300 
301  // YCbCr -> RGB SMPTE range Rec 601 (SD)
303  mA0 = 1.000000; // Y -> G
304  mA1 = -0.336426; // Cb -> G
305  mA2 = -0.698181; // Cr -> G
306  mB0 = 1.000000; // Y -> B
307  mB1 = 1.732483; // Cb -> B
308  mB2 = 0.000000; // Cr -> B
309  mC0 = 1.000000; // Y -> R
310  mC1 = 0.000000; // Cb -> R
311  mC2 = 1.370728; // Cr -> R
312 
313  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
314  mPreOffset1 = NTV2_CSCMatrix_SMPTECOffset;
315  mPreOffset2 = NTV2_CSCMatrix_SMPTECOffset;
316 
317  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
318  mPostOffsetB = NTV2_CSCMatrix_SMPTEYOffset;
319  mPostOffsetC = NTV2_CSCMatrix_SMPTEYOffset;
320  break;
321 
322  // YCbCr Rec 601 (SD) -> YCbCr Rec 709 (HD)
324  mA0 = 1.00000000; // Y -> Y
325  mA1 = -0.11554975; // Cb -> Y
326  mA2 = -0.20793764; // Cr -> Y
327  mB0 = 0.00000000; // Y -> Cb
328  mB1 = 1.01863972; // Cb -> Cb
329  mB2 = 0.11461795; // Cr -> Cb
330  mC0 = 0.00000000; // Y -> Cr
331  mC1 = 0.07504945; // Cb -> Cr
332  mC2 = 1.02532707; // Cr -> Cr
333 
334  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset;
335  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
336  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
337 
338  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset;
339  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
340  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
341  break;
342 
343  // YCbCr Rec 709 (HD) -> YCbCr Rec 601 (SD)
345  mA0 = 1.00000000; // Y -> Y
346  mA1 = 0.09931166; // Cb -> Y
347  mA2 = 0.19169955; // Cr -> Y
348  mB0 = 0.00000000; // Y -> Cb
349  mB1 = 0.98985381; // Cb -> Cb
350  mB2 = -0.11065251; // Cr -> Cb
351  mC0 = 0.00000000; // Y -> Cr
352  mC1 = -0.07245296; // Cb -> Cr
353  mC2 = 0.98339782; // Cr -> Cr
354 
355  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset;
356  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
357  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
358 
359  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset;
360  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
361  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
362  break;
363 
364 
365 
366  // RGB Full range -> RGB SMPTE
368  mA0 = 0.856321; // Gf -> Gs
369  mA1 = 0.000000; // Bf -> Gs
370  mA2 = 0.000000; // Rf -> Gs
371  mB0 = 0.000000; // Gf -> Bs
372  mB1 = 0.856321; // Bf -> Bs
373  mB2 = 0.000000; // Rf -> Bs
374  mC0 = 0.000000; // Gf -> Rs
375  mC1 = 0.000000; // Bf -> Rs
376  mC2 = 0.856321; // Rf -> Rs
377 
378  mPreOffset0 = NTV2_CSCMatrix_ZeroOffset;
379  mPreOffset1 = NTV2_CSCMatrix_ZeroOffset;
380  mPreOffset2 = NTV2_CSCMatrix_ZeroOffset;
381 
382  mPostOffsetA = NTV2_CSCMatrix_SMPTEYOffset;
383  mPostOffsetB = NTV2_CSCMatrix_SMPTEYOffset;
384  mPostOffsetC = NTV2_CSCMatrix_SMPTEYOffset;
385  break;
386 
387  // RGB SMPTE range -> RGB Full
389  mA0 = 1.167786; // Gs -> Gf
390  mA1 = 0.000000; // Bs -> Gf
391  mA2 = 0.000000; // Rs -> Gf
392  mB0 = 0.000000; // Gs -> Bf
393  mB1 = 1.167786; // Bs -> Bf
394  mB2 = 0.000000; // Rs -> Bf
395  mC0 = 0.000000; // Gs -> Rf
396  mC1 = 0.000000; // Bs -> Rf
397  mC2 = 1.167786; // Rs -> Rf
398 
399  mPreOffset0 = NTV2_CSCMatrix_SMPTEYOffset;
400  mPreOffset1 = NTV2_CSCMatrix_SMPTEYOffset;
401  mPreOffset2 = NTV2_CSCMatrix_SMPTEYOffset;
402 
403  mPostOffsetA = NTV2_CSCMatrix_ZeroOffset;
404  mPostOffsetB = NTV2_CSCMatrix_ZeroOffset;
405  mPostOffsetC = NTV2_CSCMatrix_ZeroOffset;
406  break;
407  }
408 
409  mPreset = inPreset;
410 }
411 
412 
413 double CNTV2CSCMatrix::GetCoefficient (const NTV2CSCCoeffIndex inCoeffIndex) const
414 {
415  switch (inCoeffIndex)
416  {
417  case NTV2CSCCoeffIndex_A0: return mA0;
418  case NTV2CSCCoeffIndex_A1: return mA1;
419  case NTV2CSCCoeffIndex_A2: return mA2;
420  case NTV2CSCCoeffIndex_B0: return mB0;
421  case NTV2CSCCoeffIndex_B1: return mB1;
422  case NTV2CSCCoeffIndex_B2: return mB2;
423  case NTV2CSCCoeffIndex_C0: return mC0;
424  case NTV2CSCCoeffIndex_C1: return mC1;
425  case NTV2CSCCoeffIndex_C2: return mC2;
426  }
427  // Must never get here
428  NTV2_ASSERT (false && "Unhandled coefficient index");
429  return 0.0;
430 }
431 
432 
433 void CNTV2CSCMatrix::SetCoefficient (const NTV2CSCCoeffIndex inCoeffIndex, const double inCoefficient)
434 {
435  switch (inCoeffIndex)
436  {
437  case NTV2CSCCoeffIndex_A0: mA0 = inCoefficient; break;
438  case NTV2CSCCoeffIndex_A1: mA1 = inCoefficient; break;
439  case NTV2CSCCoeffIndex_A2: mA2 = inCoefficient; break;
440  case NTV2CSCCoeffIndex_B0: mB0 = inCoefficient; break;
441  case NTV2CSCCoeffIndex_B1: mB1 = inCoefficient; break;
442  case NTV2CSCCoeffIndex_B2: mB2 = inCoefficient; break;
443  case NTV2CSCCoeffIndex_C0: mC0 = inCoefficient; break;
444  case NTV2CSCCoeffIndex_C1: mC1 = inCoefficient; break;
445  case NTV2CSCCoeffIndex_C2: mC2 = inCoefficient; break;
446  }
447  mPreset = NTV2_Custom_Matrix;
448 }
449 
450 
451 int16_t CNTV2CSCMatrix::GetOffset (const NTV2CSCOffsetIndex inOffsetIndex) const
452 {
453  switch (inOffsetIndex)
454  {
455  case NTV2CSCOffsetIndex_Pre0: return mPreOffset0;
456  case NTV2CSCOffsetIndex_Pre1: return mPreOffset1;
457  case NTV2CSCOffsetIndex_Pre2: return mPreOffset2;
458  case NTV2CSCOffsetIndex_PostA: return mPostOffsetA;
459  case NTV2CSCOffsetIndex_PostB: return mPostOffsetB;
460  case NTV2CSCOffsetIndex_PostC: return mPostOffsetC;
461  }
462  // Must never get here
463  NTV2_ASSERT(false && "Unhandled offset index");
464  return 0;
465 }
466 
467 
468 void CNTV2CSCMatrix::SetOffset (const NTV2CSCOffsetIndex inOffsetIndex, const int16_t inOffset)
469 {
470  switch (inOffsetIndex)
471  {
472  case NTV2CSCOffsetIndex_Pre0: mPreOffset0 = inOffset; break;
473  case NTV2CSCOffsetIndex_Pre1: mPreOffset1 = inOffset; break;
474  case NTV2CSCOffsetIndex_Pre2: mPreOffset2 = inOffset; break;
475  case NTV2CSCOffsetIndex_PostA: mPostOffsetA = inOffset; break;
476  case NTV2CSCOffsetIndex_PostB: mPostOffsetB = inOffset; break;
477  case NTV2CSCOffsetIndex_PostC: mPostOffsetC = inOffset; break;
478  }
479  mPreset = NTV2_Custom_Matrix;
480 }
481 
482 
484 {
485  // clone the current settings
486  CNTV2CSCMatrix current (*this);
487 
488  // do matrix multiply
489  mA0 = (pre.mA0 * current.mA0) + (pre.mB0 * current.mA1) + (pre.mC0 * current.mA2);
490  mA1 = (pre.mA1 * current.mA0) + (pre.mB1 * current.mA1) + (pre.mC1 * current.mA2);
491  mA2 = (pre.mA2 * current.mA0) + (pre.mB2 * current.mA1) + (pre.mC2 * current.mA2);
492 
493  mB0 = (pre.mA0 * current.mB0) + (pre.mB0 * current.mB1) + (pre.mC0 * current.mB2);
494  mB1 = (pre.mA1 * current.mB0) + (pre.mB1 * current.mB1) + (pre.mC1 * current.mB2);
495  mB2 = (pre.mA2 * current.mB0) + (pre.mB2 * current.mB1) + (pre.mC2 * current.mB2);
496 
497  mC0 = (pre.mA0 * current.mC0) + (pre.mB0 * current.mC1) + (pre.mC0 * current.mC2);
498  mC1 = (pre.mA1 * current.mC0) + (pre.mB1 * current.mC1) + (pre.mC1 * current.mC2);
499  mC2 = (pre.mA2 * current.mC0) + (pre.mB2 * current.mC1) + (pre.mC2 * current.mC2);
500 
501  mPreset = NTV2_Custom_Matrix;
502 }
503 
504 
506 {
507  // clone the current settings
508  CNTV2CSCMatrix current (*this);
509 
510  // do matrix multiply
511  mA0 = (current.mA0 * post.mA0) + (current.mB0 * post.mA1) + (current.mC0 * post.mA2);
512  mA1 = (current.mA1 * post.mA0) + (current.mB1 * post.mA1) + (current.mC1 * post.mA2);
513  mA2 = (current.mA2 * post.mA0) + (current.mB2 * post.mA1) + (current.mC2 * post.mA2);
514 
515  mB0 = (current.mA0 * post.mB0) + (current.mB0 * post.mB1) + (current.mC0 * post.mB2);
516  mB1 = (current.mA1 * post.mB0) + (current.mB1 * post.mB1) + (current.mC1 * post.mB2);
517  mB2 = (current.mA2 * post.mB0) + (current.mB2 * post.mB1) + (current.mC2 * post.mB2);
518 
519  mC0 = (current.mA0 * post.mC0) + (current.mB0 * post.mC1) + (current.mC0 * post.mC2);
520  mC1 = (current.mA1 * post.mC0) + (current.mB1 * post.mC1) + (current.mC1 * post.mC2);
521  mC2 = (current.mA2 * post.mC0) + (current.mB2 * post.mC1) + (current.mC2 * post.mC2);
522 
523  mPreset = NTV2_Custom_Matrix;
524 }
525 
526 
527 void CNTV2CSCMatrix::SetGain (const double inGain0, const double inGain1, const double inGain2)
528 {
529  mA0 = inGain0;
530  mB1 = inGain1;
531  mC2 = inGain2;
532  mPreset = NTV2_Custom_Matrix;
533 }
534 
535 
536 void CNTV2CSCMatrix::SetHueRotate (const double inDegrees)
537 {
538  double rad = kPi * inDegrees / 180.0;
539  mB1 = cos (rad);
540  mB2 = sin (rad);
541  mC1 = -sin (rad);
542  mC2 = cos (rad);
543  mPreset = NTV2_Custom_Matrix;
544 }
545 
546 
547 void CNTV2CSCMatrix::SetPreOffsets (const int16_t inOffset0, const int16_t inOffset1, const int16_t inOffset2)
548 {
549  mPreOffset0 = inOffset0;
550  mPreOffset1 = inOffset1;
551  mPreOffset2 = inOffset2;
552  mPreset = NTV2_Custom_Matrix;
553 }
554 
555 
556 void CNTV2CSCMatrix::AddPreOffsets (const int16_t inOffset0, const int16_t inOffset1, const int16_t inOffset2)
557 {
558  mPreOffset0 += inOffset0;
559  mPreOffset1 += inOffset1;
560  mPreOffset2 += inOffset2;
561  mPreset = NTV2_Custom_Matrix;
562 }
563 
564 
565 void CNTV2CSCMatrix::SetPostOffsets (const int16_t inOffsetA, const int16_t inOffsetB, const int16_t inOffsetC)
566 {
567  mPostOffsetA = inOffsetA;
568  mPostOffsetB = inOffsetB;
569  mPostOffsetC = inOffsetC;
570  mPreset = NTV2_Custom_Matrix;
571 }
572 
573 void CNTV2CSCMatrix::AddPostOffsets (const int16_t inOffsetA, const int16_t inOffsetB, const int16_t inOffsetC)
574 {
575  mPostOffsetA += inOffsetA;
576  mPostOffsetB += inOffsetB;
577  mPostOffsetC += inOffsetC;
578  mPreset = NTV2_Custom_Matrix;
579 }
580 
581 
583 {
584  bool bResult = true; // assume positive result: now look for a reason to negate it
585 
586  if (mA0 != 1.0 || mA1 != 0.0 || mA2 != 0.0)
587  bResult = false;
588 
589  if (mB0 != 0.0 || mB1 != 1.0 || mB2 != 0.0)
590  bResult = false;
591 
592  if (mC0 != 0.0 || mC1 != 0.0 || mC2 != 1.0)
593  bResult = false;
594 
595  // note: we're NOT looking at offsets, so this test will return true for EITHER
596  // NTV2_Unity_Matrix or NTV2_Unity_SMPTE_Matrix
597  return bResult;
598 }
599 
600 
602 {
603  if ( (mA0 != rhs.mA0) || (mA1 != rhs.mA1) || (mA2 != rhs.mA2) )
604  return false;
605 
606  if ( (mB0 != rhs.mB0) || (mB1 != rhs.mB1) || (mB2 != rhs.mB2) )
607  return false;
608 
609  if ( (mC0 != rhs.mC0) || (mC1 != rhs.mC1) || (mC2 != rhs.mC2) )
610  return false;
611 
612  if ( (mPreOffset0 != rhs.mPreOffset0) || (mPreOffset1 != rhs.mPreOffset1) || (mPreOffset2 != rhs.mPreOffset2) )
613  return false;
614 
615  if ( (mPostOffsetA != rhs.mPostOffsetA) || (mPostOffsetB != rhs.mPostOffsetB) || (mPostOffsetC != rhs.mPostOffsetC) )
616  return false;
617 
618  return true;
619 }
620 
621 
622 bool CNTV2CSCMatrix::IsEqual (const CNTV2CSCMatrix & inCSCMatrix, const double inMaxDiff)
623 {
624  bool bResult = true; // assume positive result: now look for a reason to negate it
625 
626  if (!CoeffEqual(mA0, inCSCMatrix.mA0, inMaxDiff) || !CoeffEqual(mA1, inCSCMatrix.mA1, inMaxDiff) || !CoeffEqual(mA2, inCSCMatrix.mA2, inMaxDiff))
627  bResult = false;
628 
629  if (!CoeffEqual(mB0, inCSCMatrix.mB0, inMaxDiff) || !CoeffEqual(mB1, inCSCMatrix.mB1, inMaxDiff) || !CoeffEqual(mB2, inCSCMatrix.mB2, inMaxDiff))
630  bResult = false;
631 
632  if (!CoeffEqual(mC0, inCSCMatrix.mC0, inMaxDiff) || !CoeffEqual(mC1, inCSCMatrix.mC1, inMaxDiff) || !CoeffEqual(mC2, inCSCMatrix.mC2, inMaxDiff))
633  bResult = false;
634 
635  return bResult;
636 }
637 
638 
639 bool CNTV2CSCMatrix::CoeffEqual (const double inCoeff1, const double inCoeff2, const double inMaxDiff)
640 {
641  return ::fabs(inCoeff1 - inCoeff2) < inMaxDiff;
642 }
643 
ntv2cscmatrix.h
Declares the utility class for abstract color space matrix operations.
NTV2CSCCoeffIndex_A0
@ NTV2CSCCoeffIndex_A0
Proportion of input component 0 applied to A output.
Definition: ntv2cscmatrix.h:25
NTV2CSCOffsetIndex_Pre1
@ NTV2CSCOffsetIndex_Pre1
Definition: ntv2cscmatrix.h:42
NTV2_ASSERT
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:506
CNTV2CSCMatrix::InitMatrix
virtual void InitMatrix(const NTV2ColorSpaceMatrixType inPreset)
Replace the current matrix coefficients with a known set of coefficients.
Definition: ntv2cscmatrix.cpp:20
NTV2CSCOffsetIndex_PostC
@ NTV2CSCOffsetIndex_PostC
Definition: ntv2cscmatrix.h:47
CNTV2CSCMatrix
This class supports the color space conversion matrix described below.
Definition: ntv2cscmatrix.h:98
CNTV2CSCMatrix::operator==
virtual bool operator==(const CNTV2CSCMatrix &rhs) const
Returns true if the matrix coefficients and offsets EXACTLY match those of the specified instance.
Definition: ntv2cscmatrix.cpp:601
NTV2_YCbCr_to_GBRFull_Rec2020_Matrix
@ NTV2_YCbCr_to_GBRFull_Rec2020_Matrix
Definition: ntv2enums.h:3409
CNTV2CSCMatrix::SetHueRotate
virtual void SetHueRotate(const double inDegrees)
Set matrix for hue rotation.
Definition: ntv2cscmatrix.cpp:536
NTV2_YCbCrRec601_to_YCbCrRec709_Matrix
@ NTV2_YCbCrRec601_to_YCbCrRec709_Matrix
Definition: ntv2enums.h:3401
NTV2_YCbCr_to_GBRSMPTE_Rec601_Matrix
@ NTV2_YCbCr_to_GBRSMPTE_Rec601_Matrix
Definition: ntv2enums.h:3399
NTV2CSCCoeffIndex_C0
@ NTV2CSCCoeffIndex_C0
Proportion of input component 0 applied to C output.
Definition: ntv2cscmatrix.h:33
NTV2_CSCMatrix_SMPTECOffset
const int16_t NTV2_CSCMatrix_SMPTECOffset
Definition: ntv2cscmatrix.h:20
CNTV2CSCMatrix::CoeffEqual
virtual bool CoeffEqual(const double inCoeff1, const double inCoeff2, const double inMaxDiff)
Tests if two coefficients differ by less than the fiven tolerance.
Definition: ntv2cscmatrix.cpp:639
NTV2_GBRSMPTE_to_YCbCr_Rec709_Matrix
@ NTV2_GBRSMPTE_to_YCbCr_Rec709_Matrix
Definition: ntv2enums.h:3393
NTV2CSCOffsetIndex_PostA
@ NTV2CSCOffsetIndex_PostA
Definition: ntv2cscmatrix.h:45
NTV2_YCbCr_to_GBRFull_Rec709_Matrix
@ NTV2_YCbCr_to_GBRFull_Rec709_Matrix
Definition: ntv2enums.h:3396
CNTV2CSCMatrix::SetOffset
virtual void SetOffset(const NTV2CSCOffsetIndex inOffsetIndex, const int16_t inOffset)
Changes the specified offset to the given value.
Definition: ntv2cscmatrix.cpp:468
NTV2_CSCMatrix_SMPTEYOffset
const int16_t NTV2_CSCMatrix_SMPTEYOffset
Definition: ntv2cscmatrix.h:19
NTV2_GBRFull_to_GBRSMPTE_Matrix
@ NTV2_GBRFull_to_GBRSMPTE_Matrix
Definition: ntv2enums.h:3404
CNTV2CSCMatrix::CNTV2CSCMatrix
CNTV2CSCMatrix(const NTV2ColorSpaceMatrixType inPreset=NTV2_Unity_Matrix)
Instantiates and initializes the instance with a known set of coefficients.
Definition: ntv2cscmatrix.cpp:14
NTV2_GBRSMPTE_to_YCbCr_Rec2020_Matrix
@ NTV2_GBRSMPTE_to_YCbCr_Rec2020_Matrix
Definition: ntv2enums.h:3408
NTV2_Custom_Matrix
@ NTV2_Custom_Matrix
Definition: ntv2enums.h:3385
NTV2_CSCMatrix_ZeroOffset
const int16_t NTV2_CSCMatrix_ZeroOffset
Definition: ntv2cscmatrix.h:18
NTV2CSCCoeffIndex_B0
@ NTV2CSCCoeffIndex_B0
Proportion of input component 0 applied to B output.
Definition: ntv2cscmatrix.h:29
NTV2CSCCoeffIndex
enum NTV2CSCCoeff NTV2CSCCoeffIndex
NTV2CSCCoeffIndex_C2
@ NTV2CSCCoeffIndex_C2
Proportion of input component 2 applied to C output.
Definition: ntv2cscmatrix.h:35
CNTV2CSCMatrix::PostMultiply
virtual void PostMultiply(const CNTV2CSCMatrix &inPostInstance)
Post-multiply the current 3x3 matrix by the matrix of the given instance.
Definition: ntv2cscmatrix.cpp:505
CNTV2CSCMatrix::GetCoefficient
virtual double GetCoefficient(const NTV2CSCCoeffIndex inCoeffIndex) const
Returns the value of a requested matrix coefficient.
Definition: ntv2cscmatrix.cpp:413
NTV2_Unity_Matrix
@ NTV2_Unity_Matrix
Definition: ntv2enums.h:3387
CNTV2CSCMatrix::SetCoefficient
virtual void SetCoefficient(const NTV2CSCCoeffIndex inCoeffIndex, const double inCoefficient)
Changes the specified matrix coefficient to the given value.
Definition: ntv2cscmatrix.cpp:433
CNTV2CSCMatrix::SetGain
virtual void SetGain(const double inGain0, const double inGain1, const double inGain2)
Set the matrix diagonals (gains).
Definition: ntv2cscmatrix.cpp:527
NTV2CSCCoeffIndex_C1
@ NTV2CSCCoeffIndex_C1
Proportion of input component 1 applied to C output.
Definition: ntv2cscmatrix.h:34
NTV2CSCOffsetIndex
enum NTV2CSCOffset NTV2CSCOffsetIndex
CNTV2CSCMatrix::AddPostOffsets
virtual void AddPostOffsets(const int16_t inIncrementA, const int16_t inIncrementB, const int16_t inIncrementC)
Add post-offsets.
Definition: ntv2cscmatrix.cpp:573
NTV2CSCOffsetIndex_Pre0
@ NTV2CSCOffsetIndex_Pre0
Definition: ntv2cscmatrix.h:41
CNTV2CSCMatrix::GetOffset
virtual int16_t GetOffset(const NTV2CSCOffsetIndex inOffsetIndex) const
Returns the value of a requested offset.
Definition: ntv2cscmatrix.cpp:451
NTV2_GBRSMPTE_to_GBRFull_Matrix
@ NTV2_GBRSMPTE_to_GBRFull_Matrix
Definition: ntv2enums.h:3405
NTV2_GBRFull_to_YCbCr_Rec2020_Matrix
@ NTV2_GBRFull_to_YCbCr_Rec2020_Matrix
Definition: ntv2enums.h:3407
CNTV2CSCMatrix::IsUnityMatrix
virtual bool IsUnityMatrix(void)
Returns 'true' if this CSC Matrix has unity matrix coefficients.
Definition: ntv2cscmatrix.cpp:582
NTV2_YCbCr_to_GBRFull_Rec601_Matrix
@ NTV2_YCbCr_to_GBRFull_Rec601_Matrix
Definition: ntv2enums.h:3397
CNTV2CSCMatrix::IsEqual
virtual bool IsEqual(const CNTV2CSCMatrix &inCSCMatrix, const double inMaxDiff=NTV2CSCMatrix_MaxCoeffDiff)
Tests if the matrix coefficients can all be considered equal to those of the specified instance,...
Definition: ntv2cscmatrix.cpp:622
NTV2CSCOffsetIndex_Pre2
@ NTV2CSCOffsetIndex_Pre2
Definition: ntv2cscmatrix.h:43
CNTV2CSCMatrix::AddPreOffsets
virtual void AddPreOffsets(const int16_t inIncrement0, const int16_t inIncrement1, const int16_t inIncrement2)
Add pre-offsets.
Definition: ntv2cscmatrix.cpp:556
NTV2_YCbCrRec709_to_YCbCrRec601_Matrix
@ NTV2_YCbCrRec709_to_YCbCrRec601_Matrix
Definition: ntv2enums.h:3402
NTV2_GBRFull_to_YCbCr_Rec601_Matrix
@ NTV2_GBRFull_to_YCbCr_Rec601_Matrix
Definition: ntv2enums.h:3392
NTV2_GBRFull_to_YCbCr_Rec709_Matrix
@ NTV2_GBRFull_to_YCbCr_Rec709_Matrix
Definition: ntv2enums.h:3391
NTV2_YCbCr_to_GBRSMPTE_Rec2020_Matrix
@ NTV2_YCbCr_to_GBRSMPTE_Rec2020_Matrix
Definition: ntv2enums.h:3410
kPi
static const double kPi(3.1415926536)
NTV2ColorSpaceMatrixType
NTV2ColorSpaceMatrixType
Definition: ntv2enums.h:3378
NTV2_YCbCr_to_GBRSMPTE_Rec709_Matrix
@ NTV2_YCbCr_to_GBRSMPTE_Rec709_Matrix
Definition: ntv2enums.h:3398
NTV2CSCCoeffIndex_B2
@ NTV2CSCCoeffIndex_B2
Proportion of input component 2 applied to B output.
Definition: ntv2cscmatrix.h:31
NTV2CSCCoeffIndex_A2
@ NTV2CSCCoeffIndex_A2
Proportion of input component 2 applied to A output.
Definition: ntv2cscmatrix.h:27
CNTV2CSCMatrix::SetPreOffsets
virtual void SetPreOffsets(const int16_t inOffset0, const int16_t inOffset1, const int16_t inOffset2)
Set pre-offsets.
Definition: ntv2cscmatrix.cpp:547
NTV2CSCCoeffIndex_A1
@ NTV2CSCCoeffIndex_A1
Proportion of input component 1 applied to A output.
Definition: ntv2cscmatrix.h:26
NTV2_GBRSMPTE_to_YCbCr_Rec601_Matrix
@ NTV2_GBRSMPTE_to_YCbCr_Rec601_Matrix
Definition: ntv2enums.h:3394
CNTV2CSCMatrix::PreMultiply
virtual void PreMultiply(const CNTV2CSCMatrix &inPreInstance)
Pre-multiply the current 3x3 matrix by the matrix of the given instance.
Definition: ntv2cscmatrix.cpp:483
NTV2CSCCoeffIndex_B1
@ NTV2CSCCoeffIndex_B1
Proportion of input component 1 applied to B output.
Definition: ntv2cscmatrix.h:30
NTV2CSCOffsetIndex_PostB
@ NTV2CSCOffsetIndex_PostB
Definition: ntv2cscmatrix.h:46
CNTV2CSCMatrix::SetPostOffsets
virtual void SetPostOffsets(const int16_t inOffsetA, const int16_t inOffsetB, const int16_t inOffsetC)
Set post-offsets.
Definition: ntv2cscmatrix.cpp:565
NTV2_Unity_SMPTE_Matrix
@ NTV2_Unity_SMPTE_Matrix
Definition: ntv2enums.h:3388