Coverage Report

Created: 2025-12-31 07:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jasper/src/libjasper/base/jas_icc.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2002-2003 Michael David Adams.
3
 * All rights reserved.
4
 */
5
6
/* __START_OF_JASPER_LICENSE__
7
 * 
8
 * JasPer License Version 2.0
9
 * 
10
 * Copyright (c) 2001-2006 Michael David Adams
11
 * Copyright (c) 1999-2000 Image Power, Inc.
12
 * Copyright (c) 1999-2000 The University of British Columbia
13
 * 
14
 * All rights reserved.
15
 * 
16
 * Permission is hereby granted, free of charge, to any person (the
17
 * "User") obtaining a copy of this software and associated documentation
18
 * files (the "Software"), to deal in the Software without restriction,
19
 * including without limitation the rights to use, copy, modify, merge,
20
 * publish, distribute, and/or sell copies of the Software, and to permit
21
 * persons to whom the Software is furnished to do so, subject to the
22
 * following conditions:
23
 * 
24
 * 1.  The above copyright notices and this permission notice (which
25
 * includes the disclaimer below) shall be included in all copies or
26
 * substantial portions of the Software.
27
 * 
28
 * 2.  The name of a copyright holder shall not be used to endorse or
29
 * promote products derived from the Software without specific prior
30
 * written permission.
31
 * 
32
 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
33
 * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
34
 * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
35
 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
36
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
37
 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
38
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
39
 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
40
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
41
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
42
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
43
 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
44
 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
45
 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
46
 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
47
 * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
48
 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
49
 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
50
 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
51
 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
52
 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
53
 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
54
 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
55
 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
56
 * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
57
 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
58
 * 
59
 * __END_OF_JASPER_LICENSE__
60
 */
61
62
/******************************************************************************\
63
* Includes.
64
\******************************************************************************/
65
66
#define JAS_FOR_INTERNAL_USE_ONLY
67
68
#include "jasper/jas_icc.h"
69
#include "jasper/jas_types.h"
70
#include "jasper/jas_malloc.h"
71
#include "jasper/jas_debug.h"
72
#include "jasper/jas_cm.h"
73
#include "jasper/jas_stream.h"
74
#include "jasper/jas_string.h"
75
76
#include <assert.h>
77
#include <stdlib.h>
78
#include <string.h>
79
#include <ctype.h>
80
81
/******************************************************************************\
82
*
83
\******************************************************************************/
84
85
0
#define jas_iccputuint8(out, val) jas_iccputuint(out, 1, val)
86
769k
#define jas_iccputuint16(out, val)  jas_iccputuint(out, 2, val)
87
0
#define jas_iccputsint32(out, val)  jas_iccputsint(out, 4, val)
88
1.77M
#define jas_iccputuint32(out, val)  jas_iccputuint(out, 4, val)
89
48.0k
#define jas_iccputuint64(out, val)  jas_iccputuint(out, 8, val)
90
91
static jas_iccattrval_t *jas_iccattrval_create0(void);
92
93
static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val);
94
static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val);
95
static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val);
96
static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val);
97
static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val);
98
static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val);
99
static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val);
100
static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val);
101
static jas_iccprof_t *jas_iccprof_create(void);
102
static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr);
103
static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr);
104
static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab);
105
static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab);
106
static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab, jas_iccuint32_t name);
107
static jas_iccattrtab_t *jas_iccattrtab_copy(const jas_iccattrtab_t *attrtab);
108
static const jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t name);
109
static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time);
110
static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz);
111
static int jas_icctagtabent_cmp(const void *src, const void *dst);
112
113
static void jas_icccurv_destroy(jas_iccattrval_t *attrval);
114
static int jas_icccurv_copy(jas_iccattrval_t *attrval,
115
  const jas_iccattrval_t *othattrval);
116
static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in,
117
  unsigned cnt);
118
static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval);
119
static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out);
120
static void jas_icccurv_dump(const jas_iccattrval_t *attrval, FILE *out);
121
122
static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval);
123
static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval,
124
  const jas_iccattrval_t *othattrval);
125
static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in,
126
  unsigned cnt);
127
static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval);
128
static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out);
129
static void jas_icctxtdesc_dump(const jas_iccattrval_t *attrval, FILE *out);
130
131
static void jas_icctxt_destroy(jas_iccattrval_t *attrval);
132
static int jas_icctxt_copy(jas_iccattrval_t *attrval,
133
  const jas_iccattrval_t *othattrval);
134
static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in,
135
  unsigned cnt);
136
static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval);
137
static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out);
138
static void jas_icctxt_dump(const jas_iccattrval_t *attrval, FILE *out);
139
140
static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
141
  unsigned cnt);
142
static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval);
143
static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out);
144
static void jas_iccxyz_dump(const jas_iccattrval_t *attrval, FILE *out);
145
146
static jas_iccattrtab_t *jas_iccattrtab_create(void);
147
static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab);
148
static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, unsigned maxents);
149
static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i,
150
  jas_iccuint32_t name, jas_iccattrval_t *val);
151
static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i,
152
  jas_iccuint32_t name, jas_iccattrval_t *val);
153
static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i);
154
static unsigned jas_iccpadtomult(unsigned x, unsigned y);
155
static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i,
156
  jas_iccattrname_t *name, jas_iccattrval_t **val);
157
static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab);
158
159
static void jas_icclut16_destroy(jas_iccattrval_t *attrval);
160
static int jas_icclut16_copy(jas_iccattrval_t *attrval,
161
  const jas_iccattrval_t *othattrval);
162
static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in,
163
  unsigned cnt);
164
static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval);
165
static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out);
166
static void jas_icclut16_dump(const jas_iccattrval_t *attrval, FILE *out);
167
168
static void jas_icclut8_destroy(jas_iccattrval_t *attrval);
169
static int jas_icclut8_copy(jas_iccattrval_t *attrval,
170
  const jas_iccattrval_t *othattrval);
171
static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in,
172
  unsigned cnt);
173
static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval);
174
static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out);
175
static void jas_icclut8_dump(const jas_iccattrval_t *attrval, FILE *out);
176
177
static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *ctime);
178
static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz);
179
180
static unsigned jas_iccpowi(unsigned x, unsigned n);
181
182
static char *jas_iccsigtostr(unsigned sig, char *buf);
183
184
/******************************************************************************\
185
* Data.
186
\******************************************************************************/
187
188
static const jas_iccattrvalinfo_t jas_iccattrvalinfos[] = {
189
  {
190
    JAS_ICC_TYPE_CURV, {
191
      jas_icccurv_destroy,
192
      jas_icccurv_copy,
193
      jas_icccurv_input,
194
      jas_icccurv_output,
195
      jas_icccurv_getsize,
196
      jas_icccurv_dump,
197
    },
198
  },
199
  {
200
    JAS_ICC_TYPE_XYZ,
201
    {
202
      0,
203
      0,
204
      jas_iccxyz_input,
205
      jas_iccxyz_output,
206
      jas_iccxyz_getsize,
207
      jas_iccxyz_dump,
208
    },
209
  },
210
  {
211
    JAS_ICC_TYPE_TXTDESC,
212
    {
213
      jas_icctxtdesc_destroy,
214
      jas_icctxtdesc_copy,
215
      jas_icctxtdesc_input,
216
      jas_icctxtdesc_output,
217
      jas_icctxtdesc_getsize,
218
      jas_icctxtdesc_dump,
219
    },
220
  },
221
  {
222
    JAS_ICC_TYPE_TXT,
223
    {
224
      jas_icctxt_destroy,
225
      jas_icctxt_copy,
226
      jas_icctxt_input,
227
      jas_icctxt_output,
228
      jas_icctxt_getsize,
229
      jas_icctxt_dump,
230
    },
231
  },
232
  {
233
    JAS_ICC_TYPE_LUT8,
234
    {
235
      jas_icclut8_destroy,
236
      jas_icclut8_copy,
237
      jas_icclut8_input,
238
      jas_icclut8_output,
239
      jas_icclut8_getsize,
240
      jas_icclut8_dump,
241
    },
242
  },
243
  {
244
    JAS_ICC_TYPE_LUT16, {
245
      jas_icclut16_destroy,
246
      jas_icclut16_copy,
247
      jas_icclut16_input,
248
      jas_icclut16_output,
249
      jas_icclut16_getsize,
250
      jas_icclut16_dump,
251
    },
252
  },
253
  {
254
    0,
255
    {
256
      0,
257
      0,
258
      0,
259
      0,
260
      0,
261
      0,
262
    },
263
  }
264
};
265
266
/******************************************************************************\
267
* profile class
268
\******************************************************************************/
269
270
static jas_iccprof_t *jas_iccprof_create()
271
94.2k
{
272
94.2k
  jas_iccprof_t *prof;
273
94.2k
  prof = 0;
274
94.2k
  if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) {
275
0
    goto error;
276
0
  }
277
94.2k
  prof->tagtab.numents = 0;
278
94.2k
  prof->tagtab.ents = 0;
279
94.2k
  if (!(prof->attrtab = jas_iccattrtab_create())) {
280
0
    goto error;
281
0
  }
282
94.2k
  memset(&prof->hdr, 0, sizeof(jas_icchdr_t));
283
94.2k
  return prof;
284
0
error:
285
0
  if (prof) {
286
0
    jas_iccprof_destroy(prof);
287
0
  }
288
0
  return 0;
289
94.2k
}
290
291
jas_iccprof_t *jas_iccprof_copy(const jas_iccprof_t *prof)
292
59.0k
{
293
59.0k
  jas_iccprof_t *newprof;
294
59.0k
  newprof = 0;
295
59.0k
  if (!(newprof = jas_iccprof_create())) {
296
0
    goto error;
297
0
  }
298
59.0k
  newprof->hdr = prof->hdr;
299
59.0k
  newprof->tagtab.numents = 0;
300
59.0k
  newprof->tagtab.ents = 0;
301
59.0k
  assert(newprof->attrtab);
302
59.0k
  jas_iccattrtab_destroy(newprof->attrtab);
303
59.0k
  if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab))) {
304
0
    goto error;
305
0
  }
