Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/libjasper/jas_cm.c
16337 views
1
/*
2
* Copyright (c) 2002-2003 Michael David Adams.
3
* All rights reserved.
4
*/
5
6
/* __START_OF_JASPER_LICENSE__
7
*
8
* JasPer License Version 2.0
9
*
10
* Copyright (c) 2001-2006 Michael David Adams
11
* Copyright (c) 1999-2000 Image Power, Inc.
12
* Copyright (c) 1999-2000 The University of British Columbia
13
*
14
* All rights reserved.
15
*
16
* Permission is hereby granted, free of charge, to any person (the
17
* "User") obtaining a copy of this software and associated documentation
18
* files (the "Software"), to deal in the Software without restriction,
19
* including without limitation the rights to use, copy, modify, merge,
20
* publish, distribute, and/or sell copies of the Software, and to permit
21
* persons to whom the Software is furnished to do so, subject to the
22
* following conditions:
23
*
24
* 1. The above copyright notices and this permission notice (which
25
* includes the disclaimer below) shall be included in all copies or
26
* substantial portions of the Software.
27
*
28
* 2. The name of a copyright holder shall not be used to endorse or
29
* promote products derived from the Software without specific prior
30
* written permission.
31
*
32
* THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
33
* LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
34
* THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
35
* "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
36
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
37
* PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
38
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
39
* INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
40
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
41
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
42
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
43
* PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
44
* THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
45
* EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
46
* BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
47
* PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
48
* GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
49
* ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
50
* IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
51
* SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
52
* AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
53
* SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
54
* THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
55
* PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
56
* RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
57
* EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
58
*
59
* __END_OF_JASPER_LICENSE__
60
*/
61
62
/*
63
* Color Management
64
*
65
* $Id: jas_cm.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
66
*/
67
68
#include <jasper/jas_config.h>
69
#include <math.h>
70
#include <stdlib.h>
71
#include <assert.h>
72
#include <jasper/jas_cm.h>
73
#include <jasper/jas_icc.h>
74
#include <jasper/jas_init.h>
75
#include <jasper/jas_stream.h>
76
#include <jasper/jas_malloc.h>
77
#include <jasper/jas_math.h>
78
79
static jas_cmprof_t *jas_cmprof_create(void);
80
static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *);
81
static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x);
82
83
static void jas_cmpxform_destroy(jas_cmpxform_t *pxform);
84
static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform);
85
86
static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform);
87
static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in,
88
jas_cmreal_t *out, int cnt);
89
90
static int jas_cmputint(long **bufptr, int sgnd, int prec, long val);
91
static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val);
92
static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq,
93
jas_cmpxformseq_t *othpxformseq);
94
static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
95
int, int);
96
static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n);
97
98
static int mono(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **pxformseq);
99
static int triclr(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq);
100
101
static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq);
102
static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i);
103
static jas_cmpxformseq_t *jas_cmpxformseq_create(void);
104
static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq);
105
static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]);
106
static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
107
int i, jas_cmpxform_t *pxform);
108
109
#define SEQFWD(intent) (intent)
110
#define SEQREV(intent) (4 + (intent))
111
#define SEQSIM(intent) (8 + (intent))
112
#define SEQGAM 12
113
114
#define fwdpxformseq(prof, intent) \
115
(((prof)->pxformseqs[SEQFWD(intent)]) ? \
116
((prof)->pxformseqs[SEQFWD(intent)]) : \
117
((prof)->pxformseqs[SEQFWD(0)]))
118
119
#define revpxformseq(prof, intent) \
120
(((prof)->pxformseqs[SEQREV(intent)]) ? \
121
((prof)->pxformseqs[SEQREV(intent)]) : \
122
((prof)->pxformseqs[SEQREV(0)]))
123
124
#define simpxformseq(prof, intent) \
125
(((prof)->pxformseqs[SEQSIM(intent)]) ? \
126
((prof)->pxformseqs[SEQSIM(intent)]) : \
127
((prof)->pxformseqs[SEQSIM(0)]))
128
129
#define gampxformseq(prof) ((prof)->pxformseqs[SEQGAM])
130
131
static int icctoclrspc(int iccclrspc, int refflag);
132
static jas_cmpxform_t *jas_cmpxform_create0(void);
133
static jas_cmpxform_t *jas_cmpxform_createshapmat(void);
134
static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut);
135
static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv);
136
137
static jas_cmpxformops_t shapmat_ops = {jas_cmshapmat_destroy, jas_cmshapmat_apply, 0};
138
static jas_cmprof_t *jas_cmprof_createsycc(void);
139
140
/******************************************************************************\
141
* Color profile class.
142
\******************************************************************************/
143
144
jas_cmprof_t *jas_cmprof_createfromclrspc(int clrspc)
145
{
146
jas_iccprof_t *iccprof;
147
jas_cmprof_t *prof;
148
149
iccprof = 0;
150
prof = 0;
151
switch (clrspc) {
152
case JAS_CLRSPC_SYCBCR:
153
if (!(prof = jas_cmprof_createsycc()))
154
goto error;
155
break;
156
default:
157
if (!(iccprof = jas_iccprof_createfromclrspc(clrspc)))
158
goto error;
159
if (!(prof = jas_cmprof_createfromiccprof(iccprof)))
160
goto error;
161
jas_iccprof_destroy(iccprof);
162
iccprof = 0;
163
if (!jas_clrspc_isgeneric(clrspc))
164
prof->clrspc = clrspc;
165
break;
166
}
167
return prof;
168
error:
169
if (iccprof)
170
jas_iccprof_destroy(iccprof);
171
return 0;
172
}
173
174
static jas_cmprof_t *jas_cmprof_createsycc()
175
{
176
jas_cmprof_t *prof;
177
jas_cmpxform_t *fwdpxform;
178
jas_cmpxform_t *revpxform;
179
jas_cmshapmat_t *fwdshapmat;
180
jas_cmshapmat_t *revshapmat;
181
int i;
182
int j;
183
184
if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)))
185
goto error;
186
prof->clrspc = JAS_CLRSPC_SYCBCR;
187
assert(prof->numchans == 3 && prof->numrefchans == 3);
188
assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ);
189
if (!(fwdpxform = jas_cmpxform_createshapmat()))
190
goto error;
191
fwdpxform->numinchans = 3;
192
fwdpxform->numoutchans = 3;
193
fwdshapmat = &fwdpxform->data.shapmat;
194
fwdshapmat->mono = 0;
195
fwdshapmat->order = 0;
196
fwdshapmat->useluts = 0;
197
fwdshapmat->usemat = 1;
198
fwdshapmat->mat[0][0] = 1.0;
199
fwdshapmat->mat[0][1] = 0.0;
200
fwdshapmat->mat[0][2] = 1.402;
201
fwdshapmat->mat[1][0] = 1.0;
202
fwdshapmat->mat[1][1] = -0.34413;
203
fwdshapmat->mat[1][2] = -0.71414;
204
fwdshapmat->mat[2][0] = 1.0;
205
fwdshapmat->mat[2][1] = 1.772;
206
fwdshapmat->mat[2][2] = 0.0;
207
fwdshapmat->mat[0][3] = -0.5 * (1.402);
208
fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414);
209
fwdshapmat->mat[2][3] = -0.5 * (1.772);
210
if (!(revpxform = jas_cmpxform_createshapmat()))
211
goto error;
212
revpxform->numinchans = 3;
213
revpxform->numoutchans = 3;
214
revshapmat = &revpxform->data.shapmat;
215
revshapmat->mono = 0;
216
revshapmat->order = 1;
217
revshapmat->useluts = 0;
218
revshapmat->usemat = 1;
219
jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat);
220
221
for (i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) {
222
j = SEQFWD(i);
223
if (prof->pxformseqs[j]) {
224
if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0,
225
fwdpxform))
226
goto error;
227
}
228
j = SEQREV(i);
229
if (prof->pxformseqs[j]) {
230
if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j],
231
-1, revpxform))
232
goto error;
233
}
234
}
235
236
jas_cmpxform_destroy(fwdpxform);
237
jas_cmpxform_destroy(revpxform);
238
return prof;
239
error:
240
return 0;
241
}
242
243
jas_cmprof_t *jas_cmprof_createfromiccprof(jas_iccprof_t *iccprof)
244
{
245
jas_cmprof_t *prof;
246
jas_icchdr_t icchdr;
247
jas_cmpxformseq_t *fwdpxformseq;
248
jas_cmpxformseq_t *revpxformseq;
249
250
prof = 0;
251
fwdpxformseq = 0;
252
revpxformseq = 0;
253
254
if (!(prof = jas_cmprof_create()))
255
goto error;
256
jas_iccprof_gethdr(iccprof, &icchdr);
257
if (!(prof->iccprof = jas_iccprof_copy(iccprof)))
258
goto error;
259
prof->clrspc = icctoclrspc(icchdr.colorspc, 0);
260
prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1);
261
prof->numchans = jas_clrspc_numchans(prof->clrspc);
262
prof->numrefchans = jas_clrspc_numchans(prof->refclrspc);
263
264
if (prof->numchans == 1) {
265
if (mono(prof->iccprof, 0, &fwdpxformseq))
266
goto error;
267
if (mono(prof->iccprof, 1, &revpxformseq))
268
goto error;
269
} else if (prof->numchans == 3) {
270
if (triclr(prof->iccprof, 0, &fwdpxformseq))
271
goto error;
272
if (triclr(prof->iccprof, 1, &revpxformseq))
273
goto error;
274
}
275
prof->pxformseqs[SEQFWD(0)] = fwdpxformseq;
276
prof->pxformseqs[SEQREV(0)] = revpxformseq;
277
278
#if 0
279
if (prof->numchans > 1) {
280
lut(prof->iccprof, 0, PER, &pxformseq);
281
pxformseqs_set(prof, SEQFWD(PER), pxformseq);
282
lut(prof->iccprof, 1, PER, &pxformseq);
283
pxformseqs_set(prof, SEQREV(PER), pxformseq);
284
lut(prof->iccprof, 0, CLR, &pxformseq);
285
pxformseqs_set(prof, SEQREV(CLR), pxformseq);
286
lut(prof->iccprof, 1, CLR, &pxformseq);
287
pxformseqs_set(prof, SEQREV(CLR), pxformseq);
288
lut(prof->iccprof, 0, SAT, &pxformseq);
289
pxformseqs_set(prof, SEQREV(SAT), pxformseq);
290
lut(prof->iccprof, 1, SAT, &pxformseq);
291
pxformseqs_set(prof, SEQREV(SAT), pxformseq);
292
}
293
#endif
294
295
return prof;
296
297
error:
298
if (fwdpxformseq) {
299
jas_cmpxformseq_destroy(fwdpxformseq);
300
}
301
if (revpxformseq) {
302
jas_cmpxformseq_destroy(revpxformseq);
303
}
304
if (prof) {
305
jas_cmprof_destroy(prof);
306
}
307
308
return 0;
309
}
310
311
static jas_cmprof_t *jas_cmprof_create()
312
{
313
int i;
314
jas_cmprof_t *prof;
315
if (!(prof = jas_malloc(sizeof(jas_cmprof_t))))
316
return 0;
317
memset(prof, 0, sizeof(jas_cmprof_t));
318
prof->iccprof = 0;
319
for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i)
320
prof->pxformseqs[i] = 0;
321
return prof;
322
}
323
324
void jas_cmprof_destroy(jas_cmprof_t *prof)
325
{
326
int i;
327
for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
328
if (prof->pxformseqs[i]) {
329
jas_cmpxformseq_destroy(prof->pxformseqs[i]);
330
prof->pxformseqs[i] = 0;
331
}
332
}
333
if (prof->iccprof)
334
jas_iccprof_destroy(prof->iccprof);
335
jas_free(prof);
336
}
337
338
jas_cmprof_t *jas_cmprof_copy(jas_cmprof_t *prof)
339
{
340
jas_cmprof_t *newprof;
341
int i;
342
343
if (!(newprof = jas_cmprof_create()))
344
goto error;
345
newprof->clrspc = prof->clrspc;
346
newprof->numchans = prof->numchans;
347
newprof->refclrspc = prof->refclrspc;
348
newprof->numrefchans = prof->numrefchans;
349
newprof->iccprof = jas_iccprof_copy(prof->iccprof);
350
for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
351
if (prof->pxformseqs[i]) {
352
if (!(newprof->pxformseqs[i] = jas_cmpxformseq_copy(prof->pxformseqs[i])))
353
goto error;
354
}
355
}
356
return newprof;
357
error:
358
return 0;
359
}
360
361
/******************************************************************************\
362
* Transform class.
363
\******************************************************************************/
364
365
jas_cmxform_t *jas_cmxform_create(jas_cmprof_t *inprof, jas_cmprof_t *outprof,
366
jas_cmprof_t *prfprof, int op, int intent, int optimize)
367
{
368
jas_cmxform_t *xform;
369
jas_cmpxformseq_t *inpxformseq;
370
jas_cmpxformseq_t *outpxformseq;
371
jas_cmpxformseq_t *altoutpxformseq;
372
jas_cmpxformseq_t *prfpxformseq;
373
int prfintent;
374
375
/* Avoid compiler warnings about unused parameters. */
376
optimize = 0;
377
378
prfintent = intent;
379
380
if (!(xform = jas_malloc(sizeof(jas_cmxform_t))))
381
goto error;
382
if (!(xform->pxformseq = jas_cmpxformseq_create()))
383
goto error;
384
385
switch (op) {
386
case JAS_CMXFORM_OP_FWD:
387
inpxformseq = fwdpxformseq(inprof, intent);
388
outpxformseq = revpxformseq(outprof, intent);
389
if (!inpxformseq || !outpxformseq)
390
goto error;
391
if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
392
jas_cmpxformseq_appendcnvt(xform->pxformseq,
393
inprof->refclrspc, outprof->refclrspc) ||
394
jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
395
goto error;
396
xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
397
xform->numoutchans = jas_clrspc_numchans(outprof->clrspc);
398
break;
399
case JAS_CMXFORM_OP_REV:
400
outpxformseq = fwdpxformseq(outprof, intent);
401
inpxformseq = revpxformseq(inprof, intent);
402
if (!outpxformseq || !inpxformseq)
403
goto error;
404
if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
405
jas_cmpxformseq_appendcnvt(xform->pxformseq,
406
outprof->refclrspc, inprof->refclrspc) ||
407
jas_cmpxformseq_append(xform->pxformseq, inpxformseq))
408
goto error;
409
xform->numinchans = jas_clrspc_numchans(outprof->clrspc);
410
xform->numoutchans = jas_clrspc_numchans(inprof->clrspc);
411
break;
412
case JAS_CMXFORM_OP_PROOF:
413
assert(prfprof);
414
inpxformseq = fwdpxformseq(inprof, intent);
415
prfpxformseq = fwdpxformseq(prfprof, prfintent);
416
if (!inpxformseq || !prfpxformseq)
417
goto error;
418
outpxformseq = simpxformseq(outprof, intent);
419
altoutpxformseq = 0;
420
if (!outpxformseq) {
421
outpxformseq = revpxformseq(outprof, intent);
422
altoutpxformseq = fwdpxformseq(outprof, intent);
423
if (!outpxformseq || !altoutpxformseq)
424
goto error;
425
}
426
if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
427
jas_cmpxformseq_appendcnvt(xform->pxformseq,
428
inprof->refclrspc, outprof->refclrspc))
429
goto error;
430
if (altoutpxformseq) {
431
if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
432
jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq))
433
goto error;
434
} else {
435
if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
436
goto error;
437
}
438
if (jas_cmpxformseq_appendcnvt(xform->pxformseq,
439
outprof->refclrspc, inprof->refclrspc) ||
440
jas_cmpxformseq_append(xform->pxformseq, prfpxformseq))
441
goto error;
442
xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
443
xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc);
444
break;
445
case JAS_CMXFORM_OP_GAMUT:
446
inpxformseq = fwdpxformseq(inprof, intent);
447
outpxformseq = gampxformseq(outprof);
448
if (!inpxformseq || !outpxformseq)
449
goto error;
450
if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
451
jas_cmpxformseq_appendcnvt(xform->pxformseq,
452
inprof->refclrspc, outprof->refclrspc) ||
453
jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
454
goto error;
455
xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
456
xform->numoutchans = 1;
457
break;
458
}
459
return xform;
460
error:
461
return 0;
462
}
463
464
#define APPLYBUFSIZ 2048
465
int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out)
466
{
467
jas_cmcmptfmt_t *fmt;
468
jas_cmreal_t buf[2][APPLYBUFSIZ];
469
jas_cmpxformseq_t *pxformseq;
470
int i;
471
int j;
472
int width;
473
int height;
474
int total;
475
int n;
476
jas_cmreal_t *inbuf;
477
jas_cmreal_t *outbuf;
478
jas_cmpxform_t *pxform;
479
long *dataptr;
480
int maxchans;
481
int bufmax;
482
int m;
483
int bias;
484
jas_cmreal_t scale;
485
long v;
486
jas_cmreal_t *bufptr;
487
488
if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts)
489
goto error;
490
491
fmt = &in->cmptfmts[0];
492
width = fmt->width;
493
height = fmt->height;
494
for (i = 1; i < xform->numinchans; ++i) {
495
fmt = &in->cmptfmts[i];
496
if (fmt->width != width || fmt->height != height) {
497
goto error;
498
}
499
}
500
for (i = 0; i < xform->numoutchans; ++i) {
501
fmt = &out->cmptfmts[i];
502
if (fmt->width != width || fmt->height != height) {
503
goto error;
504
}
505
}
506
507
maxchans = 0;
508
pxformseq = xform->pxformseq;
509
for (i = 0; i < pxformseq->numpxforms; ++i) {
510
pxform = pxformseq->pxforms[i];
511
if (pxform->numinchans > maxchans) {
512
maxchans = pxform->numinchans;
513
}
514
if (pxform->numoutchans > maxchans) {
515
maxchans = pxform->numoutchans;
516
}
517
}
518
bufmax = APPLYBUFSIZ / maxchans;
519
assert(bufmax > 0);
520
521
total = width * height;
522
n = 0;
523
while (n < total) {
524
525
inbuf = &buf[0][0];
526
m = JAS_MIN(total - n, bufmax);
527
528
for (i = 0; i < xform->numinchans; ++i) {
529
fmt = &in->cmptfmts[i];
530
scale = (double)((1 << fmt->prec) - 1);
531
bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
532
dataptr = &fmt->buf[n];
533
bufptr = &inbuf[i];
534
for (j = 0; j < m; ++j) {
535
if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v))
536
goto error;
537
*bufptr = (v - bias) / scale;
538
bufptr += xform->numinchans;
539
}
540
}
541
542
inbuf = &buf[0][0];
543
outbuf = inbuf;
544
for (i = 0; i < pxformseq->numpxforms; ++i) {
545
pxform = pxformseq->pxforms[i];
546
if (pxform->numoutchans > pxform->numinchans) {
547
outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0];
548
} else {
549
outbuf = inbuf;
550
}
551
if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m))
552
goto error;
553
inbuf = outbuf;
554
}
555
556
for (i = 0; i < xform->numoutchans; ++i) {
557
fmt = &out->cmptfmts[i];
558
scale = (double)((1 << fmt->prec) - 1);
559
bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
560
bufptr = &outbuf[i];
561
dataptr = &fmt->buf[n];
562
for (j = 0; j < m; ++j) {
563
v = (*bufptr) * scale + bias;
564
bufptr += xform->numoutchans;
565
if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v))
566
goto error;
567
}
568
}
569
570
n += m;
571
}
572
573
return 0;
574
error:
575
return -1;
576
}
577
578
void jas_cmxform_destroy(jas_cmxform_t *xform)
579
{
580
if (xform->pxformseq)
581
jas_cmpxformseq_destroy(xform->pxformseq);
582
jas_free(xform);
583
}
584
585
/******************************************************************************\
586
* Primitive transform sequence class.
587
\******************************************************************************/
588
589
static jas_cmpxformseq_t *jas_cmpxformseq_create()
590
{
591
jas_cmpxformseq_t *pxformseq;
592
pxformseq = 0;
593
if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t))))
594
goto error;
595
pxformseq->pxforms = 0;
596
pxformseq->numpxforms = 0;
597
pxformseq->maxpxforms = 0;
598
if (jas_cmpxformseq_resize(pxformseq, 16))
599
goto error;
600
return pxformseq;
601
error:
602
if (pxformseq)
603
jas_cmpxformseq_destroy(pxformseq);
604
return 0;
605
}
606
607
static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq)
608
{
609
jas_cmpxformseq_t *newpxformseq;
610
611
if (!(newpxformseq = jas_cmpxformseq_create()))
612
goto error;
613
if (jas_cmpxformseq_append(newpxformseq, pxformseq))
614
goto error;
615
return newpxformseq;
616
error:
617
return 0;
618
}
619
620
static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq)
621
{
622
while (pxformseq->numpxforms > 0)
623
jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1);
624
if (pxformseq->pxforms)
625
jas_free(pxformseq->pxforms);
626
jas_free(pxformseq);
627
}
628
629
static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i)
630
{
631
assert(i >= 0 && i < pxformseq->numpxforms);
632
if (i != pxformseq->numpxforms - 1)
633
abort();
634
jas_cmpxform_destroy(pxformseq->pxforms[i]);
635
pxformseq->pxforms[i] = 0;
636
--pxformseq->numpxforms;
637
return 0;
638
}
639
640
static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
641
int dstclrspc, int srcclrspc)
642
{
643
if (dstclrspc == srcclrspc)
644
return 0;
645
abort();
646
/* Avoid compiler warnings about unused parameters. */
647
pxformseq = 0;
648
return -1;
649
}
650
651
static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
652
int i, jas_cmpxform_t *pxform)
653
{
654
jas_cmpxform_t *tmppxform;
655
int n;
656
if (i < 0)
657
i = pxformseq->numpxforms;
658
assert(i >= 0 && i <= pxformseq->numpxforms);
659
if (pxformseq->numpxforms >= pxformseq->maxpxforms) {
660
if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms +
661
16))
662
goto error;
663
}
664
assert(pxformseq->numpxforms < pxformseq->maxpxforms);
665
if (!(tmppxform = jas_cmpxform_copy(pxform)))
666
goto error;
667
n = pxformseq->numpxforms - i;
668
if (n > 0) {
669
memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i],
670
n * sizeof(jas_cmpxform_t *));
671
}
672
pxformseq->pxforms[i] = tmppxform;
673
++pxformseq->numpxforms;
674
return 0;
675
error:
676
return -1;
677
}
678
679
static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq,
680
jas_cmpxformseq_t *othpxformseq)
681
{
682
int n;
683
int i;
684
jas_cmpxform_t *pxform;
685
jas_cmpxform_t *othpxform;
686
n = pxformseq->numpxforms + othpxformseq->numpxforms;
687
if (n > pxformseq->maxpxforms) {
688
if (jas_cmpxformseq_resize(pxformseq, n))
689
goto error;
690
}
691
for (i = 0; i < othpxformseq->numpxforms; ++i) {
692
othpxform = othpxformseq->pxforms[i];
693
if (!(pxform = jas_cmpxform_copy(othpxform)))
694
goto error;
695
pxformseq->pxforms[pxformseq->numpxforms] = pxform;
696
++pxformseq->numpxforms;
697
}
698
return 0;
699
error:
700
return -1;
701
}
702
703
static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n)
704
{
705
jas_cmpxform_t **p;
706
assert(n >= pxformseq->numpxforms);
707
p = jas_realloc2(pxformseq->pxforms, n, sizeof(jas_cmpxform_t *));
708
if (!p) {
709
return -1;
710
}
711
pxformseq->pxforms = p;
712
pxformseq->maxpxforms = n;
713
return 0;
714
}
715
716
/******************************************************************************\
717
* Primitive transform class.
718
\******************************************************************************/
719
720
static jas_cmpxform_t *jas_cmpxform_create0()
721
{
722
jas_cmpxform_t *pxform;
723
if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t))))
724
return 0;
725
memset(pxform, 0, sizeof(jas_cmpxform_t));
726
pxform->refcnt = 0;
727
pxform->ops = 0;
728
return pxform;
729
}
730
731
static void jas_cmpxform_destroy(jas_cmpxform_t *pxform)
732
{
733
if (--pxform->refcnt <= 0) {
734
(*pxform->ops->destroy)(pxform);
735
jas_free(pxform);
736
}
737
}
738
739
static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform)
740
{
741
++pxform->refcnt;
742
return pxform;
743
}
744
745
/******************************************************************************\
746
* Shaper matrix class.
747
\******************************************************************************/
748
749
static jas_cmpxform_t *jas_cmpxform_createshapmat()
750
{
751
int i;
752
int j;
753
jas_cmpxform_t *pxform;
754
jas_cmshapmat_t *shapmat;
755
if (!(pxform = jas_cmpxform_create0()))
756
return 0;
757
pxform->ops = &shapmat_ops;
758
shapmat = &pxform->data.shapmat;
759
shapmat->mono = 0;
760
shapmat->order = 0;
761
shapmat->useluts = 0;
762
shapmat->usemat = 0;
763
for (i = 0; i < 3; ++i)
764
jas_cmshapmatlut_init(&shapmat->luts[i]);
765
for (i = 0; i < 3; ++i) {
766
for (j = 0; j < 4; ++j)
767
shapmat->mat[i][j] = 0.0;
768
}
769
++pxform->refcnt;
770
return pxform;
771
}
772
773
static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform)
774
{
775
jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
776
int i;
777
for (i = 0; i < 3; ++i)
778
jas_cmshapmatlut_cleanup(&shapmat->luts[i]);
779
}
780
781
static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in,
782
jas_cmreal_t *out, int cnt)
783
{
784
jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
785
jas_cmreal_t *src;
786
jas_cmreal_t *dst;
787
jas_cmreal_t a0;
788
jas_cmreal_t a1;
789
jas_cmreal_t a2;
790
jas_cmreal_t b0;
791
jas_cmreal_t b1;
792
jas_cmreal_t b2;
793
src = in;
794
dst = out;
795
if (!shapmat->mono) {
796
while (--cnt >= 0) {
797
a0 = *src++;
798
a1 = *src++;
799
a2 = *src++;
800
if (!shapmat->order && shapmat->useluts) {
801
a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
802
a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
803
a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
804
}
805
if (shapmat->usemat) {
806
b0 = shapmat->mat[0][0] * a0
807
+ shapmat->mat[0][1] * a1
808
+ shapmat->mat[0][2] * a2
809
+ shapmat->mat[0][3];
810
b1 = shapmat->mat[1][0] * a0
811
+ shapmat->mat[1][1] * a1
812
+ shapmat->mat[1][2] * a2
813
+ shapmat->mat[1][3];
814
b2 = shapmat->mat[2][0] * a0
815
+ shapmat->mat[2][1] * a1
816
+ shapmat->mat[2][2] * a2
817
+ shapmat->mat[2][3];
818
a0 = b0;
819
a1 = b1;
820
a2 = b2;
821
}
822
if (shapmat->order && shapmat->useluts) {
823
a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
824
a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
825
a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
826
}
827
*dst++ = a0;
828
*dst++ = a1;
829
*dst++ = a2;
830
}
831
} else {
832
if (!shapmat->order) {
833
while (--cnt >= 0) {
834
a0 = *src++;
835
if (shapmat->useluts)
836
a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
837
a2 = a0 * shapmat->mat[2][0];
838
a1 = a0 * shapmat->mat[1][0];
839
a0 = a0 * shapmat->mat[0][0];
840
*dst++ = a0;
841
*dst++ = a1;
842
*dst++ = a2;
843
}
844
} else {
845
while (--cnt >= 0) {
846
a0 = *src++;
847
src++;
848
src++;
849
a0 = a0 * shapmat->mat[0][0];
850
if (shapmat->useluts)
851
a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
852
*dst++ = a0;
853
}
854
}
855
}
856
857
return 0;
858
}
859
860
static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut)
861
{
862
lut->data = 0;
863
lut->size = 0;
864
}
865
866
static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut)
867
{
868
if (lut->data) {
869
jas_free(lut->data);
870
lut->data = 0;
871
}
872
lut->size = 0;
873
}
874
875
static double gammafn(double x, double gamma)
876
{
877
if (x == 0.0)
878
return 0.0;
879
return pow(x, gamma);
880
}
881
882
static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv)
883
{
884
jas_cmreal_t gamma;
885
int i;
886
gamma = 0;
887
jas_cmshapmatlut_cleanup(lut);
888
if (curv->numents == 0) {
889
lut->size = 2;
890
if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t))))
891
goto error;
892
lut->data[0] = 0.0;
893
lut->data[1] = 1.0;
894
} else if (curv->numents == 1) {
895
lut->size = 256;
896
if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t))))
897
goto error;
898
gamma = curv->ents[0] / 256.0;
899
for (i = 0; i < lut->size; ++i) {
900
lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma);
901
}
902
} else {
903
lut->size = curv->numents;
904
if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t))))
905
goto error;
906
for (i = 0; i < lut->size; ++i) {
907
lut->data[i] = curv->ents[i] / 65535.0;
908
}
909
}
910
return 0;
911
error:
912
return -1;
913
}
914
915
static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x)
916
{
917
jas_cmreal_t t;
918
int lo;
919
int hi;
920
t = x * (lut->size - 1);
921
lo = floor(t);
922
if (lo < 0)
923
return lut->data[0];
924
hi = ceil(t);
925
if (hi >= lut->size)
926
return lut->data[lut->size - 1];
927
return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]);
928
}
929
930
static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut,
931
jas_cmshapmatlut_t *lut, int n)
932
{
933
int i;
934
int j;
935
int k;
936
jas_cmreal_t ax;
937
jas_cmreal_t ay;
938
jas_cmreal_t bx;
939
jas_cmreal_t by;
940
jas_cmreal_t sx;
941
jas_cmreal_t sy;
942
assert(n >= 2);
943
if (invlut->data) {
944
jas_free(invlut->data);
945
invlut->data = 0;
946
}
947
/* The sample values should be nondecreasing. */
948
for (i = 1; i < lut->size; ++i) {
949
if (lut->data[i - 1] > lut->data[i]) {
950
assert(0);
951
return -1;
952
}
953
}
954
if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t))))
955
return -1;
956
invlut->size = n;
957
for (i = 0; i < invlut->size; ++i) {
958
sy = ((double) i) / (invlut->size - 1);
959
sx = 1.0;
960
for (j = 0; j < lut->size; ++j) {
961
ay = lut->data[j];
962
if (sy == ay) {
963
for (k = j + 1; k < lut->size; ++k) {
964
by = lut->data[k];
965
if (by != sy)
966
break;
967
#if 0
968
assert(0);
969
#endif
970
}
971
if (k < lut->size) {
972
--k;
973
ax = ((double) j) / (lut->size - 1);
974
bx = ((double) k) / (lut->size - 1);
975
sx = (ax + bx) / 2.0;
976
}
977
break;
978
}
979
if (j < lut->size - 1) {
980
by = lut->data[j + 1];
981
if (sy > ay && sy < by) {
982
ax = ((double) j) / (lut->size - 1);
983
bx = ((double) j + 1) / (lut->size - 1);
984
sx = ax +
985
(sy - ay) / (by - ay) * (bx - ax);
986
break;
987
}
988
}
989
}
990
invlut->data[i] = sx;
991
}
992
#if 0
993
for (i=0;i<lut->size;++i)
994
jas_eprintf("lut[%d]=%f ", i, lut->data[i]);
995
for (i=0;i<invlut->size;++i)
996
jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]);
997
#endif
998
return 0;
999
}
1000
1001
static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4])
1002
{
1003
jas_cmreal_t d;
1004
d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1])
1005
- in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0])
1006
+ in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
1007
#if 0
1008
jas_eprintf("delta=%f\n", d);
1009
#endif
1010
if (JAS_ABS(d) < 1e-6)
1011
return -1;
1012
out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d;
1013
out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d;
1014
out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d;
1015
out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d;
1016
out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d;
1017
out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d;
1018
out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d;
1019
out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d;
1020
out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d;
1021
out[0][3] = -in[0][3];
1022
out[1][3] = -in[1][3];
1023
out[2][3] = -in[2][3];
1024
#if 0
1025
jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1026
in[0][0], in[0][1], in[0][2], in[0][3],
1027
in[1][0], in[1][1], in[1][2], in[1][3],
1028
in[2][0], in[2][1], in[2][2], in[2][3]);
1029
jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1030
out[0][0], out[0][1], out[0][2], out[0][3],
1031
out[1][0], out[1][1], out[1][2], out[1][3],
1032
out[2][0], out[2][1], out[2][2], out[2][3]);
1033
#endif
1034
return 0;
1035
}
1036
1037
/******************************************************************************\
1038
*
1039
\******************************************************************************/
1040
1041
static int icctoclrspc(int iccclrspc, int refflag)
1042
{
1043
if (refflag) {
1044
switch (iccclrspc) {
1045
case JAS_ICC_COLORSPC_XYZ:
1046
return JAS_CLRSPC_CIEXYZ;
1047
case JAS_ICC_COLORSPC_LAB:
1048
return JAS_CLRSPC_CIELAB;
1049
default:
1050
abort();
1051
break;
1052
}
1053
} else {
1054
switch (iccclrspc) {
1055
case JAS_ICC_COLORSPC_YCBCR:
1056
return JAS_CLRSPC_GENYCBCR;
1057
case JAS_ICC_COLORSPC_RGB:
1058
return JAS_CLRSPC_GENRGB;
1059
case JAS_ICC_COLORSPC_GRAY:
1060
return JAS_CLRSPC_GENGRAY;
1061
default:
1062
abort();
1063
break;
1064
}
1065
}
1066
}
1067
1068
static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
1069
{
1070
jas_iccattrval_t *graytrc;
1071
jas_cmshapmat_t *shapmat;
1072
jas_cmpxform_t *pxform;
1073
jas_cmpxformseq_t *pxformseq;
1074
jas_cmshapmatlut_t lut;
1075
1076
jas_cmshapmatlut_init(&lut);
1077
if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) ||
1078
graytrc->type != JAS_ICC_TYPE_CURV)
1079
goto error;
1080
if (!(pxform = jas_cmpxform_createshapmat()))
1081
goto error;
1082
shapmat = &pxform->data.shapmat;
1083
if (!(pxformseq = jas_cmpxformseq_create()))
1084
goto error;
1085
if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
1086
goto error;
1087
1088
pxform->numinchans = 1;
1089
pxform->numoutchans = 3;
1090
1091
shapmat->mono = 1;
1092
shapmat->useluts = 1;
1093
shapmat->usemat = 1;
1094
if (!op) {
1095
shapmat->order = 0;
1096
shapmat->mat[0][0] = 0.9642;
1097
shapmat->mat[1][0] = 1.0;
1098
shapmat->mat[2][0] = 0.8249;
1099
if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv))
1100
goto error;
1101
} else {
1102
shapmat->order = 1;
1103
shapmat->mat[0][0] = 1.0 / 0.9642;
1104
shapmat->mat[1][0] = 1.0;
1105
shapmat->mat[2][0] = 1.0 / 0.8249;
1106
jas_cmshapmatlut_init(&lut);
1107
if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv))
1108
goto error;
1109
if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size))
1110
goto error;
1111
jas_cmshapmatlut_cleanup(&lut);
1112
}
1113
jas_iccattrval_destroy(graytrc);
1114
jas_cmpxform_destroy(pxform);
1115
*retpxformseq = pxformseq;
1116
return 0;
1117
error:
1118
return -1;
1119
}
1120
1121
static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
1122
{
1123
int i;
1124
jas_iccattrval_t *trcs[3];
1125
jas_iccattrval_t *cols[3];
1126
jas_cmshapmat_t *shapmat;
1127
jas_cmpxform_t *pxform;
1128
jas_cmpxformseq_t *pxformseq;
1129
jas_cmreal_t mat[3][4];
1130
jas_cmshapmatlut_t lut;
1131
1132
pxform = 0;
1133
pxformseq = 0;
1134
for (i = 0; i < 3; ++i) {
1135
trcs[i] = 0;
1136
cols[i] = 0;
1137
}
1138
jas_cmshapmatlut_init(&lut);
1139
1140
if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) ||
1141
!(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) ||
1142
!(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) ||
1143
!(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) ||
1144
!(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) ||
1145
!(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL)))
1146
goto error;
1147
for (i = 0; i < 3; ++i) {
1148
if (trcs[i]->type != JAS_ICC_TYPE_CURV ||
1149
cols[i]->type != JAS_ICC_TYPE_XYZ)
1150
goto error;
1151
}
1152
if (!(pxform = jas_cmpxform_createshapmat()))
1153
goto error;
1154
pxform->numinchans = 3;
1155
pxform->numoutchans = 3;
1156
shapmat = &pxform->data.shapmat;
1157
if (!(pxformseq = jas_cmpxformseq_create()))
1158
goto error;
1159
if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
1160
goto error;
1161
shapmat->mono = 0;
1162
shapmat->useluts = 1;
1163
shapmat->usemat = 1;
1164
if (!op) {
1165
shapmat->order = 0;
1166
for (i = 0; i < 3; ++i) {
1167
shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0;
1168
shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0;
1169
shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0;
1170
}
1171
for (i = 0; i < 3; ++i)
1172
shapmat->mat[i][3] = 0.0;
1173
for (i = 0; i < 3; ++i) {
1174
if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv))
1175
goto error;
1176
}
1177
} else {
1178
shapmat->order = 1;
1179
for (i = 0; i < 3; ++i) {
1180
mat[0][i] = cols[i]->data.xyz.x / 65536.0;
1181
mat[1][i] = cols[i]->data.xyz.y / 65536.0;
1182
mat[2][i] = cols[i]->data.xyz.z / 65536.0;
1183
}
1184
for (i = 0; i < 3; ++i)
1185
mat[i][3] = 0.0;
1186
if (jas_cmshapmat_invmat(shapmat->mat, mat))
1187
goto error;
1188
for (i = 0; i < 3; ++i) {
1189
jas_cmshapmatlut_init(&lut);
1190
if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv))
1191
goto error;
1192
if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size))
1193
goto error;
1194
jas_cmshapmatlut_cleanup(&lut);
1195
}
1196
}
1197
for (i = 0; i < 3; ++i) {
1198
jas_iccattrval_destroy(trcs[i]);
1199
jas_iccattrval_destroy(cols[i]);
1200
}
1201
jas_cmpxform_destroy(pxform);
1202
*retpxformseq = pxformseq;
1203
return 0;
1204
1205
error:
1206
1207
for (i = 0; i < 3; ++i) {
1208
if (trcs[i]) {
1209
jas_iccattrval_destroy(trcs[i]);
1210
}
1211
if (cols[i]) {
1212
jas_iccattrval_destroy(cols[i]);
1213
}
1214
}
1215
if (pxformseq) {
1216
jas_cmpxformseq_destroy(pxformseq);
1217
}
1218
if (pxform) {
1219
jas_cmpxform_destroy(pxform);
1220
}
1221
1222
return -1;
1223
}
1224
1225
static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val)
1226
{
1227
long v;
1228
int m;
1229
v = **bufptr;
1230
if (sgnd) {
1231
m = (1 << (prec - 1));
1232
if (v < -m || v >= m)
1233
return -1;
1234
} else {
1235
if (v < 0 || v >= (1 << prec))
1236
return -1;
1237
}
1238
++(*bufptr);
1239
*val = v;
1240
return 0;
1241
}
1242
1243
static int jas_cmputint(long **bufptr, int sgnd, int prec, long val)
1244
{
1245
int m;
1246
if (sgnd) {
1247
m = (1 << (prec - 1));
1248
if (val < -m || val >= m)
1249
return -1;
1250
} else {
1251
if (val < 0 || val >= (1 << prec))
1252
return -1;
1253
}
1254
**bufptr = val;
1255
++(*bufptr);
1256
return 0;
1257
}
1258
1259
int jas_clrspc_numchans(int clrspc)
1260
{
1261
switch (jas_clrspc_fam(clrspc)) {
1262
case JAS_CLRSPC_FAM_XYZ:
1263
case JAS_CLRSPC_FAM_LAB:
1264
case JAS_CLRSPC_FAM_RGB:
1265
case JAS_CLRSPC_FAM_YCBCR:
1266
return 3;
1267
break;
1268
case JAS_CLRSPC_FAM_GRAY:
1269
return 1;
1270
break;
1271
default:
1272
abort();
1273
break;
1274
}
1275
}
1276
1277
jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof)
1278
{
1279
return jas_iccprof_copy(prof->iccprof);
1280
}
1281
1282