Home | History | Annotate | Download | only in libjasper
      1 /*
      2  * Copyright (c) 1999-2000 Image Power, Inc. and the University of
      3  *   British Columbia.
      4  * Copyright (c) 2001-2002 Michael David Adams.
      5  * All rights reserved.
      6  */
      7 
      8 /*
      9  * Modified by Andrey Kiselev <dron (at) remotesensing.org> to handle UUID
     10  * box properly.
     11  */
     12 
     13 /* __START_OF_JASPER_LICENSE__
     14  *
     15  * JasPer License Version 2.0
     16  *
     17  * Copyright (c) 2001-2006 Michael David Adams
     18  * Copyright (c) 1999-2000 Image Power, Inc.
     19  * Copyright (c) 1999-2000 The University of British Columbia
     20  *
     21  * All rights reserved.
     22  *
     23  * Permission is hereby granted, free of charge, to any person (the
     24  * "User") obtaining a copy of this software and associated documentation
     25  * files (the "Software"), to deal in the Software without restriction,
     26  * including without limitation the rights to use, copy, modify, merge,
     27  * publish, distribute, and/or sell copies of the Software, and to permit
     28  * persons to whom the Software is furnished to do so, subject to the
     29  * following conditions:
     30  *
     31  * 1.  The above copyright notices and this permission notice (which
     32  * includes the disclaimer below) shall be included in all copies or
     33  * substantial portions of the Software.
     34  *
     35  * 2.  The name of a copyright holder shall not be used to endorse or
     36  * promote products derived from the Software without specific prior
     37  * written permission.
     38  *
     39  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
     40  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
     41  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
     42  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
     43  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     44  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
     45  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
     46  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
     47  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     48  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     49  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
     50  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
     51  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
     52  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
     53  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
     54  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
     55  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
     56  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
     57  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
     58  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
     59  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
     60  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
     61  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
     62  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
     63  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
     64  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
     65  *
     66  * __END_OF_JASPER_LICENSE__
     67  */
     68 
     69 /*
     70  * JP2 Library
     71  *
     72  * $Id: jp2_cod.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
     73  */
     74 
     75 /******************************************************************************\
     76 * Includes.
     77 \******************************************************************************/
     78 
     79 #include <assert.h>
     80 #include <stdlib.h>
     81 
     82 #include "jasper/jas_stream.h"
     83 #include "jasper/jas_malloc.h"
     84 #include "jasper/jas_debug.h"
     85 
     86 #include "jp2_cod.h"
     87 
     88 /******************************************************************************\
     89 * Function prototypes.
     90 \******************************************************************************/
     91 
     92 #define	ONES(n)	((1 << (n)) - 1)
     93 
     94 jp2_boxinfo_t *jp2_boxinfolookup(int type);
     95 
     96 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val);
     97 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val);
     98 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val);
     99 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val);
    100 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val);
    101 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val);
    102 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val);
    103 static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val);
    104 
    105 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val);
    106 
    107 jp2_box_t *jp2_box_get(jas_stream_t *in);
    108 void jp2_box_dump(jp2_box_t *box, FILE *out);
    109 
    110 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in);
    111 static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out);
    112 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in);
    113 static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out);
    114 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in);
    115 static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out);
    116 static void jp2_bpcc_destroy(jp2_box_t *box);
    117 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in);
    118 static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out);
    119 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in);
    120 static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out);
    121 static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out);
    122 static void jp2_colr_destroy(jp2_box_t *box);
    123 static void jp2_cdef_destroy(jp2_box_t *box);
    124 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in);
    125 static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out);
    126 static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out);
    127 static void jp2_cmap_destroy(jp2_box_t *box);
    128 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in);
    129 static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out);
    130 static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out);
    131 static void jp2_pclr_destroy(jp2_box_t *box);
    132 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in);
    133 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out);
    134 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out);
    135 static void jp2_uuid_destroy(jp2_box_t *box);
    136 static int jp2_uuid_getdata(jp2_box_t *box, jas_stream_t *in);
    137 static int jp2_uuid_putdata(jp2_box_t *box, jas_stream_t *out);
    138 
    139 /******************************************************************************\
    140 * Local data.
    141 \******************************************************************************/
    142 
    143 jp2_boxinfo_t jp2_boxinfos[] = {
    144     {JP2_BOX_JP, "JP", 0,
    145       {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}},
    146     {JP2_BOX_FTYP, "FTYP", 0,
    147       {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}},
    148     {JP2_BOX_JP2H, "JP2H", JP2_BOX_SUPER,
    149       {0, 0, 0, 0, 0}},
    150     {JP2_BOX_IHDR, "IHDR", 0,
    151       {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}},
    152     {JP2_BOX_BPCC, "BPCC", 0,
    153       {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}},
    154     {JP2_BOX_COLR, "COLR", 0,
    155       {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}},
    156     {JP2_BOX_PCLR, "PCLR", 0,
    157       {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}},
    158     {JP2_BOX_CMAP, "CMAP", 0,
    159       {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}},
    160     {JP2_BOX_CDEF, "CDEF", 0,
    161       {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}},
    162     {JP2_BOX_RES, "RES", JP2_BOX_SUPER,
    163       {0, 0, 0, 0, 0}},
    164     {JP2_BOX_RESC, "RESC", 0,
    165       {0, 0, 0, 0, 0}},
    166     {JP2_BOX_RESD, "RESD", 0,
    167       {0, 0, 0, 0, 0}},
    168     {JP2_BOX_JP2C, "JP2C", JP2_BOX_NODATA,
    169       {0, 0, 0, 0, 0}},
    170     {JP2_BOX_JP2I, "JP2I", 0,
    171       {0, 0, 0, 0, 0}},
    172     {JP2_BOX_XML, "XML", 0,
    173       {0, 0, 0, 0, 0}},
    174     {JP2_BOX_UUID, "UUID", 0,
    175       {0, jp2_uuid_destroy, jp2_uuid_getdata, jp2_uuid_putdata, 0}},
    176     {JP2_BOX_UINF, "UINF", JP2_BOX_SUPER,
    177       {0, 0, 0, 0, 0}},
    178     {JP2_BOX_ULST, "ULST", 0,
    179       {0, 0, 0, 0, 0}},
    180     {JP2_BOX_URL, "URL", 0,
    181       {0, 0, 0, 0, 0}},
    182     {0, 0, 0, {0, 0, 0, 0, 0}},
    183 };
    184 
    185 jp2_boxinfo_t jp2_boxinfo_unk = {
    186     0, "Unknown", 0, {0, 0, 0, 0, 0}
    187 };
    188 
    189 /******************************************************************************\
    190 * Box constructor.
    191 \******************************************************************************/
    192 
    193 jp2_box_t *jp2_box_create(int type)
    194 {
    195     jp2_box_t *box;
    196     jp2_boxinfo_t *boxinfo;
    197 
    198     if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
    199         return 0;
    200     }
    201     memset(box, 0, sizeof(jp2_box_t));
    202     box->type = type;
    203     box->len = 0;
    204     if (!(boxinfo = jp2_boxinfolookup(type))) {
    205         return 0;
    206     }
    207     box->info = boxinfo;
    208     box->ops = &boxinfo->ops;
    209     return box;
    210 }
    211 
    212 /******************************************************************************\
    213 * Box destructor.
    214 \******************************************************************************/
    215 
    216 void jp2_box_destroy(jp2_box_t *box)
    217 {
    218     if (box->ops->destroy) {
    219         (*box->ops->destroy)(box);
    220     }
    221     jas_free(box);
    222 }
    223 
    224 static void jp2_bpcc_destroy(jp2_box_t *box)
    225 {
    226     jp2_bpcc_t *bpcc = &box->data.bpcc;
    227     if (bpcc->bpcs) {
    228         jas_free(bpcc->bpcs);
    229         bpcc->bpcs = 0;
    230     }
    231 }
    232 
    233 static void jp2_cdef_destroy(jp2_box_t *box)
    234 {
    235     jp2_cdef_t *cdef = &box->data.cdef;
    236     if (cdef->ents) {
    237         jas_free(cdef->ents);
    238         cdef->ents = 0;
    239     }
    240 }
    241 
    242 /******************************************************************************\
    243 * Box input.
    244 \******************************************************************************/
    245 
    246 jp2_box_t *jp2_box_get(jas_stream_t *in)
    247 {
    248     jp2_box_t *box;
    249     jp2_boxinfo_t *boxinfo;
    250     jas_stream_t *tmpstream;
    251     uint_fast32_t len;
    252     uint_fast64_t extlen;
    253     bool dataflag;
    254 
    255     box = 0;
    256     tmpstream = 0;
    257 
    258     if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
    259         goto error;
    260     }
    261     box->ops = &jp2_boxinfo_unk.ops;
    262     if (jp2_getuint32(in, &len) || jp2_getuint32(in, &box->type)) {
    263         goto error;
    264     }
    265     boxinfo = jp2_boxinfolookup(box->type);
    266     box->info = boxinfo;
    267     box->ops = &boxinfo->ops;
    268     box->len = len;
    269     if (box->len == 1) {
    270         if (jp2_getuint64(in, &extlen)) {
    271             goto error;
    272         }
    273         if (extlen > 0xffffffffUL) {
    274             jas_eprintf("warning: cannot handle large 64-bit box length\n");
    275             extlen = 0xffffffffUL;
    276         }
    277         box->len = extlen;
    278         box->datalen = extlen - JP2_BOX_HDRLEN(true);
    279     } else {
    280         box->datalen = box->len - JP2_BOX_HDRLEN(false);
    281     }
    282     if (box->len != 0 && box->len < 8) {
    283         goto error;
    284     }
    285 
    286     dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA));
    287 
    288     if (dataflag) {
    289         if (!(tmpstream = jas_stream_memopen(0, 0))) {
    290             goto error;
    291         }
    292         if (jas_stream_copy(tmpstream, in, box->datalen)) {
    293             jas_eprintf("cannot copy box data\n");
    294             goto error;
    295         }
    296         jas_stream_rewind(tmpstream);
    297 
    298         if (box->ops->getdata) {
    299             if ((*box->ops->getdata)(box, tmpstream)) {
    300                 jas_eprintf("cannot parse box data\n");
    301                 goto error;
    302             }
    303         }
    304         jas_stream_close(tmpstream);
    305     }
    306 
    307     if (jas_getdbglevel() >= 1) {
    308         jp2_box_dump(box, stderr);
    309     }
    310 
    311     return box;
    312     abort();
    313 
    314 error:
    315     if (box) {
    316         jp2_box_destroy(box);
    317     }
    318     if (tmpstream) {
    319         jas_stream_close(tmpstream);
    320     }
    321     return 0;
    322 }
    323 
    324 void jp2_box_dump(jp2_box_t *box, FILE *out)
    325 {
    326     jp2_boxinfo_t *boxinfo;
    327     boxinfo = jp2_boxinfolookup(box->type);
    328     assert(boxinfo);
    329 
    330     fprintf(out, "JP2 box: ");
    331     fprintf(out, "type=%c%s%c (0x%08x); length=%d\n", '"', boxinfo->name,
    332       '"', (unsigned)box->type, (int)box->len);
    333     if (box->ops->dumpdata) {
    334         (*box->ops->dumpdata)(box, out);
    335     }
    336 }
    337 
    338 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in)
    339 {
    340     jp2_jp_t *jp = &box->data.jp;
    341     if (jp2_getuint32(in, &jp->magic)) {
    342         return -1;
    343     }
    344     return 0;
    345 }
    346 
    347 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in)
    348 {
    349     jp2_ftyp_t *ftyp = &box->data.ftyp;
    350     unsigned int i;
    351     if (jp2_getuint32(in, &ftyp->majver) || jp2_getuint32(in, &ftyp->minver)) {
    352         return -1;
    353     }
    354     ftyp->numcompatcodes = (box->datalen - 8) / 4;
    355     if (ftyp->numcompatcodes > JP2_FTYP_MAXCOMPATCODES) {
    356         return -1;
    357     }
    358     for (i = 0; i < ftyp->numcompatcodes; ++i) {
    359         if (jp2_getuint32(in, &ftyp->compatcodes[i])) {
    360             return -1;
    361         }
    362     }
    363     return 0;
    364 }
    365 
    366 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in)
    367 {
    368     jp2_ihdr_t *ihdr = &box->data.ihdr;
    369     if (jp2_getuint32(in, &ihdr->height) || jp2_getuint32(in, &ihdr->width) ||
    370       jp2_getuint16(in, &ihdr->numcmpts) || jp2_getuint8(in, &ihdr->bpc) ||
    371       jp2_getuint8(in, &ihdr->comptype) || jp2_getuint8(in, &ihdr->csunk) ||
    372       jp2_getuint8(in, &ihdr->ipr)) {
    373         return -1;
    374     }
    375     return 0;
    376 }
    377 
    378 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in)
    379 {
    380     jp2_bpcc_t *bpcc = &box->data.bpcc;
    381     unsigned int i;
    382     bpcc->numcmpts = box->datalen;
    383     if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts, sizeof(uint_fast8_t)))) {
    384         return -1;
    385     }
    386     for (i = 0; i < bpcc->numcmpts; ++i) {
    387         if (jp2_getuint8(in, &bpcc->bpcs[i])) {
    388             return -1;
    389         }
    390     }
    391     return 0;
    392 }
    393 
    394 static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out)
    395 {
    396     jp2_colr_t *colr = &box->data.colr;
    397     fprintf(out, "method=%d; pri=%d; approx=%d\n", (int)colr->method, (int)colr->pri, (int)colr->approx);
    398     switch (colr->method) {
    399     case JP2_COLR_ENUM:
    400         fprintf(out, "csid=%d\n", (int)colr->csid);
    401         break;
    402     case JP2_COLR_ICC:
    403         jas_memdump(out, colr->iccp, colr->iccplen);
    404         break;
    405     }
    406 }
    407 
    408 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in)
    409 {
    410     jp2_colr_t *colr = &box->data.colr;
    411     colr->csid = 0;
    412     colr->iccp = 0;
    413     colr->iccplen = 0;
    414 
    415     if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) ||
    416       jp2_getuint8(in, &colr->approx)) {
    417         return -1;
    418     }
    419     switch (colr->method) {
    420     case JP2_COLR_ENUM:
    421         if (jp2_getuint32(in, &colr->csid)) {
    422             return -1;
    423         }
    424         break;
    425     case JP2_COLR_ICC:
    426         colr->iccplen = box->datalen - 3;
    427         if (!(colr->iccp = jas_alloc2(colr->iccplen, sizeof(uint_fast8_t)))) {
    428             return -1;
    429         }
    430         if (jas_stream_read(in, colr->iccp, colr->iccplen) != colr->iccplen) {
    431             return -1;
    432         }
    433         break;
    434     }
    435     return 0;
    436 }
    437 
    438 static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out)
    439 {
    440     jp2_cdef_t *cdef = &box->data.cdef;
    441     unsigned int i;
    442     for (i = 0; i < cdef->numchans; ++i) {
    443         fprintf(out, "channo=%d; type=%d; assoc=%d\n",
    444           (int)cdef->ents[i].channo, (int)cdef->ents[i].type, (int)cdef->ents[i].assoc);
    445     }
    446 }
    447 
    448 static void jp2_colr_destroy(jp2_box_t *box)
    449 {
    450     jp2_colr_t *colr = &box->data.colr;
    451     if (colr->iccp) {
    452         jas_free(colr->iccp);
    453     }
    454 }
    455 
    456 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in)
    457 {
    458     jp2_cdef_t *cdef = &box->data.cdef;
    459     jp2_cdefchan_t *chan;
    460     unsigned int channo;
    461     if (jp2_getuint16(in, &cdef->numchans)) {
    462         return -1;
    463     }
    464     if (!(cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t)))) {
    465         return -1;
    466     }
    467     for (channo = 0; channo < cdef->numchans; ++channo) {
    468         chan = &cdef->ents[channo];
    469         if (jp2_getuint16(in, &chan->channo) || jp2_getuint16(in, &chan->type) ||
    470           jp2_getuint16(in, &chan->assoc)) {
    471             return -1;
    472         }
    473     }
    474     return 0;
    475 }
    476 
    477 /******************************************************************************\
    478 * Box output.
    479 \******************************************************************************/
    480 
    481 int jp2_box_put(jp2_box_t *box, jas_stream_t *out)
    482 {
    483     jas_stream_t *tmpstream;
    484     bool extlen;
    485     bool dataflag;
    486 
    487     tmpstream = 0;
    488 
    489     dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA));
    490 
    491     if (dataflag) {
    492         tmpstream = jas_stream_memopen(0, 0);
    493         if (box->ops->putdata) {
    494             if ((*box->ops->putdata)(box, tmpstream)) {
    495                 goto error;
    496             }
    497         }
    498         box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false);
    499         jas_stream_rewind(tmpstream);
    500     }
    501     //extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0;
    502     if (jp2_putuint32(out, /*extlen ? 1 :*/ box->len)) {
    503         goto error;
    504     }
    505     if (jp2_putuint32(out, box->type)) {
    506         goto error;
    507     }
    508     /*if (extlen) {
    509         if (jp2_putuint64(out, box->len)) {
    510             goto error;
    511         }
    512     }*/
    513 
    514     if (dataflag) {
    515         if (jas_stream_copy(out, tmpstream, box->len - JP2_BOX_HDRLEN(false))) {
    516             goto error;
    517         }
    518         jas_stream_close(tmpstream);
    519     }
    520 
    521     return 0;
    522     abort();
    523 
    524 error:
    525 
    526     if (tmpstream) {
    527         jas_stream_close(tmpstream);
    528     }
    529     return -1;
    530 }
    531 
    532 static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out)
    533 {
    534     jp2_jp_t *jp = &box->data.jp;
    535     if (jp2_putuint32(out, jp->magic)) {
    536         return -1;
    537     }
    538     return 0;
    539 }
    540 
    541 static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out)
    542 {
    543     jp2_ftyp_t *ftyp = &box->data.ftyp;
    544     unsigned int i;
    545     if (jp2_putuint32(out, ftyp->majver) || jp2_putuint32(out, ftyp->minver)) {
    546         return -1;
    547     }
    548     for (i = 0; i < ftyp->numcompatcodes; ++i) {
    549         if (jp2_putuint32(out, ftyp->compatcodes[i])) {
    550             return -1;
    551         }
    552     }
    553     return 0;
    554 }
    555 
    556 static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out)
    557 {
    558     jp2_ihdr_t *ihdr = &box->data.ihdr;
    559     if (jp2_putuint32(out, ihdr->height) || jp2_putuint32(out, ihdr->width) ||
    560       jp2_putuint16(out, ihdr->numcmpts) || jp2_putuint8(out, ihdr->bpc) ||
    561       jp2_putuint8(out, ihdr->comptype) || jp2_putuint8(out, ihdr->csunk) ||
    562       jp2_putuint8(out, ihdr->ipr)) {
    563         return -1;
    564     }
    565     return 0;
    566 }
    567 
    568 static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out)
    569 {
    570     jp2_bpcc_t *bpcc = &box->data.bpcc;
    571     unsigned int i;
    572     for (i = 0; i < bpcc->numcmpts; ++i) {
    573         if (jp2_putuint8(out, bpcc->bpcs[i])) {
    574             return -1;
    575         }
    576     }
    577     return 0;
    578 }
    579 
    580 static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out)
    581 {
    582     jp2_colr_t *colr = &box->data.colr;
    583     if (jp2_putuint8(out, colr->method) || jp2_putuint8(out, colr->pri) ||
    584       jp2_putuint8(out, colr->approx)) {
    585         return -1;
    586     }
    587     switch (colr->method) {
    588     case JP2_COLR_ENUM:
    589         if (jp2_putuint32(out, colr->csid)) {
    590             return -1;
    591         }
    592         break;
    593     case JP2_COLR_ICC:
    594         if (jas_stream_write(out, colr->iccp,
    595           JAS_CAST(int, colr->iccplen)) != JAS_CAST(int, colr->iccplen))
    596             return -1;
    597         break;
    598     }
    599     return 0;
    600 }
    601 
    602 static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out)
    603 {
    604     jp2_cdef_t *cdef = &box->data.cdef;
    605     unsigned int i;
    606     jp2_cdefchan_t *ent;
    607 
    608     if (jp2_putuint16(out, cdef->numchans)) {
    609         return -1;
    610     }
    611 
    612     for (i = 0; i < cdef->numchans; ++i) {
    613         ent = &cdef->ents[i];
    614         if (jp2_putuint16(out, ent->channo) ||
    615           jp2_putuint16(out, ent->type) ||
    616           jp2_putuint16(out, ent->assoc)) {
    617             return -1;
    618         }
    619     }
    620     return 0;
    621 }
    622 
    623 /******************************************************************************\
    624 * Input operations for primitive types.
    625 \******************************************************************************/
    626 
    627 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val)
    628 {
    629     int c;
    630     if ((c = jas_stream_getc(in)) == EOF) {
    631         return -1;
    632     }
    633     if (val) {
    634         *val = c;
    635     }
    636     return 0;
    637 }
    638 
    639 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val)
    640 {
    641     uint_fast16_t v;
    642     int c;
    643     if ((c = jas_stream_getc(in)) == EOF) {
    644         return -1;
    645     }
    646     v = c;
    647     if ((c = jas_stream_getc(in)) == EOF) {
    648         return -1;
    649     }
    650     v = (v << 8) | c;
    651     if (val) {
    652         *val = v;
    653     }
    654     return 0;
    655 }
    656 
    657 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val)
    658 {
    659     uint_fast32_t v;
    660     int c;
    661     if ((c = jas_stream_getc(in)) == EOF) {
    662         return -1;
    663     }
    664     v = c;
    665     if ((c = jas_stream_getc(in)) == EOF) {
    666         return -1;
    667     }
    668     v = (v << 8) | c;
    669     if ((c = jas_stream_getc(in)) == EOF) {
    670         return -1;
    671     }
    672     v = (v << 8) | c;
    673     if ((c = jas_stream_getc(in)) == EOF) {
    674         return -1;
    675     }
    676     v = (v << 8) | c;
    677     if (val) {
    678         *val = v;
    679     }
    680     return 0;
    681 }
    682 
    683 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val)
    684 {
    685     uint_fast64_t tmpval;
    686     int i;
    687     int c;
    688 
    689     tmpval = 0;
    690     for (i = 0; i < 8; ++i) {
    691         tmpval <<= 8;
    692         if ((c = jas_stream_getc(in)) == EOF) {
    693             return -1;
    694         }
    695         tmpval |= (c & 0xff);
    696     }
    697     *val = tmpval;
    698 
    699     return 0;
    700 }
    701 
    702 /******************************************************************************\
    703 * Output operations for primitive types.
    704 \******************************************************************************/
    705 
    706 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val)
    707 {
    708     if (jas_stream_putc(out, val & 0xff) == EOF) {
    709         return -1;
    710     }
    711     return 0;
    712 }
    713 
    714 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val)
    715 {
    716     if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
    717       jas_stream_putc(out, val & 0xff) == EOF) {
    718         return -1;
    719     }
    720     return 0;
    721 }
    722 
    723 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val)
    724 {
    725     if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF ||
    726       jas_stream_putc(out, (val >> 16) & 0xff) == EOF ||
    727       jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
    728       jas_stream_putc(out, val & 0xff) == EOF) {
    729         return -1;
    730     }
    731     return 0;
    732 }
    733 
    734 static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val)
    735 {
    736     if (jp2_putuint32(out, (val >> 32) & 0xffffffffUL) ||
    737       jp2_putuint32(out, val & 0xffffffffUL)) {
    738         return -1;
    739     }
    740     return 0;
    741 }
    742 
    743 /******************************************************************************\
    744 * Miscellaneous code.
    745 \******************************************************************************/
    746 
    747 jp2_boxinfo_t *jp2_boxinfolookup(int type)
    748 {
    749     jp2_boxinfo_t *boxinfo;
    750     for (boxinfo = jp2_boxinfos; boxinfo->name; ++boxinfo) {
    751         if (boxinfo->type == type) {
    752             return boxinfo;
    753         }
    754     }
    755     return &jp2_boxinfo_unk;
    756 }
    757 
    758 
    759 
    760 
    761 
    762 static void jp2_cmap_destroy(jp2_box_t *box)
    763 {
    764     jp2_cmap_t *cmap = &box->data.cmap;
    765     if (cmap->ents) {
    766         jas_free(cmap->ents);
    767     }
    768 }
    769 
    770 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in)
    771 {
    772     jp2_cmap_t *cmap = &box->data.cmap;
    773     jp2_cmapent_t *ent;
    774     unsigned int i;
    775 
    776     cmap->numchans = (box->datalen) / 4;
    777     if (!(cmap->ents = jas_alloc2(cmap->numchans, sizeof(jp2_cmapent_t)))) {
    778         return -1;
    779     }
    780     for (i = 0; i < cmap->numchans; ++i) {
    781         ent = &cmap->ents[i];
    782         if (jp2_getuint16(in, &ent->cmptno) ||
    783           jp2_getuint8(in, &ent->map) ||
    784           jp2_getuint8(in, &ent->pcol)) {
    785             return -1;
    786         }
    787     }
    788 
    789     return 0;
    790 }
    791 
    792 static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out)
    793 {
    794     /* Eliminate compiler warning about unused variables. */
    795     box = 0;
    796     out = 0;
    797 
    798     return -1;
    799 }
    800 
    801 static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out)
    802 {
    803     jp2_cmap_t *cmap = &box->data.cmap;
    804     unsigned int i;
    805     jp2_cmapent_t *ent;
    806     fprintf(out, "numchans = %d\n", (int) cmap->numchans);
    807     for (i = 0; i < cmap->numchans; ++i) {
    808         ent = &cmap->ents[i];
    809         fprintf(out, "cmptno=%d; map=%d; pcol=%d\n",
    810           (int) ent->cmptno, (int) ent->map, (int) ent->pcol);
    811     }
    812 }
    813 
    814 static void jp2_pclr_destroy(jp2_box_t *box)
    815 {
    816     jp2_pclr_t *pclr = &box->data.pclr;
    817     if (pclr->lutdata) {
    818         jas_free(pclr->lutdata);
    819     }
    820     if (pclr->bpc)
    821         jas_free(pclr->bpc);
    822 }
    823 
    824 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in)
    825 {
    826     jp2_pclr_t *pclr = &box->data.pclr;
    827     int lutsize;
    828     unsigned int i;
    829     unsigned int j;
    830     int_fast32_t x;
    831 
    832     pclr->lutdata = 0;
    833 
    834     if (jp2_getuint16(in, &pclr->numlutents) ||
    835       jp2_getuint8(in, &pclr->numchans)) {
    836         return -1;
    837     }
    838     lutsize = pclr->numlutents * pclr->numchans;
    839     if (!(pclr->lutdata = jas_alloc2(lutsize, sizeof(int_fast32_t)))) {
    840         return -1;
    841     }
    842     if (!(pclr->bpc = jas_alloc2(pclr->numchans, sizeof(uint_fast8_t)))) {
    843         return -1;
    844     }
    845     for (i = 0; i < pclr->numchans; ++i) {
    846         if (jp2_getuint8(in, &pclr->bpc[i])) {
    847             return -1;
    848         }
    849     }
    850     for (i = 0; i < pclr->numlutents; ++i) {
    851         for (j = 0; j < pclr->numchans; ++j) {
    852             if (jp2_getint(in, (pclr->bpc[j] & 0x80) != 0,
    853               (pclr->bpc[j] & 0x7f) + 1, &x)) {
    854                 return -1;
    855             }
    856             pclr->lutdata[i * pclr->numchans + j] = x;
    857         }
    858     }
    859     return 0;
    860 }
    861 
    862 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out)
    863 {
    864 #if 0
    865     jp2_pclr_t *pclr = &box->data.pclr;
    866 #endif
    867 /* Eliminate warning about unused variable. */
    868 box = 0;
    869 out = 0;
    870     return -1;
    871 }
    872 
    873 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out)
    874 {
    875     jp2_pclr_t *pclr = &box->data.pclr;
    876     unsigned int i;
    877     int j;
    878     fprintf(out, "numents=%d; numchans=%d\n", (int) pclr->numlutents,
    879       (int) pclr->numchans);
    880     for (i = 0; i < pclr->numlutents; ++i) {
    881         for (j = 0; j < pclr->numchans; ++j) {
    882             fprintf(out, "LUT[%d][%d]=%d\n", i, j, (int)pclr->lutdata[i * pclr->numchans + j]);
    883         }
    884     }
    885 }
    886 
    887 static void jp2_uuid_destroy(jp2_box_t *box)
    888 {
    889     jp2_uuid_t *uuid = &box->data.uuid;
    890     if (uuid->data)
    891     {
    892         jas_free(uuid->data);
    893         uuid->data = NULL;
    894     }
    895 }
    896 
    897 static int jp2_uuid_getdata(jp2_box_t *box, jas_stream_t *in)
    898 {
    899     jp2_uuid_t *uuid = &box->data.uuid;
    900     int i;
    901 
    902     for (i = 0; i < 16; i++)
    903     {
    904         if (jp2_getuint8(in, &uuid->uuid[i]))
    905         return -1;
    906     }
    907 
    908     uuid->datalen = box->datalen - 16;
    909     uuid->data = jas_malloc(uuid->datalen * sizeof(uint_fast8_t));
    910     for (i = 0; i < uuid->datalen; i++)
    911     {
    912         if (jp2_getuint8(in, &uuid->data[i]))
    913         return -1;
    914     }
    915     return 0;
    916 }
    917 
    918 static int jp2_uuid_putdata(jp2_box_t *box, jas_stream_t *out)
    919 {
    920     jp2_uuid_t *uuid = &box->data.uuid;
    921     int i;
    922 
    923     for (i = 0; i < 16; i++)
    924     {
    925         if (jp2_putuint8(out, uuid->uuid[i]))
    926         return -1;
    927     }
    928 
    929     for (i = 0; i < uuid->datalen; i++)
    930     {
    931         if (jp2_putuint8(out, uuid->data[i]))
    932         return -1;
    933     }
    934     return 0;
    935 }
    936 
    937 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val)
    938 {
    939     int c;
    940     int i;
    941     uint_fast32_t v;
    942     int m;
    943 
    944     m = (n + 7) / 8;
    945 
    946     v = 0;
    947     for (i = 0; i < m; ++i) {
    948         if ((c = jas_stream_getc(in)) == EOF) {
    949             return -1;
    950         }
    951         v = (v << 8) | c;
    952     }
    953     v &= ONES(n);
    954     if (s) {
    955         int sb;
    956         sb = v & (1 << (8 * m - 1));
    957         *val = ((~v) + 1) & ONES(8 * m);
    958         if (sb) {
    959             *val = -*val;
    960         }
    961     } else {
    962         *val = v;
    963     }
    964 
    965     return 0;
    966 }
    967 
    968 jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo)
    969 {
    970     unsigned int i;
    971     jp2_cdefchan_t *cdefent;
    972     for (i = 0; i < cdef->numchans; ++i) {
    973         cdefent = &cdef->ents[i];
    974         if (cdefent->channo == JAS_CAST(unsigned int, channo)) {
    975             return cdefent;
    976         }
    977     }
    978     return 0;
    979 }
    980