306
59.0k
  return newprof;
307
0
error:
308
0
  if (newprof) {
309
0
    jas_iccprof_destroy(newprof);
310
0
  }
311
0
  return 0;
312
59.0k
}
313
314
void jas_iccprof_destroy(jas_iccprof_t *prof)
315
94.2k
{
316
94.2k
  if (prof->attrtab) {
317
94.2k
    jas_iccattrtab_destroy(prof->attrtab);
318
94.2k
  }
319
94.2k
  if (prof->tagtab.ents) {
320
59.2k
    jas_free(prof->tagtab.ents);
321
59.2k
  }
322
94.2k
  jas_free(prof);
323
94.2k
}
324
325
void jas_iccprof_dump(const jas_iccprof_t *prof, FILE *out)
326
0
{
327
0
  jas_iccattrtab_dump(prof->attrtab, out);
328
0
}
329
330
jas_iccprof_t *jas_iccprof_load(jas_stream_t *in)
331
35.2k
{
332
35.2k
  jas_iccprof_t *prof;
333
35.2k
  long curoff;
334
35.2k
  long reloff;
335
35.2k
  long prevoff;
336
35.2k
  jas_iccsig_t type;
337
35.2k
  jas_iccattrval_t *attrval;
338
35.2k
  jas_iccattrval_t *prevattrval;
339
340
35.2k
  prof = 0;
341
35.2k
  attrval = 0;
342
343
35.2k
  if (!(prof = jas_iccprof_create())) {
344
0
    goto error;
345
0
  }
346
347
35.2k
  if (jas_iccprof_readhdr(in, &prof->hdr)) {
348
4
    jas_logerrorf("cannot get header\n");
349
4
    goto error;
350
4
  }
351
35.2k
  if (jas_iccprof_gettagtab(in, &prof->tagtab)) {
352
21
    jas_logerrorf("cannot get tab table\n");
353
21
    goto error;
354
21
  }
355
35.1k
  jas_iccprof_sorttagtab(&prof->tagtab);
356
357
35.1k
  const unsigned numtags = prof->tagtab.numents;
358
35.1k
  curoff = JAS_ICC_HDRLEN + 4 + 12 * numtags;
359
35.1k
  prevoff = 0;
360
35.1k
  prevattrval = 0;
361
184k
  for (unsigned i = 0; i < numtags; ++i) {
362
149k
    const jas_icctagtabent_t *tagtabent = &prof->tagtab.ents[i];
363
149k
    if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) {
364
2.30k
      if (prevattrval) {
365
1.19k
        if (!(attrval = jas_iccattrval_clone(prevattrval))) {
366
0
          goto error;
367
0
        }
368
1.19k
        if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) {
369
0
          goto error;
370
0
        }
371
1.19k
        jas_iccattrval_destroy(attrval);
372
1.19k
        attrval = 0;
373
1.19k
      } else {
374
1.10k
        jas_logwarnf("warning: skipping unknown tag type\n");
375
1.10k
      }
376
2.30k
      continue;
377
2.30k
    }
378
147k
    reloff = tagtabent->off - curoff;
379
147k
    if (reloff > 0) {
380
72.3k
      if (jas_stream_gobble(in, reloff) != reloff) {
381
54
        goto error;
382
54
      }
383
72.3k
      curoff += reloff;
384
74.6k
    } else if (reloff < 0) {
385
22
      goto error;
386
22
    }
387
146k
    prevoff = curoff;
388
146k
    if (jas_iccgetuint32(in, &type)) {
389
1
      goto error;
390
1
    }
391
146k
    if (jas_stream_gobble(in, 4) != 4) {
392
1
      goto error;
393
1
    }
394
146k
    curoff += 8;
395
146k
    if (!jas_iccattrvalinfo_lookup(type)) {
396
2.18k
      jas_logwarnf("warning: skipping unknown tag type\n");
397
2.18k
      prevattrval = 0;
398
2.18k
      continue;
399
2.18k
    }
400
144k
    if (!(attrval = jas_iccattrval_create(type))) {
401
0
      goto error;
402
0
    }
403
144k
    const unsigned len = tagtabent->len - 8;
404
144k
    if ((*attrval->ops->input)(attrval, in, len)) {
405
61
      goto error;
406
61
    }
407
144k
    curoff += len;
408
144k
    if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) {
409
0
      goto error;
410
0
    }
411
144k
    prevattrval = attrval; /* This is correct, but slimey. */
412
144k
    jas_iccattrval_destroy(attrval);
413
144k
    attrval = 0;
414
144k
  }
415
416
35.0k
  return prof;
417
418
164
error:
419
164
  if (prof) {
420
164
    jas_iccprof_destroy(prof);
421
164
  }
422
164
  if (attrval) {
423
61
    jas_iccattrval_destroy(attrval);
424
61
  }
425
164
  return 0;
426
35.1k
}
427
428
int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out)
429
24.0k
{
430
24.0k
  long curoff;
431
24.0k
  long reloff;
432
24.0k
  long newoff;
433
24.0k
  jas_icctagtabent_t *tagtabent;
434
24.0k
  jas_icctagtabent_t *sharedtagtabent;
435
24.0k
  jas_icctagtabent_t *tmptagtabent;
436
24.0k
  jas_iccuint32_t attrname;
437
24.0k
  jas_iccattrval_t *attrval;
438
24.0k
  jas_icctagtab_t *tagtab;
439
440
24.0k
  tagtab = &prof->tagtab;
441
24.0k
  if (!(tagtab->ents = jas_alloc2(prof->attrtab->numattrs,
442
24.0k
    sizeof(jas_icctagtabent_t)))) {
443
0
    goto error;
444
0
  }
445
24.0k
  tagtab->numents = prof->attrtab->numattrs;
446
24.0k
  curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
447
124k
  for (unsigned i = 0; i < tagtab->numents; ++i) {
448
100k
    tagtabent = &tagtab->ents[i];
449
100k
    if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) {
450
0
      goto error;
451
0
    }
452
100k
    assert(attrval->ops->output);
453
100k
    tagtabent->tag = attrname;
454
100k
    tagtabent->data = &attrval->data;
455
100k
    sharedtagtabent = 0;
456
278k
    for (unsigned j = 0; j < i; ++j) {
457
179k
      tmptagtabent = &tagtab->ents[j];
458
179k
      if (tagtabent->data == tmptagtabent->data) {
459
842
        sharedtagtabent = tmptagtabent;
460
842
        break;
461
842
      }
462
179k
    }
463
100k
    if (sharedtagtabent) {
464
842
      tagtabent->off = sharedtagtabent->off;
465
842
      tagtabent->len = sharedtagtabent->len;
466
842
      tagtabent->first = sharedtagtabent;
467
99.4k
    } else {
468
99.4k
      tagtabent->off = curoff;
469
99.4k
      tagtabent->len = (*attrval->ops->getsize)(attrval) + 8;
470
99.4k
      tagtabent->first = 0;
471
99.4k
      if (i < tagtab->numents - 1) {
472
75.8k
        curoff = jas_iccpadtomult(curoff + tagtabent->len, 4);
473
75.8k
      } else {
474
23.6k
        curoff += tagtabent->len;
475
23.6k
      }
476
99.4k
    }
477
100k
    jas_iccattrval_destroy(attrval);
478
100k
  }
479
24.0k
  prof->hdr.size = curoff;
480
24.0k
  if (jas_iccprof_writehdr(out, &prof->hdr)) {
481
0
    goto error;
482
0
  }
483
24.0k
  if (jas_iccprof_puttagtab(out, &prof->tagtab)) {
484
0
    goto error;
485
0
  }
486
24.0k
  curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
487
123k
  for (unsigned i = 0; i < tagtab->numents;) {
488
99.4k
    tagtabent = &tagtab->ents[i];
489
99.4k
    assert(curoff == JAS_CAST(long, tagtabent->off));
490
99.4k
    if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) {
491
0
      goto error;
492
0
    }
493
99.4k
    if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out,
494
99.4k
      4, 0) != 4) {
495
0
      goto error;
496
0
    }
497
99.4k
    if ((*attrval->ops->output)(attrval, out)) {
498
0
      goto error;
499
0
    }
500
99.4k
    jas_iccattrval_destroy(attrval);
501
99.4k
    curoff += tagtabent->len;
502
99.4k
    ++i;
503
100k
    while (i < tagtab->numents && tagtab->ents[i].first) {
504
842
      ++i;
505
842
    }
506
99.4k
    newoff = (i < tagtab->numents) ?
507
75.4k
      tagtab->ents[i].off : prof->hdr.size;
508
99.4k
    reloff = newoff - curoff;
509
99.4k
    assert(reloff >= 0);
510
99.4k
    if (reloff > 0) {
511
48.0k
      if (jas_stream_pad(out, reloff, 0) != reloff) {
512
0
        goto error;
513
0
      }
514
48.0k
      curoff += reloff;
515
48.0k
    }
516
99.4k
  }  
517
24.0k
  return 0;
518
0
error:
519
  /* XXX - need to free some resources here */
520
0
  return -1;
