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