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 /* __START_OF_JASPER_LICENSE__
      9  *
     10  * JasPer License Version 2.0
     11  *
     12  * Copyright (c) 2001-2006 Michael David Adams
     13  * Copyright (c) 1999-2000 Image Power, Inc.
     14  * Copyright (c) 1999-2000 The University of British Columbia
     15  *
     16  * All rights reserved.
     17  *
     18  * Permission is hereby granted, free of charge, to any person (the
     19  * "User") obtaining a copy of this software and associated documentation
     20  * files (the "Software"), to deal in the Software without restriction,
     21  * including without limitation the rights to use, copy, modify, merge,
     22  * publish, distribute, and/or sell copies of the Software, and to permit
     23  * persons to whom the Software is furnished to do so, subject to the
     24  * following conditions:
     25  *
     26  * 1.  The above copyright notices and this permission notice (which
     27  * includes the disclaimer below) shall be included in all copies or
     28  * substantial portions of the Software.
     29  *
     30  * 2.  The name of a copyright holder shall not be used to endorse or
     31  * promote products derived from the Software without specific prior
     32  * written permission.
     33  *
     34  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
     35  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
     36  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
     37  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
     38  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     39  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
     40  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
     41  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
     42  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     43  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     44  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
     45  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
     46  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
     47  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
     48  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
     49  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
     50  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
     51  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
     52  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
     53  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
     54  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
     55  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
     56  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
     57  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
     58  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
     59  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
     60  *
     61  * __END_OF_JASPER_LICENSE__
     62  */
     63 
     64 /*
     65  * JPEG-2000 Code Stream Library
     66  *
     67  * $Id: jpc_cs.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
     68  */
     69 
     70 /******************************************************************************\
     71 * Includes.
     72 \******************************************************************************/
     73 
     74 #include <stdlib.h>
     75 #include <assert.h>
     76 #include <ctype.h>
     77 
     78 #include "jasper/jas_malloc.h"
     79 #include "jasper/jas_debug.h"
     80 
     81 #include "jpc_cs.h"
     82 
     83 /******************************************************************************\
     84 * Types.
     85 \******************************************************************************/
     86 
     87 /* Marker segment table entry. */
     88 typedef struct {
     89     int id;
     90     char *name;
     91     jpc_msops_t ops;
     92 } jpc_mstabent_t;
     93 
     94 /******************************************************************************\
     95 * Local prototypes.
     96 \******************************************************************************/
     97 
     98 static jpc_mstabent_t *jpc_mstab_lookup(int id);
     99 
    100 static int jpc_poc_dumpparms(jpc_ms_t *ms, FILE *out);
    101 static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    102 static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    103 static void jpc_poc_destroyparms(jpc_ms_t *ms);
    104 
    105 static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    106 static int jpc_sot_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    107 static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    108 static int jpc_cod_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    109 static int jpc_coc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    110 static int jpc_qcd_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    111 static int jpc_qcc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    112 static int jpc_rgn_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    113 static int jpc_sop_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    114 static int jpc_ppm_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    115 static int jpc_ppt_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    116 static int jpc_crg_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    117 static int jpc_com_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in);
    118 
    119 static int jpc_sot_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    120 static int jpc_siz_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    121 static int jpc_cod_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    122 static int jpc_coc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    123 static int jpc_qcd_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    124 static int jpc_qcc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    125 static int jpc_rgn_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    126 static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    127 static int jpc_sop_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    128 static int jpc_ppm_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    129 static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    130 static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    131 static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out);
    132 
    133 static int jpc_sot_dumpparms(jpc_ms_t *ms, FILE *out);
    134 static int jpc_siz_dumpparms(jpc_ms_t *ms, FILE *out);
    135 static int jpc_cod_dumpparms(jpc_ms_t *ms, FILE *out);
    136 static int jpc_coc_dumpparms(jpc_ms_t *ms, FILE *out);
    137 static int jpc_qcd_dumpparms(jpc_ms_t *ms, FILE *out);
    138 static int jpc_qcc_dumpparms(jpc_ms_t *ms, FILE *out);
    139 static int jpc_rgn_dumpparms(jpc_ms_t *ms, FILE *out);
    140 static int jpc_unk_dumpparms(jpc_ms_t *ms, FILE *out);
    141 static int jpc_sop_dumpparms(jpc_ms_t *ms, FILE *out);
    142 static int jpc_ppm_dumpparms(jpc_ms_t *ms, FILE *out);
    143 static int jpc_ppt_dumpparms(jpc_ms_t *ms, FILE *out);
    144 static int jpc_crg_dumpparms(jpc_ms_t *ms, FILE *out);
    145 static int jpc_com_dumpparms(jpc_ms_t *ms, FILE *out);
    146 
    147 static void jpc_siz_destroyparms(jpc_ms_t *ms);
    148 static void jpc_qcd_destroyparms(jpc_ms_t *ms);
    149 static void jpc_qcc_destroyparms(jpc_ms_t *ms);
    150 static void jpc_cod_destroyparms(jpc_ms_t *ms);
    151 static void jpc_coc_destroyparms(jpc_ms_t *ms);
    152 static void jpc_unk_destroyparms(jpc_ms_t *ms);
    153 static void jpc_ppm_destroyparms(jpc_ms_t *ms);
    154 static void jpc_ppt_destroyparms(jpc_ms_t *ms);
    155 static void jpc_crg_destroyparms(jpc_ms_t *ms);
    156 static void jpc_com_destroyparms(jpc_ms_t *ms);
    157 
    158 static void jpc_qcx_destroycompparms(jpc_qcxcp_t *compparms);
    159 static int jpc_qcx_getcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate,
    160   jas_stream_t *in, uint_fast16_t len);
    161 static int jpc_qcx_putcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate,
    162   jas_stream_t *out);
    163 static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms);
    164 static int jpc_cox_getcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
    165   jas_stream_t *in, int prtflag, jpc_coxcp_t *compparms);
    166 static int jpc_cox_putcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
    167   jas_stream_t *out, int prtflag, jpc_coxcp_t *compparms);
    168 
    169 /******************************************************************************\
    170 * Global data.
    171 \******************************************************************************/
    172 
    173 static jpc_mstabent_t jpc_mstab[] = {
    174     {JPC_MS_SOC, "SOC", {0, 0, 0, 0}},
    175     {JPC_MS_SOT, "SOT", {0, jpc_sot_getparms, jpc_sot_putparms,
    176       jpc_sot_dumpparms}},
    177     {JPC_MS_SOD, "SOD", {0, 0, 0, 0}},
    178     {JPC_MS_EOC, "EOC", {0, 0, 0, 0}},
    179     {JPC_MS_SIZ, "SIZ", {jpc_siz_destroyparms, jpc_siz_getparms,
    180       jpc_siz_putparms, jpc_siz_dumpparms}},
    181     {JPC_MS_COD, "COD", {jpc_cod_destroyparms, jpc_cod_getparms,
    182       jpc_cod_putparms, jpc_cod_dumpparms}},
    183     {JPC_MS_COC, "COC", {jpc_coc_destroyparms, jpc_coc_getparms,
    184       jpc_coc_putparms, jpc_coc_dumpparms}},
    185     {JPC_MS_RGN, "RGN", {0, jpc_rgn_getparms, jpc_rgn_putparms,
    186       jpc_rgn_dumpparms}},
    187     {JPC_MS_QCD, "QCD", {jpc_qcd_destroyparms, jpc_qcd_getparms,
    188       jpc_qcd_putparms, jpc_qcd_dumpparms}},
    189     {JPC_MS_QCC, "QCC", {jpc_qcc_destroyparms, jpc_qcc_getparms,
    190       jpc_qcc_putparms, jpc_qcc_dumpparms}},
    191     {JPC_MS_POC, "POC", {jpc_poc_destroyparms, jpc_poc_getparms,
    192       jpc_poc_putparms, jpc_poc_dumpparms}},
    193     {JPC_MS_TLM, "TLM", {0, jpc_unk_getparms, jpc_unk_putparms, 0}},
    194     {JPC_MS_PLM, "PLM", {0, jpc_unk_getparms, jpc_unk_putparms, 0}},
    195     {JPC_MS_PPM, "PPM", {jpc_ppm_destroyparms, jpc_ppm_getparms,
    196       jpc_ppm_putparms, jpc_ppm_dumpparms}},
    197     {JPC_MS_PPT, "PPT", {jpc_ppt_destroyparms, jpc_ppt_getparms,
    198       jpc_ppt_putparms, jpc_ppt_dumpparms}},
    199     {JPC_MS_SOP, "SOP", {0, jpc_sop_getparms, jpc_sop_putparms,
    200       jpc_sop_dumpparms}},
    201     {JPC_MS_EPH, "EPH", {0, 0, 0, 0}},
    202     {JPC_MS_CRG, "CRG", {0, jpc_crg_getparms, jpc_crg_putparms,
    203       jpc_crg_dumpparms}},
    204     {JPC_MS_COM, "COM", {jpc_com_destroyparms, jpc_com_getparms,
    205       jpc_com_putparms, jpc_com_dumpparms}},
    206     {-1, "UNKNOWN",  {jpc_unk_destroyparms, jpc_unk_getparms,
    207       jpc_unk_putparms, jpc_unk_dumpparms}}
    208 };
    209 
    210 /******************************************************************************\
    211 * Code stream manipulation functions.
    212 \******************************************************************************/
    213 
    214 /* Create a code stream state object. */
    215 jpc_cstate_t *jpc_cstate_create()
    216 {
    217     jpc_cstate_t *cstate;
    218     if (!(cstate = jas_malloc(sizeof(jpc_cstate_t)))) {
    219         return 0;
    220     }
    221     cstate->numcomps = 0;
    222     return cstate;
    223 }
    224 
    225 /* Destroy a code stream state object. */
    226 void jpc_cstate_destroy(jpc_cstate_t *cstate)
    227 {
    228     jas_free(cstate);
    229 }
    230 
    231 /* Read a marker segment from a stream. */
    232 jpc_ms_t *jpc_getms(jas_stream_t *in, jpc_cstate_t *cstate)
    233 {
    234     jpc_ms_t *ms;
    235     jpc_mstabent_t *mstabent;
    236     jas_stream_t *tmpstream;
    237 
    238     if (!(ms = jpc_ms_create(0))) {
    239         return 0;
    240     }
    241 
    242     /* Get the marker type. */
    243     if (jpc_getuint16(in, &ms->id) || ms->id < JPC_MS_MIN /*|| ms->id > JPC_MS_MAX*/) {
    244         jpc_ms_destroy(ms);
    245         return 0;
    246     }
    247 
    248     mstabent = jpc_mstab_lookup(ms->id);
    249     ms->ops = &mstabent->ops;
    250 
    251     /* Get the marker segment length and parameters if present. */
    252     /* Note: It is tacitly assumed that a marker segment cannot have
    253       parameters unless it has a length field.  That is, there cannot
    254       be a parameters field without a length field and vice versa. */
    255     if (JPC_MS_HASPARMS(ms->id)) {
    256         /* Get the length of the marker segment. */
    257         if (jpc_getuint16(in, &ms->len) || ms->len < 3) {
    258             jpc_ms_destroy(ms);
    259             return 0;
    260         }
    261         /* Calculate the length of the marker segment parameters. */
    262         ms->len -= 2;
    263         /* Create and prepare a temporary memory stream from which to
    264           read the marker segment parameters. */
    265         /* Note: This approach provides a simple way of ensuring that
    266           we never read beyond the end of the marker segment (even if
    267           the marker segment length is errantly set too small). */
    268         if (!(tmpstream = jas_stream_memopen(0, 0))) {
    269             jpc_ms_destroy(ms);
    270             return 0;
    271         }
    272         if (jas_stream_copy(tmpstream, in, ms->len) ||
    273           jas_stream_seek(tmpstream, 0, SEEK_SET) < 0) {
    274             jas_stream_close(tmpstream);
    275             jpc_ms_destroy(ms);
    276             return 0;
    277         }
    278         /* Get the marker segment parameters. */
    279         if ((*ms->ops->getparms)(ms, cstate, tmpstream)) {
    280             ms->ops = 0;
    281             jpc_ms_destroy(ms);
    282             jas_stream_close(tmpstream);
    283             return 0;
    284         }
    285 
    286         if (jas_getdbglevel() > 0) {
    287             jpc_ms_dump(ms, stderr);
    288         }
    289 
    290         if (JAS_CAST(ulong, jas_stream_tell(tmpstream)) != ms->len) {
    291             jas_eprintf("warning: trailing garbage in marker segment (%ld bytes)\n",
    292               ms->len - jas_stream_tell(tmpstream));
    293         }
    294 
    295         /* Close the temporary stream. */
    296         jas_stream_close(tmpstream);
    297 
    298     } else {
    299         /* There are no marker segment parameters. */
    300         ms->len = 0;
    301 
    302         if (jas_getdbglevel() > 0) {
    303             jpc_ms_dump(ms, stderr);
    304         }
    305     }
    306 
    307     /* Update the code stream state information based on the type of
    308       marker segment read. */
    309     /* Note: This is a bit of a hack, but I'm not going to define another
    310       type of virtual function for this one special case. */
    311     if (ms->id == JPC_MS_SIZ) {
    312         cstate->numcomps = ms->parms.siz.numcomps;
    313     }
    314 
    315     return ms;
    316 }
    317 
    318 /* Write a marker segment to a stream. */
    319 int jpc_putms(jas_stream_t *out, jpc_cstate_t *cstate, jpc_ms_t *ms)
    320 {
    321     jas_stream_t *tmpstream;
    322     int len;
    323 
    324     /* Output the marker segment type. */
    325     if (jpc_putuint16(out, ms->id)) {
    326         return -1;
    327     }
    328 
    329     /* Output the marker segment length and parameters if necessary. */
    330     if (ms->ops->putparms) {
    331         /* Create a temporary stream in which to buffer the
    332           parameter data. */
    333         if (!(tmpstream = jas_stream_memopen(0, 0))) {
    334             return -1;
    335         }
    336         if ((*ms->ops->putparms)(ms, cstate, tmpstream)) {
    337             jas_stream_close(tmpstream);
    338             return -1;
    339         }
    340         /* Get the number of bytes of parameter data written. */
    341         if ((len = jas_stream_tell(tmpstream)) < 0) {
    342             jas_stream_close(tmpstream);
    343             return -1;
    344         }
    345         ms->len = len;
    346         /* Write the marker segment length and parameter data to
    347           the output stream. */
    348         if (jas_stream_seek(tmpstream, 0, SEEK_SET) < 0 ||
    349           jpc_putuint16(out, ms->len + 2) ||
    350           jas_stream_copy(out, tmpstream, ms->len) < 0) {
    351             jas_stream_close(tmpstream);
    352             return -1;
    353         }
    354         /* Close the temporary stream. */
    355         jas_stream_close(tmpstream);
    356     }
    357 
    358     /* This is a bit of a hack, but I'm not going to define another
    359       type of virtual function for this one special case. */
    360     if (ms->id == JPC_MS_SIZ) {
    361         cstate->numcomps = ms->parms.siz.numcomps;
    362     }
    363 
    364     if (jas_getdbglevel() > 0) {
    365         jpc_ms_dump(ms, stderr);
    366     }
    367 
    368     return 0;
    369 }
    370 
    371 /******************************************************************************\
    372 * Marker segment operations.
    373 \******************************************************************************/
    374 
    375 /* Create a marker segment of the specified type. */
    376 jpc_ms_t *jpc_ms_create(int type)
    377 {
    378     jpc_ms_t *ms;
    379     jpc_mstabent_t *mstabent;
    380 
    381     if (!(ms = jas_malloc(sizeof(jpc_ms_t)))) {
    382         return 0;
    383     }
    384     ms->id = type;
    385     ms->len = 0;
    386     mstabent = jpc_mstab_lookup(ms->id);
    387     ms->ops = &mstabent->ops;
    388     memset(&ms->parms, 0, sizeof(jpc_msparms_t));
    389     return ms;
    390 }
    391 
    392 /* Destroy a marker segment. */
    393 void jpc_ms_destroy(jpc_ms_t *ms)
    394 {
    395     if (ms->ops && ms->ops->destroyparms) {
    396         (*ms->ops->destroyparms)(ms);
    397     }
    398     jas_free(ms);
    399 }
    400 
    401 /* Dump a marker segment to a stream for debugging. */
    402 void jpc_ms_dump(jpc_ms_t *ms, FILE *out)
    403 {
    404     jpc_mstabent_t *mstabent;
    405     mstabent = jpc_mstab_lookup(ms->id);
    406     fprintf(out, "type = 0x%04x (%s);", (unsigned)ms->id, mstabent->name);
    407     if (JPC_MS_HASPARMS(ms->id)) {
    408         fprintf(out, " len = %d;", (int)(ms->len + 2));
    409         if (ms->ops->dumpparms) {
    410             (*ms->ops->dumpparms)(ms, out);
    411         } else {
    412             fprintf(out, "\n");
    413         }
    414     } else {
    415         fprintf(out, "\n");
    416     }
    417 }
    418 
    419 /******************************************************************************\
    420 * SOT marker segment operations.
    421 \******************************************************************************/
    422 
    423 static int jpc_sot_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
    424 {
    425     jpc_sot_t *sot = &ms->parms.sot;
    426 
    427     /* Eliminate compiler warning about unused variables. */
    428     cstate = 0;
    429 
    430     if (jpc_getuint16(in, &sot->tileno) ||
    431       jpc_getuint32(in, &sot->len) ||
    432       jpc_getuint8(in, &sot->partno) ||
    433       jpc_getuint8(in, &sot->numparts)) {
    434         return -1;
    435     }
    436     if (jas_stream_eof(in)) {
    437         return -1;
    438     }
    439     return 0;
    440 }
    441 
    442 static int jpc_sot_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    443 {
    444     jpc_sot_t *sot = &ms->parms.sot;
    445 
    446     /* Eliminate compiler warning about unused variables. */
    447     cstate = 0;
    448 
    449     if (jpc_putuint16(out, sot->tileno) ||
    450       jpc_putuint32(out, sot->len) ||
    451       jpc_putuint8(out, sot->partno) ||
    452       jpc_putuint8(out, sot->numparts)) {
    453         return -1;
    454     }
    455     return 0;
    456 }
    457 
    458 static int jpc_sot_dumpparms(jpc_ms_t *ms, FILE *out)
    459 {
    460     jpc_sot_t *sot = &ms->parms.sot;
    461     fprintf(out, "tileno = %d; len = %d; partno = %d; numparts = %d\n",
    462       (int)sot->tileno, (int)sot->len, sot->partno, sot->numparts);
    463     return 0;
    464 }
    465 
    466 /******************************************************************************\
    467 * SIZ marker segment operations.
    468 \******************************************************************************/
    469 
    470 static void jpc_siz_destroyparms(jpc_ms_t *ms)
    471 {
    472     jpc_siz_t *siz = &ms->parms.siz;
    473     if (siz->comps) {
    474         jas_free(siz->comps);
    475     }
    476 }
    477 
    478 static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
    479   jas_stream_t *in)
    480 {
    481     jpc_siz_t *siz = &ms->parms.siz;
    482     unsigned int i;
    483     uint_fast8_t tmp;
    484 
    485     /* Eliminate compiler warning about unused variables. */
    486     cstate = 0;
    487 
    488     if (jpc_getuint16(in, &siz->caps) ||
    489       jpc_getuint32(in, &siz->width) ||
    490       jpc_getuint32(in, &siz->height) ||
    491       jpc_getuint32(in, &siz->xoff) ||
    492       jpc_getuint32(in, &siz->yoff) ||
    493       jpc_getuint32(in, &siz->tilewidth) ||
    494       jpc_getuint32(in, &siz->tileheight) ||
    495       jpc_getuint32(in, &siz->tilexoff) ||
    496       jpc_getuint32(in, &siz->tileyoff) ||
    497       jpc_getuint16(in, &siz->numcomps)) {
    498         return -1;
    499     }
    500     if (!siz->width || !siz->height || !siz->tilewidth ||
    501       !siz->tileheight || !siz->numcomps) {
    502         return -1;
    503     }
    504     if (!(siz->comps = jas_alloc2(siz->numcomps, sizeof(jpc_sizcomp_t)))) {
    505         return -1;
    506     }
    507     for (i = 0; i < siz->numcomps; ++i) {
    508         if (jpc_getuint8(in, &tmp) ||
    509           jpc_getuint8(in, &siz->comps[i].hsamp) ||
    510           jpc_getuint8(in, &siz->comps[i].vsamp)) {
    511             jas_free(siz->comps);
    512             return -1;
    513         }
    514         siz->comps[i].sgnd = (tmp >> 7) & 1;
    515         siz->comps[i].prec = (tmp & 0x7f) + 1;
    516     }
    517     if (jas_stream_eof(in)) {
    518         jas_free(siz->comps);
    519         return -1;
    520     }
    521     return 0;
    522 }
    523 
    524 static int jpc_siz_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    525 {
    526     jpc_siz_t *siz = &ms->parms.siz;
    527     unsigned int i;
    528 
    529     /* Eliminate compiler warning about unused variables. */
    530     cstate = 0;
    531 
    532     assert(siz->width && siz->height && siz->tilewidth &&
    533       siz->tileheight && siz->numcomps);
    534     if (jpc_putuint16(out, siz->caps) ||
    535       jpc_putuint32(out, siz->width) ||
    536       jpc_putuint32(out, siz->height) ||
    537       jpc_putuint32(out, siz->xoff) ||
    538       jpc_putuint32(out, siz->yoff) ||
    539       jpc_putuint32(out, siz->tilewidth) ||
    540       jpc_putuint32(out, siz->tileheight) ||
    541       jpc_putuint32(out, siz->tilexoff) ||
    542       jpc_putuint32(out, siz->tileyoff) ||
    543       jpc_putuint16(out, siz->numcomps)) {
    544         return -1;
    545     }
    546     for (i = 0; i < siz->numcomps; ++i) {
    547         if (jpc_putuint8(out, ((siz->comps[i].sgnd & 1) << 7) |
    548           ((siz->comps[i].prec - 1) & 0x7f)) ||
    549           jpc_putuint8(out, siz->comps[i].hsamp) ||
    550           jpc_putuint8(out, siz->comps[i].vsamp)) {
    551             return -1;
    552         }
    553     }
    554     return 0;
    555 }
    556 
    557 static int jpc_siz_dumpparms(jpc_ms_t *ms, FILE *out)
    558 {
    559     jpc_siz_t *siz = &ms->parms.siz;
    560     unsigned int i;
    561     fprintf(out, "caps = 0x%02x;\n", (unsigned)siz->caps);
    562     fprintf(out, "width = %d; height = %d; xoff = %d; yoff = %d;\n",
    563       (int)siz->width, (int)siz->height, (int)siz->xoff, (int)siz->yoff);
    564     fprintf(out, "tilewidth = %d; tileheight = %d; tilexoff = %d; "
    565       "tileyoff = %d;\n", (int)siz->tilewidth, (int)siz->tileheight, (int)siz->tilexoff,
    566       (int)siz->tileyoff);
    567     for (i = 0; i < siz->numcomps; ++i) {
    568         fprintf(out, "prec[%d] = %d; sgnd[%d] = %d; hsamp[%d] = %d; "
    569           "vsamp[%d] = %d\n", i, siz->comps[i].prec, i,
    570           siz->comps[i].sgnd, i, siz->comps[i].hsamp, i,
    571           siz->comps[i].vsamp);
    572     }
    573     return 0;
    574 }
    575 
    576 /******************************************************************************\
    577 * COD marker segment operations.
    578 \******************************************************************************/
    579 
    580 static void jpc_cod_destroyparms(jpc_ms_t *ms)
    581 {
    582     jpc_cod_t *cod = &ms->parms.cod;
    583     jpc_cox_destroycompparms(&cod->compparms);
    584 }
    585 
    586 static int jpc_cod_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
    587 {
    588     jpc_cod_t *cod = &ms->parms.cod;
    589     if (jpc_getuint8(in, &cod->csty)) {
    590         return -1;
    591     }
    592     if (jpc_getuint8(in, &cod->prg) ||
    593       jpc_getuint16(in, &cod->numlyrs) ||
    594       jpc_getuint8(in, &cod->mctrans)) {
    595         return -1;
    596     }
    597     if (jpc_cox_getcompparms(ms, cstate, in,
    598       (cod->csty & JPC_COX_PRT) != 0, &cod->compparms)) {
    599         return -1;
    600     }
    601     if (jas_stream_eof(in)) {
    602         jpc_cod_destroyparms(ms);
    603         return -1;
    604     }
    605     return 0;
    606 }
    607 
    608 static int jpc_cod_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    609 {
    610     jpc_cod_t *cod = &ms->parms.cod;
    611     assert(cod->numlyrs > 0 && cod->compparms.numdlvls <= 32);
    612     assert(cod->compparms.numdlvls == cod->compparms.numrlvls - 1);
    613     if (jpc_putuint8(out, cod->compparms.csty) ||
    614       jpc_putuint8(out, cod->prg) ||
    615       jpc_putuint16(out, cod->numlyrs) ||
    616       jpc_putuint8(out, cod->mctrans)) {
    617         return -1;
    618     }
    619     if (jpc_cox_putcompparms(ms, cstate, out,
    620       (cod->csty & JPC_COX_PRT) != 0, &cod->compparms)) {
    621         return -1;
    622     }
    623     return 0;
    624 }
    625 
    626 static int jpc_cod_dumpparms(jpc_ms_t *ms, FILE *out)
    627 {
    628     jpc_cod_t *cod = &ms->parms.cod;
    629     int i;
    630     fprintf(out, "csty = 0x%02x;\n", cod->compparms.csty);
    631     fprintf(out, "numdlvls = %d; qmfbid = %d; mctrans = %d\n",
    632       cod->compparms.numdlvls, cod->compparms.qmfbid, cod->mctrans);
    633     fprintf(out, "prg = %d; numlyrs = %d;\n",
    634       cod->prg, (int)cod->numlyrs);
    635     fprintf(out, "cblkwidthval = %d; cblkheightval = %d; "
    636       "cblksty = 0x%02x;\n", cod->compparms.cblkwidthval, cod->compparms.cblkheightval,
    637       cod->compparms.cblksty);
    638     if (cod->csty & JPC_COX_PRT) {
    639         for (i = 0; i < cod->compparms.numrlvls; ++i) {
    640             jas_eprintf("prcwidth[%d] = %d, prcheight[%d] = %d\n",
    641               i, cod->compparms.rlvls[i].parwidthval,
    642               i, cod->compparms.rlvls[i].parheightval);
    643         }
    644     }
    645     return 0;
    646 }
    647 
    648 /******************************************************************************\
    649 * COC marker segment operations.
    650 \******************************************************************************/
    651 
    652 static void jpc_coc_destroyparms(jpc_ms_t *ms)
    653 {
    654     jpc_coc_t *coc = &ms->parms.coc;
    655     jpc_cox_destroycompparms(&coc->compparms);
    656 }
    657 
    658 static int jpc_coc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
    659 {
    660     jpc_coc_t *coc = &ms->parms.coc;
    661     uint_fast8_t tmp;
    662     if (cstate->numcomps <= 256) {
    663         if (jpc_getuint8(in, &tmp)) {
    664             return -1;
    665         }
    666         coc->compno = tmp;
    667     } else {
    668         if (jpc_getuint16(in, &coc->compno)) {
    669             return -1;
    670         }
    671     }
    672     if (jpc_getuint8(in, &coc->compparms.csty)) {
    673         return -1;
    674     }
    675     if (jpc_cox_getcompparms(ms, cstate, in,
    676       (coc->compparms.csty & JPC_COX_PRT) != 0, &coc->compparms)) {
    677         return -1;
    678     }
    679     if (jas_stream_eof(in)) {
    680         return -1;
    681     }
    682     return 0;
    683 }
    684 
    685 static int jpc_coc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    686 {
    687     jpc_coc_t *coc = &ms->parms.coc;
    688     assert(coc->compparms.numdlvls <= 32);
    689     if (cstate->numcomps <= 256) {
    690         if (jpc_putuint8(out, coc->compno)) {
    691             return -1;
    692         }
    693     } else {
    694         if (jpc_putuint16(out, coc->compno)) {
    695             return -1;
    696         }
    697     }
    698     if (jpc_putuint8(out, coc->compparms.csty)) {
    699         return -1;
    700     }
    701     if (jpc_cox_putcompparms(ms, cstate, out,
    702       (coc->compparms.csty & JPC_COX_PRT) != 0, &coc->compparms)) {
    703         return -1;
    704     }
    705     return 0;
    706 }
    707 
    708 static int jpc_coc_dumpparms(jpc_ms_t *ms, FILE *out)
    709 {
    710     jpc_coc_t *coc = &ms->parms.coc;
    711     fprintf(out, "compno = %d; csty = 0x%02x; numdlvls = %d;\n",
    712       (int)coc->compno, coc->compparms.csty, coc->compparms.numdlvls);
    713     fprintf(out, "cblkwidthval = %d; cblkheightval = %d; "
    714       "cblksty = 0x%02x; qmfbid = %d;\n", coc->compparms.cblkwidthval,
    715       coc->compparms.cblkheightval, coc->compparms.cblksty, coc->compparms.qmfbid);
    716     return 0;
    717 }
    718 /******************************************************************************\
    719 * COD/COC marker segment operation helper functions.
    720 \******************************************************************************/
    721 
    722 static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms)
    723 {
    724     /* Eliminate compiler warning about unused variables. */
    725     compparms = 0;
    726 }
    727 
    728 static int jpc_cox_getcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
    729   jas_stream_t *in, int prtflag, jpc_coxcp_t *compparms)
    730 {
    731     uint_fast8_t tmp;
    732     int i;
    733 
    734     /* Eliminate compiler warning about unused variables. */
    735     ms = 0;
    736     cstate = 0;
    737 
    738     if (jpc_getuint8(in, &compparms->numdlvls) ||
    739       jpc_getuint8(in, &compparms->cblkwidthval) ||
    740       jpc_getuint8(in, &compparms->cblkheightval) ||
    741       jpc_getuint8(in, &compparms->cblksty) ||
    742       jpc_getuint8(in, &compparms->qmfbid)) {
    743         return -1;
    744     }
    745     compparms->numrlvls = compparms->numdlvls + 1;
    746     if (compparms->numrlvls > JPC_MAXRLVLS) {
    747         jpc_cox_destroycompparms(compparms);
    748         return -1;
    749     }
    750     if (prtflag) {
    751         for (i = 0; i < compparms->numrlvls; ++i) {
    752             if (jpc_getuint8(in, &tmp)) {
    753                 jpc_cox_destroycompparms(compparms);
    754                 return -1;
    755             }
    756             compparms->rlvls[i].parwidthval = tmp & 0xf;
    757             compparms->rlvls[i].parheightval = (tmp >> 4) & 0xf;
    758         }
    759 /* Sigh.  This bit should be in the same field in both COC and COD mrk segs. */
    760 compparms->csty |= JPC_COX_PRT;
    761     } else {
    762     }
    763     if (jas_stream_eof(in)) {
    764         jpc_cox_destroycompparms(compparms);
    765         return -1;
    766     }
    767     return 0;
    768 }
    769 
    770 static int jpc_cox_putcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
    771   jas_stream_t *out, int prtflag, jpc_coxcp_t *compparms)
    772 {
    773     int i;
    774     assert(compparms->numdlvls <= 32);
    775 
    776     /* Eliminate compiler warning about unused variables. */
    777     ms = 0;
    778     cstate = 0;
    779 
    780     if (jpc_putuint8(out, compparms->numdlvls) ||
    781       jpc_putuint8(out, compparms->cblkwidthval) ||
    782       jpc_putuint8(out, compparms->cblkheightval) ||
    783       jpc_putuint8(out, compparms->cblksty) ||
    784       jpc_putuint8(out, compparms->qmfbid)) {
    785         return -1;
    786     }
    787     if (prtflag) {
    788         for (i = 0; i < compparms->numrlvls; ++i) {
    789             if (jpc_putuint8(out,
    790               ((compparms->rlvls[i].parheightval & 0xf) << 4) |
    791               (compparms->rlvls[i].parwidthval & 0xf))) {
    792                 return -1;
    793             }
    794         }
    795     }
    796     return 0;
    797 }
    798 
    799 /******************************************************************************\
    800 * RGN marker segment operations.
    801 \******************************************************************************/
    802 
    803 static int jpc_rgn_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
    804 {
    805     jpc_rgn_t *rgn = &ms->parms.rgn;
    806     uint_fast8_t tmp;
    807     if (cstate->numcomps <= 256) {
    808         if (jpc_getuint8(in, &tmp)) {
    809             return -1;
    810         }
    811         rgn->compno = tmp;
    812     } else {
    813         if (jpc_getuint16(in, &rgn->compno)) {
    814             return -1;
    815         }
    816     }
    817     if (jpc_getuint8(in, &rgn->roisty) ||
    818       jpc_getuint8(in, &rgn->roishift)) {
    819         return -1;
    820     }
    821     return 0;
    822 }
    823 
    824 static int jpc_rgn_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    825 {
    826     jpc_rgn_t *rgn = &ms->parms.rgn;
    827     if (cstate->numcomps <= 256) {
    828         if (jpc_putuint8(out, rgn->compno)) {
    829             return -1;
    830         }
    831     } else {
    832         if (jpc_putuint16(out, rgn->compno)) {
    833             return -1;
    834         }
    835     }
    836     if (jpc_putuint8(out, rgn->roisty) ||
    837       jpc_putuint8(out, rgn->roishift)) {
    838         return -1;
    839     }
    840     return 0;
    841 }
    842 
    843 static int jpc_rgn_dumpparms(jpc_ms_t *ms, FILE *out)
    844 {
    845     jpc_rgn_t *rgn = &ms->parms.rgn;
    846     fprintf(out, "compno = %d; roisty = %d; roishift = %d\n",
    847       (int)rgn->compno, rgn->roisty, rgn->roishift);
    848     return 0;
    849 }
    850 
    851 /******************************************************************************\
    852 * QCD marker segment operations.
    853 \******************************************************************************/
    854 
    855 static void jpc_qcd_destroyparms(jpc_ms_t *ms)
    856 {
    857     jpc_qcd_t *qcd = &ms->parms.qcd;
    858     jpc_qcx_destroycompparms(&qcd->compparms);
    859 }
    860 
    861 static int jpc_qcd_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
    862 {
    863     jpc_qcxcp_t *compparms = &ms->parms.qcd.compparms;
    864     return jpc_qcx_getcompparms(compparms, cstate, in, ms->len);
    865 }
    866 
    867 static int jpc_qcd_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    868 {
    869     jpc_qcxcp_t *compparms = &ms->parms.qcd.compparms;
    870     return jpc_qcx_putcompparms(compparms, cstate, out);
    871 }
    872 
    873 static int jpc_qcd_dumpparms(jpc_ms_t *ms, FILE *out)
    874 {
    875     jpc_qcd_t *qcd = &ms->parms.qcd;
    876     int i;
    877     fprintf(out, "qntsty = %d; numguard = %d; numstepsizes = %d\n",
    878       (int) qcd->compparms.qntsty, qcd->compparms.numguard, qcd->compparms.numstepsizes);
    879     for (i = 0; i < qcd->compparms.numstepsizes; ++i) {
    880         fprintf(out, "expn[%d] = 0x%04x; mant[%d] = 0x%04x;\n",
    881           i, (unsigned) JPC_QCX_GETEXPN(qcd->compparms.stepsizes[i]),
    882           i, (unsigned) JPC_QCX_GETMANT(qcd->compparms.stepsizes[i]));
    883     }
    884     return 0;
    885 }
    886 
    887 /******************************************************************************\
    888 * QCC marker segment operations.
    889 \******************************************************************************/
    890 
    891 static void jpc_qcc_destroyparms(jpc_ms_t *ms)
    892 {
    893     jpc_qcc_t *qcc = &ms->parms.qcc;
    894     jpc_qcx_destroycompparms(&qcc->compparms);
    895 }
    896 
    897 static int jpc_qcc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
    898 {
    899     jpc_qcc_t *qcc = &ms->parms.qcc;
    900     uint_fast8_t tmp;
    901     int len;
    902     len = ms->len;
    903     if (cstate->numcomps <= 256) {
    904         jpc_getuint8(in, &tmp);
    905         qcc->compno = tmp;
    906         --len;
    907     } else {
    908         jpc_getuint16(in, &qcc->compno);
    909         len -= 2;
    910     }
    911     if (jpc_qcx_getcompparms(&qcc->compparms, cstate, in, len)) {
    912         return -1;
    913     }
    914     if (jas_stream_eof(in)) {
    915         jpc_qcc_destroyparms(ms);
    916         return -1;
    917     }
    918     return 0;
    919 }
    920 
    921 static int jpc_qcc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
    922 {
    923     jpc_qcc_t *qcc = &ms->parms.qcc;
    924     if (cstate->numcomps <= 256) {
    925         jpc_putuint8(out, qcc->compno);
    926     } else {
    927         jpc_putuint16(out, qcc->compno);
    928     }
    929     if (jpc_qcx_putcompparms(&qcc->compparms, cstate, out)) {
    930         return -1;
    931     }
    932     return 0;
    933 }
    934 
    935 static int jpc_qcc_dumpparms(jpc_ms_t *ms, FILE *out)
    936 {
    937     jpc_qcc_t *qcc = &ms->parms.qcc;
    938     int i;
    939     fprintf(out, "compno = %d; qntsty = %d; numguard = %d; "
    940       "numstepsizes = %d\n", (int)qcc->compno, qcc->compparms.qntsty, qcc->compparms.numguard,
    941       qcc->compparms.numstepsizes);
    942     for (i = 0; i < qcc->compparms.numstepsizes; ++i) {
    943         fprintf(out, "expn[%d] = 0x%04x; mant[%d] = 0x%04x;\n",
    944           i, (unsigned) JPC_QCX_GETEXPN(qcc->compparms.stepsizes[i]),
    945           i, (unsigned) JPC_QCX_GETMANT(qcc->compparms.stepsizes[i]));
    946     }
    947     return 0;
    948 }
    949 
    950 /******************************************************************************\
    951 * QCD/QCC marker segment helper functions.
    952 \******************************************************************************/
    953 
    954 static void jpc_qcx_destroycompparms(jpc_qcxcp_t *compparms)
    955 {
    956     if (compparms->stepsizes) {
    957         jas_free(compparms->stepsizes);
    958     }
    959 }
    960 
    961 static int jpc_qcx_getcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate,
    962   jas_stream_t *in, uint_fast16_t len)
    963 {
    964     uint_fast8_t tmp;
    965     int n;
    966     int i;
    967 
    968     /* Eliminate compiler warning about unused variables. */
    969     cstate = 0;
    970 
    971     n = 0;
    972     jpc_getuint8(in, &tmp);
    973     ++n;
    974     compparms->qntsty = tmp & 0x1f;
    975     compparms->numguard = (tmp >> 5) & 7;
    976     switch (compparms->qntsty) {
    977     case JPC_QCX_SIQNT:
    978         compparms->numstepsizes = 1;
    979         break;
    980     case JPC_QCX_NOQNT:
    981         compparms->numstepsizes = (len - n);
    982         break;
    983     case JPC_QCX_SEQNT:
    984         /* XXX - this is a hack */
    985         compparms->numstepsizes = (len - n) / 2;
    986         break;
    987     }
    988     if (compparms->numstepsizes > 3 * JPC_MAXRLVLS + 1) {
    989         jpc_qcx_destroycompparms(compparms);
    990                 return -1;
    991         } else if (compparms->numstepsizes > 0) {
    992         compparms->stepsizes = jas_malloc(compparms->numstepsizes *
    993           sizeof(uint_fast16_t));
    994         assert(compparms->stepsizes);
    995         for (i = 0; i < compparms->numstepsizes; ++i) {
    996             if (compparms->qntsty == JPC_QCX_NOQNT) {
    997                 jpc_getuint8(in, &tmp);
    998                 compparms->stepsizes[i] = JPC_QCX_EXPN(tmp >> 3);
    999             } else {
   1000                 jpc_getuint16(in, &compparms->stepsizes[i]);
   1001             }
   1002         }
   1003     } else {
   1004         compparms->stepsizes = 0;
   1005     }
   1006     if (jas_stream_error(in) || jas_stream_eof(in)) {
   1007         jpc_qcx_destroycompparms(compparms);
   1008         return -1;
   1009     }
   1010     return 0;
   1011 }
   1012 
   1013 static int jpc_qcx_putcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate,
   1014   jas_stream_t *out)
   1015 {
   1016     int i;
   1017 
   1018     /* Eliminate compiler warning about unused variables. */
   1019     cstate = 0;
   1020 
   1021     jpc_putuint8(out, ((compparms->numguard & 7) << 5) | compparms->qntsty);
   1022     for (i = 0; i < compparms->numstepsizes; ++i) {
   1023         if (compparms->qntsty == JPC_QCX_NOQNT) {
   1024             jpc_putuint8(out, JPC_QCX_GETEXPN(
   1025               compparms->stepsizes[i]) << 3);
   1026         } else {
   1027             jpc_putuint16(out, compparms->stepsizes[i]);
   1028         }
   1029     }
   1030     return 0;
   1031 }
   1032 
   1033 /******************************************************************************\
   1034 * SOP marker segment operations.
   1035 \******************************************************************************/
   1036 
   1037 static int jpc_sop_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1038 {
   1039     jpc_sop_t *sop = &ms->parms.sop;
   1040 
   1041     /* Eliminate compiler warning about unused variable. */
   1042     cstate = 0;
   1043 
   1044     if (jpc_getuint16(in, &sop->seqno)) {
   1045         return -1;
   1046     }
   1047     return 0;
   1048 }
   1049 
   1050 static int jpc_sop_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1051 {
   1052     jpc_sop_t *sop = &ms->parms.sop;
   1053 
   1054     /* Eliminate compiler warning about unused variable. */
   1055     cstate = 0;
   1056 
   1057     if (jpc_putuint16(out, sop->seqno)) {
   1058         return -1;
   1059     }
   1060     return 0;
   1061 }
   1062 
   1063 static int jpc_sop_dumpparms(jpc_ms_t *ms, FILE *out)
   1064 {
   1065     jpc_sop_t *sop = &ms->parms.sop;
   1066     fprintf(out, "seqno = %d;\n", (int)sop->seqno);
   1067     return 0;
   1068 }
   1069 
   1070 /******************************************************************************\
   1071 * PPM marker segment operations.
   1072 \******************************************************************************/
   1073 
   1074 static void jpc_ppm_destroyparms(jpc_ms_t *ms)
   1075 {
   1076     jpc_ppm_t *ppm = &ms->parms.ppm;
   1077     if (ppm->data) {
   1078         jas_free(ppm->data);
   1079     }
   1080 }
   1081 
   1082 static int jpc_ppm_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1083 {
   1084     jpc_ppm_t *ppm = &ms->parms.ppm;
   1085 
   1086     /* Eliminate compiler warning about unused variables. */
   1087     cstate = 0;
   1088 
   1089     ppm->data = 0;
   1090 
   1091     if (ms->len < 1) {
   1092         goto error;
   1093     }
   1094     if (jpc_getuint8(in, &ppm->ind)) {
   1095         goto error;
   1096     }
   1097 
   1098     ppm->len = ms->len - 1;
   1099     if (ppm->len > 0) {
   1100         if (!(ppm->data = jas_malloc(ppm->len))) {
   1101             goto error;
   1102         }
   1103         if (JAS_CAST(uint, jas_stream_read(in, ppm->data, ppm->len)) != ppm->len) {
   1104             goto error;
   1105         }
   1106     } else {
   1107         ppm->data = 0;
   1108     }
   1109     return 0;
   1110 
   1111 error:
   1112     jpc_ppm_destroyparms(ms);
   1113     return -1;
   1114 }
   1115 
   1116 static int jpc_ppm_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1117 {
   1118     jpc_ppm_t *ppm = &ms->parms.ppm;
   1119 
   1120     /* Eliminate compiler warning about unused variables. */
   1121     cstate = 0;
   1122 
   1123     if (JAS_CAST(uint, jas_stream_write(out, (char *) ppm->data, ppm->len)) != ppm->len) {
   1124         return -1;
   1125     }
   1126     return 0;
   1127 }
   1128 
   1129 static int jpc_ppm_dumpparms(jpc_ms_t *ms, FILE *out)
   1130 {
   1131     jpc_ppm_t *ppm = &ms->parms.ppm;
   1132     fprintf(out, "ind=%d; len = %d;\n", ppm->ind, (int)ppm->len);
   1133     if (ppm->len > 0) {
   1134         fprintf(out, "data =\n");
   1135         jas_memdump(out, ppm->data, ppm->len);
   1136     }
   1137     return 0;
   1138 }
   1139 
   1140 /******************************************************************************\
   1141 * PPT marker segment operations.
   1142 \******************************************************************************/
   1143 
   1144 static void jpc_ppt_destroyparms(jpc_ms_t *ms)
   1145 {
   1146     jpc_ppt_t *ppt = &ms->parms.ppt;
   1147     if (ppt->data) {
   1148         jas_free(ppt->data);
   1149     }
   1150 }
   1151 
   1152 static int jpc_ppt_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1153 {
   1154     jpc_ppt_t *ppt = &ms->parms.ppt;
   1155 
   1156     /* Eliminate compiler warning about unused variables. */
   1157     cstate = 0;
   1158 
   1159     ppt->data = 0;
   1160 
   1161     if (ms->len < 1) {
   1162         goto error;
   1163     }
   1164     if (jpc_getuint8(in, &ppt->ind)) {
   1165         goto error;
   1166     }
   1167     ppt->len = ms->len - 1;
   1168     if (ppt->len > 0) {
   1169         if (!(ppt->data = jas_malloc(ppt->len))) {
   1170             goto error;
   1171         }
   1172         if (jas_stream_read(in, (char *) ppt->data, ppt->len) != JAS_CAST(int, ppt->len)) {
   1173             goto error;
   1174         }
   1175     } else {
   1176         ppt->data = 0;
   1177     }
   1178     return 0;
   1179 
   1180 error:
   1181     jpc_ppt_destroyparms(ms);
   1182     return -1;
   1183 }
   1184 
   1185 static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1186 {
   1187     jpc_ppt_t *ppt = &ms->parms.ppt;
   1188 
   1189     /* Eliminate compiler warning about unused variable. */
   1190     cstate = 0;
   1191 
   1192     if (jpc_putuint8(out, ppt->ind)) {
   1193         return -1;
   1194     }
   1195     if (jas_stream_write(out, (char *) ppt->data, ppt->len) != JAS_CAST(int, ppt->len)) {
   1196         return -1;
   1197     }
   1198     return 0;
   1199 }
   1200 
   1201 static int jpc_ppt_dumpparms(jpc_ms_t *ms, FILE *out)
   1202 {
   1203     jpc_ppt_t *ppt = &ms->parms.ppt;
   1204     fprintf(out, "ind=%d; len = %d;\n", ppt->ind, (int)ppt->len);
   1205     if (ppt->len > 0) {
   1206         fprintf(out, "data =\n");
   1207         jas_memdump(out, ppt->data, ppt->len);
   1208     }
   1209     return 0;
   1210 }
   1211 
   1212 /******************************************************************************\
   1213 * POC marker segment operations.
   1214 \******************************************************************************/
   1215 
   1216 static void jpc_poc_destroyparms(jpc_ms_t *ms)
   1217 {
   1218     jpc_poc_t *poc = &ms->parms.poc;
   1219     if (poc->pchgs) {
   1220         jas_free(poc->pchgs);
   1221     }
   1222 }
   1223 
   1224 static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1225 {
   1226     jpc_poc_t *poc = &ms->parms.poc;
   1227     jpc_pocpchg_t *pchg;
   1228     int pchgno;
   1229     uint_fast8_t tmp;
   1230     poc->numpchgs = (cstate->numcomps > 256) ? (ms->len / 9) :
   1231       (ms->len / 7);
   1232     if (!(poc->pchgs = jas_alloc2(poc->numpchgs, sizeof(jpc_pocpchg_t)))) {
   1233         goto error;
   1234     }
   1235     for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs; ++pchgno,
   1236       ++pchg) {
   1237         if (jpc_getuint8(in, &pchg->rlvlnostart)) {
   1238             goto error;
   1239         }
   1240         if (cstate->numcomps > 256) {
   1241             if (jpc_getuint16(in, &pchg->compnostart)) {
   1242                 goto error;
   1243             }
   1244         } else {
   1245             if (jpc_getuint8(in, &tmp)) {
   1246                 goto error;
   1247             };
   1248             pchg->compnostart = tmp;
   1249         }
   1250         if (jpc_getuint16(in, &pchg->lyrnoend) ||
   1251           jpc_getuint8(in, &pchg->rlvlnoend)) {
   1252             goto error;
   1253         }
   1254         if (cstate->numcomps > 256) {
   1255             if (jpc_getuint16(in, &pchg->compnoend)) {
   1256                 goto error;
   1257             }
   1258         } else {
   1259             if (jpc_getuint8(in, &tmp)) {
   1260                 goto error;
   1261             }
   1262             pchg->compnoend = tmp;
   1263         }
   1264         if (jpc_getuint8(in, &pchg->prgord)) {
   1265             goto error;
   1266         }
   1267         if (pchg->rlvlnostart > pchg->rlvlnoend ||
   1268           pchg->compnostart > pchg->compnoend) {
   1269             goto error;
   1270         }
   1271     }
   1272     return 0;
   1273 
   1274 error:
   1275     jpc_poc_destroyparms(ms);
   1276     return -1;
   1277 }
   1278 
   1279 static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1280 {
   1281     jpc_poc_t *poc = &ms->parms.poc;
   1282     jpc_pocpchg_t *pchg;
   1283     int pchgno;
   1284     for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs; ++pchgno,
   1285       ++pchg) {
   1286         if (jpc_putuint8(out, pchg->rlvlnostart) ||
   1287           ((cstate->numcomps > 256) ?
   1288           jpc_putuint16(out, pchg->compnostart) :
   1289           jpc_putuint8(out, pchg->compnostart)) ||
   1290           jpc_putuint16(out, pchg->lyrnoend) ||
   1291           jpc_putuint8(out, pchg->rlvlnoend) ||
   1292           ((cstate->numcomps > 256) ?
   1293           jpc_putuint16(out, pchg->compnoend) :
   1294           jpc_putuint8(out, pchg->compnoend)) ||
   1295           jpc_putuint8(out, pchg->prgord)) {
   1296             return -1;
   1297         }
   1298     }
   1299     return 0;
   1300 }
   1301 
   1302 static int jpc_poc_dumpparms(jpc_ms_t *ms, FILE *out)
   1303 {
   1304     jpc_poc_t *poc = &ms->parms.poc;
   1305     jpc_pocpchg_t *pchg;
   1306     int pchgno;
   1307     for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs;
   1308       ++pchgno, ++pchg) {
   1309         fprintf(out, "po[%d] = %d; ", pchgno, pchg->prgord);
   1310         fprintf(out, "cs[%d] = %d; ce[%d] = %d; ",
   1311           pchgno, (int)pchg->compnostart, pchgno, (int)pchg->compnoend);
   1312         fprintf(out, "rs[%d] = %d; re[%d] = %d; ",
   1313           pchgno, pchg->rlvlnostart, pchgno, pchg->rlvlnoend);
   1314         fprintf(out, "le[%d] = %d\n", pchgno, (int)pchg->lyrnoend);
   1315     }
   1316     return 0;
   1317 }
   1318 
   1319 /******************************************************************************\
   1320 * CRG marker segment operations.
   1321 \******************************************************************************/
   1322 
   1323 static void jpc_crg_destroyparms(jpc_ms_t *ms)
   1324 {
   1325     jpc_crg_t *crg = &ms->parms.crg;
   1326     if (crg->comps) {
   1327         jas_free(crg->comps);
   1328     }
   1329 }
   1330 
   1331 static int jpc_crg_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1332 {
   1333     jpc_crg_t *crg = &ms->parms.crg;
   1334     jpc_crgcomp_t *comp;
   1335     uint_fast16_t compno;
   1336     crg->numcomps = cstate->numcomps;
   1337     if (!(crg->comps = jas_alloc2(cstate->numcomps, sizeof(jpc_crgcomp_t)))) {
   1338         return -1;
   1339     }
   1340     for (compno = 0, comp = crg->comps; compno < cstate->numcomps;
   1341       ++compno, ++comp) {
   1342         if (jpc_getuint16(in, &comp->hoff) ||
   1343           jpc_getuint16(in, &comp->voff)) {
   1344             jpc_crg_destroyparms(ms);
   1345             return -1;
   1346         }
   1347     }
   1348     return 0;
   1349 }
   1350 
   1351 static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1352 {
   1353     jpc_crg_t *crg = &ms->parms.crg;
   1354     int compno;
   1355     jpc_crgcomp_t *comp;
   1356 
   1357     /* Eliminate compiler warning about unused variables. */
   1358     cstate = 0;
   1359 
   1360     for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno,
   1361       ++comp) {
   1362         if (jpc_putuint16(out, comp->hoff) ||
   1363           jpc_putuint16(out, comp->voff)) {
   1364             return -1;
   1365         }
   1366     }
   1367     return 0;
   1368 }
   1369 
   1370 static int jpc_crg_dumpparms(jpc_ms_t *ms, FILE *out)
   1371 {
   1372     jpc_crg_t *crg = &ms->parms.crg;
   1373     int compno;
   1374     jpc_crgcomp_t *comp;
   1375     for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno,
   1376       ++comp) {
   1377         fprintf(out, "hoff[%d] = %d; voff[%d] = %d\n", compno,
   1378           (int)comp->hoff, compno, (int)comp->voff);
   1379     }
   1380     return 0;
   1381 }
   1382 
   1383 /******************************************************************************\
   1384 * Operations for COM marker segment.
   1385 \******************************************************************************/
   1386 
   1387 static void jpc_com_destroyparms(jpc_ms_t *ms)
   1388 {
   1389     jpc_com_t *com = &ms->parms.com;
   1390     if (com->data) {
   1391         jas_free(com->data);
   1392     }
   1393 }
   1394 
   1395 static int jpc_com_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1396 {
   1397     jpc_com_t *com = &ms->parms.com;
   1398 
   1399     /* Eliminate compiler warning about unused variables. */
   1400     cstate = 0;
   1401 
   1402     if (jpc_getuint16(in, &com->regid)) {
   1403         return -1;
   1404     }
   1405     com->len = ms->len - 2;
   1406     if (com->len > 0) {
   1407         if (!(com->data = jas_malloc(com->len))) {
   1408             return -1;
   1409         }
   1410         if (jas_stream_read(in, com->data, com->len) != JAS_CAST(int, com->len)) {
   1411             return -1;
   1412         }
   1413     } else {
   1414         com->data = 0;
   1415     }
   1416     return 0;
   1417 }
   1418 
   1419 static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1420 {
   1421     jpc_com_t *com = &ms->parms.com;
   1422 
   1423     /* Eliminate compiler warning about unused variables. */
   1424     cstate = 0;
   1425 
   1426     if (jpc_putuint16(out, com->regid)) {
   1427         return -1;
   1428     }
   1429     if (jas_stream_write(out, com->data, com->len) != JAS_CAST(int, com->len)) {
   1430         return -1;
   1431     }
   1432     return 0;
   1433 }
   1434 
   1435 static int jpc_com_dumpparms(jpc_ms_t *ms, FILE *out)
   1436 {
   1437     jpc_com_t *com = &ms->parms.com;
   1438     unsigned int i;
   1439     int printable;
   1440     fprintf(out, "regid = %d;\n", (int)com->regid);
   1441     printable = 1;
   1442     for (i = 0; i < com->len; ++i) {
   1443         if (!isprint(com->data[i])) {
   1444             printable = 0;
   1445             break;
   1446         }
   1447     }
   1448     if (printable) {
   1449         fprintf(out, "data = ");
   1450         fwrite(com->data, sizeof(char), com->len, out);
   1451         fprintf(out, "\n");
   1452     }
   1453     return 0;
   1454 }
   1455 
   1456 /******************************************************************************\
   1457 * Operations for unknown types of marker segments.
   1458 \******************************************************************************/
   1459 
   1460 static void jpc_unk_destroyparms(jpc_ms_t *ms)
   1461 {
   1462     jpc_unk_t *unk = &ms->parms.unk;
   1463     if (unk->data) {
   1464         jas_free(unk->data);
   1465     }
   1466 }
   1467 
   1468 static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
   1469 {
   1470     jpc_unk_t *unk = &ms->parms.unk;
   1471 
   1472     /* Eliminate compiler warning about unused variables. */
   1473     cstate = 0;
   1474 
   1475     if (ms->len > 0) {
   1476         if (!(unk->data = jas_malloc(ms->len))) {
   1477             return -1;
   1478         }
   1479         if (jas_stream_read(in, (char *) unk->data, ms->len) != JAS_CAST(int, ms->len)) {
   1480             jas_free(unk->data);
   1481             return -1;
   1482         }
   1483         unk->len = ms->len;
   1484     } else {
   1485         unk->data = 0;
   1486         unk->len = 0;
   1487     }
   1488     return 0;
   1489 }
   1490 
   1491 static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
   1492 {
   1493     /* Eliminate compiler warning about unused variables. */
   1494     cstate = 0;
   1495     ms = 0;
   1496     out = 0;
   1497 
   1498     /* If this function is called, we are trying to write an unsupported
   1499       type of marker segment.  Return with an error indication.  */
   1500     return -1;
   1501 }
   1502 
   1503 static int jpc_unk_dumpparms(jpc_ms_t *ms, FILE *out)
   1504 {
   1505     unsigned int i;
   1506     jpc_unk_t *unk = &ms->parms.unk;
   1507     for (i = 0; i < unk->len; ++i) {
   1508         fprintf(out, "%02x ", unk->data[i]);
   1509     }
   1510     return 0;
   1511 }
   1512 
   1513 /******************************************************************************\
   1514 * Primitive I/O operations.
   1515 \******************************************************************************/
   1516 
   1517 int jpc_getuint8(jas_stream_t *in, uint_fast8_t *val)
   1518 {
   1519     int c;
   1520     if ((c = jas_stream_getc(in)) == EOF) {
   1521         return -1;
   1522     }
   1523     if (val) {
   1524         *val = c;
   1525     }
   1526     return 0;
   1527 }
   1528 
   1529 int jpc_putuint8(jas_stream_t *out, uint_fast8_t val)
   1530 {
   1531     if (jas_stream_putc(out, val & 0xff) == EOF) {
   1532         return -1;
   1533     }
   1534     return 0;
   1535 }
   1536 
   1537 int jpc_getuint16(jas_stream_t *in, uint_fast16_t *val)
   1538 {
   1539     uint_fast16_t v;
   1540     int c;
   1541     if ((c = jas_stream_getc(in)) == EOF) {
   1542         return -1;
   1543     }
   1544     v = c;
   1545     if ((c = jas_stream_getc(in)) == EOF) {
   1546         return -1;
   1547     }
   1548     v = (v << 8) | c;
   1549     if (val) {
   1550         *val = v;
   1551     }
   1552     return 0;
   1553 }
   1554 
   1555 int jpc_putuint16(jas_stream_t *out, uint_fast16_t val)
   1556 {
   1557     if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
   1558       jas_stream_putc(out, val & 0xff) == EOF) {
   1559         return -1;
   1560     }
   1561     return 0;
   1562 }
   1563 
   1564 int jpc_getuint32(jas_stream_t *in, uint_fast32_t *val)
   1565 {
   1566     uint_fast32_t v;
   1567     int c;
   1568     if ((c = jas_stream_getc(in)) == EOF) {
   1569         return -1;
   1570     }
   1571     v = c;
   1572     if ((c = jas_stream_getc(in)) == EOF) {
   1573         return -1;
   1574     }
   1575     v = (v << 8) | c;
   1576     if ((c = jas_stream_getc(in)) == EOF) {
   1577         return -1;
   1578     }
   1579     v = (v << 8) | c;
   1580     if ((c = jas_stream_getc(in)) == EOF) {
   1581         return -1;
   1582     }
   1583     v = (v << 8) | c;
   1584     if (val) {
   1585         *val = v;
   1586     }
   1587     return 0;
   1588 }
   1589 
   1590 int jpc_putuint32(jas_stream_t *out, uint_fast32_t val)
   1591 {
   1592     if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF ||
   1593       jas_stream_putc(out, (val >> 16) & 0xff) == EOF ||
   1594       jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
   1595       jas_stream_putc(out, val & 0xff) == EOF) {
   1596         return -1;
   1597     }
   1598     return 0;
   1599 }
   1600 
   1601 /******************************************************************************\
   1602 * Miscellany
   1603 \******************************************************************************/
   1604 
   1605 static jpc_mstabent_t *jpc_mstab_lookup(int id)
   1606 {
   1607     jpc_mstabent_t *mstabent;
   1608     for (mstabent = jpc_mstab;; ++mstabent) {
   1609         if (mstabent->id == id || mstabent->id < 0) {
   1610             return mstabent;
   1611         }
   1612     }
   1613     assert(0);
   1614     return 0;
   1615 }
   1616 
   1617 int jpc_validate(jas_stream_t *in)
   1618 {
   1619     int n;
   1620     int i;
   1621     unsigned char buf[2];
   1622 
   1623     assert(JAS_STREAM_MAXPUTBACK >= 2);
   1624 
   1625     if ((n = jas_stream_read(in, (char *) buf, 2)) < 0) {
   1626         return -1;
   1627     }
   1628     for (i = n - 1; i >= 0; --i) {
   1629         if (jas_stream_ungetc(in, buf[i]) == EOF) {
   1630             return -1;
   1631         }
   1632     }
   1633     if (n < 2) {
   1634         return -1;
   1635     }
   1636     if (buf[0] == (JPC_MS_SOC >> 8) && buf[1] == (JPC_MS_SOC & 0xff)) {
   1637         return 0;
   1638     }
   1639     return -1;
   1640 }
   1641 
   1642 int jpc_getdata(jas_stream_t *in, jas_stream_t *out, long len)
   1643 {
   1644     return jas_stream_copy(out, in, len);
   1645 }
   1646 
   1647 int jpc_putdata(jas_stream_t *out, jas_stream_t *in, long len)
   1648 {
   1649     return jas_stream_copy(out, in, len);
   1650 }
   1651