521
24.0k
}
522
523
static int jas_iccprof_writehdr(jas_stream_t *out, const jas_icchdr_t *hdr)
524
24.0k
{
525
24.0k
  if (jas_iccputuint32(out, hdr->size) ||
526
24.0k
    jas_iccputuint32(out, hdr->cmmtype) ||
527
24.0k
    jas_iccputuint32(out, hdr->version) ||
528
24.0k
    jas_iccputuint32(out, hdr->clas) ||
529
24.0k
    jas_iccputuint32(out, hdr->colorspc) ||
530
24.0k
    jas_iccputuint32(out, hdr->refcolorspc) ||
531
24.0k
    jas_iccputtime(out, &hdr->ctime) ||
532
24.0k
    jas_iccputuint32(out, hdr->magic) ||
533
24.0k
    jas_iccputuint32(out, hdr->platform) ||
534
24.0k
    jas_iccputuint32(out, hdr->flags) ||
535
24.0k
    jas_iccputuint32(out, hdr->maker) ||
536
24.0k
    jas_iccputuint32(out, hdr->model) ||
537
24.0k
    jas_iccputuint64(out, hdr->attr) ||
538
24.0k
    jas_iccputuint32(out, hdr->intent) ||
539
24.0k
    jas_iccputxyz(out, &hdr->illum) ||
540
24.0k
    jas_iccputuint32(out, hdr->creator) ||
541
24.0k
    jas_stream_pad(out, 44, 0) != 44) {
542
0
    return -1;
543
0
  }
544
24.0k
  return 0;
545
24.0k
}
546
547
static int jas_iccprof_puttagtab(jas_stream_t *out, const jas_icctagtab_t *tagtab)
548
24.0k
{
549
24.0k
  jas_icctagtabent_t *tagtabent;
550
24.0k
  if (jas_iccputuint32(out, tagtab->numents)) {
551
0
    goto error;
552
0
  }
553
124k
  for (unsigned i = 0; i < tagtab->numents; ++i) {
554
100k
    tagtabent = &tagtab->ents[i];
555
100k
    if (jas_iccputuint32(out, tagtabent->tag) ||
556
100k
      jas_iccputuint32(out, tagtabent->off) ||
557
100k
      jas_iccputuint32(out, tagtabent->len)) {
558
0
      goto error;
559
0
    }
560
100k
  }
561
24.0k
  return 0;
562
0
error:
563
0
  return -1;
564
24.0k
}
565
566
static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr)
567
35.2k
{
568
35.2k
  if (jas_iccgetuint32(in, &hdr->size) ||
569
35.2k
    jas_iccgetuint32(in, &hdr->cmmtype) ||
570
35.2k
    jas_iccgetuint32(in, &hdr->version) ||
571
35.2k
    jas_iccgetuint32(in, &hdr->clas) ||
572
35.2k
    jas_iccgetuint32(in, &hdr->colorspc) ||
573
35.2k
    jas_iccgetuint32(in, &hdr->refcolorspc) ||
574
35.2k
    jas_iccgettime(in, &hdr->ctime) ||
575
35.2k
    jas_iccgetuint32(in, &hdr->magic) ||
576
35.2k
    jas_iccgetuint32(in, &hdr->platform) ||
577
35.2k
    jas_iccgetuint32(in, &hdr->flags) ||
578
35.2k
    jas_iccgetuint32(in, &hdr->maker) ||
579
35.2k
    jas_iccgetuint32(in, &hdr->model) ||
580
35.2k
    jas_iccgetuint64(in, &hdr->attr) ||
581
35.2k
    jas_iccgetuint32(in, &hdr->intent) ||
582
35.2k
    jas_iccgetxyz(in, &hdr->illum) ||
583
35.2k
    jas_iccgetuint32(in, &hdr->creator) ||
584
35.2k
    jas_stream_gobble(in, 44) != 44) {
585
4
    return -1;
586
4
  }
587
35.2k
  return 0;
588
35.2k
}
589
590
static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab)
591
35.2k
{
592
35.2k
  jas_icctagtabent_t *tagtabent;
593
594
35.2k
  if (tagtab->ents) {
595
0
    jas_free(tagtab->ents);
596
0
    tagtab->ents = 0;
597
0
  }
598
35.2k
  if (jas_iccgetuint32(in, &tagtab->numents)) {
599
0
    goto error;
600
0
  }
601
35.2k
  if (!(tagtab->ents = jas_alloc2(tagtab->numents,
602
35.2k
    sizeof(jas_icctagtabent_t)))) {
603
14
    goto error;
604
14
  }
605
35.1k
  tagtabent = tagtab->ents;
606
188k
  for (unsigned i = 0; i < tagtab->numents; ++i) {
607
153k
    if (jas_iccgetuint32(in, &tagtabent->tag) ||
608
153k
    jas_iccgetuint32(in, &tagtabent->off) ||
609
153k
    jas_iccgetuint32(in, &tagtabent->len)) {
610
7
      goto error;
611
7
    }
612
153k
    ++tagtabent;
613
153k
  }
614
35.1k
  return 0;
615
21
error:
616
21
  if (tagtab->ents) {
617
7
    jas_free(tagtab->ents);
618
7
    tagtab->ents = 0;
619
7
  }
620
21
  return -1;
621
35.1k
}
622
623
jas_iccattrval_t *jas_iccprof_getattr(const jas_iccprof_t *prof,
624
  jas_iccattrname_t name)
625
75.6k
{
626
75.6k
  int i;
627
75.6k
  jas_iccattrval_t *attrval;
628
75.6k
  if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0) {
629
8
    goto error;
630
8
  }
631
75.6k
  if (!(attrval = jas_iccattrval_clone(prof->attrtab->attrs[i].val))) {
632
0
    goto error;
633
0
  }
634
75.6k
  return attrval;
635
8
error:
636
8
  return 0;
637
75.6k
}
638
639
int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name,
640
  jas_iccattrval_t *val)
641
145k
{
642
145k
  int i;
643
145k
  if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) {
644
14
    if (val) {
645
14
      if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) {
646
0
        goto error;
647
0
      }
648
14
    } else {
649
0
      jas_iccattrtab_delete(prof->attrtab, i);
650
0
    }
651
145k
  } else {
652
145k
    if (val) {
653
145k
      if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) {
654
0
        goto error;
655
0
      }
656
145k
    } else {
657
      /* NOP */
658
0
    }
659
145k
  }
660
145k
  return 0;
661
0
error:
662
0
  return -1;
663
145k
}
664
665
int jas_iccprof_gethdr(const jas_iccprof_t *prof, jas_icchdr_t *hdr)
666
35.0k
{
667
35.0k
  *hdr = prof->hdr;
668
35.0k
  return 0;
669
35.0k
}
670
671
int jas_iccprof_sethdr(jas_iccprof_t *prof, const jas_icchdr_t *hdr)
672
0
{
673
0
  prof->hdr = *hdr;
674
0
  return 0;
675
0
}
676
677
static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab)
678
35.1k
{
679
35.1k
  qsort(tagtab->ents, tagtab->numents, sizeof(jas_icctagtabent_t),
680
35.1k
    jas_icctagtabent_cmp);
681
35.1k
}
682
683
static int jas_icctagtabent_cmp(const void *src, const void *dst)
684
171k
{
685
171k
  const jas_icctagtabent_t *srctagtabent =
686
171k
    JAS_CAST(const jas_icctagtabent_t *, src);
687
171k
  const jas_icctagtabent_t *dsttagtabent =
688
171k
    JAS_CAST(const jas_icctagtabent_t *, dst);
689
171k
  if (srctagtabent->off > dsttagtabent->off) {
690
6.10k
    return 1;
691
165k
  } else if (srctagtabent->off < dsttagtabent->off) {
692
160k
    return -1;
693
160k
  }
694
4.25k
  return 0;
695
171k
}
696
697
static const jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t type)
698
291k
{
699
291k
  const jas_iccattrvalinfo_t *info = jas_iccattrvalinfos;
700
737k
  for (info = jas_iccattrvalinfos; info->type; ++info) {
701
735k
    if (info->type == type) {
702
289k
      return info;
703
289k
    }
704
735k
  }
705
2.18k
  return 0;
706
291k
}
707
708
static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time)
709
35.2k
{
710
35.2k
  if (jas_iccgetuint16(in, &time->year) ||
711
35.2k
    jas_iccgetuint16(in, &time->month) ||
712
35.2k
    jas_iccgetuint16(in, &time->day) ||
713
35.2k
    jas_iccgetuint16(in, &time->hour) ||
714
35.2k
    jas_iccgetuint16(in, &time->min) ||
715
35.2k
    jas_iccgetuint16(in, &time->sec)) {
716
0
    return -1;
717
0
  }
718
35.2k
  return 0;
719
35.2k
}
720
721
static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz)
722
73.1k
{
723
73.1k
  if (jas_iccgetsint32(in, &xyz->x) ||
724
73.1k
    jas_iccgetsint32(in, &xyz->y) ||
725
73.1k
    jas_iccgetsint32(in, &xyz->z)) {
726
0
    return -1;
727
0
  }
728
73.1k
  return 0;
729
73.1k
}
730
731
static int jas_iccputtime(jas_stream_t *out, const jas_icctime_t *time)
732
24.0k
{
733
24.0k
  if (jas_iccputuint16(out, time->year) ||
734
24.0k
    jas_iccputuint16(out, time->month) ||
735
24.0k
    jas_iccputuint16(out, time->day) ||
736
24.0k
    jas_iccputuint16(out, time->hour) ||
737
24.0k
    jas_iccputuint16(out, time->min) ||
738
24.0k
    jas_iccputuint16(out, time->sec)) {
739
0
    return -1;
740
0
  }
741
24.0k
  return 0;
742
24.0k
}
743
744
static int jas_iccputxyz(jas_stream_t *out, const jas_iccxyz_t *xyz)
745
24.0k
{
746
24.0k
  if (jas_iccputuint32(out, xyz->x) ||
747
24.0k
    jas_iccputuint32(out, xyz->y) ||
748
24.0k
    jas_iccputuint32(out, xyz->z)) {
749
0
    return -1;
750
0
  }
751
24.0k
  return 0;
752
24.0k
}
753
754
/******************************************************************************\
755
* attribute table class
756
\******************************************************************************/
757
758
static jas_iccattrtab_t *jas_iccattrtab_create()
759
153k
{
760
153k
  jas_iccattrtab_t *tab;
761
153k
  tab = 0;
762
153k
  if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) {
763
0
    goto error;
764
0
  }
