jas_cm.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
jas_cm.c (34364B)
---
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) 1999-2000 Image Power, Inc.
11 * Copyright (c) 1999-2000 The University of British Columbia
12 * Copyright (c) 2001-2003 Michael David Adams
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 1918 2005-07-24 14:12:08Z baford $
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 #if 0
162 jas_iccprof_destroy(iccprof);
163 #else
164 prof->iccprof = iccprof;
165 #endif
166 if (!jas_clrspc_isgeneric(clrspc))
167 prof->clrspc = clrspc;
168 break;
169 }
170 return prof;
171 error:
172 if (iccprof)
173 jas_iccprof_destroy(iccprof);
174 return 0;
175 }
176
177 static jas_cmprof_t *jas_cmprof_createsycc()
178 {
179 jas_cmprof_t *prof;
180 jas_cmpxform_t *fwdpxform;
181 jas_cmpxform_t *revpxform;
182 jas_cmshapmat_t *fwdshapmat;
183 jas_cmshapmat_t *revshapmat;
184 int i;
185 int j;
186
187 if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)))
188 goto error;
189 prof->clrspc = JAS_CLRSPC_SYCBCR;
190 assert(prof->numchans == 3 && prof->numrefchans == 3);
191 assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ);
192 if (!(fwdpxform = jas_cmpxform_createshapmat()))
193 goto error;
194 fwdpxform->numinchans = 3;
195 fwdpxform->numoutchans = 3;
196 fwdshapmat = &fwdpxform->data.shapmat;
197 fwdshapmat->mono = 0;
198 fwdshapmat->order = 0;
199 fwdshapmat->useluts = 0;
200 fwdshapmat->usemat = 1;
201 fwdshapmat->mat[0][0] = 1.0;
202 fwdshapmat->mat[0][1] = 0.0;
203 fwdshapmat->mat[0][2] = 1.402;
204 fwdshapmat->mat[1][0] = 1.0;
205 fwdshapmat->mat[1][1] = -0.34413;
206 fwdshapmat->mat[1][2] = -0.71414;
207 fwdshapmat->mat[2][0] = 1.0;
208 fwdshapmat->mat[2][1] = 1.772;
209 fwdshapmat->mat[2][2] = 0.0;
210 fwdshapmat->mat[0][3] = -0.5 * (1.402);
211 fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414);
212 fwdshapmat->mat[2][3] = -0.5 * (1.772);
213 if (!(revpxform = jas_cmpxform_createshapmat()))
214 goto error;
215 revpxform->numinchans = 3;
216 revpxform->numoutchans = 3;
217 revshapmat = &revpxform->data.shapmat;
218 revshapmat->mono = 0;
219 revshapmat->order = 1;
220 revshapmat->useluts = 0;
221 revshapmat->usemat = 1;
222 jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat);
223
224 for (i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) {
225 j = SEQFWD(i);
226 if (prof->pxformseqs[j]) {
227 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0,
228 fwdpxform))
229 goto error;
230 }
231 j = SEQREV(i);
232 if (prof->pxformseqs[j]) {
233 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j],
234 -1, revpxform))
235 goto error;
236 }
237 }
238
239 jas_cmpxform_destroy(fwdpxform);
240 jas_cmpxform_destroy(revpxform);
241 return prof;
242 error:
243 return 0;
244 }
245
246 jas_cmprof_t *jas_cmprof_createfromiccprof(jas_iccprof_t *iccprof)
247 {
248 jas_cmprof_t *prof;
249 jas_icchdr_t icchdr;
250 jas_cmpxformseq_t *fwdpxformseq;
251 jas_cmpxformseq_t *revpxformseq;
252
253 if (!(prof = jas_cmprof_create()))
254 goto error;
255 jas_iccprof_gethdr(iccprof, &icchdr);
256 if (!(prof->iccprof = jas_iccprof_copy(iccprof)))
257 goto error;
258 prof->clrspc = icctoclrspc(icchdr.colorspc, 0);
259 prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1);
260 prof->numchans = jas_clrspc_numchans(prof->clrspc);
261 prof->numrefchans = jas_clrspc_numchans(prof->refclrspc);
262
263 if (prof->numchans == 1) {
264 if (mono(prof->iccprof, 0, &fwdpxformseq))
265 goto error;
266 if (mono(prof->iccprof, 1, &revpxformseq))
267 goto error;
268 } else if (prof->numchans == 3) {
269 if (triclr(prof->iccprof, 0, &fwdpxformseq))
270 goto error;
271 if (triclr(prof->iccprof, 1, &revpxformseq))
272 goto error;
273 }
274 prof->pxformseqs[SEQFWD(0)] = fwdpxformseq;
275 prof->pxformseqs[SEQREV(0)] = revpxformseq;
276
277 #if 0
278 if (prof->numchans > 1) {
279 lut(prof->iccprof, 0, PER, &pxformseq);
280 pxformseqs_set(prof, SEQFWD(PER), pxformseq);
281 lut(prof->iccprof, 1, PER, &pxformseq);
282 pxformseqs_set(prof, SEQREV(PER), pxformseq);
283 lut(prof->iccprof, 0, CLR, &pxformseq);
284 pxformseqs_set(prof, SEQREV(CLR), pxformseq);
285 lut(prof->iccprof, 1, CLR, &pxformseq);
286 pxformseqs_set(prof, SEQREV(CLR), pxformseq);
287 lut(prof->iccprof, 0, SAT, &pxformseq);
288 pxformseqs_set(prof, SEQREV(SAT), pxformseq);
289 lut(prof->iccprof, 1, SAT, &pxformseq);
290 pxformseqs_set(prof, SEQREV(SAT), pxformseq);
291 }
292 #endif
293
294 return prof;
295 error:
296 return 0;
297 }
298
299 static jas_cmprof_t *jas_cmprof_create()
300 {
301 int i;
302 jas_cmprof_t *prof;
303 if (!(prof = jas_malloc(sizeof(jas_cmprof_t))))
304 return 0;
305 memset(prof, 0, sizeof(jas_cmprof_t));
306 prof->iccprof = 0;
307 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i)
308 prof->pxformseqs[i] = 0;
309 return prof;
310 }
311
312 void jas_cmprof_destroy(jas_cmprof_t *prof)
313 {
314 int i;
315 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
316 if (prof->pxformseqs[i]) {
317 jas_cmpxformseq_destroy(prof->pxformseqs[i]);
318 prof->pxformseqs[i] = 0;
319 }
320 }
321 if (prof->iccprof)
322 jas_iccprof_destroy(prof->iccprof);
323 jas_free(prof);
324 }
325
326 jas_cmprof_t *jas_cmprof_copy(jas_cmprof_t *prof)
327 {
328 jas_cmprof_t *newprof;
329 int i;
330
331 if (!(newprof = jas_cmprof_create()))
332 goto error;
333 newprof->clrspc = prof->clrspc;
334 newprof->numchans = prof->numchans;
335 newprof->refclrspc = prof->refclrspc;
336 newprof->numrefchans = prof->numrefchans;
337 newprof->iccprof = jas_iccprof_copy(prof->iccprof);
338 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
339 if (prof->pxformseqs[i]) {
340 if (!(newprof->pxformseqs[i] = jas_cmpxformseq_copy(prof->pxformseqs[i])))
341 goto error;
342 }
343 }
344 return newprof;
345 error:
346 return 0;
347 }
348
349 /******************************************************************************\
350 * Transform class.
351 \******************************************************************************/
352
353 jas_cmxform_t *jas_cmxform_create(jas_cmprof_t *inprof, jas_cmprof_t *outprof,
354 jas_cmprof_t *prfprof, int op, int intent, int optimize)
355 {
356 jas_cmxform_t *xform;
357 jas_cmpxformseq_t *inpxformseq;
358 jas_cmpxformseq_t *outpxformseq;
359 jas_cmpxformseq_t *altoutpxformseq;
360 jas_cmpxformseq_t *prfpxformseq;
361 int prfintent;
362
363 /* Avoid compiler warnings about unused parameters. */
364 optimize = 0;
365
366 prfintent = intent;
367
368 if (!(xform = jas_malloc(sizeof(jas_cmxform_t))))
369 goto error;
370 if (!(xform->pxformseq = jas_cmpxformseq_create()))
371 goto error;
372
373 switch (op) {
374 case JAS_CMXFORM_OP_FWD:
375 inpxformseq = fwdpxformseq(inprof, intent);
376 outpxformseq = revpxformseq(outprof, intent);
377 if (!inpxformseq || !outpxformseq)
378 goto error;
379 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
380 jas_cmpxformseq_appendcnvt(xform->pxformseq,
381 inprof->refclrspc, outprof->refclrspc) ||
382 jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
383 goto error;
384 xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
385 xform->numoutchans = jas_clrspc_numchans(outprof->clrspc);
386 break;
387 case JAS_CMXFORM_OP_REV:
388 outpxformseq = fwdpxformseq(outprof, intent);
389 inpxformseq = revpxformseq(inprof, intent);
390 if (!outpxformseq || !inpxformseq)
391 goto error;
392 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
393 jas_cmpxformseq_appendcnvt(xform->pxformseq,
394 outprof->refclrspc, inprof->refclrspc) ||
395 jas_cmpxformseq_append(xform->pxformseq, inpxformseq))
396 goto error;
397 xform->numinchans = jas_clrspc_numchans(outprof->clrspc);
398 xform->numoutchans = jas_clrspc_numchans(inprof->clrspc);
399 break;
400 case JAS_CMXFORM_OP_PROOF:
401 assert(prfprof);
402 inpxformseq = fwdpxformseq(inprof, intent);
403 prfpxformseq = fwdpxformseq(prfprof, prfintent);
404 if (!inpxformseq || !prfpxformseq)
405 goto error;
406 outpxformseq = simpxformseq(outprof, intent);
407 altoutpxformseq = 0;
408 if (!outpxformseq) {
409 outpxformseq = revpxformseq(outprof, intent);
410 altoutpxformseq = fwdpxformseq(outprof, intent);
411 if (!outpxformseq || !altoutpxformseq)
412 goto error;
413 }
414 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
415 jas_cmpxformseq_appendcnvt(xform->pxformseq,
416 inprof->refclrspc, outprof->refclrspc))
417 goto error;
418 if (altoutpxformseq) {
419 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
420 jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq))
421 goto error;
422 } else {
423 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
424 goto error;
425 }
426 if (jas_cmpxformseq_appendcnvt(xform->pxformseq,
427 outprof->refclrspc, inprof->refclrspc) ||
428 jas_cmpxformseq_append(xform->pxformseq, prfpxformseq))
429 goto error;
430 xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
431 xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc);
432 break;
433 case JAS_CMXFORM_OP_GAMUT:
434 inpxformseq = fwdpxformseq(inprof, intent);
435 outpxformseq = gampxformseq(outprof);
436 if (!inpxformseq || !outpxformseq)
437 goto error;
438 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
439 jas_cmpxformseq_appendcnvt(xform->pxformseq,
440 inprof->refclrspc, outprof->refclrspc) ||
441 jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
442 goto error;
443 xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
444 xform->numoutchans = 1;
445 break;
446 }
447 return xform;
448 error:
449 return 0;
450 }
451
452 #define APPLYBUFSIZ 2048
453 int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out)
454 {
455 jas_cmcmptfmt_t *fmt;
456 jas_cmreal_t buf[2][APPLYBUFSIZ];
457 jas_cmpxformseq_t *pxformseq;
458 int i;
459 int j;
460 int width;
461 int height;
462 int total;
463 int n;
464 jas_cmreal_t *inbuf;
465 jas_cmreal_t *outbuf;
466 jas_cmpxform_t *pxform;
467 long *dataptr;
468 int maxchans;
469 int bufmax;
470 int m;
471 int bias;
472 jas_cmreal_t scale;
473 long v;
474 jas_cmreal_t *bufptr;
475
476 if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts)
477 goto error;
478
479 fmt = &in->cmptfmts[0];
480 width = fmt->width;
481 height = fmt->height;
482 for (i = 1; i < xform->numinchans; ++i) {
483 fmt = &in->cmptfmts[i];
484 if (fmt->width != width || fmt->height != height) {
485 goto error;
486 }
487 }
488 for (i = 0; i < xform->numoutchans; ++i) {
489 fmt = &out->cmptfmts[i];
490 if (fmt->width != width || fmt->height != height) {
491 goto error;
492 }
493 }
494
495 maxchans = 0;
496 pxformseq = xform->pxformseq;
497 for (i = 0; i < pxformseq->numpxforms; ++i) {
498 pxform = pxformseq->pxforms[i];
499 if (pxform->numinchans > maxchans) {
500 maxchans = pxform->numinchans;
501 }
502 if (pxform->numoutchans > maxchans) {
503 maxchans = pxform->numoutchans;
504 }
505 }
506 bufmax = APPLYBUFSIZ / maxchans;
507 assert(bufmax > 0);
508
509 total = width * height;
510 n = 0;
511 while (n < total) {
512
513 inbuf = &buf[0][0];
514 m = JAS_MIN(total - n, bufmax);
515
516 for (i = 0; i < xform->numinchans; ++i) {
517 fmt = &in->cmptfmts[i];
518 scale = (double)((1 << fmt->prec) - 1);
519 bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
520 dataptr = &fmt->buf[n];
521 bufptr = &inbuf[i];
522 for (j = 0; j < m; ++j) {
523 if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v))
524 goto error;
525 *bufptr = (v - bias) / scale;
526 bufptr += xform->numinchans;
527 }
528 }
529
530 inbuf = &buf[0][0];
531 outbuf = inbuf;
532 for (i = 0; i < pxformseq->numpxforms; ++i) {
533 pxform = pxformseq->pxforms[i];
534 if (pxform->numoutchans > pxform->numinchans) {
535 outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0];
536 } else {
537 outbuf = inbuf;
538 }
539 if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m))
540 goto error;
541 inbuf = outbuf;
542 }
543
544 for (i = 0; i < xform->numoutchans; ++i) {
545 fmt = &out->cmptfmts[i];
546 scale = (double)((1 << fmt->prec) - 1);
547 bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
548 bufptr = &outbuf[i];
549 dataptr = &fmt->buf[n];
550 for (j = 0; j < m; ++j) {
551 v = (*bufptr) * scale + bias;
552 bufptr += xform->numoutchans;
553 if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v))
554 goto error;
555 }
556 }
557
558 n += m;
559 }
560
561 return 0;
562 error:
563 return -1;
564 }
565
566 void jas_cmxform_destroy(jas_cmxform_t *xform)
567 {
568 if (xform->pxformseq)
569 jas_cmpxformseq_destroy(xform->pxformseq);
570 jas_free(xform);
571 }
572
573 /******************************************************************************\
574 * Primitive transform sequence class.
575 \******************************************************************************/
576
577 static jas_cmpxformseq_t *jas_cmpxformseq_create()
578 {
579 jas_cmpxformseq_t *pxformseq;
580 pxformseq = 0;
581 if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t))))
582 goto error;
583 pxformseq->pxforms = 0;
584 pxformseq->numpxforms = 0;
585 pxformseq->maxpxforms = 0;
586 if (jas_cmpxformseq_resize(pxformseq, 16))
587 goto error;
588 return pxformseq;
589 error:
590 if (pxformseq)
591 jas_cmpxformseq_destroy(pxformseq);
592 return 0;
593 }
594
595 static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq)
596 {
597 jas_cmpxformseq_t *newpxformseq;
598
599 if (!(newpxformseq = jas_cmpxformseq_create()))
600 goto error;
601 if (jas_cmpxformseq_append(newpxformseq, pxformseq))
602 goto error;
603 return newpxformseq;
604 error:
605 return 0;
606 }
607
608 static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq)
609 {
610 while (pxformseq->numpxforms > 0)
611 jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1);
612 if (pxformseq->pxforms)
613 jas_free(pxformseq->pxforms);
614 jas_free(pxformseq);
615 }
616
617 static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i)
618 {
619 assert(i >= 0 && i < pxformseq->numpxforms);
620 if (i != pxformseq->numpxforms - 1)
621 abort();
622 jas_cmpxform_destroy(pxformseq->pxforms[i]);
623 pxformseq->pxforms[i] = 0;
624 --pxformseq->numpxforms;
625 return 0;
626 }
627
628 static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
629 int dstclrspc, int srcclrspc)
630 {
631 if (dstclrspc == srcclrspc)
632 return 0;
633 abort();
634 /* Avoid compiler warnings about unused parameters. */
635 pxformseq = 0;
636 return -1;
637 }
638
639 static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
640 int i, jas_cmpxform_t *pxform)
641 {
642 jas_cmpxform_t *tmppxform;
643 int n;
644 if (i < 0)
645 i = pxformseq->numpxforms;
646 assert(i >= 0 && i <= pxformseq->numpxforms);
647 if (pxformseq->numpxforms >= pxformseq->maxpxforms) {
648 if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms +
649 16))
650 goto error;
651 }
652 assert(pxformseq->numpxforms < pxformseq->maxpxforms);
653 if (!(tmppxform = jas_cmpxform_copy(pxform)))
654 goto error;
655 n = pxformseq->numpxforms - i;
656 if (n > 0) {
657 memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i],
658 n * sizeof(jas_cmpxform_t *));
659 }
660 pxformseq->pxforms[i] = tmppxform;
661 ++pxformseq->numpxforms;
662 return 0;
663 error:
664 return -1;
665 }
666
667 static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq,
668 jas_cmpxformseq_t *othpxformseq)
669 {
670 int n;
671 int i;
672 jas_cmpxform_t *pxform;
673 jas_cmpxform_t *othpxform;
674 n = pxformseq->numpxforms + othpxformseq->numpxforms;
675 if (n > pxformseq->maxpxforms) {
676 if (jas_cmpxformseq_resize(pxformseq, n))
677 goto error;
678 }
679 for (i = 0; i < othpxformseq->numpxforms; ++i) {
680 othpxform = othpxformseq->pxforms[i];
681 if (!(pxform = jas_cmpxform_copy(othpxform)))
682 goto error;
683 pxformseq->pxforms[pxformseq->numpxforms] = pxform;
684 ++pxformseq->numpxforms;
685 }
686 return 0;
687 error:
688 return -1;
689 }
690
691 static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n)
692 {
693 jas_cmpxform_t **p;
694 assert(n >= pxformseq->numpxforms);
695 p = (!pxformseq->pxforms) ? jas_malloc(n * sizeof(jas_cmpxform_t *)) :
696 jas_realloc(pxformseq->pxforms, n * sizeof(jas_cmpxform_t *));
697 if (!p) {
698 return -1;
699 }
700 pxformseq->pxforms = p;
701 pxformseq->maxpxforms = n;
702 return 0;
703 }
704
705 /******************************************************************************\
706 * Primitive transform class.
707 \******************************************************************************/
708
709 static jas_cmpxform_t *jas_cmpxform_create0()
710 {
711 jas_cmpxform_t *pxform;
712 if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t))))
713 return 0;
714 memset(pxform, 0, sizeof(jas_cmpxform_t));
715 pxform->refcnt = 0;
716 pxform->ops = 0;
717 return pxform;
718 }
719
720 static void jas_cmpxform_destroy(jas_cmpxform_t *pxform)
721 {
722 if (--pxform->refcnt <= 0) {
723 (*pxform->ops->destroy)(pxform);
724 jas_free(pxform);
725 }
726 }
727
728 static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform)
729 {
730 ++pxform->refcnt;
731 return pxform;
732 }
733
734 /******************************************************************************\
735 * Shaper matrix class.
736 \******************************************************************************/
737
738 static jas_cmpxform_t *jas_cmpxform_createshapmat()
739 {
740 int i;
741 int j;
742 jas_cmpxform_t *pxform;
743 jas_cmshapmat_t *shapmat;
744 if (!(pxform = jas_cmpxform_create0()))
745 return 0;
746 pxform->ops = &shapmat_ops;
747 shapmat = &pxform->data.shapmat;
748 shapmat->mono = 0;
749 shapmat->order = 0;
750 shapmat->useluts = 0;
751 shapmat->usemat = 0;
752 for (i = 0; i < 3; ++i)
753 jas_cmshapmatlut_init(&shapmat->luts[i]);
754 for (i = 0; i < 3; ++i) {
755 for (j = 0; j < 4; ++j)
756 shapmat->mat[i][j] = 0.0;
757 }
758 ++pxform->refcnt;
759 return pxform;
760 }
761
762 static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform)
763 {
764 jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
765 int i;
766 for (i = 0; i < 3; ++i)
767 jas_cmshapmatlut_cleanup(&shapmat->luts[i]);
768 }
769
770 static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in,
771 jas_cmreal_t *out, int cnt)
772 {
773 jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
774 jas_cmreal_t *src;
775 jas_cmreal_t *dst;
776 jas_cmreal_t a0;
777 jas_cmreal_t a1;
778 jas_cmreal_t a2;
779 jas_cmreal_t b0;
780 jas_cmreal_t b1;
781 jas_cmreal_t b2;
782 src = in;
783 dst = out;
784 if (!shapmat->mono) {
785 while (--cnt >= 0) {
786 a0 = *src++;
787 a1 = *src++;
788 a2 = *src++;
789 if (!shapmat->order && shapmat->useluts) {
790 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
791 a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
792 a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
793 }
794 if (shapmat->usemat) {
795 b0 = shapmat->mat[0][0] * a0
796 + shapmat->mat[0][1] * a1
797 + shapmat->mat[0][2] * a2
798 + shapmat->mat[0][3];
799 b1 = shapmat->mat[1][0] * a0
800 + shapmat->mat[1][1] * a1
801 + shapmat->mat[1][2] * a2
802 + shapmat->mat[1][3];
803 b2 = shapmat->mat[2][0] * a0
804 + shapmat->mat[2][1] * a1
805 + shapmat->mat[2][2] * a2
806 + shapmat->mat[2][3];
807 a0 = b0;
808 a1 = b1;
809 a2 = b2;
810 }
811 if (shapmat->order && shapmat->useluts) {
812 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
813 a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
814 a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
815 }
816 *dst++ = a0;
817 *dst++ = a1;
818 *dst++ = a2;
819 }
820 } else {
821 if (!shapmat->order) {
822 while (--cnt >= 0) {
823 a0 = *src++;
824 if (shapmat->useluts)
825 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
826 a2 = a0 * shapmat->mat[2][0];
827 a1 = a0 * shapmat->mat[1][0];
828 a0 = a0 * shapmat->mat[0][0];
829 *dst++ = a0;
830 *dst++ = a1;
831 *dst++ = a2;
832 }
833 } else {
834 assert(0);
835 while (--cnt >= 0) {
836 a0 = *src++;
837 src++;
838 src++;
839 a0 = a0 * shapmat->mat[0][0];
840 if (shapmat->useluts)
841 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
842 *dst++ = a0;
843 }
844 }
845 }
846
847 return 0;
848 }
849
850 static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut)
851 {
852 lut->data = 0;
853 lut->size = 0;
854 }
855
856 static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut)
857 {
858 if (lut->data) {
859 jas_free(lut->data);
860 lut->data = 0;
861 }
862 lut->size = 0;
863 }
864
865 static double gammafn(double x, double gamma)
866 {
867 if (x == 0.0)
868 return 0.0;
869 return pow(x, gamma);
870 }
871
872 static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv)
873 {
874 jas_cmreal_t gamma;
875 int i;
876 gamma = 0;
877 jas_cmshapmatlut_cleanup(lut);
878 if (curv->numents == 0) {
879 lut->size = 2;
880 if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t))))
881 goto error;
882 lut->data[0] = 0.0;
883 lut->data[1] = 1.0;
884 } else if (curv->numents == 1) {
885 lut->size = 256;
886 if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t))))
887 goto error;
888 gamma = curv->ents[0] / 256.0;
889 for (i = 0; i < lut->size; ++i) {
890 lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma);
891 }
892 } else {
893 lut->size = curv->numents;
894 if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t))))
895 goto error;
896 for (i = 0; i < lut->size; ++i) {
897 lut->data[i] = curv->ents[i] / 65535.0;
898 }
899 }
900 return 0;
901 error:
902 return -1;
903 }
904
905 static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x)
906 {
907 jas_cmreal_t t;
908 int lo;
909 int hi;
910 t = x * (lut->size - 1);
911 lo = floor(t);
912 if (lo < 0)
913 return lut->data[0];
914 hi = ceil(t);
915 if (hi >= lut->size)
916 return lut->data[lut->size - 1];
917 return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]);
918 }
919
920 static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut,
921 jas_cmshapmatlut_t *lut, int n)
922 {
923 int i;
924 int j;
925 int k;
926 jas_cmreal_t ax;
927 jas_cmreal_t ay;
928 jas_cmreal_t bx;
929 jas_cmreal_t by;
930 jas_cmreal_t sx;
931 jas_cmreal_t sy;
932 assert(n >= 2);
933 if (invlut->data) {
934 jas_free(invlut->data);
935 invlut->data = 0;
936 }
937 /* The sample values should be nondecreasing. */
938 for (i = 1; i < lut->size; ++i) {
939 if (lut->data[i - 1] > lut->data[i]) {
940 assert(0);
941 return -1;
942 }
943 }
944 if (!(invlut->data = jas_malloc(n * sizeof(jas_cmreal_t))))
945 return -1;
946 invlut->size = n;
947 for (i = 0; i < invlut->size; ++i) {
948 sy = ((double) i) / (invlut->size - 1);
949 sx = 1.0;
950 for (j = 0; j < lut->size; ++j) {
951 ay = lut->data[j];
952 if (sy == ay) {
953 for (k = j + 1; k < lut->size; ++k) {
954 by = lut->data[k];
955 if (by != sy)
956 break;
957 #if 0
958 assert(0);
959 #endif
960 }
961 if (k < lut->size) {
962 --k;
963 ax = ((double) j) / (lut->size - 1);
964 bx = ((double) k) / (lut->size - 1);
965 sx = (ax + bx) / 2.0;
966 }
967 break;
968 }
969 if (j < lut->size - 1) {
970 by = lut->data[j + 1];
971 if (sy > ay && sy < by) {
972 ax = ((double) j) / (lut->size - 1);
973 bx = ((double) j + 1) / (lut->size - 1);
974 sx = ax +
975 (sy - ay) / (by - ay) * (bx - ax);
976 break;
977 }
978 }
979 }
980 invlut->data[i] = sx;
981 }
982 #if 0
983 for (i=0;i<lut->size;++i)
984 fprintf(stderr, "lut[%d]=%f ", i, lut->data[i]);
985 for (i=0;i<invlut->size;++i)
986 fprintf(stderr, "invlut[%d]=%f ", i, invlut->data[i]);
987 #endif
988 return 0;
989 }
990
991 static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4])
992 {
993 jas_cmreal_t d;
994 d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1])
995 - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0])
996 + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
997 #if 0
998 fprintf(stderr, "delta=%f\n", d);
999 #endif
1000 if (JAS_ABS(d) < 1e-6)
1001 return -1;
1002 out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d;
1003 out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d;
1004 out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d;
1005 out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d;
1006 out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d;
1007 out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d;
1008 out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d;
1009 out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d;
1010 out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d;
1011 out[0][3] = -in[0][3];
1012 out[1][3] = -in[1][3];
1013 out[2][3] = -in[2][3];
1014 #if 0
1015 fprintf(stderr, "[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1016 in[0][0], in[0][1], in[0][2], in[0][3],
1017 in[1][0], in[1][1], in[1][2], in[1][3],
1018 in[2][0], in[2][1], in[2][2], in[2][3]);
1019 fprintf(stderr, "[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
1020 out[0][0], out[0][1], out[0][2], out[0][3],
1021 out[1][0], out[1][1], out[1][2], out[1][3],
1022 out[2][0], out[2][1], out[2][2], out[2][3]);
1023 #endif
1024 return 0;
1025 }
1026
1027 /******************************************************************************\
1028 *
1029 \******************************************************************************/
1030
1031 static int icctoclrspc(int iccclrspc, int refflag)
1032 {
1033 if (refflag) {
1034 switch (iccclrspc) {
1035 case JAS_ICC_COLORSPC_XYZ:
1036 return JAS_CLRSPC_CIEXYZ;
1037 case JAS_ICC_COLORSPC_LAB:
1038 return JAS_CLRSPC_CIELAB;
1039 default:
1040 abort();
1041 break;
1042 }
1043 } else {
1044 switch (iccclrspc) {
1045 case JAS_ICC_COLORSPC_YCBCR:
1046 return JAS_CLRSPC_GENYCBCR;
1047 case JAS_ICC_COLORSPC_RGB:
1048 return JAS_CLRSPC_GENRGB;
1049 case JAS_ICC_COLORSPC_GRAY:
1050 return JAS_CLRSPC_GENGRAY;
1051 default:
1052 abort();
1053 break;
1054 }
1055 }
1056 }
1057
1058 static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
1059 {
1060 jas_iccattrval_t *graytrc;
1061 jas_cmshapmat_t *shapmat;
1062 jas_cmpxform_t *pxform;
1063 jas_cmpxformseq_t *pxformseq;
1064 jas_cmshapmatlut_t lut;
1065
1066 jas_cmshapmatlut_init(&lut);
1067 if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) ||
1068 graytrc->type != JAS_ICC_TYPE_CURV)
1069 goto error;
1070 if (!(pxform = jas_cmpxform_createshapmat()))
1071 goto error;
1072 shapmat = &pxform->data.shapmat;
1073 if (!(pxformseq = jas_cmpxformseq_create()))
1074 goto error;
1075 if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
1076 goto error;
1077
1078 pxform->numinchans = 1;
1079 pxform->numoutchans = 3;
1080
1081 shapmat->mono = 1;
1082 shapmat->useluts = 1;
1083 shapmat->usemat = 1;
1084 if (!op) {
1085 shapmat->order = 0;
1086 shapmat->mat[0][0] = 0.9642;
1087 shapmat->mat[1][0] = 1.0;
1088 shapmat->mat[2][0] = 0.8249;
1089 if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv))
1090 goto error;
1091 } else {
1092 shapmat->order = 1;
1093 shapmat->mat[0][0] = 1.0 / 0.9642;
1094 shapmat->mat[1][0] = 1.0;
1095 shapmat->mat[2][0] = 1.0 / 0.8249;
1096 jas_cmshapmatlut_init(&lut);
1097 if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv))
1098 goto error;
1099 if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size))
1100 goto error;
1101 jas_cmshapmatlut_cleanup(&lut);
1102 }
1103 jas_iccattrval_destroy(graytrc);
1104 jas_cmpxform_destroy(pxform);
1105 *retpxformseq = pxformseq;
1106 return 0;
1107 error:
1108 return -1;
1109 }
1110
1111 static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
1112 {
1113 int i;
1114 jas_iccattrval_t *trcs[3];
1115 jas_iccattrval_t *cols[3];
1116 jas_cmshapmat_t *shapmat;
1117 jas_cmpxform_t *pxform;
1118 jas_cmpxformseq_t *pxformseq;
1119 jas_cmreal_t mat[3][4];
1120 jas_cmshapmatlut_t lut;
1121 jas_cmshapmatlut_init(&lut);
1122 for (i = 0; i < 3; ++i) {
1123 trcs[i] = 0;
1124 cols[i] = 0;
1125 }
1126 if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) ||
1127 !(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) ||
1128 !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) ||
1129 !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) ||
1130 !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) ||
1131 !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL)))
1132 goto error;
1133 for (i = 0; i < 3; ++i) {
1134 if (trcs[i]->type != JAS_ICC_TYPE_CURV ||
1135 cols[i]->type != JAS_ICC_TYPE_XYZ)
1136 goto error;
1137 }
1138 if (!(pxform = jas_cmpxform_createshapmat()))
1139 goto error;
1140 pxform->numinchans = 3;
1141 pxform->numoutchans = 3;
1142 shapmat = &pxform->data.shapmat;
1143 if (!(pxformseq = jas_cmpxformseq_create()))
1144 goto error;
1145 if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
1146 goto error;
1147 shapmat->mono = 0;
1148 shapmat->useluts = 1;
1149 shapmat->usemat = 1;
1150 if (!op) {
1151 shapmat->order = 0;
1152 for (i = 0; i < 3; ++i) {
1153 shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0;
1154 shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0;
1155 shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0;
1156 }
1157 for (i = 0; i < 3; ++i)
1158 shapmat->mat[i][3] = 0.0;
1159 for (i = 0; i < 3; ++i) {
1160 if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv))
1161 goto error;
1162 }
1163 } else {
1164 shapmat->order = 1;
1165 for (i = 0; i < 3; ++i) {
1166 mat[0][i] = cols[i]->data.xyz.x / 65536.0;
1167 mat[1][i] = cols[i]->data.xyz.y / 65536.0;
1168 mat[2][i] = cols[i]->data.xyz.z / 65536.0;
1169 }
1170 for (i = 0; i < 3; ++i)
1171 mat[i][3] = 0.0;
1172 if (jas_cmshapmat_invmat(shapmat->mat, mat))
1173 goto error;
1174 for (i = 0; i < 3; ++i) {
1175 jas_cmshapmatlut_init(&lut);
1176 if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv))
1177 goto error;
1178 if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size))
1179 goto error;
1180 jas_cmshapmatlut_cleanup(&lut);
1181 }
1182 }
1183 for (i = 0; i < 3; ++i) {
1184 jas_iccattrval_destroy(trcs[i]);
1185 jas_iccattrval_destroy(cols[i]);
1186 }
1187 jas_cmpxform_destroy(pxform);
1188 *retpxformseq = pxformseq;
1189 return 0;
1190 error:
1191 return -1;
1192 }
1193
1194 static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val)
1195 {
1196 long v;
1197 int m;
1198 v = **bufptr;
1199 if (sgnd) {
1200 m = (1 << (prec - 1));
1201 if (v < -m || v >= m)
1202 return -1;
1203 } else {
1204 if (v < 0 || v >= (1 << prec))
1205 return -1;
1206 }
1207 ++(*bufptr);
1208 *val = v;
1209 return 0;
1210 }
1211
1212 static int jas_cmputint(long **bufptr, int sgnd, int prec, long val)
1213 {
1214 int m;
1215 if (sgnd) {
1216 m = (1 << (prec - 1));
1217 if (val < -m || val >= m)
1218 return -1;
1219 } else {
1220 if (val < 0 || val >= (1 << prec))
1221 return -1;
1222 }
1223 **bufptr = val;
1224 ++(*bufptr);
1225 return 0;
1226 }
1227
1228 int jas_clrspc_numchans(int clrspc)
1229 {
1230 switch (jas_clrspc_fam(clrspc)) {
1231 case JAS_CLRSPC_FAM_XYZ:
1232 case JAS_CLRSPC_FAM_LAB:
1233 case JAS_CLRSPC_FAM_RGB:
1234 case JAS_CLRSPC_FAM_YCBCR:
1235 return 3;
1236 break;
1237 case JAS_CLRSPC_FAM_GRAY:
1238 return 1;
1239 break;
1240 default:
1241 abort();
1242 break;
1243 }
1244 }
1245
1246 jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof)
1247 {
1248 return jas_iccprof_copy(prof->iccprof);
1249 }