vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

jas_icc.c (47993B)


      1 /*
      2  * Copyright (c) 2002-2003 Michael David Adams.
      3  * All rights reserved.
      4  */
      5 
      6 /* __START_OF_JASPER_LICENSE__
      7  * 
      8  * JasPer License Version 2.0
      9  * 
     10  * Copyright (c) 1999-2000 Image Power, Inc.
     11  * Copyright (c) 1999-2000 The University of British Columbia
     12  * Copyright (c) 2001-2003 Michael David Adams
     13  * 
     14  * All rights reserved.
     15  * 
     16  * Permission is hereby granted, free of charge, to any person (the
     17  * "User") obtaining a copy of this software and associated documentation
     18  * files (the "Software"), to deal in the Software without restriction,
     19  * including without limitation the rights to use, copy, modify, merge,
     20  * publish, distribute, and/or sell copies of the Software, and to permit
     21  * persons to whom the Software is furnished to do so, subject to the
     22  * following conditions:
     23  * 
     24  * 1.  The above copyright notices and this permission notice (which
     25  * includes the disclaimer below) shall be included in all copies or
     26  * substantial portions of the Software.
     27  * 
     28  * 2.  The name of a copyright holder shall not be used to endorse or
     29  * promote products derived from the Software without specific prior
     30  * written permission.
     31  * 
     32  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
     33  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
     34  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
     35  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
     36  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     37  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
     38  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
     39  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
     40  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     41  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     42  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
     43  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
     44  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
     45  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
     46  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
     47  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
     48  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
     49  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
     50  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
     51  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
     52  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
     53  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
     54  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
     55  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
     56  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
     57  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
     58  * 
     59  * __END_OF_JASPER_LICENSE__
     60  */
     61 
     62 #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 
     71 #include <stdlib.h>
     72 #include <ctype.h>
     73 
     74 #define	jas_iccputuint8(out, val)	jas_iccputuint(out, 1, val)
     75 #define	jas_iccputuint16(out, val)	jas_iccputuint(out, 2, val)
     76 #define	jas_iccputsint32(out, val)	jas_iccputsint(out, 4, val)
     77 #define	jas_iccputuint32(out, val)	jas_iccputuint(out, 4, val)
     78 #define	jas_iccputuint64(out, val)	jas_iccputuint(out, 8, val)
     79 
     80 static jas_iccattrval_t *jas_iccattrval_create0(void);
     81 
     82 static int jas_iccgetuint(jas_stream_t *in, int n, ulonglong *val);
     83 static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val);
     84 static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val);
     85 static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val);
     86 static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val);
     87 static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val);
     88 static int jas_iccputuint(jas_stream_t *out, int n, ulonglong val);
     89 static int jas_iccputsint(jas_stream_t *out, int n, longlong val);
     90 static jas_iccprof_t *jas_iccprof_create(void);
     91 static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr);
     92 static int jas_iccprof_writehdr(jas_stream_t *out, jas_icchdr_t *hdr);
     93 static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab);
     94 static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab);
     95 static int jas_iccattrtab_lookup(jas_iccattrtab_t *attrtab, jas_iccuint32_t name);
     96 static jas_iccattrtab_t *jas_iccattrtab_copy(jas_iccattrtab_t *attrtab);
     97 static jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t name);
     98 static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time);
     99 static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz);
    100 static int jas_icctagtabent_cmp(const void *src, const void *dst);
    101 
    102 static void jas_icccurv_destroy(jas_iccattrval_t *attrval);
    103 static int jas_icccurv_copy(jas_iccattrval_t *attrval,
    104   jas_iccattrval_t *othattrval);
    105 static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in,
    106   int cnt);
    107 static int jas_icccurv_getsize(jas_iccattrval_t *attrval);
    108 static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out);
    109 static void jas_icccurv_dump(jas_iccattrval_t *attrval, FILE *out);
    110 
    111 static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval);
    112 static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval,
    113   jas_iccattrval_t *othattrval);
    114 static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in,
    115   int cnt);
    116 static int jas_icctxtdesc_getsize(jas_iccattrval_t *attrval);
    117 static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out);
    118 static void jas_icctxtdesc_dump(jas_iccattrval_t *attrval, FILE *out);
    119 
    120 static void jas_icctxt_destroy(jas_iccattrval_t *attrval);
    121 static int jas_icctxt_copy(jas_iccattrval_t *attrval,
    122   jas_iccattrval_t *othattrval);
    123 static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in,
    124   int cnt);
    125 static int jas_icctxt_getsize(jas_iccattrval_t *attrval);
    126 static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out);
    127 static void jas_icctxt_dump(jas_iccattrval_t *attrval, FILE *out);
    128 
    129 static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
    130   int cnt);
    131 static int jas_iccxyz_getsize(jas_iccattrval_t *attrval);
    132 static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out);
    133 static void jas_iccxyz_dump(jas_iccattrval_t *attrval, FILE *out);
    134 
    135 static jas_iccattrtab_t *jas_iccattrtab_create(void);
    136 static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab);
    137 static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, int maxents);
    138 static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i,
    139   jas_iccuint32_t name, jas_iccattrval_t *val);
    140 static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, int i,
    141   jas_iccuint32_t name, jas_iccattrval_t *val);
    142 static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, int i);
    143 static long jas_iccpadtomult(long x, long y);
    144 static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, int i,
    145   jas_iccattrname_t *name, jas_iccattrval_t **val);
    146 static int jas_iccprof_puttagtab(jas_stream_t *out, jas_icctagtab_t *tagtab);
    147 
    148 static void jas_icclut16_destroy(jas_iccattrval_t *attrval);
    149 static int jas_icclut16_copy(jas_iccattrval_t *attrval,
    150   jas_iccattrval_t *othattrval);
    151 static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in,
    152   int cnt);
    153 static int jas_icclut16_getsize(jas_iccattrval_t *attrval);
    154 static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out);
    155 static void jas_icclut16_dump(jas_iccattrval_t *attrval, FILE *out);
    156 
    157 static void jas_icclut8_destroy(jas_iccattrval_t *attrval);
    158 static int jas_icclut8_copy(jas_iccattrval_t *attrval,
    159   jas_iccattrval_t *othattrval);
    160 static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in,
    161   int cnt);
    162 static int jas_icclut8_getsize(jas_iccattrval_t *attrval);
    163 static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out);
    164 static void jas_icclut8_dump(jas_iccattrval_t *attrval, FILE *out);
    165 
    166 static int jas_iccputtime(jas_stream_t *out, jas_icctime_t *ctime);
    167 static int jas_iccputxyz(jas_stream_t *out, jas_iccxyz_t *xyz);
    168 
    169 static long jas_iccpowi(int x, int n);
    170 
    171 static char *jas_iccsigtostr(int sig, char *buf);
    172 
    173 
    174 jas_iccattrvalinfo_t jas_iccattrvalinfos[] = {
    175 	{JAS_ICC_TYPE_CURV, {jas_icccurv_destroy, jas_icccurv_copy,
    176 	  jas_icccurv_input, jas_icccurv_output, jas_icccurv_getsize,
    177 	  jas_icccurv_dump}},
    178 	{JAS_ICC_TYPE_XYZ, {0, 0, jas_iccxyz_input, jas_iccxyz_output,
    179 	  jas_iccxyz_getsize, jas_iccxyz_dump}},
    180 	{JAS_ICC_TYPE_TXTDESC, {jas_icctxtdesc_destroy,
    181 	  jas_icctxtdesc_copy, jas_icctxtdesc_input, jas_icctxtdesc_output,
    182 	  jas_icctxtdesc_getsize, jas_icctxtdesc_dump}},
    183 	{JAS_ICC_TYPE_TXT, {jas_icctxt_destroy, jas_icctxt_copy,
    184 	  jas_icctxt_input, jas_icctxt_output, jas_icctxt_getsize,
    185 	  jas_icctxt_dump}},
    186 	{JAS_ICC_TYPE_LUT8, {jas_icclut8_destroy, jas_icclut8_copy,
    187 	  jas_icclut8_input, jas_icclut8_output, jas_icclut8_getsize,
    188 	  jas_icclut8_dump}},
    189 	{JAS_ICC_TYPE_LUT16, {jas_icclut16_destroy, jas_icclut16_copy,
    190 	  jas_icclut16_input, jas_icclut16_output, jas_icclut16_getsize,
    191 	  jas_icclut16_dump}},
    192 	{0, {0, 0, 0, 0, 0, 0}}
    193 };
    194 
    195 typedef struct {
    196 	jas_iccuint32_t tag;
    197 	char *name;
    198 } jas_icctaginfo_t;
    199 
    200 /******************************************************************************\
    201 * profile class
    202 \******************************************************************************/
    203 
    204 static jas_iccprof_t *jas_iccprof_create()
    205 {
    206 	jas_iccprof_t *prof;
    207 	prof = 0;
    208 	if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) {
    209 		goto error;
    210 	}
    211 	if (!(prof->attrtab = jas_iccattrtab_create()))
    212 		goto error;
    213 	memset(&prof->hdr, 0, sizeof(jas_icchdr_t));
    214 	prof->tagtab.numents = 0;
    215 	prof->tagtab.ents = 0;
    216 	return prof;
    217 error:
    218 	if (prof)
    219 		jas_iccprof_destroy(prof);
    220 	return 0;
    221 }
    222 
    223 jas_iccprof_t *jas_iccprof_copy(jas_iccprof_t *prof)
    224 {
    225 	jas_iccprof_t *newprof;
    226 	newprof = 0;
    227 	if (!(newprof = jas_iccprof_create()))
    228 		goto error;
    229 	newprof->hdr = prof->hdr;
    230 	newprof->tagtab.numents = 0;
    231 	newprof->tagtab.ents = 0;
    232 	assert(newprof->attrtab);
    233 	jas_iccattrtab_destroy(newprof->attrtab);
    234 	if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab)))
    235 		goto error;
    236 	return newprof;
    237 error:
    238 	if (newprof)
    239 		jas_iccprof_destroy(newprof);
    240 	return 0;
    241 }
    242 
    243 void jas_iccprof_destroy(jas_iccprof_t *prof)
    244 {
    245 	if (prof->attrtab)
    246 		jas_iccattrtab_destroy(prof->attrtab);
    247 	if (prof->tagtab.ents)
    248 		jas_free(prof->tagtab.ents);
    249 	jas_free(prof);
    250 }
    251 
    252 void jas_iccprof_dump(jas_iccprof_t *prof, FILE *out)
    253 {
    254 	jas_iccattrtab_dump(prof->attrtab, out);
    255 }
    256 
    257 jas_iccprof_t *jas_iccprof_load(jas_stream_t *in)
    258 {
    259 	jas_iccprof_t *prof;
    260 	int numtags;
    261 	long curoff;
    262 	long reloff;
    263 	long prevoff;
    264 	jas_iccsig_t type;
    265 	jas_iccattrval_t *attrval;
    266 	jas_iccattrval_t *prevattrval;
    267 	jas_icctagtabent_t *tagtabent;
    268 	jas_iccattrvalinfo_t *attrvalinfo;
    269 	int i;
    270 	int len;
    271 
    272 	prof = 0;
    273 	attrval = 0;
    274 
    275 	if (!(prof = jas_iccprof_create())) {
    276 		goto error;
    277 	}
    278 
    279 	if (jas_iccprof_readhdr(in, &prof->hdr)) {
    280 		jas_eprintf("cannot get header\n");
    281 		goto error;
    282 	}
    283 	if (jas_iccprof_gettagtab(in, &prof->tagtab)) {
    284 		jas_eprintf("cannot get tab table\n");
    285 		goto error;
    286 	}
    287 	jas_iccprof_sorttagtab(&prof->tagtab);
    288 
    289 	numtags = prof->tagtab.numents;
    290 	curoff = JAS_ICC_HDRLEN + 4 + 12 * numtags;
    291 	prevoff = 0;
    292 	prevattrval = 0;
    293 	for (i = 0; i < numtags; ++i) {
    294 		tagtabent = &prof->tagtab.ents[i];
    295 		if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) {
    296 			if (prevattrval) {
    297 				if (!(attrval = jas_iccattrval_clone(prevattrval)))
    298 					goto error;
    299 				if (jas_iccprof_setattr(prof, tagtabent->tag, attrval))
    300 					goto error;
    301 				jas_iccattrval_destroy(attrval);
    302 			} else {
    303 #if 0
    304 				jas_eprintf("warning: skipping unknown tag type\n");
    305 #endif
    306 			}
    307 			continue;
    308 		}
    309 		reloff = tagtabent->off - curoff;
    310 		if (reloff > 0) {
    311 			if (jas_stream_gobble(in, reloff) != reloff)
    312 				goto error;
    313 			curoff += reloff;
    314 		} else if (reloff < 0) {
    315 			/* This should never happen since we read the tagged
    316 			element data in a single pass. */
    317 			abort();
    318 		}
    319 		prevoff = curoff;
    320 		if (jas_iccgetuint32(in, &type)) {
    321 			goto error;
    322 		}
    323 		if (jas_stream_gobble(in, 4) != 4) {
    324 			goto error;
    325 		}
    326 		curoff += 8;
    327 		if (!(attrvalinfo = jas_iccattrvalinfo_lookup(type))) {
    328 #if 0
    329 			jas_eprintf("warning: skipping unknown tag type\n");
    330 #endif
    331 			prevattrval = 0;
    332 			continue;
    333 		}
    334 		if (!(attrval = jas_iccattrval_create(type))) {
    335 			goto error;
    336 		}
    337 		len = tagtabent->len - 8;
    338 		if ((*attrval->ops->input)(attrval, in, len)) {
    339 			goto error;
    340 		}
    341 		curoff += len;
    342 		if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) {
    343 			goto error;
    344 		}
    345 		prevattrval = attrval; /* This is correct, but slimey. */
    346 		jas_iccattrval_destroy(attrval);
    347 		attrval = 0;
    348 	}
    349 
    350 	return prof;
    351 
    352 error:
    353 	if (prof)
    354 		jas_iccprof_destroy(prof);
    355 	if (attrval)
    356 		jas_iccattrval_destroy(attrval);
    357 	return 0;
    358 }
    359 
    360 int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out)
    361 {
    362 	long curoff;
    363 	long reloff;
    364 	long newoff;
    365 	int i;
    366 	int j;
    367 	jas_icctagtabent_t *tagtabent;
    368 	jas_icctagtabent_t *sharedtagtabent;
    369 	jas_icctagtabent_t *tmptagtabent;
    370 	jas_iccuint32_t attrname;
    371 	jas_iccattrval_t *attrval;
    372 	jas_icctagtab_t *tagtab;
    373 
    374 	tagtab = &prof->tagtab;
    375 	if (!(tagtab->ents = jas_malloc(prof->attrtab->numattrs *
    376 	  sizeof(jas_icctagtabent_t))))
    377 		goto error;
    378 	tagtab->numents = prof->attrtab->numattrs;
    379 	curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
    380 	for (i = 0; i < JAS_CAST(int, tagtab->numents); ++i) {
    381 		tagtabent = &tagtab->ents[i];
    382 		if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval))
    383 			goto error;
    384 		assert(attrval->ops->output);
    385 		tagtabent->tag = attrname;
    386 		tagtabent->data = &attrval->data;
    387 		sharedtagtabent = 0;
    388 		for (j = 0; j < i; ++j) {
    389 			tmptagtabent = &tagtab->ents[j];
    390 			if (tagtabent->data == tmptagtabent->data) {
    391 				sharedtagtabent = tmptagtabent;
    392 				break;
    393 			}
    394 		}
    395 		if (sharedtagtabent) {
    396 			tagtabent->off = sharedtagtabent->off;
    397 			tagtabent->len = sharedtagtabent->len;
    398 			tagtabent->first = sharedtagtabent;
    399 		} else {
    400 			tagtabent->off = curoff;
    401 			tagtabent->len = (*attrval->ops->getsize)(attrval) + 8;
    402 			tagtabent->first = 0;
    403 			if (i < JAS_CAST(int, tagtab->numents - 1)) {
    404 				curoff = jas_iccpadtomult(curoff + tagtabent->len, 4);
    405 			} else {
    406 				curoff += tagtabent->len;
    407 			}
    408 		}
    409 		jas_iccattrval_destroy(attrval);
    410 	}
    411 	prof->hdr.size = curoff;
    412 	if (jas_iccprof_writehdr(out, &prof->hdr))
    413 		goto error;
    414 	if (jas_iccprof_puttagtab(out, &prof->tagtab))
    415 		goto error;
    416 	curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
    417 	for (i = 0; i < JAS_CAST(int, tagtab->numents);) {
    418 		tagtabent = &tagtab->ents[i];
    419 		assert(curoff == JAS_CAST(long, tagtabent->off));
    420 		if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval))
    421 			goto error;
    422 		if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out,
    423 		  4, 0) != 4)
    424 			goto error;
    425 		if ((*attrval->ops->output)(attrval, out))
    426 			goto error;
    427 		jas_iccattrval_destroy(attrval);
    428 		curoff += tagtabent->len;
    429 		++i;
    430 		while (i < JAS_CAST(int, tagtab->numents) &&
    431 		  tagtab->ents[i].first)
    432 			++i;
    433 		newoff = (i < JAS_CAST(int, tagtab->numents)) ?
    434 		  tagtab->ents[i].off : prof->hdr.size;
    435 		reloff = newoff - curoff;
    436 		assert(reloff >= 0);
    437 		if (reloff > 0) {
    438 			if (jas_stream_pad(out, reloff, 0) != reloff)
    439 				goto error;
    440 			curoff += reloff;
    441 		}
    442 	}	
    443 	return 0;
    444 error:
    445 	/* XXX - need to free some resources here */
    446 	return -1;
    447 }
    448 
    449 static int jas_iccprof_writehdr(jas_stream_t *out, jas_icchdr_t *hdr)
    450 {
    451 	if (jas_iccputuint32(out, hdr->size) ||
    452 	  jas_iccputuint32(out, hdr->cmmtype) ||
    453 	  jas_iccputuint32(out, hdr->version) ||
    454 	  jas_iccputuint32(out, hdr->clas) ||
    455 	  jas_iccputuint32(out, hdr->colorspc) ||
    456 	  jas_iccputuint32(out, hdr->refcolorspc) ||
    457 	  jas_iccputtime(out, &hdr->ctime) ||
    458 	  jas_iccputuint32(out, hdr->magic) ||
    459 	  jas_iccputuint32(out, hdr->platform) ||
    460 	  jas_iccputuint32(out, hdr->flags) ||
    461 	  jas_iccputuint32(out, hdr->maker) ||
    462 	  jas_iccputuint32(out, hdr->model) ||
    463 	  jas_iccputuint64(out, hdr->attr) ||
    464 	  jas_iccputuint32(out, hdr->intent) ||
    465 	  jas_iccputxyz(out, &hdr->illum) ||
    466 	  jas_iccputuint32(out, hdr->creator) ||
    467 	  jas_stream_pad(out, 44, 0) != 44)
    468 		return -1;
    469 	return 0;
    470 }
    471 
    472 static int jas_iccprof_puttagtab(jas_stream_t *out, jas_icctagtab_t *tagtab)
    473 {
    474 	int i;
    475 	jas_icctagtabent_t *tagtabent;
    476 	if (jas_iccputuint32(out, tagtab->numents))
    477 		goto error;
    478 	for (i = 0; i < JAS_CAST(int, tagtab->numents); ++i) {
    479 		tagtabent = &tagtab->ents[i];
    480 		if (jas_iccputuint32(out, tagtabent->tag) ||
    481 		  jas_iccputuint32(out, tagtabent->off) ||
    482 		  jas_iccputuint32(out, tagtabent->len))
    483 			goto error;
    484 	}
    485 	return 0;
    486 error:
    487 	return -1;
    488 }
    489 
    490 static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr)
    491 {
    492 	if (jas_iccgetuint32(in, &hdr->size) ||
    493 	  jas_iccgetuint32(in, &hdr->cmmtype) ||
    494 	  jas_iccgetuint32(in, &hdr->version) ||
    495 	  jas_iccgetuint32(in, &hdr->clas) ||
    496 	  jas_iccgetuint32(in, &hdr->colorspc) ||
    497 	  jas_iccgetuint32(in, &hdr->refcolorspc) ||
    498 	  jas_iccgettime(in, &hdr->ctime) ||
    499 	  jas_iccgetuint32(in, &hdr->magic) ||
    500 	  jas_iccgetuint32(in, &hdr->platform) ||
    501 	  jas_iccgetuint32(in, &hdr->flags) ||
    502 	  jas_iccgetuint32(in, &hdr->maker) ||
    503 	  jas_iccgetuint32(in, &hdr->model) ||
    504 	  jas_iccgetuint64(in, &hdr->attr) ||
    505 	  jas_iccgetuint32(in, &hdr->intent) ||
    506 	  jas_iccgetxyz(in, &hdr->illum) ||
    507 	  jas_iccgetuint32(in, &hdr->creator) ||
    508 	  jas_stream_gobble(in, 44) != 44)
    509 		return -1;
    510 	return 0;
    511 }
    512 
    513 static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab)
    514 {
    515 	int i;
    516 	jas_icctagtabent_t *tagtabent;
    517 
    518 	if (tagtab->ents) {
    519 		jas_free(tagtab->ents);
    520 		tagtab->ents = 0;
    521 	}
    522 	if (jas_iccgetuint32(in, &tagtab->numents))
    523 		goto error;
    524 	if (!(tagtab->ents = jas_malloc(tagtab->numents *
    525 	  sizeof(jas_icctagtabent_t))))
    526 		goto error;
    527 	tagtabent = tagtab->ents;
    528 	for (i = 0; i < JAS_CAST(long, tagtab->numents); ++i) {
    529 		if (jas_iccgetuint32(in, &tagtabent->tag) ||
    530 		jas_iccgetuint32(in, &tagtabent->off) ||
    531 		jas_iccgetuint32(in, &tagtabent->len))
    532 			goto error;
    533 		++tagtabent;
    534 	}
    535 	return 0;
    536 error:
    537 	if (tagtab->ents) {
    538 		jas_free(tagtab->ents);
    539 		tagtab->ents = 0;
    540 	}
    541 	return -1;
    542 }
    543 
    544 jas_iccattrval_t *jas_iccprof_getattr(jas_iccprof_t *prof,
    545   jas_iccattrname_t name)
    546 {
    547 	int i;
    548 	jas_iccattrval_t *attrval;
    549 	if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0)
    550 		goto error;
    551 	if (!(attrval = jas_iccattrval_clone(prof->attrtab->attrs[i].val)))
    552 		goto error;
    553 	return attrval;
    554 error:
    555 	return 0;
    556 }
    557 
    558 int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name,
    559   jas_iccattrval_t *val)
    560 {
    561 	int i;
    562 	if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) {
    563 		if (val) {
    564 			if (jas_iccattrtab_replace(prof->attrtab, i, name, val))
    565 				goto error;
    566 		} else {
    567 			jas_iccattrtab_delete(prof->attrtab, i);
    568 		}
    569 	} else {
    570 		if (val) {
    571 			if (jas_iccattrtab_add(prof->attrtab, -1, name, val))
    572 				goto error;
    573 		} else {
    574 			/* NOP */
    575 		}
    576 	}
    577 	return 0;
    578 error:
    579 	return -1;
    580 }
    581 
    582 int jas_iccprof_gethdr(jas_iccprof_t *prof, jas_icchdr_t *hdr)
    583 {
    584 	*hdr = prof->hdr;
    585 	return 0;
    586 }
    587 
    588 int jas_iccprof_sethdr(jas_iccprof_t *prof, jas_icchdr_t *hdr)
    589 {
    590 	prof->hdr = *hdr;
    591 	return 0;
    592 }
    593 
    594 static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab)
    595 {
    596 	qsort(tagtab->ents, tagtab->numents, sizeof(jas_icctagtabent_t),
    597 	  jas_icctagtabent_cmp);
    598 }
    599 
    600 static int jas_icctagtabent_cmp(const void *src, const void *dst)
    601 {
    602 	jas_icctagtabent_t *srctagtabent = JAS_CAST(jas_icctagtabent_t *, src);
    603 	jas_icctagtabent_t *dsttagtabent = JAS_CAST(jas_icctagtabent_t *, dst);
    604 	if (srctagtabent->off > dsttagtabent->off) {
    605 		return 1;
    606 	} else if (srctagtabent->off < dsttagtabent->off) {
    607 		return -1;
    608 	}
    609 	return 0;
    610 }
    611 
    612 static jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t type)
    613 {
    614 	jas_iccattrvalinfo_t *info;
    615 	info = jas_iccattrvalinfos;
    616 	for (info = jas_iccattrvalinfos; info->type; ++info) {
    617 		if (info->type == type) {
    618 			return info;
    619 		}
    620 	}
    621 	return 0;
    622 }
    623 
    624 static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time)
    625 {
    626 	if (jas_iccgetuint16(in, &time->year) ||
    627 	  jas_iccgetuint16(in, &time->month) ||
    628 	  jas_iccgetuint16(in, &time->day) ||
    629 	  jas_iccgetuint16(in, &time->hour) ||
    630 	  jas_iccgetuint16(in, &time->min) ||
    631 	  jas_iccgetuint16(in, &time->sec)) {
    632 		return -1;
    633 	}
    634 	return 0;
    635 }
    636 
    637 static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz)
    638 {
    639 	if (jas_iccgetsint32(in, &xyz->x) ||
    640 	  jas_iccgetsint32(in, &xyz->y) ||
    641 	  jas_iccgetsint32(in, &xyz->z)) {
    642 		return -1;
    643 	}
    644 	return 0;
    645 }
    646 
    647 static int jas_iccputtime(jas_stream_t *out, jas_icctime_t *time)
    648 {
    649 	jas_iccputuint16(out, time->year);
    650 	jas_iccputuint16(out, time->month);
    651 	jas_iccputuint16(out, time->day);
    652 	jas_iccputuint16(out, time->hour);
    653 	jas_iccputuint16(out, time->min);
    654 	jas_iccputuint16(out, time->sec);
    655 	return 0;
    656 }
    657 
    658 static int jas_iccputxyz(jas_stream_t *out, jas_iccxyz_t *xyz)
    659 {
    660 	jas_iccputuint32(out, xyz->x);
    661 	jas_iccputuint32(out, xyz->y);
    662 	jas_iccputuint32(out, xyz->z);
    663 	return 0;
    664 }
    665 
    666 /******************************************************************************\
    667 * attribute table class
    668 \******************************************************************************/
    669 
    670 static jas_iccattrtab_t *jas_iccattrtab_create()
    671 {
    672 	jas_iccattrtab_t *tab;
    673 	tab = 0;
    674 	if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t))))
    675 		goto error;
    676 	tab->maxattrs = 0;
    677 	tab->numattrs = 0;
    678 	tab->attrs = 0;
    679 	if (jas_iccattrtab_resize(tab, 32))
    680 		goto error;
    681 	return tab;
    682 error:
    683 	if (tab)
    684 		jas_iccattrtab_destroy(tab);
    685 	return 0;
    686 }
    687 
    688 static jas_iccattrtab_t *jas_iccattrtab_copy(jas_iccattrtab_t *attrtab)
    689 {
    690 	jas_iccattrtab_t *newattrtab;
    691 	int i;
    692 	if (!(newattrtab = jas_iccattrtab_create()))
    693 		goto error;
    694 	for (i = 0; i < attrtab->numattrs; ++i) {
    695 		if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name,
    696 		  attrtab->attrs[i].val))
    697 			goto error;
    698 	}
    699 	return newattrtab;
    700 error:
    701 	return 0;
    702 }
    703 
    704 static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab)
    705 {
    706 	if (tab->attrs) {
    707 		while (tab->numattrs > 0) {
    708 			jas_iccattrtab_delete(tab, 0);
    709 		}
    710 		jas_free(tab->attrs);
    711 	}
    712 	jas_free(tab);
    713 }
    714 
    715 void jas_iccattrtab_dump(jas_iccattrtab_t *attrtab, FILE *out)
    716 {
    717 	int i;
    718 	jas_iccattr_t *attr;
    719 	jas_iccattrval_t *attrval;
    720 	jas_iccattrvalinfo_t *info;
    721 	char buf[16];
    722 	fprintf(out, "numattrs=%d\n", attrtab->numattrs);
    723 	fprintf(out, "---\n");
    724 	for (i = 0; i < attrtab->numattrs; ++i) {
    725 		attr = &attrtab->attrs[i];
    726 		attrval = attr->val;
    727 		info = jas_iccattrvalinfo_lookup(attrval->type);
    728 		if (!info) abort();
    729 		fprintf(out, "attrno=%d; attrname=\"%s\"(0x%08x); attrtype=\"%s\"(0x%08x)\n",
    730 		  i,
    731 		  jas_iccsigtostr(attr->name, &buf[0]),
    732 		  (int)attr->name,
    733 		  jas_iccsigtostr(attrval->type, &buf[8]),
    734 		  (int)attrval->type
    735 		  );
    736 		jas_iccattrval_dump(attrval, out);
    737 		fprintf(out, "---\n");
    738 	}
    739 }
    740 
    741 static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, int maxents)
    742 {
    743 	jas_iccattr_t *newattrs;
    744 	assert(maxents >= tab->numattrs);
    745 	newattrs = tab->attrs ? jas_realloc(tab->attrs, maxents *
    746 	  sizeof(jas_iccattr_t)) : jas_malloc(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 fprintf(stderr, "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 	  (int)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_malloc(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_malloc(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", (int)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 = 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_malloc(clutsize * sizeof(jas_iccuint8_t))) ||
   1295 	  !(lut8->intabsbuf = jas_malloc(lut8->numinchans *
   1296 	  lut8->numintabents * sizeof(jas_iccuint8_t))) ||
   1297 	  !(lut8->intabs = jas_malloc(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_malloc(lut8->numoutchans *
   1303 	  lut8->numouttabents * sizeof(jas_iccuint8_t))) ||
   1304 	  !(lut8->outtabs = jas_malloc(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_malloc(clutsize * sizeof(jas_iccuint16_t))) ||
   1464 	  !(lut16->intabsbuf = jas_malloc(lut16->numinchans *
   1465 	  lut16->numintabents * sizeof(jas_iccuint16_t))) ||
   1466 	  !(lut16->intabs = jas_malloc(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_malloc(lut16->numoutchans *
   1472 	  lut16->numouttabents * sizeof(jas_iccuint16_t))) ||
   1473 	  !(lut16->outtabs = jas_malloc(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 }