765
153k
  tab->maxattrs = 0;
766
153k
  tab->numattrs = 0;
767
153k
  tab->attrs = 0;
768
153k
  if (jas_iccattrtab_resize(tab, 32)) {
769
0
    goto error;
770
0
  }
771
153k
  return tab;
772
0
error:
773
0
  if (tab) {
774
0
    jas_iccattrtab_destroy(tab);
775
0
  }
776
0
  return 0;
777
153k
}
778
779
static jas_iccattrtab_t *jas_iccattrtab_copy(const jas_iccattrtab_t *attrtab)
780
59.0k
{
781
59.0k
  jas_iccattrtab_t *newattrtab;
782
59.0k
  if (!(newattrtab = jas_iccattrtab_create())) {
783
0
    return NULL;
784
0
  }
785
305k
  for (unsigned i = 0; i < attrtab->numattrs; ++i) {
786
245k
    if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name,
787
245k
      attrtab->attrs[i].val)) {
788
0
      goto error;
789
0
    }
790
245k
  }
791
59.0k
  return newattrtab;
792
0
 error:
793
0
  jas_iccattrtab_destroy(newattrtab);
794
0
  return 0;
795
59.0k
}
796
797
static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab)
798
153k
{
799
153k
  if (tab->attrs) {
800
545k
    while (tab->numattrs > 0) {
801
391k
      jas_iccattrtab_delete(tab, 0);
802
391k
    }
803
153k
    jas_free(tab->attrs);
804
153k
  }
805
153k
  jas_free(tab);
806
153k
}
807
808
void jas_iccattrtab_dump(const jas_iccattrtab_t *attrtab, FILE *out)
809
0
{
810
0
  char buf[16];
811
0
  fprintf(out, "numattrs=%d\n", attrtab->numattrs);
812
0
  fprintf(out, "---\n");
813
0
  for (unsigned i = 0; i < attrtab->numattrs; ++i) {
814
0
    const jas_iccattr_t *attr = &attrtab->attrs[i];
815
0
    const jas_iccattrval_t *attrval = attr->val;
816
0
    const jas_iccattrvalinfo_t *info = jas_iccattrvalinfo_lookup(attrval->type);
817
0
    assert(info);
818
0
    JAS_UNUSED(info);
819
0
    fprintf(out, "attrno=%d; attrname=\"%s\"(0x%08"PRIxFAST32"); attrtype=\"%s\"(0x%08"PRIxFAST32")\n",
820
0
      i,
821
0
      jas_iccsigtostr(attr->name, &buf[0]),
822
0
      attr->name,
823
0
      jas_iccsigtostr(attrval->type, &buf[8]),
824
0
      attrval->type
825
0
      );
826
0
    jas_iccattrval_dump(attrval, out);
827
0
    fprintf(out, "---\n");
828
0
  }
829
0
}
830
831
static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, unsigned maxents)
832
153k
{
833
153k
  jas_iccattr_t *newattrs;
834
153k
  assert(maxents >= tab->numattrs);
835
153k
  newattrs = tab->attrs ? jas_realloc2(tab->attrs, maxents,
836
153k
    sizeof(jas_iccattr_t)) : jas_alloc2(maxents, sizeof(jas_iccattr_t));
837
153k
  if (!newattrs) {
838
0
    return -1;
839
0
  }
840
153k
  tab->attrs = newattrs;
841
153k
  tab->maxattrs = maxents;
842
153k
  return 0;
843
153k
}
844
845
static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i,
846
  jas_iccuint32_t name, jas_iccattrval_t *val)
847
391k
{
848
391k
  jas_iccattr_t *attr;
849
391k
  jas_iccattrval_t *tmpattrval;
850
391k
  if (i < 0) {
851
145k
    i = attrtab->numattrs;
852
145k
  }
853
391k
  assert(i >= 0 && (unsigned)i <= attrtab->numattrs);
854
391k
  if (attrtab->numattrs >= attrtab->maxattrs) {
855
0
    if (jas_iccattrtab_resize(attrtab, attrtab->numattrs + 32)) {
856
0
      return -1;
857
0
    }
858
0
  }
859
391k
  if (!(tmpattrval = jas_iccattrval_clone(val))) {
860
0
    return -1;
861
0
  }
862
391k
  const unsigned n = attrtab->numattrs - i;
863
391k
  if (n > 0) {
864
0
    memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i],
865
0
      n * sizeof(jas_iccattr_t));
866
0
  }
867
391k
  attr = &attrtab->attrs[i];
868
391k
  attr->name = name;
869
391k
  attr->val = tmpattrval;
870
391k
  ++attrtab->numattrs;
871
391k
  return 0;
872
391k
}
873
874
static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, unsigned i,
875
  jas_iccuint32_t name, jas_iccattrval_t *val)
876
14
{
877
14
  jas_iccattrval_t *newval;
878
14
  jas_iccattr_t *attr;
879
14
  if (!(newval = jas_iccattrval_clone(val))) {
880
0
    goto error;
881
0
  }
882
14
  attr = &attrtab->attrs[i];
883
14
  jas_iccattrval_destroy(attr->val);
884
14
  attr->name = name;
885
14
  attr->val = newval;
886
14
  return 0;
887
0
error:
888
0
  return -1;
889
14
}
890
891
static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, unsigned i)
892
391k
{
893
391k
  unsigned n;
894
391k
  jas_iccattrval_destroy(attrtab->attrs[i].val);
895
391k
  if ((n = attrtab->numattrs - i - 1) > 0) {
896
297k
    memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1],
897
297k
      n * sizeof(jas_iccattr_t));
898
297k
  }
899
391k
  --attrtab->numattrs;
900
391k
}
901
902
static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, unsigned i,
903
  jas_iccattrname_t *name, jas_iccattrval_t **val)
904
199k
{
905
199k
  jas_iccattr_t *attr;
906
199k
  if (i >= attrtab->numattrs) {
907
0
    goto error;
908
0
  }
909
199k
  attr = &attrtab->attrs[i];
910
199k
  *name = attr->name;
911
199k
  if (!(*val = jas_iccattrval_clone(attr->val))) {
912
0
    goto error;
913
0
  }
914
199k
  return 0;
915
0
error:
916
0
  return -1;
917
199k
}
918
919
static int jas_iccattrtab_lookup(const jas_iccattrtab_t *attrtab,
920
  jas_iccuint32_t name)
921
221k
{
922
221k
  jas_iccattr_t *attr;
923
743k
  for (unsigned i = 0; i < attrtab->numattrs; ++i) {
924
597k
    attr = &attrtab->attrs[i];
925
597k
    if (attr->name == name) {
926
75.6k
      return i;
927
75.6k
    }
928
597k
  }
929
145k
  return -1;
930
221k
}
931
932
/******************************************************************************\
933
* attribute value class
934
\******************************************************************************/
935
936
jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type)
937
144k
{
938
144k
  jas_iccattrval_t *attrval;
939
144k
  const jas_iccattrvalinfo_t *info;
940
941
144k
  if (!(info = jas_iccattrvalinfo_lookup(type))) {
942
0
    goto error;
943
0
  }
944
144k
  if (!(attrval = jas_iccattrval_create0())) {
945
0
    goto error;
946
0
  }
947
144k
  attrval->ops = &info->ops;
948
144k
  attrval->type = type;
949
144k
  ++attrval->refcnt;
950
144k
  memset(&attrval->data, 0, sizeof(attrval->data));
951
144k
  return attrval;
952
0
error:
953
0
  return 0;
954
144k
}
955
956
jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval)
957
668k
{
958
668k
  ++attrval->refcnt;
959
668k
  return attrval;
960
668k
}
961
962
void jas_iccattrval_destroy(jas_iccattrval_t *attrval)
963
813k
{
964
#if 0
965
jas_eprintf("refcnt=%d\n", attrval->refcnt);
966
#endif
967
813k
  if (--attrval->refcnt <= 0) {
968
144k
    if (attrval->ops->destroy) {
969
106k
      (*attrval->ops->destroy)(attrval);
970
106k
    }
971
144k
    jas_free(attrval);
972
144k
  }
973
813k
}
974
975
void jas_iccattrval_dump(const jas_iccattrval_t *attrval, FILE *out)
976
0
{
977
0
  char buf[8];
978
0
  jas_iccsigtostr(attrval->type, buf);
979
0
  fprintf(out, "refcnt = %d; type = 0x%08"PRIxFAST32" %s\n", attrval->refcnt,
980
0
    attrval->type, jas_iccsigtostr(attrval->type, &buf[0]));
981
0
  if (attrval->ops->dump) {
982
0
    (*attrval->ops->dump)(attrval, out);
983
0
  }
984
0
}
985
986
int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx)
987
0
{
988
0
  jas_iccattrval_t *newattrval;
989
0
  jas_iccattrval_t *attrval = *attrvalx;
990
0
  newattrval = 0;
991
0
  if (attrval->refcnt > 1) {
992
0
    if (!(newattrval = jas_iccattrval_create0())) {
993
0
      goto error;
994
0
    }
995
0
    newattrval->ops = attrval->ops;
996
0
    newattrval->type = attrval->type;
997
0
    ++newattrval->refcnt;
998
0
    if (newattrval->ops->copy) {
999
0
      if ((*newattrval->ops->copy)(newattrval, attrval)) {
1000
0
        goto error;
1001
0
      }
1002
0
    } else {
1003
0
      memcpy(&newattrval->data, &attrval->data,
1004
0
        sizeof(newattrval->data));
1005
0
    }
1006
0
    *attrvalx = newattrval;
1007
0
  }
1008
0
  return 0;
1009
0
error:
1010
0
  if (newattrval) {
1011
0
    jas_free(newattrval);
1012
0
  }
1013
0
  return -1;
1014
0
}
1015
1016
static jas_iccattrval_t *jas_iccattrval_create0()
1017
144k
{
1018
144k
  jas_iccattrval_t *attrval;
1019
144k
  if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) {
1020
0
    return 0;
1021
0
  }
