1*3ac0a46fSAndroid Build Coastguard Worker //---------------------------------------------------------------------------------
2*3ac0a46fSAndroid Build Coastguard Worker //
3*3ac0a46fSAndroid Build Coastguard Worker // Little Color Management System
4*3ac0a46fSAndroid Build Coastguard Worker // Copyright (c) 1998-2023 Marti Maria Saguer
5*3ac0a46fSAndroid Build Coastguard Worker //
6*3ac0a46fSAndroid Build Coastguard Worker // Permission is hereby granted, free of charge, to any person obtaining
7*3ac0a46fSAndroid Build Coastguard Worker // a copy of this software and associated documentation files (the "Software"),
8*3ac0a46fSAndroid Build Coastguard Worker // to deal in the Software without restriction, including without limitation
9*3ac0a46fSAndroid Build Coastguard Worker // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*3ac0a46fSAndroid Build Coastguard Worker // and/or sell copies of the Software, and to permit persons to whom the Software
11*3ac0a46fSAndroid Build Coastguard Worker // is furnished to do so, subject to the following conditions:
12*3ac0a46fSAndroid Build Coastguard Worker //
13*3ac0a46fSAndroid Build Coastguard Worker // The above copyright notice and this permission notice shall be included in
14*3ac0a46fSAndroid Build Coastguard Worker // all copies or substantial portions of the Software.
15*3ac0a46fSAndroid Build Coastguard Worker //
16*3ac0a46fSAndroid Build Coastguard Worker // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*3ac0a46fSAndroid Build Coastguard Worker // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18*3ac0a46fSAndroid Build Coastguard Worker // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*3ac0a46fSAndroid Build Coastguard Worker // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20*3ac0a46fSAndroid Build Coastguard Worker // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21*3ac0a46fSAndroid Build Coastguard Worker // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22*3ac0a46fSAndroid Build Coastguard Worker // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*3ac0a46fSAndroid Build Coastguard Worker //
24*3ac0a46fSAndroid Build Coastguard Worker //---------------------------------------------------------------------------------
25*3ac0a46fSAndroid Build Coastguard Worker //
26*3ac0a46fSAndroid Build Coastguard Worker
27*3ac0a46fSAndroid Build Coastguard Worker #include "lcms2_internal.h"
28*3ac0a46fSAndroid Build Coastguard Worker
29*3ac0a46fSAndroid Build Coastguard Worker
30*3ac0a46fSAndroid Build Coastguard Worker // ------------------------------------------------------------------------
31*3ac0a46fSAndroid Build Coastguard Worker
32*3ac0a46fSAndroid Build Coastguard Worker // Gamut boundary description by using Jan Morovic's Segment maxima method
33*3ac0a46fSAndroid Build Coastguard Worker // Many thanks to Jan for allowing me to use his algorithm.
34*3ac0a46fSAndroid Build Coastguard Worker
35*3ac0a46fSAndroid Build Coastguard Worker // r = C*
36*3ac0a46fSAndroid Build Coastguard Worker // alpha = Hab
37*3ac0a46fSAndroid Build Coastguard Worker // theta = L*
38*3ac0a46fSAndroid Build Coastguard Worker
39*3ac0a46fSAndroid Build Coastguard Worker #define SECTORS 16 // number of divisions in alpha and theta
40*3ac0a46fSAndroid Build Coastguard Worker
41*3ac0a46fSAndroid Build Coastguard Worker // Spherical coordinates
42*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
43*3ac0a46fSAndroid Build Coastguard Worker
44*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number r;
45*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number alpha;
46*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number theta;
47*3ac0a46fSAndroid Build Coastguard Worker
48*3ac0a46fSAndroid Build Coastguard Worker } cmsSpherical;
49*3ac0a46fSAndroid Build Coastguard Worker
50*3ac0a46fSAndroid Build Coastguard Worker typedef enum {
51*3ac0a46fSAndroid Build Coastguard Worker GP_EMPTY,
52*3ac0a46fSAndroid Build Coastguard Worker GP_SPECIFIED,
53*3ac0a46fSAndroid Build Coastguard Worker GP_MODELED
54*3ac0a46fSAndroid Build Coastguard Worker
55*3ac0a46fSAndroid Build Coastguard Worker } GDBPointType;
56*3ac0a46fSAndroid Build Coastguard Worker
57*3ac0a46fSAndroid Build Coastguard Worker
58*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
59*3ac0a46fSAndroid Build Coastguard Worker
60*3ac0a46fSAndroid Build Coastguard Worker GDBPointType Type;
61*3ac0a46fSAndroid Build Coastguard Worker cmsSpherical p; // Keep also alpha & theta of maximum
62*3ac0a46fSAndroid Build Coastguard Worker
63*3ac0a46fSAndroid Build Coastguard Worker } cmsGDBPoint;
64*3ac0a46fSAndroid Build Coastguard Worker
65*3ac0a46fSAndroid Build Coastguard Worker
66*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
67*3ac0a46fSAndroid Build Coastguard Worker
68*3ac0a46fSAndroid Build Coastguard Worker cmsContext ContextID;
69*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint Gamut[SECTORS][SECTORS];
70*3ac0a46fSAndroid Build Coastguard Worker
71*3ac0a46fSAndroid Build Coastguard Worker } cmsGDB;
72*3ac0a46fSAndroid Build Coastguard Worker
73*3ac0a46fSAndroid Build Coastguard Worker
74*3ac0a46fSAndroid Build Coastguard Worker // A line using the parametric form
75*3ac0a46fSAndroid Build Coastguard Worker // P = a + t*u
76*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
77*3ac0a46fSAndroid Build Coastguard Worker
78*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 a;
79*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 u;
80*3ac0a46fSAndroid Build Coastguard Worker
81*3ac0a46fSAndroid Build Coastguard Worker } cmsLine;
82*3ac0a46fSAndroid Build Coastguard Worker
83*3ac0a46fSAndroid Build Coastguard Worker
84*3ac0a46fSAndroid Build Coastguard Worker // A plane using the parametric form
85*3ac0a46fSAndroid Build Coastguard Worker // Q = b + r*v + s*w
86*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
87*3ac0a46fSAndroid Build Coastguard Worker
88*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 b;
89*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 v;
90*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 w;
91*3ac0a46fSAndroid Build Coastguard Worker
92*3ac0a46fSAndroid Build Coastguard Worker } cmsPlane;
93*3ac0a46fSAndroid Build Coastguard Worker
94*3ac0a46fSAndroid Build Coastguard Worker
95*3ac0a46fSAndroid Build Coastguard Worker
96*3ac0a46fSAndroid Build Coastguard Worker // --------------------------------------------------------------------------------------------
97*3ac0a46fSAndroid Build Coastguard Worker
98*3ac0a46fSAndroid Build Coastguard Worker // ATAN2() which always returns degree positive numbers
99*3ac0a46fSAndroid Build Coastguard Worker
100*3ac0a46fSAndroid Build Coastguard Worker static
_cmsAtan2(cmsFloat64Number y,cmsFloat64Number x)101*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number _cmsAtan2(cmsFloat64Number y, cmsFloat64Number x)
102*3ac0a46fSAndroid Build Coastguard Worker {
103*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number a;
104*3ac0a46fSAndroid Build Coastguard Worker
105*3ac0a46fSAndroid Build Coastguard Worker // Deal with undefined case
106*3ac0a46fSAndroid Build Coastguard Worker if (x == 0.0 && y == 0.0) return 0;
107*3ac0a46fSAndroid Build Coastguard Worker
108*3ac0a46fSAndroid Build Coastguard Worker a = (atan2(y, x) * 180.0) / M_PI;
109*3ac0a46fSAndroid Build Coastguard Worker
110*3ac0a46fSAndroid Build Coastguard Worker while (a < 0) {
111*3ac0a46fSAndroid Build Coastguard Worker a += 360;
112*3ac0a46fSAndroid Build Coastguard Worker }
113*3ac0a46fSAndroid Build Coastguard Worker
114*3ac0a46fSAndroid Build Coastguard Worker return a;
115*3ac0a46fSAndroid Build Coastguard Worker }
116*3ac0a46fSAndroid Build Coastguard Worker
117*3ac0a46fSAndroid Build Coastguard Worker // Convert to spherical coordinates
118*3ac0a46fSAndroid Build Coastguard Worker static
ToSpherical(cmsSpherical * sp,const cmsVEC3 * v)119*3ac0a46fSAndroid Build Coastguard Worker void ToSpherical(cmsSpherical* sp, const cmsVEC3* v)
120*3ac0a46fSAndroid Build Coastguard Worker {
121*3ac0a46fSAndroid Build Coastguard Worker
122*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number L, a, b;
123*3ac0a46fSAndroid Build Coastguard Worker
124*3ac0a46fSAndroid Build Coastguard Worker L = v ->n[VX];
125*3ac0a46fSAndroid Build Coastguard Worker a = v ->n[VY];
126*3ac0a46fSAndroid Build Coastguard Worker b = v ->n[VZ];
127*3ac0a46fSAndroid Build Coastguard Worker
128*3ac0a46fSAndroid Build Coastguard Worker sp ->r = sqrt( L*L + a*a + b*b );
129*3ac0a46fSAndroid Build Coastguard Worker
130*3ac0a46fSAndroid Build Coastguard Worker if (sp ->r == 0) {
131*3ac0a46fSAndroid Build Coastguard Worker sp ->alpha = sp ->theta = 0;
132*3ac0a46fSAndroid Build Coastguard Worker return;
133*3ac0a46fSAndroid Build Coastguard Worker }
134*3ac0a46fSAndroid Build Coastguard Worker
135*3ac0a46fSAndroid Build Coastguard Worker sp ->alpha = _cmsAtan2(a, b);
136*3ac0a46fSAndroid Build Coastguard Worker sp ->theta = _cmsAtan2(sqrt(a*a + b*b), L);
137*3ac0a46fSAndroid Build Coastguard Worker }
138*3ac0a46fSAndroid Build Coastguard Worker
139*3ac0a46fSAndroid Build Coastguard Worker
140*3ac0a46fSAndroid Build Coastguard Worker // Convert to cartesian from spherical
141*3ac0a46fSAndroid Build Coastguard Worker static
ToCartesian(cmsVEC3 * v,const cmsSpherical * sp)142*3ac0a46fSAndroid Build Coastguard Worker void ToCartesian(cmsVEC3* v, const cmsSpherical* sp)
143*3ac0a46fSAndroid Build Coastguard Worker {
144*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number sin_alpha;
145*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number cos_alpha;
146*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number sin_theta;
147*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number cos_theta;
148*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number L, a, b;
149*3ac0a46fSAndroid Build Coastguard Worker
150*3ac0a46fSAndroid Build Coastguard Worker sin_alpha = sin((M_PI * sp ->alpha) / 180.0);
151*3ac0a46fSAndroid Build Coastguard Worker cos_alpha = cos((M_PI * sp ->alpha) / 180.0);
152*3ac0a46fSAndroid Build Coastguard Worker sin_theta = sin((M_PI * sp ->theta) / 180.0);
153*3ac0a46fSAndroid Build Coastguard Worker cos_theta = cos((M_PI * sp ->theta) / 180.0);
154*3ac0a46fSAndroid Build Coastguard Worker
155*3ac0a46fSAndroid Build Coastguard Worker a = sp ->r * sin_theta * sin_alpha;
156*3ac0a46fSAndroid Build Coastguard Worker b = sp ->r * sin_theta * cos_alpha;
157*3ac0a46fSAndroid Build Coastguard Worker L = sp ->r * cos_theta;
158*3ac0a46fSAndroid Build Coastguard Worker
159*3ac0a46fSAndroid Build Coastguard Worker v ->n[VX] = L;
160*3ac0a46fSAndroid Build Coastguard Worker v ->n[VY] = a;
161*3ac0a46fSAndroid Build Coastguard Worker v ->n[VZ] = b;
162*3ac0a46fSAndroid Build Coastguard Worker }
163*3ac0a46fSAndroid Build Coastguard Worker
164*3ac0a46fSAndroid Build Coastguard Worker
165*3ac0a46fSAndroid Build Coastguard Worker // Quantize sector of a spherical coordinate. Saturate 360, 180 to last sector
166*3ac0a46fSAndroid Build Coastguard Worker // The limits are the centers of each sector, so
167*3ac0a46fSAndroid Build Coastguard Worker static
QuantizeToSector(const cmsSpherical * sp,int * alpha,int * theta)168*3ac0a46fSAndroid Build Coastguard Worker void QuantizeToSector(const cmsSpherical* sp, int* alpha, int* theta)
169*3ac0a46fSAndroid Build Coastguard Worker {
170*3ac0a46fSAndroid Build Coastguard Worker *alpha = (int) floor(((sp->alpha * (SECTORS)) / 360.0) );
171*3ac0a46fSAndroid Build Coastguard Worker *theta = (int) floor(((sp->theta * (SECTORS)) / 180.0) );
172*3ac0a46fSAndroid Build Coastguard Worker
173*3ac0a46fSAndroid Build Coastguard Worker if (*alpha >= SECTORS)
174*3ac0a46fSAndroid Build Coastguard Worker *alpha = SECTORS-1;
175*3ac0a46fSAndroid Build Coastguard Worker if (*theta >= SECTORS)
176*3ac0a46fSAndroid Build Coastguard Worker *theta = SECTORS-1;
177*3ac0a46fSAndroid Build Coastguard Worker }
178*3ac0a46fSAndroid Build Coastguard Worker
179*3ac0a46fSAndroid Build Coastguard Worker
180*3ac0a46fSAndroid Build Coastguard Worker // Line determined by 2 points
181*3ac0a46fSAndroid Build Coastguard Worker static
LineOf2Points(cmsLine * line,cmsVEC3 * a,cmsVEC3 * b)182*3ac0a46fSAndroid Build Coastguard Worker void LineOf2Points(cmsLine* line, cmsVEC3* a, cmsVEC3* b)
183*3ac0a46fSAndroid Build Coastguard Worker {
184*3ac0a46fSAndroid Build Coastguard Worker
185*3ac0a46fSAndroid Build Coastguard Worker _cmsVEC3init(&line ->a, a ->n[VX], a ->n[VY], a ->n[VZ]);
186*3ac0a46fSAndroid Build Coastguard Worker _cmsVEC3init(&line ->u, b ->n[VX] - a ->n[VX],
187*3ac0a46fSAndroid Build Coastguard Worker b ->n[VY] - a ->n[VY],
188*3ac0a46fSAndroid Build Coastguard Worker b ->n[VZ] - a ->n[VZ]);
189*3ac0a46fSAndroid Build Coastguard Worker }
190*3ac0a46fSAndroid Build Coastguard Worker
191*3ac0a46fSAndroid Build Coastguard Worker
192*3ac0a46fSAndroid Build Coastguard Worker // Evaluate parametric line
193*3ac0a46fSAndroid Build Coastguard Worker static
GetPointOfLine(cmsVEC3 * p,const cmsLine * line,cmsFloat64Number t)194*3ac0a46fSAndroid Build Coastguard Worker void GetPointOfLine(cmsVEC3* p, const cmsLine* line, cmsFloat64Number t)
195*3ac0a46fSAndroid Build Coastguard Worker {
196*3ac0a46fSAndroid Build Coastguard Worker p ->n[VX] = line ->a.n[VX] + t * line->u.n[VX];
197*3ac0a46fSAndroid Build Coastguard Worker p ->n[VY] = line ->a.n[VY] + t * line->u.n[VY];
198*3ac0a46fSAndroid Build Coastguard Worker p ->n[VZ] = line ->a.n[VZ] + t * line->u.n[VZ];
199*3ac0a46fSAndroid Build Coastguard Worker }
200*3ac0a46fSAndroid Build Coastguard Worker
201*3ac0a46fSAndroid Build Coastguard Worker
202*3ac0a46fSAndroid Build Coastguard Worker
203*3ac0a46fSAndroid Build Coastguard Worker /*
204*3ac0a46fSAndroid Build Coastguard Worker Closest point in sector line1 to sector line2 (both are defined as 0 <=t <= 1)
205*3ac0a46fSAndroid Build Coastguard Worker http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
206*3ac0a46fSAndroid Build Coastguard Worker
207*3ac0a46fSAndroid Build Coastguard Worker Copyright 2001, softSurfer (www.softsurfer.com)
208*3ac0a46fSAndroid Build Coastguard Worker This code may be freely used and modified for any purpose
209*3ac0a46fSAndroid Build Coastguard Worker providing that this copyright notice is included with it.
210*3ac0a46fSAndroid Build Coastguard Worker SoftSurfer makes no warranty for this code, and cannot be held
211*3ac0a46fSAndroid Build Coastguard Worker liable for any real or imagined damage resulting from its use.
212*3ac0a46fSAndroid Build Coastguard Worker Users of this code must verify correctness for their application.
213*3ac0a46fSAndroid Build Coastguard Worker
214*3ac0a46fSAndroid Build Coastguard Worker */
215*3ac0a46fSAndroid Build Coastguard Worker
216*3ac0a46fSAndroid Build Coastguard Worker static
ClosestLineToLine(cmsVEC3 * r,const cmsLine * line1,const cmsLine * line2)217*3ac0a46fSAndroid Build Coastguard Worker cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2)
218*3ac0a46fSAndroid Build Coastguard Worker {
219*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number a, b, c, d, e, D;
220*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number sc, sN, sD;
221*3ac0a46fSAndroid Build Coastguard Worker //cmsFloat64Number tc; // left for future use
222*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number tN, tD;
223*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 w0;
224*3ac0a46fSAndroid Build Coastguard Worker
225*3ac0a46fSAndroid Build Coastguard Worker _cmsVEC3minus(&w0, &line1 ->a, &line2 ->a);
226*3ac0a46fSAndroid Build Coastguard Worker
227*3ac0a46fSAndroid Build Coastguard Worker a = _cmsVEC3dot(&line1 ->u, &line1 ->u);
228*3ac0a46fSAndroid Build Coastguard Worker b = _cmsVEC3dot(&line1 ->u, &line2 ->u);
229*3ac0a46fSAndroid Build Coastguard Worker c = _cmsVEC3dot(&line2 ->u, &line2 ->u);
230*3ac0a46fSAndroid Build Coastguard Worker d = _cmsVEC3dot(&line1 ->u, &w0);
231*3ac0a46fSAndroid Build Coastguard Worker e = _cmsVEC3dot(&line2 ->u, &w0);
232*3ac0a46fSAndroid Build Coastguard Worker
233*3ac0a46fSAndroid Build Coastguard Worker D = a*c - b * b; // Denominator
234*3ac0a46fSAndroid Build Coastguard Worker sD = tD = D; // default sD = D >= 0
235*3ac0a46fSAndroid Build Coastguard Worker
236*3ac0a46fSAndroid Build Coastguard Worker if (D < MATRIX_DET_TOLERANCE) { // the lines are almost parallel
237*3ac0a46fSAndroid Build Coastguard Worker
238*3ac0a46fSAndroid Build Coastguard Worker sN = 0.0; // force using point P0 on segment S1
239*3ac0a46fSAndroid Build Coastguard Worker sD = 1.0; // to prevent possible division by 0.0 later
240*3ac0a46fSAndroid Build Coastguard Worker tN = e;
241*3ac0a46fSAndroid Build Coastguard Worker tD = c;
242*3ac0a46fSAndroid Build Coastguard Worker }
243*3ac0a46fSAndroid Build Coastguard Worker else { // get the closest points on the infinite lines
244*3ac0a46fSAndroid Build Coastguard Worker
245*3ac0a46fSAndroid Build Coastguard Worker sN = (b*e - c*d);
246*3ac0a46fSAndroid Build Coastguard Worker tN = (a*e - b*d);
247*3ac0a46fSAndroid Build Coastguard Worker
248*3ac0a46fSAndroid Build Coastguard Worker if (sN < 0.0) { // sc < 0 => the s=0 edge is visible
249*3ac0a46fSAndroid Build Coastguard Worker
250*3ac0a46fSAndroid Build Coastguard Worker sN = 0.0;
251*3ac0a46fSAndroid Build Coastguard Worker tN = e;
252*3ac0a46fSAndroid Build Coastguard Worker tD = c;
253*3ac0a46fSAndroid Build Coastguard Worker }
254*3ac0a46fSAndroid Build Coastguard Worker else if (sN > sD) { // sc > 1 => the s=1 edge is visible
255*3ac0a46fSAndroid Build Coastguard Worker sN = sD;
256*3ac0a46fSAndroid Build Coastguard Worker tN = e + b;
257*3ac0a46fSAndroid Build Coastguard Worker tD = c;
258*3ac0a46fSAndroid Build Coastguard Worker }
259*3ac0a46fSAndroid Build Coastguard Worker }
260*3ac0a46fSAndroid Build Coastguard Worker
261*3ac0a46fSAndroid Build Coastguard Worker if (tN < 0.0) { // tc < 0 => the t=0 edge is visible
262*3ac0a46fSAndroid Build Coastguard Worker
263*3ac0a46fSAndroid Build Coastguard Worker tN = 0.0;
264*3ac0a46fSAndroid Build Coastguard Worker // recompute sc for this edge
265*3ac0a46fSAndroid Build Coastguard Worker if (-d < 0.0)
266*3ac0a46fSAndroid Build Coastguard Worker sN = 0.0;
267*3ac0a46fSAndroid Build Coastguard Worker else if (-d > a)
268*3ac0a46fSAndroid Build Coastguard Worker sN = sD;
269*3ac0a46fSAndroid Build Coastguard Worker else {
270*3ac0a46fSAndroid Build Coastguard Worker sN = -d;
271*3ac0a46fSAndroid Build Coastguard Worker sD = a;
272*3ac0a46fSAndroid Build Coastguard Worker }
273*3ac0a46fSAndroid Build Coastguard Worker }
274*3ac0a46fSAndroid Build Coastguard Worker else if (tN > tD) { // tc > 1 => the t=1 edge is visible
275*3ac0a46fSAndroid Build Coastguard Worker
276*3ac0a46fSAndroid Build Coastguard Worker tN = tD;
277*3ac0a46fSAndroid Build Coastguard Worker
278*3ac0a46fSAndroid Build Coastguard Worker // recompute sc for this edge
279*3ac0a46fSAndroid Build Coastguard Worker if ((-d + b) < 0.0)
280*3ac0a46fSAndroid Build Coastguard Worker sN = 0;
281*3ac0a46fSAndroid Build Coastguard Worker else if ((-d + b) > a)
282*3ac0a46fSAndroid Build Coastguard Worker sN = sD;
283*3ac0a46fSAndroid Build Coastguard Worker else {
284*3ac0a46fSAndroid Build Coastguard Worker sN = (-d + b);
285*3ac0a46fSAndroid Build Coastguard Worker sD = a;
286*3ac0a46fSAndroid Build Coastguard Worker }
287*3ac0a46fSAndroid Build Coastguard Worker }
288*3ac0a46fSAndroid Build Coastguard Worker // finally do the division to get sc and tc
289*3ac0a46fSAndroid Build Coastguard Worker sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD);
290*3ac0a46fSAndroid Build Coastguard Worker //tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); // left for future use.
291*3ac0a46fSAndroid Build Coastguard Worker
292*3ac0a46fSAndroid Build Coastguard Worker GetPointOfLine(r, line1, sc);
293*3ac0a46fSAndroid Build Coastguard Worker return TRUE;
294*3ac0a46fSAndroid Build Coastguard Worker }
295*3ac0a46fSAndroid Build Coastguard Worker
296*3ac0a46fSAndroid Build Coastguard Worker
297*3ac0a46fSAndroid Build Coastguard Worker
298*3ac0a46fSAndroid Build Coastguard Worker // ------------------------------------------------------------------ Wrapper
299*3ac0a46fSAndroid Build Coastguard Worker
300*3ac0a46fSAndroid Build Coastguard Worker
301*3ac0a46fSAndroid Build Coastguard Worker // Allocate & free structure
cmsGBDAlloc(cmsContext ContextID)302*3ac0a46fSAndroid Build Coastguard Worker cmsHANDLE CMSEXPORT cmsGBDAlloc(cmsContext ContextID)
303*3ac0a46fSAndroid Build Coastguard Worker {
304*3ac0a46fSAndroid Build Coastguard Worker cmsGDB* gbd = (cmsGDB*) _cmsMallocZero(ContextID, sizeof(cmsGDB));
305*3ac0a46fSAndroid Build Coastguard Worker if (gbd == NULL) return NULL;
306*3ac0a46fSAndroid Build Coastguard Worker
307*3ac0a46fSAndroid Build Coastguard Worker gbd -> ContextID = ContextID;
308*3ac0a46fSAndroid Build Coastguard Worker
309*3ac0a46fSAndroid Build Coastguard Worker return (cmsHANDLE) gbd;
310*3ac0a46fSAndroid Build Coastguard Worker }
311*3ac0a46fSAndroid Build Coastguard Worker
312*3ac0a46fSAndroid Build Coastguard Worker
cmsGBDFree(cmsHANDLE hGBD)313*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD)
314*3ac0a46fSAndroid Build Coastguard Worker {
315*3ac0a46fSAndroid Build Coastguard Worker cmsGDB* gbd = (cmsGDB*) hGBD;
316*3ac0a46fSAndroid Build Coastguard Worker if (hGBD != NULL)
317*3ac0a46fSAndroid Build Coastguard Worker _cmsFree(gbd->ContextID, (void*) gbd);
318*3ac0a46fSAndroid Build Coastguard Worker }
319*3ac0a46fSAndroid Build Coastguard Worker
320*3ac0a46fSAndroid Build Coastguard Worker
321*3ac0a46fSAndroid Build Coastguard Worker // Auxiliary to retrieve a pointer to the segmentr containing the Lab value
322*3ac0a46fSAndroid Build Coastguard Worker static
GetPoint(cmsGDB * gbd,const cmsCIELab * Lab,cmsSpherical * sp)323*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp)
324*3ac0a46fSAndroid Build Coastguard Worker {
325*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 v;
326*3ac0a46fSAndroid Build Coastguard Worker int alpha, theta;
327*3ac0a46fSAndroid Build Coastguard Worker
328*3ac0a46fSAndroid Build Coastguard Worker // Housekeeping
329*3ac0a46fSAndroid Build Coastguard Worker _cmsAssert(gbd != NULL);
330*3ac0a46fSAndroid Build Coastguard Worker _cmsAssert(Lab != NULL);
331*3ac0a46fSAndroid Build Coastguard Worker _cmsAssert(sp != NULL);
332*3ac0a46fSAndroid Build Coastguard Worker
333*3ac0a46fSAndroid Build Coastguard Worker // Center L* by subtracting half of its domain, that's 50
334*3ac0a46fSAndroid Build Coastguard Worker _cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b);
335*3ac0a46fSAndroid Build Coastguard Worker
336*3ac0a46fSAndroid Build Coastguard Worker // Convert to spherical coordinates
337*3ac0a46fSAndroid Build Coastguard Worker ToSpherical(sp, &v);
338*3ac0a46fSAndroid Build Coastguard Worker
339*3ac0a46fSAndroid Build Coastguard Worker if (sp ->r < 0 || sp ->alpha < 0 || sp->theta < 0) {
340*3ac0a46fSAndroid Build Coastguard Worker cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, "spherical value out of range");
341*3ac0a46fSAndroid Build Coastguard Worker return NULL;
342*3ac0a46fSAndroid Build Coastguard Worker }
343*3ac0a46fSAndroid Build Coastguard Worker
344*3ac0a46fSAndroid Build Coastguard Worker // On which sector it falls?
345*3ac0a46fSAndroid Build Coastguard Worker QuantizeToSector(sp, &alpha, &theta);
346*3ac0a46fSAndroid Build Coastguard Worker
347*3ac0a46fSAndroid Build Coastguard Worker if (alpha < 0 || theta < 0 || alpha >= SECTORS || theta >= SECTORS) {
348*3ac0a46fSAndroid Build Coastguard Worker cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, " quadrant out of range");
349*3ac0a46fSAndroid Build Coastguard Worker return NULL;
350*3ac0a46fSAndroid Build Coastguard Worker }
351*3ac0a46fSAndroid Build Coastguard Worker
352*3ac0a46fSAndroid Build Coastguard Worker // Get pointer to the sector
353*3ac0a46fSAndroid Build Coastguard Worker return &gbd ->Gamut[theta][alpha];
354*3ac0a46fSAndroid Build Coastguard Worker }
355*3ac0a46fSAndroid Build Coastguard Worker
356*3ac0a46fSAndroid Build Coastguard Worker // Add a point to gamut descriptor. Point to add is in Lab color space.
357*3ac0a46fSAndroid Build Coastguard Worker // GBD is centered on a=b=0 and L*=50
cmsGDBAddPoint(cmsHANDLE hGBD,const cmsCIELab * Lab)358*3ac0a46fSAndroid Build Coastguard Worker cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
359*3ac0a46fSAndroid Build Coastguard Worker {
360*3ac0a46fSAndroid Build Coastguard Worker cmsGDB* gbd = (cmsGDB*) hGBD;
361*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* ptr;
362*3ac0a46fSAndroid Build Coastguard Worker cmsSpherical sp;
363*3ac0a46fSAndroid Build Coastguard Worker
364*3ac0a46fSAndroid Build Coastguard Worker
365*3ac0a46fSAndroid Build Coastguard Worker // Get pointer to the sector
366*3ac0a46fSAndroid Build Coastguard Worker ptr = GetPoint(gbd, Lab, &sp);
367*3ac0a46fSAndroid Build Coastguard Worker if (ptr == NULL) return FALSE;
368*3ac0a46fSAndroid Build Coastguard Worker
369*3ac0a46fSAndroid Build Coastguard Worker // If no samples at this sector, add it
370*3ac0a46fSAndroid Build Coastguard Worker if (ptr ->Type == GP_EMPTY) {
371*3ac0a46fSAndroid Build Coastguard Worker
372*3ac0a46fSAndroid Build Coastguard Worker ptr -> Type = GP_SPECIFIED;
373*3ac0a46fSAndroid Build Coastguard Worker ptr -> p = sp;
374*3ac0a46fSAndroid Build Coastguard Worker }
375*3ac0a46fSAndroid Build Coastguard Worker else {
376*3ac0a46fSAndroid Build Coastguard Worker
377*3ac0a46fSAndroid Build Coastguard Worker
378*3ac0a46fSAndroid Build Coastguard Worker // Substitute only if radius is greater
379*3ac0a46fSAndroid Build Coastguard Worker if (sp.r > ptr -> p.r) {
380*3ac0a46fSAndroid Build Coastguard Worker
381*3ac0a46fSAndroid Build Coastguard Worker ptr -> Type = GP_SPECIFIED;
382*3ac0a46fSAndroid Build Coastguard Worker ptr -> p = sp;
383*3ac0a46fSAndroid Build Coastguard Worker }
384*3ac0a46fSAndroid Build Coastguard Worker }
385*3ac0a46fSAndroid Build Coastguard Worker
386*3ac0a46fSAndroid Build Coastguard Worker return TRUE;
387*3ac0a46fSAndroid Build Coastguard Worker }
388*3ac0a46fSAndroid Build Coastguard Worker
389*3ac0a46fSAndroid Build Coastguard Worker // Check if a given point falls inside gamut
cmsGDBCheckPoint(cmsHANDLE hGBD,const cmsCIELab * Lab)390*3ac0a46fSAndroid Build Coastguard Worker cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
391*3ac0a46fSAndroid Build Coastguard Worker {
392*3ac0a46fSAndroid Build Coastguard Worker cmsGDB* gbd = (cmsGDB*) hGBD;
393*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* ptr;
394*3ac0a46fSAndroid Build Coastguard Worker cmsSpherical sp;
395*3ac0a46fSAndroid Build Coastguard Worker
396*3ac0a46fSAndroid Build Coastguard Worker // Get pointer to the sector
397*3ac0a46fSAndroid Build Coastguard Worker ptr = GetPoint(gbd, Lab, &sp);
398*3ac0a46fSAndroid Build Coastguard Worker if (ptr == NULL) return FALSE;
399*3ac0a46fSAndroid Build Coastguard Worker
400*3ac0a46fSAndroid Build Coastguard Worker // If no samples at this sector, return no data
401*3ac0a46fSAndroid Build Coastguard Worker if (ptr ->Type == GP_EMPTY) return FALSE;
402*3ac0a46fSAndroid Build Coastguard Worker
403*3ac0a46fSAndroid Build Coastguard Worker // In gamut only if radius is greater
404*3ac0a46fSAndroid Build Coastguard Worker
405*3ac0a46fSAndroid Build Coastguard Worker return (sp.r <= ptr -> p.r);
406*3ac0a46fSAndroid Build Coastguard Worker }
407*3ac0a46fSAndroid Build Coastguard Worker
408*3ac0a46fSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------------------------------------------------
409*3ac0a46fSAndroid Build Coastguard Worker
410*3ac0a46fSAndroid Build Coastguard Worker // Find near sectors. The list of sectors found is returned on Close[].
411*3ac0a46fSAndroid Build Coastguard Worker // The function returns the number of sectors as well.
412*3ac0a46fSAndroid Build Coastguard Worker
413*3ac0a46fSAndroid Build Coastguard Worker // 24 9 10 11 12
414*3ac0a46fSAndroid Build Coastguard Worker // 23 8 1 2 13
415*3ac0a46fSAndroid Build Coastguard Worker // 22 7 * 3 14
416*3ac0a46fSAndroid Build Coastguard Worker // 21 6 5 4 15
417*3ac0a46fSAndroid Build Coastguard Worker // 20 19 18 17 16
418*3ac0a46fSAndroid Build Coastguard Worker //
419*3ac0a46fSAndroid Build Coastguard Worker // Those are the relative movements
420*3ac0a46fSAndroid Build Coastguard Worker // {-2,-2}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2},
421*3ac0a46fSAndroid Build Coastguard Worker // {-2,-1}, {-1, -1}, {0, -1}, {+1, -1}, {+2, -1},
422*3ac0a46fSAndroid Build Coastguard Worker // {-2, 0}, {-1, 0}, {0, 0}, {+1, 0}, {+2, 0},
423*3ac0a46fSAndroid Build Coastguard Worker // {-2,+1}, {-1, +1}, {0, +1}, {+1, +1}, {+2, +1},
424*3ac0a46fSAndroid Build Coastguard Worker // {-2,+2}, {-1, +2}, {0, +2}, {+1, +2}, {+2, +2}};
425*3ac0a46fSAndroid Build Coastguard Worker
426*3ac0a46fSAndroid Build Coastguard Worker
427*3ac0a46fSAndroid Build Coastguard Worker static
428*3ac0a46fSAndroid Build Coastguard Worker const struct _spiral {
429*3ac0a46fSAndroid Build Coastguard Worker
430*3ac0a46fSAndroid Build Coastguard Worker int AdvX, AdvY;
431*3ac0a46fSAndroid Build Coastguard Worker
432*3ac0a46fSAndroid Build Coastguard Worker } Spiral[] = { {0, -1}, {+1, -1}, {+1, 0}, {+1, +1}, {0, +1}, {-1, +1},
433*3ac0a46fSAndroid Build Coastguard Worker {-1, 0}, {-1, -1}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2},
434*3ac0a46fSAndroid Build Coastguard Worker {+2, -1}, {+2, 0}, {+2, +1}, {+2, +2}, {+1, +2}, {0, +2},
435*3ac0a46fSAndroid Build Coastguard Worker {-1, +2}, {-2, +2}, {-2, +1}, {-2, 0}, {-2, -1}, {-2, -2} };
436*3ac0a46fSAndroid Build Coastguard Worker
437*3ac0a46fSAndroid Build Coastguard Worker #define NSTEPS (sizeof(Spiral) / sizeof(struct _spiral))
438*3ac0a46fSAndroid Build Coastguard Worker
439*3ac0a46fSAndroid Build Coastguard Worker static
FindNearSectors(cmsGDB * gbd,int alpha,int theta,cmsGDBPoint * Close[])440*3ac0a46fSAndroid Build Coastguard Worker int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[])
441*3ac0a46fSAndroid Build Coastguard Worker {
442*3ac0a46fSAndroid Build Coastguard Worker int nSectors = 0;
443*3ac0a46fSAndroid Build Coastguard Worker int a, t;
444*3ac0a46fSAndroid Build Coastguard Worker cmsUInt32Number i;
445*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* pt;
446*3ac0a46fSAndroid Build Coastguard Worker
447*3ac0a46fSAndroid Build Coastguard Worker for (i=0; i < NSTEPS; i++) {
448*3ac0a46fSAndroid Build Coastguard Worker
449*3ac0a46fSAndroid Build Coastguard Worker a = alpha + Spiral[i].AdvX;
450*3ac0a46fSAndroid Build Coastguard Worker t = theta + Spiral[i].AdvY;
451*3ac0a46fSAndroid Build Coastguard Worker
452*3ac0a46fSAndroid Build Coastguard Worker // Cycle at the end
453*3ac0a46fSAndroid Build Coastguard Worker a %= SECTORS;
454*3ac0a46fSAndroid Build Coastguard Worker t %= SECTORS;
455*3ac0a46fSAndroid Build Coastguard Worker
456*3ac0a46fSAndroid Build Coastguard Worker // Cycle at the begin
457*3ac0a46fSAndroid Build Coastguard Worker if (a < 0) a = SECTORS + a;
458*3ac0a46fSAndroid Build Coastguard Worker if (t < 0) t = SECTORS + t;
459*3ac0a46fSAndroid Build Coastguard Worker
460*3ac0a46fSAndroid Build Coastguard Worker pt = &gbd ->Gamut[t][a];
461*3ac0a46fSAndroid Build Coastguard Worker
462*3ac0a46fSAndroid Build Coastguard Worker if (pt -> Type != GP_EMPTY) {
463*3ac0a46fSAndroid Build Coastguard Worker
464*3ac0a46fSAndroid Build Coastguard Worker Close[nSectors++] = pt;
465*3ac0a46fSAndroid Build Coastguard Worker }
466*3ac0a46fSAndroid Build Coastguard Worker }
467*3ac0a46fSAndroid Build Coastguard Worker
468*3ac0a46fSAndroid Build Coastguard Worker return nSectors;
469*3ac0a46fSAndroid Build Coastguard Worker }
470*3ac0a46fSAndroid Build Coastguard Worker
471*3ac0a46fSAndroid Build Coastguard Worker
472*3ac0a46fSAndroid Build Coastguard Worker // Interpolate a missing sector. Method identifies whatever this is top, bottom or mid
473*3ac0a46fSAndroid Build Coastguard Worker static
InterpolateMissingSector(cmsGDB * gbd,int alpha,int theta)474*3ac0a46fSAndroid Build Coastguard Worker cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta)
475*3ac0a46fSAndroid Build Coastguard Worker {
476*3ac0a46fSAndroid Build Coastguard Worker cmsSpherical sp;
477*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 Lab;
478*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 Centre;
479*3ac0a46fSAndroid Build Coastguard Worker cmsLine ray;
480*3ac0a46fSAndroid Build Coastguard Worker int nCloseSectors;
481*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* Close[NSTEPS + 1];
482*3ac0a46fSAndroid Build Coastguard Worker cmsSpherical closel, templ;
483*3ac0a46fSAndroid Build Coastguard Worker cmsLine edge;
484*3ac0a46fSAndroid Build Coastguard Worker int k, m;
485*3ac0a46fSAndroid Build Coastguard Worker
486*3ac0a46fSAndroid Build Coastguard Worker // Is that point already specified?
487*3ac0a46fSAndroid Build Coastguard Worker if (gbd ->Gamut[theta][alpha].Type != GP_EMPTY) return TRUE;
488*3ac0a46fSAndroid Build Coastguard Worker
489*3ac0a46fSAndroid Build Coastguard Worker // Fill close points
490*3ac0a46fSAndroid Build Coastguard Worker nCloseSectors = FindNearSectors(gbd, alpha, theta, Close);
491*3ac0a46fSAndroid Build Coastguard Worker
492*3ac0a46fSAndroid Build Coastguard Worker
493*3ac0a46fSAndroid Build Coastguard Worker // Find a central point on the sector
494*3ac0a46fSAndroid Build Coastguard Worker sp.alpha = (cmsFloat64Number) ((alpha + 0.5) * 360.0) / (SECTORS);
495*3ac0a46fSAndroid Build Coastguard Worker sp.theta = (cmsFloat64Number) ((theta + 0.5) * 180.0) / (SECTORS);
496*3ac0a46fSAndroid Build Coastguard Worker sp.r = 50.0;
497*3ac0a46fSAndroid Build Coastguard Worker
498*3ac0a46fSAndroid Build Coastguard Worker // Convert to Cartesian
499*3ac0a46fSAndroid Build Coastguard Worker ToCartesian(&Lab, &sp);
500*3ac0a46fSAndroid Build Coastguard Worker
501*3ac0a46fSAndroid Build Coastguard Worker // Create a ray line from centre to this point
502*3ac0a46fSAndroid Build Coastguard Worker _cmsVEC3init(&Centre, 50.0, 0, 0);
503*3ac0a46fSAndroid Build Coastguard Worker LineOf2Points(&ray, &Lab, &Centre);
504*3ac0a46fSAndroid Build Coastguard Worker
505*3ac0a46fSAndroid Build Coastguard Worker // For all close sectors
506*3ac0a46fSAndroid Build Coastguard Worker closel.r = 0.0;
507*3ac0a46fSAndroid Build Coastguard Worker closel.alpha = 0;
508*3ac0a46fSAndroid Build Coastguard Worker closel.theta = 0;
509*3ac0a46fSAndroid Build Coastguard Worker
510*3ac0a46fSAndroid Build Coastguard Worker for (k=0; k < nCloseSectors; k++) {
511*3ac0a46fSAndroid Build Coastguard Worker
512*3ac0a46fSAndroid Build Coastguard Worker for(m = k+1; m < nCloseSectors; m++) {
513*3ac0a46fSAndroid Build Coastguard Worker
514*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 temp, a1, a2;
515*3ac0a46fSAndroid Build Coastguard Worker
516*3ac0a46fSAndroid Build Coastguard Worker // A line from sector to sector
517*3ac0a46fSAndroid Build Coastguard Worker ToCartesian(&a1, &Close[k]->p);
518*3ac0a46fSAndroid Build Coastguard Worker ToCartesian(&a2, &Close[m]->p);
519*3ac0a46fSAndroid Build Coastguard Worker
520*3ac0a46fSAndroid Build Coastguard Worker LineOf2Points(&edge, &a1, &a2);
521*3ac0a46fSAndroid Build Coastguard Worker
522*3ac0a46fSAndroid Build Coastguard Worker // Find a line
523*3ac0a46fSAndroid Build Coastguard Worker ClosestLineToLine(&temp, &ray, &edge);
524*3ac0a46fSAndroid Build Coastguard Worker
525*3ac0a46fSAndroid Build Coastguard Worker // Convert to spherical
526*3ac0a46fSAndroid Build Coastguard Worker ToSpherical(&templ, &temp);
527*3ac0a46fSAndroid Build Coastguard Worker
528*3ac0a46fSAndroid Build Coastguard Worker
529*3ac0a46fSAndroid Build Coastguard Worker if ( templ.r > closel.r &&
530*3ac0a46fSAndroid Build Coastguard Worker templ.theta >= (theta*180.0/SECTORS) &&
531*3ac0a46fSAndroid Build Coastguard Worker templ.theta <= ((theta+1)*180.0/SECTORS) &&
532*3ac0a46fSAndroid Build Coastguard Worker templ.alpha >= (alpha*360.0/SECTORS) &&
533*3ac0a46fSAndroid Build Coastguard Worker templ.alpha <= ((alpha+1)*360.0/SECTORS)) {
534*3ac0a46fSAndroid Build Coastguard Worker
535*3ac0a46fSAndroid Build Coastguard Worker closel = templ;
536*3ac0a46fSAndroid Build Coastguard Worker }
537*3ac0a46fSAndroid Build Coastguard Worker }
538*3ac0a46fSAndroid Build Coastguard Worker }
539*3ac0a46fSAndroid Build Coastguard Worker
540*3ac0a46fSAndroid Build Coastguard Worker gbd ->Gamut[theta][alpha].p = closel;
541*3ac0a46fSAndroid Build Coastguard Worker gbd ->Gamut[theta][alpha].Type = GP_MODELED;
542*3ac0a46fSAndroid Build Coastguard Worker
543*3ac0a46fSAndroid Build Coastguard Worker return TRUE;
544*3ac0a46fSAndroid Build Coastguard Worker
545*3ac0a46fSAndroid Build Coastguard Worker }
546*3ac0a46fSAndroid Build Coastguard Worker
547*3ac0a46fSAndroid Build Coastguard Worker
548*3ac0a46fSAndroid Build Coastguard Worker // Interpolate missing parts. The algorithm fist computes slices at
549*3ac0a46fSAndroid Build Coastguard Worker // theta=0 and theta=Max.
cmsGDBCompute(cmsHANDLE hGBD,cmsUInt32Number dwFlags)550*3ac0a46fSAndroid Build Coastguard Worker cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGBD, cmsUInt32Number dwFlags)
551*3ac0a46fSAndroid Build Coastguard Worker {
552*3ac0a46fSAndroid Build Coastguard Worker int alpha, theta;
553*3ac0a46fSAndroid Build Coastguard Worker cmsGDB* gbd = (cmsGDB*) hGBD;
554*3ac0a46fSAndroid Build Coastguard Worker
555*3ac0a46fSAndroid Build Coastguard Worker _cmsAssert(hGBD != NULL);
556*3ac0a46fSAndroid Build Coastguard Worker
557*3ac0a46fSAndroid Build Coastguard Worker // Interpolate black
558*3ac0a46fSAndroid Build Coastguard Worker for (alpha = 0; alpha < SECTORS; alpha++) {
559*3ac0a46fSAndroid Build Coastguard Worker
560*3ac0a46fSAndroid Build Coastguard Worker if (!InterpolateMissingSector(gbd, alpha, 0)) return FALSE;
561*3ac0a46fSAndroid Build Coastguard Worker }
562*3ac0a46fSAndroid Build Coastguard Worker
563*3ac0a46fSAndroid Build Coastguard Worker // Interpolate white
564*3ac0a46fSAndroid Build Coastguard Worker for (alpha = 0; alpha < SECTORS; alpha++) {
565*3ac0a46fSAndroid Build Coastguard Worker
566*3ac0a46fSAndroid Build Coastguard Worker if (!InterpolateMissingSector(gbd, alpha, SECTORS-1)) return FALSE;
567*3ac0a46fSAndroid Build Coastguard Worker }
568*3ac0a46fSAndroid Build Coastguard Worker
569*3ac0a46fSAndroid Build Coastguard Worker
570*3ac0a46fSAndroid Build Coastguard Worker // Interpolate Mid
571*3ac0a46fSAndroid Build Coastguard Worker for (theta = 1; theta < SECTORS; theta++) {
572*3ac0a46fSAndroid Build Coastguard Worker for (alpha = 0; alpha < SECTORS; alpha++) {
573*3ac0a46fSAndroid Build Coastguard Worker
574*3ac0a46fSAndroid Build Coastguard Worker if (!InterpolateMissingSector(gbd, alpha, theta)) return FALSE;
575*3ac0a46fSAndroid Build Coastguard Worker }
576*3ac0a46fSAndroid Build Coastguard Worker }
577*3ac0a46fSAndroid Build Coastguard Worker
578*3ac0a46fSAndroid Build Coastguard Worker // Done
579*3ac0a46fSAndroid Build Coastguard Worker return TRUE;
580*3ac0a46fSAndroid Build Coastguard Worker
581*3ac0a46fSAndroid Build Coastguard Worker cmsUNUSED_PARAMETER(dwFlags);
582*3ac0a46fSAndroid Build Coastguard Worker }
583*3ac0a46fSAndroid Build Coastguard Worker
584*3ac0a46fSAndroid Build Coastguard Worker
585*3ac0a46fSAndroid Build Coastguard Worker
586*3ac0a46fSAndroid Build Coastguard Worker
587*3ac0a46fSAndroid Build Coastguard Worker // --------------------------------------------------------------------------------------------------------
588*3ac0a46fSAndroid Build Coastguard Worker
589*3ac0a46fSAndroid Build Coastguard Worker // Great for debug, but not suitable for real use
590*3ac0a46fSAndroid Build Coastguard Worker
591*3ac0a46fSAndroid Build Coastguard Worker #if 0
592*3ac0a46fSAndroid Build Coastguard Worker cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
593*3ac0a46fSAndroid Build Coastguard Worker {
594*3ac0a46fSAndroid Build Coastguard Worker FILE* fp;
595*3ac0a46fSAndroid Build Coastguard Worker int i, j;
596*3ac0a46fSAndroid Build Coastguard Worker cmsGDB* gbd = (cmsGDB*) hGBD;
597*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* pt;
598*3ac0a46fSAndroid Build Coastguard Worker
599*3ac0a46fSAndroid Build Coastguard Worker fp = fopen (fname, "wt");
600*3ac0a46fSAndroid Build Coastguard Worker if (fp == NULL)
601*3ac0a46fSAndroid Build Coastguard Worker return FALSE;
602*3ac0a46fSAndroid Build Coastguard Worker
603*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "#VRML V2.0 utf8\n");
604*3ac0a46fSAndroid Build Coastguard Worker
605*3ac0a46fSAndroid Build Coastguard Worker // set the viewing orientation and distance
606*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "DEF CamTest Group {\n");
607*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\tchildren [\n");
608*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\tDEF Cameras Group {\n");
609*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\tchildren [\n");
610*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tDEF DefaultView Viewpoint {\n");
611*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tposition 0 0 340\n");
612*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\torientation 0 0 1 0\n");
613*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tdescription \"default view\"\n");
614*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t}\n");
615*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t]\n");
616*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t},\n");
617*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t]\n");
618*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "}\n");
619*3ac0a46fSAndroid Build Coastguard Worker
620*3ac0a46fSAndroid Build Coastguard Worker // Output the background stuff
621*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "Background {\n");
622*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\tskyColor [\n");
623*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t.5 .5 .5\n");
624*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t]\n");
625*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "}\n");
626*3ac0a46fSAndroid Build Coastguard Worker
627*3ac0a46fSAndroid Build Coastguard Worker // Output the shape stuff
628*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "Transform {\n");
629*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\tscale .3 .3 .3\n");
630*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\tchildren [\n");
631*3ac0a46fSAndroid Build Coastguard Worker
632*3ac0a46fSAndroid Build Coastguard Worker // Draw the axes as a shape:
633*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\tShape {\n");
634*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\tappearance Appearance {\n");
635*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tmaterial Material {\n");
636*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n");
637*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\temissiveColor 1.0 1.0 1.0\n");
638*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tshininess 0.8\n");
639*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t}\n");
640*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t}\n");
641*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\tgeometry IndexedLineSet {\n");
642*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
643*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tpoint [\n");
644*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t0.0 0.0 0.0,\n");
645*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t%f 0.0 0.0,\n", 255.0);
646*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t0.0 %f 0.0,\n", 255.0);
647*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t0.0 0.0 %f]\n", 255.0);
648*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t}\n");
649*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tcoordIndex [\n");
650*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t0, 1, -1\n");
651*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t0, 2, -1\n");
652*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t0, 3, -1]\n");
653*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t}\n");
654*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t}\n");
655*3ac0a46fSAndroid Build Coastguard Worker
656*3ac0a46fSAndroid Build Coastguard Worker
657*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\tShape {\n");
658*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\tappearance Appearance {\n");
659*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tmaterial Material {\n");
660*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n");
661*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\temissiveColor 1 1 1\n");
662*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tshininess 0.8\n");
663*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t}\n");
664*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t}\n");
665*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\tgeometry PointSet {\n");
666*3ac0a46fSAndroid Build Coastguard Worker
667*3ac0a46fSAndroid Build Coastguard Worker // fill in the points here
668*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
669*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tpoint [\n");
670*3ac0a46fSAndroid Build Coastguard Worker
671*3ac0a46fSAndroid Build Coastguard Worker // We need to transverse all gamut hull.
672*3ac0a46fSAndroid Build Coastguard Worker for (i=0; i < SECTORS; i++)
673*3ac0a46fSAndroid Build Coastguard Worker for (j=0; j < SECTORS; j++) {
674*3ac0a46fSAndroid Build Coastguard Worker
675*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 v;
676*3ac0a46fSAndroid Build Coastguard Worker
677*3ac0a46fSAndroid Build Coastguard Worker pt = &gbd ->Gamut[i][j];
678*3ac0a46fSAndroid Build Coastguard Worker ToCartesian(&v, &pt ->p);
679*3ac0a46fSAndroid Build Coastguard Worker
680*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t%g %g %g", v.n[0]+50, v.n[1], v.n[2]);
681*3ac0a46fSAndroid Build Coastguard Worker
682*3ac0a46fSAndroid Build Coastguard Worker if ((j == SECTORS - 1) && (i == SECTORS - 1))
683*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "]\n");
684*3ac0a46fSAndroid Build Coastguard Worker else
685*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, ",\n");
686*3ac0a46fSAndroid Build Coastguard Worker
687*3ac0a46fSAndroid Build Coastguard Worker }
688*3ac0a46fSAndroid Build Coastguard Worker
689*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t}\n");
690*3ac0a46fSAndroid Build Coastguard Worker
691*3ac0a46fSAndroid Build Coastguard Worker
692*3ac0a46fSAndroid Build Coastguard Worker
693*3ac0a46fSAndroid Build Coastguard Worker // fill in the face colors
694*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\tcolor Color {\n");
695*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\tcolor [\n");
696*3ac0a46fSAndroid Build Coastguard Worker
697*3ac0a46fSAndroid Build Coastguard Worker for (i=0; i < SECTORS; i++)
698*3ac0a46fSAndroid Build Coastguard Worker for (j=0; j < SECTORS; j++) {
699*3ac0a46fSAndroid Build Coastguard Worker
700*3ac0a46fSAndroid Build Coastguard Worker cmsVEC3 v;
701*3ac0a46fSAndroid Build Coastguard Worker
702*3ac0a46fSAndroid Build Coastguard Worker pt = &gbd ->Gamut[i][j];
703*3ac0a46fSAndroid Build Coastguard Worker
704*3ac0a46fSAndroid Build Coastguard Worker
705*3ac0a46fSAndroid Build Coastguard Worker ToCartesian(&v, &pt ->p);
706*3ac0a46fSAndroid Build Coastguard Worker
707*3ac0a46fSAndroid Build Coastguard Worker
708*3ac0a46fSAndroid Build Coastguard Worker if (pt ->Type == GP_EMPTY)
709*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t%g %g %g", 0.0, 0.0, 0.0);
710*3ac0a46fSAndroid Build Coastguard Worker else
711*3ac0a46fSAndroid Build Coastguard Worker if (pt ->Type == GP_MODELED)
712*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, .5, .5);
713*3ac0a46fSAndroid Build Coastguard Worker else {
714*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, 1.0, 1.0);
715*3ac0a46fSAndroid Build Coastguard Worker
716*3ac0a46fSAndroid Build Coastguard Worker }
717*3ac0a46fSAndroid Build Coastguard Worker
718*3ac0a46fSAndroid Build Coastguard Worker if ((j == SECTORS - 1) && (i == SECTORS - 1))
719*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "]\n");
720*3ac0a46fSAndroid Build Coastguard Worker else
721*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, ",\n");
722*3ac0a46fSAndroid Build Coastguard Worker }
723*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t}\n");
724*3ac0a46fSAndroid Build Coastguard Worker
725*3ac0a46fSAndroid Build Coastguard Worker
726*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t\t}\n");
727*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t\t}\n");
728*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "\t]\n");
729*3ac0a46fSAndroid Build Coastguard Worker fprintf (fp, "}\n");
730*3ac0a46fSAndroid Build Coastguard Worker
731*3ac0a46fSAndroid Build Coastguard Worker fclose (fp);
732*3ac0a46fSAndroid Build Coastguard Worker
733*3ac0a46fSAndroid Build Coastguard Worker return TRUE;
734*3ac0a46fSAndroid Build Coastguard Worker }
735*3ac0a46fSAndroid Build Coastguard Worker #endif
736*3ac0a46fSAndroid Build Coastguard Worker
737