Move the sources to trunk
[opencv] / otherlibs / _graphics / src / libjasper / jas_cm.c
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,v 1.1 2007/01/15 16:09:23 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 #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 }