1022
144k
  memset(attrval, 0, sizeof(jas_iccattrval_t));
1023
144k
  attrval->refcnt = 0;
1024
144k
  attrval->ops = 0;
1025
144k
  attrval->type = 0;
1026
144k
  return attrval;
1027
144k
}
1028
1029
/******************************************************************************\
1030
*
1031
\******************************************************************************/
1032
1033
static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
1034
  unsigned len)
1035
37.9k
{
1036
37.9k
  if (len != 4 * 3) {
1037
8
    return -1;
1038
8
  }
1039
37.9k
  return jas_iccgetxyz(in, &attrval->data.xyz);
1040
37.9k
}
1041
1042
static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out)
1043
26.1k
{
1044
26.1k
  const jas_iccxyz_t *xyz = &attrval->data.xyz;
1045
26.1k
  if (jas_iccputuint32(out, xyz->x) ||
1046
26.1k
    jas_iccputuint32(out, xyz->y) ||
1047
26.1k
    jas_iccputuint32(out, xyz->z)) {
1048
0
    return -1;
1049
0
  }
1050
26.1k
  return 0;
1051
26.1k
}
1052
1053
static unsigned jas_iccxyz_getsize(const jas_iccattrval_t *attrval)
1054
26.1k
{
1055
26.1k
  JAS_UNUSED(attrval);
1056
26.1k
  return 12;
1057
26.1k
}
1058
1059
static void jas_iccxyz_dump(const jas_iccattrval_t *attrval, FILE *out)
1060
0
{
1061
0
  const jas_iccxyz_t *xyz = &attrval->data.xyz;
1062
0
  fprintf(out, "(%f, %f, %f)\n", xyz->x / 65536.0, xyz->y / 65536.0,
1063
0
    xyz->z / 65536.0);
1064
0
}
1065
1066
/******************************************************************************\
1067
* attribute table class
1068
\******************************************************************************/
1069
1070
static void jas_icccurv_destroy(jas_iccattrval_t *attrval)
1071
35.0k
{
1072
35.0k
  jas_icccurv_t *curv = &attrval->data.curv;
1073
35.0k
  if (curv->ents) {
1074
35.0k
    jas_free(curv->ents);
1075
35.0k
    curv->ents = 0;
1076
35.0k
  }
1077
35.0k
}
1078
1079
static int jas_icccurv_copy(jas_iccattrval_t *attrval,
1080
  const jas_iccattrval_t *othattrval)
1081
0
{
1082
0
  JAS_UNUSED(attrval);
1083
0
  JAS_UNUSED(othattrval);
1084
1085
  /* Not yet implemented. */
1086
0
  abort();
1087
0
  return -1;
1088
0
}
1089
1090
static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in,
1091
  unsigned cnt)
1092
35.0k
{
1093
35.0k
  jas_icccurv_t *curv = &attrval->data.curv;
1094
1095
35.0k
  curv->numents = 0;
1096
35.0k
  curv->ents = 0;
1097
1098
35.0k
  if (jas_iccgetuint32(in, &curv->numents)) {
1099
0
    goto error;
1100
0
  }
1101
35.0k
  if (!(curv->ents = jas_alloc2(curv->numents, sizeof(jas_iccuint16_t)))) {
1102
11
    goto error;
1103
11
  }
1104
673k
  for (unsigned i = 0; i < curv->numents; ++i) {
1105
637k
    if (jas_iccgetuint16(in, &curv->ents[i])) {
1106
2
      goto error;
1107
2
    }
1108
637k
  }
1109
1110
35.0k
  if (4 + 2 * curv->numents != cnt) {
1111
11
    goto error;
1112
11
  }
1113
35.0k
  return 0;
1114
1115
24
error:
1116
24
  jas_icccurv_destroy(attrval);
1117
24
  return -1;
1118
35.0k
}
1119
1120
static unsigned jas_icccurv_getsize(const jas_iccattrval_t *attrval)
1121
24.0k
{
1122
24.0k
  const jas_icccurv_t *curv = &attrval->data.curv;
1123
24.0k
  return 4 + 2 * curv->numents;
1124
24.0k
}
1125
1126
static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out)
1127
24.0k
{
1128
24.0k
  const jas_icccurv_t *curv = &attrval->data.curv;
1129
1130
24.0k
  if (jas_iccputuint32(out, curv->numents)) {
1131
0
    goto error;
1132
0
  }
1133
478k
  for (unsigned i = 0; i < curv->numents; ++i) {
1134
454k
    if (jas_iccputuint16(out, curv->ents[i])) {
1135
0
      goto error;
1136
0
    }
1137
454k
  }
1138
24.0k
  return 0;
1139
0
error:
1140
0
  return -1;
1141
24.0k
}
1142
1143
static void jas_icccurv_dump(const jas_iccattrval_t *attrval, FILE *out)
1144
0
{
1145
0
  const jas_icccurv_t *curv = &attrval->data.curv;
1146
0
  fprintf(out, "number of entries = %"PRIuFAST32"\n", curv->numents);
1147
0
  if (curv->numents == 1) {
1148
0
    fprintf(out, "gamma = %f\n", curv->ents[0] / 256.0);
1149
0
  } else {
1150
0
    for (unsigned i = 0; i < curv->numents; ++i) {
1151
0
      if (i < 3 || i >= curv->numents - 3) {
1152
0
        fprintf(out, "entry[%d] = %f\n", i, curv->ents[i] / 65535.0);
1153
0
      }
1154
0
    }
1155
0
  }
1156
0
}
1157
1158
/******************************************************************************\
1159
*
1160
\******************************************************************************/
1161
1162
static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval)
1163
36.7k
{
1164
36.7k
  jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
1165
36.7k
  if (txtdesc->ascdata) {
1166
36.7k
    jas_free(txtdesc->ascdata);
1167
36.7k
    txtdesc->ascdata = 0;
1168
36.7k
  }
1169
36.7k
  if (txtdesc->ucdata) {
1170
36.7k
    jas_free(txtdesc->ucdata);
1171
36.7k
    txtdesc->ucdata = 0;
1172
36.7k
  }
1173
36.7k
}
1174
1175
static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval,
1176
  const jas_iccattrval_t *othattrval)
1177
0
{
1178
0
  jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
1179
1180
0
  JAS_UNUSED(attrval);
1181
0
  JAS_UNUSED(othattrval);
1182
0
  JAS_UNUSED(txtdesc);
1183
1184
  /* Not yet implemented. */
1185
0
  abort();
1186
0
  return -1;
1187
0
}
1188
1189
static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in,
1190
  unsigned cnt)
1191
36.7k
{
1192
36.7k
  int c;
1193
36.7k
  jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
1194
36.7k
  txtdesc->ascdata = 0;
1195
36.7k
  txtdesc->ucdata = 0;
1196
36.7k
  if (jas_iccgetuint32(in, &txtdesc->asclen)) {
1197
0
    goto error;
1198
0
  }
1199
36.7k
  if (txtdesc->asclen < 1) {
1200
1
    goto error;
1201
1
  }
1202
36.7k
  if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) {
1203
3
    goto error;
1204
3
  }
1205
36.7k
  if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) !=
1206
36.7k
    txtdesc->asclen) {
1207
2
    goto error;
1208
2
  }
1209
36.7k
  txtdesc->ascdata[txtdesc->asclen - 1] = '\0';
1210
36.7k
  if (jas_iccgetuint32(in, &txtdesc->uclangcode) ||
1211
36.7k
    jas_iccgetuint32(in, &txtdesc->uclen)) {
1212
4
    goto error;
1213
4
  }
1214
36.7k
  if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2))) {
1215
3
    goto error;
1216
3
  }
1217
36.7k
  if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) !=
1218
36.7k
    txtdesc->uclen * 2) {
1219
6
    goto error;
1220
6
  }
1221
36.7k
  if (jas_iccgetuint16(in, &txtdesc->sccode)) {
1222
1
    goto error;
1223
1
  }
1224
36.7k
  if ((c = jas_stream_getc(in)) == EOF) {
1225
1
    goto error;
1226
1
  }
1227
36.7k
  txtdesc->maclen = c;
1228
36.7k
  if (jas_stream_read(in, txtdesc->macdata, 67) != 67) {
1229
1
    goto error;
1230
1
  }
1231
36.7k
  txtdesc->asclen = JAS_CAST(jas_iccuint32_t, strlen(txtdesc->ascdata) + 1);
1232
36.7k
#define WORKAROUND_BAD_PROFILES
1233
36.7k
#ifdef WORKAROUND_BAD_PROFILES
1234
36.7k
  const unsigned n = txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67;
1235
36.7k
  if (n > cnt) {
1236
1
    return -1;
1237
1
  }
1238
36.6k
  if (n < cnt) {
1239
12
    if (jas_stream_gobble(in, cnt - n) != (int)(cnt - n)) {
1240
2
      goto error;
1241
2
    }
1242
12
  }
1243
#else
1244
  if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) {
1245
    return -1;
1246
  }
1247
#endif
1248
36.6k
  return 0;
1249
24
error:
1250
24
  jas_icctxtdesc_destroy(attrval);
1251
24
  return -1;
