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