Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

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