1252
36.6k
}
1253
1254
static unsigned jas_icctxtdesc_getsize(const jas_iccattrval_t *attrval)
1255
25.2k
{
1256
25.2k
  const jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
1257
25.2k
  return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67;
1258
25.2k
}
1259
1260
static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out)
1261
25.2k
{
1262
25.2k
  const jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
1263
25.2k
  if (jas_iccputuint32(out, txtdesc->asclen) ||
1264
25.2k
    jas_stream_puts(out, txtdesc->ascdata) ||
1265
25.2k
    jas_stream_putc(out, 0) == EOF ||
1266
25.2k
    jas_iccputuint32(out, txtdesc->uclangcode) ||
1267
25.2k
    jas_iccputuint32(out, txtdesc->uclen) ||
1268
25.2k
    jas_stream_write(out, txtdesc->ucdata, txtdesc->uclen * 2) !=
1269
25.2k
    txtdesc->uclen * 2 ||
1270
25.2k
    jas_iccputuint16(out, txtdesc->sccode) ||
1271
25.2k
    jas_stream_putc(out, txtdesc->maclen) == EOF) {
1272
0
    goto error;
1273
0
  }
1274
25.2k
  if (txtdesc->maclen > 0) {
1275
1.68k
    if (jas_stream_write(out, txtdesc->macdata, 67) != 67) {
1276
0
      goto error;
1277
0
    }
1278
23.6k
  } else {
1279
23.6k
    if (jas_stream_pad(out, 67, 0) != 67) {
1280
0
      goto error;
1281
0
    }
1282
23.6k
  }
1283
25.2k
  return 0;
1284
0
error:
1285
0
  return -1;
1286
25.2k
}
1287
1288
static void jas_icctxtdesc_dump(const jas_iccattrval_t *attrval, FILE *out)
1289
0
{
1290
0
  const jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
1291
0
  fprintf(out, "ascii = \"%s\"\n", txtdesc->ascdata);
1292
0
  fprintf(out, "uclangcode = %"PRIuFAST32"; uclen = %"PRIuFAST32"\n",
1293
0
    txtdesc->uclangcode, txtdesc->uclen);
1294
0
  fprintf(out, "sccode = %"PRIuFAST16"\n", txtdesc->sccode);
1295
0
  fprintf(out, "maclen = %d\n", txtdesc->maclen);
1296
0
}
1297
1298
/******************************************************************************\
1299
*
1300
\******************************************************************************/
1301
1302
static void jas_icctxt_destroy(jas_iccattrval_t *attrval)
1303
35.0k
{
1304
35.0k
  jas_icctxt_t *txt = &attrval->data.txt;
1305
35.0k
  if (txt->string) {
1306
35.0k
    jas_free(txt->string);
1307
35.0k
    txt->string = 0;
1308
35.0k
  }
1309
35.0k
}
1310
1311
static int jas_icctxt_copy(jas_iccattrval_t *attrval,
1312
  const jas_iccattrval_t *othattrval)
1313
0
{
1314
0
  jas_icctxt_t *txt = &attrval->data.txt;
1315
0
  const jas_icctxt_t *othtxt = &othattrval->data.txt;
1316
0
  if (!(txt->string = jas_strdup(othtxt->string))) {
1317
0
    return -1;
1318
0
  }
1319
0
  return 0;
1320
0
}
1321
1322
static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in,
1323
  unsigned cnt)
1324
35.0k
{
1325
35.0k
  jas_icctxt_t *txt = &attrval->data.txt;
1326
35.0k
  txt->string = 0;
1327
  /* The string must at least contain a single null character. */
1328
35.0k
  if (cnt < 1) {
1329
0
    goto error;
1330
0
  }
1331
35.0k
  if (!(txt->string = jas_malloc(cnt))) {
1332
1
    goto error;
1333
1
  }
1334
35.0k
  if (jas_stream_read(in, txt->string, cnt) != cnt) {
1335
1
    goto error;
1336
1
  }
1337
  /* Ensure that the string is null terminated. */
1338
35.0k
  if (txt->string[cnt - 1] != '\0') {
1339
1
    goto error;
1340
1
  }
1341
  /* The following line is redundant, unless we do not enforce that
1342
    the last character must be null. */
1343
35.0k
  txt->string[cnt - 1] = '\0';
1344
35.0k
  if (strlen(txt->string) + 1 != cnt) {
1345
1
    goto error;
1346
1
  }
1347
35.0k
  return 0;
1348
4
error:
1349
4
  jas_icctxt_destroy(attrval);
1350
4
  return -1;
1351
35.0k
}
1352
1353
static unsigned jas_icctxt_getsize(const jas_iccattrval_t *attrval)
1354
24.0k
{
1355
24.0k
  const jas_icctxt_t *txt = &attrval->data.txt;
1356
24.0k
  return strlen(txt->string) + 1;
1357
24.0k
}
1358
1359
static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out)
1360
24.0k
{
1361
24.0k
  const jas_icctxt_t *txt = &attrval->data.txt;
1362
24.0k
  if (jas_stream_puts(out, txt->string) ||
1363
24.0k
    jas_stream_putc(out, 0) == EOF) {
1364
0
    return -1;
1365
0
  }
1366
24.0k
  return 0;
1367
24.0k
}
1368
1369
static void jas_icctxt_dump(const jas_iccattrval_t *attrval, FILE *out)
1370
0
{
1371
0
  const jas_icctxt_t *txt = &attrval->data.txt;
1372
0
  fprintf(out, "string = \"%s\"\n", txt->string);
1373
0
}
1374
1375
/******************************************************************************\
1376
*
1377
\******************************************************************************/
1378
1379
static void jas_icclut8_destroy(jas_iccattrval_t *attrval)
1380
0
{
1381
0
  jas_icclut8_t *lut8 = &attrval->data.lut8;
1382
0
  if (lut8->clut) {
1383
0
    jas_free(lut8->clut);
1384
0
    lut8->clut = 0;
1385
0
  }
1386
0
  if (lut8->intabs) {
1387
0
    jas_free(lut8->intabs);
1388
0
    lut8->intabs = 0;
1389
0
  }
1390
0
  if (lut8->intabsbuf) {
1391
0
    jas_free(lut8->intabsbuf);
1392
0
    lut8->intabsbuf = 0;
1393
0
  }
1394
0
  if (lut8->outtabs) {
1395
0
    jas_free(lut8->outtabs);
1396
0
    lut8->outtabs = 0;
1397
0
  }
1398
0
  if (lut8->outtabsbuf) {
1399
0
    jas_free(lut8->outtabsbuf);
1400
0
    lut8->outtabsbuf = 0;
1401
0
  }
1402
0
}
1403
1404
static int jas_icclut8_copy(jas_iccattrval_t *attrval,
1405
  const jas_iccattrval_t *othattrval)
1406
0
{
1407
0
  JAS_UNUSED(attrval);
1408
0
  JAS_UNUSED(othattrval);
1409
0
  abort();
1410
0
  return -1;
1411
0
}
1412
1413
static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in,
1414
  unsigned cnt)
1415
0
{
1416
0
  jas_icclut8_t *lut8 = &attrval->data.lut8;
1417
0
  lut8->clut = 0;
1418
0
  lut8->intabs = 0;
1419
0
  lut8->intabsbuf = 0;
1420
0
  lut8->outtabs = 0;
1421
0
  lut8->outtabsbuf = 0;
1422
0
  if (jas_iccgetuint8(in, &lut8->numinchans) ||
1423
0
    jas_iccgetuint8(in, &lut8->numoutchans) ||
1424
0
    jas_iccgetuint8(in, &lut8->clutlen) ||
1425
0
    jas_stream_getc(in) == EOF) {
1426
0
    goto error;
1427
0
  }
1428
0
  for (unsigned i = 0; i < 3; ++i) {
1429
0
    for (unsigned j = 0; j < 3; ++j) {
1430
0
      if (jas_iccgetsint32(in, &lut8->e[i][j])) {
1431
0
        goto error;
1432
0
      }
1433
0
    }
1434
0
  }
1435
0
  if (jas_iccgetuint16(in, &lut8->numintabents) ||
1436
0
    jas_iccgetuint16(in, &lut8->numouttabents)) {
1437
0
    goto error;
1438
0
  }
1439
0
  const unsigned clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
1440
0
  if (!(lut8->clut = jas_alloc2(clutsize, sizeof(jas_iccuint8_t))) ||
1441
0
    !(lut8->intabsbuf = jas_alloc3(lut8->numinchans,
1442
0
    lut8->numintabents, sizeof(jas_iccuint8_t))) ||
1443
0
    !(lut8->intabs = jas_alloc2(lut8->numinchans,
1444
0
    sizeof(jas_iccuint8_t *)))) {
1445
0
    goto error;
1446
0
  }
1447
0
  for (unsigned i = 0; i < lut8->numinchans; ++i)
1448
0
    lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents];
1449
0
  if (!(lut8->outtabsbuf = jas_alloc3(lut8->numoutchans,
1450
0
    lut8->numouttabents, sizeof(jas_iccuint8_t))) ||
1451
0
    !(lut8->outtabs = jas_alloc2(lut8->numoutchans,
1452
0
    sizeof(jas_iccuint8_t *)))) {
1453
0
    goto error;
1454
0
  }
1455
0
  for (unsigned i = 0; i < lut8->numoutchans; ++i) {
1456
0
    lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents];
1457
0
  }
1458
0
  for (unsigned i = 0; i < lut8->numinchans; ++i) {
1459
0
    for (unsigned j = 0; j < lut8->numintabents; ++j) {
1460
0
      if (jas_iccgetuint8(in, &lut8->intabs[i][j])) {
1461
0
        goto error;
1462
0
      }
1463
0
    }
1464
0
  }
