/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 | } |