1465
0
  for (unsigned i = 0; i < lut8->numoutchans; ++i) {
1466
0
    for (unsigned j = 0; j < lut8->numouttabents; ++j) {
1467
0
      if (jas_iccgetuint8(in, &lut8->outtabs[i][j])) {
1468
0
        goto error;
1469
0
      }
1470
0
    }
1471
0
  }
1472
0
  for (unsigned i = 0; i < clutsize; ++i) {
1473
0
    if (jas_iccgetuint8(in, &lut8->clut[i])) {
1474
0
      goto error;
1475
0
    }
1476
0
  }
1477
0
  if (44 + lut8->numinchans * lut8->numintabents +
1478
0
    lut8->numoutchans * lut8->numouttabents +
1479
0
    jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans !=
1480
0
    cnt) {
1481
0
    goto error;
1482
0
  }
1483
0
  return 0;
1484
0
error:
1485
0
  jas_icclut8_destroy(attrval);
1486
0
  return -1;
1487
0
}
1488
1489
static unsigned jas_icclut8_getsize(const jas_iccattrval_t *attrval)
1490
0
{
1491
0
  const jas_icclut8_t *lut8 = &attrval->data.lut8;
1492
0
  return 44 + lut8->numinchans * lut8->numintabents +
1493
0
    lut8->numoutchans * lut8->numouttabents +
1494
0
    jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
1495
0
}
1496
1497
static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out)
1498
0
{
1499
0
  jas_icclut8_t *lut8 = &attrval->data.lut8;
1500
0
  lut8->clut = 0;
1501
0
  lut8->intabs = 0;
1502
0
  lut8->intabsbuf = 0;
1503
0
  lut8->outtabs = 0;
1504
0
  lut8->outtabsbuf = 0;
1505
0
  if (jas_stream_putc(out, lut8->numinchans) == EOF ||
1506
0
    jas_stream_putc(out, lut8->numoutchans) == EOF ||
1507
0
    jas_stream_putc(out, lut8->clutlen) == EOF ||
1508
0
    jas_stream_putc(out, 0) == EOF) {
1509
0
    goto error;
1510
0
  }
1511
0
  for (unsigned i = 0; i < 3; ++i) {
1512
0
    for (unsigned j = 0; j < 3; ++j) {
1513
0
      if (jas_iccputsint32(out, lut8->e[i][j])) {
1514
0
        goto error;
1515
0
      }
1516
0
    }
1517
0
  }
1518
0
  if (jas_iccputuint16(out, lut8->numintabents) ||
1519
0
    jas_iccputuint16(out, lut8->numouttabents)) {
1520
0
    goto error;
1521
0
  }
1522
0
  for (unsigned i = 0, n = lut8->numinchans * lut8->numintabents; i < n;
1523
0
    ++i) {
1524
0
    if (jas_iccputuint8(out, lut8->intabsbuf[i])) {
1525
0
      goto error;
1526
0
    }
1527
0
  }
1528
0
  for (unsigned i = 0, n = lut8->numoutchans * lut8->numouttabents; i < n;
1529
0
    ++i) {
1530
0
    if (jas_iccputuint8(out, lut8->outtabsbuf[i])) {
1531
0
      goto error;
1532
0
    }
1533
0
  }
1534
0
  for (unsigned i = 0, n = jas_iccpowi(lut8->clutlen, lut8->numinchans) *
1535
0
    lut8->numoutchans; i < n; ++i) {
1536
0
    if (jas_iccputuint8(out, lut8->clut[i])) {
1537
0
      goto error;
1538
0
    }
1539
0
  }
1540
0
  return 0;
1541
0
error:
1542
0
  return -1;
1543
0
}
1544
1545
static void jas_icclut8_dump(const jas_iccattrval_t *attrval, FILE *out)
1546
0
{
1547
0
  const jas_icclut8_t *lut8 = &attrval->data.lut8;
1548
0
  fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n",
1549
0
    lut8->numinchans, lut8->numoutchans, lut8->clutlen);
1550
0
  for (unsigned i = 0; i < 3; ++i) {
1551
0
    for (unsigned j = 0; j < 3; ++j) {
1552
0
      fprintf(out, "e[%d][%d]=%f ", i, j, lut8->e[i][j] / 65536.0);
1553
0
    }
1554
0
    fprintf(out, "\n");
1555
0
  }
1556
0
  fprintf(out, "numintabents=%"PRIuFAST16", numouttabents=%"PRIuFAST16"\n",
1557
0
    lut8->numintabents, lut8->numouttabents);
1558
0
}
1559
1560
/******************************************************************************\
1561
*
1562
\******************************************************************************/
1563
1564
static void jas_icclut16_destroy(jas_iccattrval_t *attrval)
1565
0
{
1566
0
  jas_icclut16_t *lut16 = &attrval->data.lut16;
1567
0
  if (lut16->clut) {
1568
0
    jas_free(lut16->clut);
1569
0
    lut16->clut = 0;
1570
0
  }
1571
0
  if (lut16->intabs) {
1572
0
    jas_free(lut16->intabs);
1573
0
    lut16->intabs = 0;
1574
0
  }
1575
0
  if (lut16->intabsbuf) {
1576
0
    jas_free(lut16->intabsbuf);
1577
0
    lut16->intabsbuf = 0;
1578
0
  }
1579
0
  if (lut16->outtabs) {
1580
0
    jas_free(lut16->outtabs);
1581
0
    lut16->outtabs = 0;
1582
0
  }
1583
0
  if (lut16->outtabsbuf) {
1584
0
    jas_free(lut16->outtabsbuf);
1585
0
    lut16->outtabsbuf = 0;
1586
0
  }
1587
0
}
1588
1589
static int jas_icclut16_copy(jas_iccattrval_t *attrval,
1590
  const jas_iccattrval_t *othattrval)
1591
0
{
1592
0
  JAS_UNUSED(attrval);
1593
0
  JAS_UNUSED(othattrval);
1594
1595
  /* Not yet implemented. */
1596
0
  abort();
1597
0
  return -1;
1598
0
}
1599
1600
static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in,
1601
  unsigned cnt)
1602
0
{
1603
0
  jas_icclut16_t *lut16 = &attrval->data.lut16;
1604
0
  lut16->clut = 0;
1605
0
  lut16->intabs = 0;
1606
0
  lut16->intabsbuf = 0;
1607
0
  lut16->outtabs = 0;
1608
0
  lut16->outtabsbuf = 0;
1609
0
  if (jas_iccgetuint8(in, &lut16->numinchans) ||
1610
0
    jas_iccgetuint8(in, &lut16->numoutchans) ||
1611
0
    jas_iccgetuint8(in, &lut16->clutlen) ||
1612
0
    jas_stream_getc(in) == EOF) {
1613
0
    goto error;
1614
0
  }
1615
0
  for (unsigned i = 0; i < 3; ++i) {
1616
0
    for (unsigned j = 0; j < 3; ++j) {
1617
0
      if (jas_iccgetsint32(in, &lut16->e[i][j])) {
1618
0
        goto error;
1619
0
      }
1620
0
    }
1621
0
  }
1622
0
  if (jas_iccgetuint16(in, &lut16->numintabents) ||
1623
0
    jas_iccgetuint16(in, &lut16->numouttabents)) {
1624
0
    goto error;
1625
0
  }
1626
0
  const unsigned clutsize = jas_iccpowi(lut16->clutlen, lut16->numinchans) *
1627
0
    lut16->numoutchans;
1628
0
  if (!(lut16->clut = jas_alloc2(clutsize, sizeof(jas_iccuint16_t))) ||
1629
0
    !(lut16->intabsbuf = jas_alloc3(lut16->numinchans,
1630
0
    lut16->numintabents, sizeof(jas_iccuint16_t))) ||
1631
0
    !(lut16->intabs = jas_alloc2(lut16->numinchans,
1632
0
    sizeof(jas_iccuint16_t *)))) {
1633
0
    goto error;
1634
0
  }
1635
0
  for (unsigned i = 0; i < lut16->numinchans; ++i) {
1636
0
    lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents];
1637
0
  }
1638
0
  if (!(lut16->outtabsbuf = jas_alloc3(lut16->numoutchans,
1639
0
    lut16->numouttabents, sizeof(jas_iccuint16_t))) ||
1640
0
    !(lut16->outtabs = jas_alloc2(lut16->numoutchans,
1641
0
    sizeof(jas_iccuint16_t *)))) {
1642
0
    goto error;
1643
0
  }
1644
0
  for (unsigned i = 0; i < lut16->numoutchans; ++i) {
1645
0
    lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents];
1646
0
  }
1647
0
  for (unsigned i = 0; i < lut16->numinchans; ++i) {
1648
0
    for (unsigned j = 0; j < lut16->numintabents; ++j) {
1649
0
      if (jas_iccgetuint16(in, &lut16->intabs[i][j])) {
1650
0
        goto error;
1651
0
      }
1652
0
    }
1653
0
  }
1654
0
  for (unsigned i = 0; i < lut16->numoutchans; ++i) {
1655
0
    for (unsigned j = 0; j < lut16->numouttabents; ++j) {
1656
0
      if (jas_iccgetuint16(in, &lut16->outtabs[i][j])) {
1657
0
        goto error;
1658
0
      }
1659
0
    }
1660
0
  }
1661
0
  for (unsigned i = 0; i < clutsize; ++i) {
1662
0
    if (jas_iccgetuint16(in, &lut16->clut[i])) {
1663
0
      goto error;
1664
0
    }
1665
0
  }
1666
0
  if (44 + 2 * (lut16->numinchans * lut16->numintabents +
1667
0
    lut16->numoutchans * lut16->numouttabents +
1668
0
    jas_iccpowi(lut16->clutlen, lut16->numinchans) *
1669
0
    lut16->numoutchans) != cnt) {
1670
0
    goto error;
1671
0
  }
1672
0
  return 0;
1673
0
error:
1674
0
  jas_icclut16_destroy(attrval);
1675
0
  return -1;
1676
0
}
1677
1678
static unsigned jas_icclut16_getsize(const jas_iccattrval_t *attrval)
1679
0
{
1680
0
  const jas_icclut16_t *lut16 = &attrval->data.lut16;
1681
0
  return 44 + 2 * (lut16->numinchans * lut16->numintabents +
1682
0
    lut16->numoutchans * lut16->numouttabents +
1683
0
    jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans);
1684
0
}
1685
1686
static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out)
1687
0
{
1688
0
  const jas_icclut16_t *lut16 = &attrval->data.lut16;
1689
0
  if (jas_stream_putc(out, lut16->numinchans) == EOF ||
1690
0
    jas_stream_putc(out, lut16->numoutchans) == EOF ||
1691
0
    jas_stream_putc(out, lut16->clutlen) == EOF ||
1692
0
    jas_stream_putc(out, 0) == EOF) {
1693
0
    goto error;
1694
0
  }
1695
0
  for (unsigned i = 0; i < 3; ++i) {
1696
0
    for (unsigned j = 0; j < 3; ++j) {
1697
0
      if (jas_iccputsint32(out, lut16->e[i][j])) {
1698
0
        goto error;
1699
0
      }
1700
0
    }
1701
0
  }
1702
0
  if (jas_iccputuint16(out, lut16->numintabents) ||
1703
0
    jas_iccputuint16(out, lut16->numouttabents)) {
1704
0
    goto error;
1705
0
  }
1706
0
  for (unsigned i = 0, n = lut16->numinchans * lut16->numintabents; i < n;
1707
0
    ++i) {
1708
0
    if (jas_iccputuint16(out, lut16->intabsbuf[i])) {
1709
0
      goto error;
1710
0
    }
1711
0
  }
1712
0
  for (unsigned i = 0, n = lut16->numoutchans * lut16->numouttabents; i < n;
1713
0
    ++i) {
1714
0
    if (jas_iccputuint16(out, lut16->outtabsbuf[i])) {
1715
0
      goto error;
1716
0
    }
1717
0
  }
1718
0
  for (unsigned i = 0, n = jas_iccpowi(lut16->clutlen, lut16->numinchans) *
1719
0
    lut16->numoutchans; i < n; ++i) {
1720
0
    if (jas_iccputuint16(out, lut16->clut[i])) {
1721
0
      goto error;
1722
0
    }
1723
0
  }
1724
0
  return 0;
1725
0
error:
1726
0
  return -1;
1727
0
}
1728
1729
static void jas_icclut16_dump(const jas_iccattrval_t *attrval, FILE *out)
1730
0
{
1731
0
  const jas_icclut16_t *lut16 = &attrval->data.lut16;
1732
0
  fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n",
1733
0
    lut16->numinchans, lut16->numoutchans, lut16->clutlen);
1734
0
  for (unsigned i = 0; i < 3; ++i) {
1735
0
    for (unsigned j = 0; j < 3; ++j) {
1736
0
      fprintf(out, "e[%d][%d]=%f ", i, j, lut16->e[i][j] / 65536.0);
1737
0
    }
1738
0
    fprintf(out, "\n");
1739
0
  }
1740
0
  fprintf(out, "numintabents=%"PRIuFAST16", numouttabents=%"PRIuFAST16"\n",
1741
0
    lut16->numintabents, lut16->numouttabents);
1742
0
}
1743
1744
/******************************************************************************\
1745
*
1746
\******************************************************************************/
1747
1748
static int jas_iccgetuint(jas_stream_t *in, unsigned n, jas_ulonglong *val)
1749
2.38M
{
1750
2.38M
  int c;
1751
2.38M
  jas_ulonglong v;
1752
2.38M
  v = 0;
1753
10.2M
  for (unsigned i = n; i > 0; --i) {
1754
7.90M
    if ((c = jas_stream_getc(in)) == EOF) {
1755
19
      return -1;
1756
19
    }
1757
7.90M
    v = (v << 8) | c;
1758
7.90M
  }
1759
2.38M
  *val = v;
1760
2.38M
  return 0;
1761
2.38M
}
1762
1763
static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val)
1764
0
{
1765
0
  int c;
1766
0
  if ((c = jas_stream_getc(in)) == EOF) {
1767
0
    return -1;
1768
0
  }
1769
0
  *val = c;
1770
0
  return 0;
1771
0
}
1772
1773
static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val)
1774
885k
{
1775
885k
  jas_ulonglong tmp;
1776
885k
  if (jas_iccgetuint(in, 2, &tmp)) {
1777
3
    return -1;
1778
3
  }
1779
885k
  *val = (jas_iccuint16_t)tmp;
1780
885k
  return 0;
1781
885k
}
1782
1783
static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val)
1784
219k
{
1785
219k
  jas_ulonglong tmp;
1786
219k
  if (jas_iccgetuint(in, 4, &tmp)) {
1787
0
    return -1;
1788
0
  }
1789
219k
  *val = (tmp & 0x80000000) ? (-JAS_CAST(jas_longlong, (((~tmp) &
1790
219k
    0x7fffffff) + 1))) : JAS_CAST(jas_longlong, tmp);
1791
219k
  return 0;
1792
219k
}
1793
1794
static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val)
1795
1.24M
{
1796
1.24M
  jas_ulonglong tmp;
1797
1.24M
  if (jas_iccgetuint(in, 4, &tmp)) {
1798
16
    return -1;
1799
16
  }
1800
1.24M
  *val = (jas_iccuint32_t)tmp;
1801
1.24M
  return 0;
1802
1.24M
}
1803
1804
static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val)
1805
35.2k
{
1806
35.2k
  jas_ulonglong tmp;
1807
35.2k
  if (jas_iccgetuint(in, 8, &tmp)) {
1808
0
    return -1;
1809
0
  }
1810
35.2k
  *val = (jas_iccuint64_t)tmp;
1811
35.2k
  return 0;
1812
35.2k
}
1813
1814
static int jas_iccputuint(jas_stream_t *out, unsigned n, jas_ulonglong val)
1815
1.63M
{
1816
1.63M
  int c;
1817
7.02M
  for (unsigned i = n; i > 0; --i) {
1818
5.38M
    c = (val >> (8 * (i - 1))) & 0xff;
1819
5.38M
    if (jas_stream_putc(out, c) == EOF) {
1820
0
      return -1;
1821
0
    }
1822
5.38M
  }
1823
1.63M
  return 0;
1824
1.63M
}
1825
1826
static int jas_iccputsint(jas_stream_t *out, unsigned n, jas_longlong val)
1827
0
{
1828
0
  assert(val >= 0);
1829
0
  jas_ulonglong tmp;
1830
0
  tmp = (val < 0) ? 0 : val;
1831
0
  return jas_iccputuint(out, n, tmp);
1832
0
}
1833
1834
/******************************************************************************\
1835
*
1836
\******************************************************************************/
1837
1838
static char *jas_iccsigtostr(unsigned sig, char *buf)
1839
0
{
1840
0
  int c;
1841
0
  char *bufptr;
1842
0
  bufptr = buf;
1843
0
  for (unsigned n = 4; n > 0; --n) {
1844
0
    c = (sig >> 24) & 0xff;
1845
0
    if (isalpha(JAS_CAST(unsigned char, c)) ||
1846
0
      isdigit(JAS_CAST(unsigned char, c))) {
1847
0
      *bufptr++ = c;
1848
0
    }
1849
0
    sig <<= 8;
1850
0
  }
1851
0
  *bufptr = '\0';
1852
0
  return buf;
1853
0
}
1854
1855
static unsigned jas_iccpadtomult(unsigned x, unsigned y)
1856
75.8k
{
1857
75.8k
  return ((x + y - 1) / y) * y;
1858
75.8k
}
1859
1860
static unsigned jas_iccpowi(unsigned x, unsigned n)
1861
0
{
1862
0
  unsigned y;
1863
0
  y = 1;
1864
0
  while (n-- > 0) {
1865
0
    y *= x;
1866
0
  }
1867
0
  return y;
1868
0
}
1869
1870
1871
jas_iccprof_t *jas_iccprof_createfrombuf(const jas_uchar *buf, unsigned len)
1872
35.2k
{
1873
35.2k
  assert(buf);
1874
35.2k
  assert(len > 0);
1875
35.2k
  jas_stream_t *in;
1876
35.2k
  jas_iccprof_t *prof;
1877
35.2k
  if (!(in = jas_stream_memopen(JAS_CAST(char *, buf), len))) {
1878
0
    goto error;
1879
0
  }
1880
35.2k
  if (!(prof = jas_iccprof_load(in))) {
1881
164
    goto error;
1882
164
  }
1883
35.0k
  jas_stream_close(in);
1884
35.0k
  return prof;
1885
164
error:
1886
164
  if (in) {
1887
164
    jas_stream_close(in);
1888
164
  }
1889
164
  return 0;
1890
35.2k
}
1891
1892
jas_iccprof_t *jas_iccprof_createfromclrspc(unsigned clrspc)
1893
35.0k
{
1894
35.0k
  jas_iccprof_t *prof;
1895
35.0k
  switch (clrspc) {
1896
559
  case JAS_CLRSPC_SRGB:
1897
559
    prof = jas_iccprof_createfrombuf(jas_iccprofdata_srgb,
1898
559
      jas_iccprofdata_srgblen);
1899
559
    break;
1900
34.4k
  case JAS_CLRSPC_SGRAY:
1901
34.4k
    prof = jas_iccprof_createfrombuf(jas_iccprofdata_sgray,
1902
34.4k
      jas_iccprofdata_sgraylen);
1903
34.4k
    break;
1904
0
  default:
1905
0
    prof = 0;
1906
0
    break;
1907
35.0k
  }
1908
35.0k
  return prof;
1909
35.0k
}