Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / libjasper / jpc_cs.c
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 ||
244           ms->id > JPC_MS_MAX) {
245                 jpc_ms_destroy(ms);
246                 return 0;
247         }
248
249         mstabent = jpc_mstab_lookup(ms->id);
250         ms->ops = &mstabent->ops;
251
252         /* Get the marker segment length and parameters if present. */
253         /* Note: It is tacitly assumed that a marker segment cannot have
254           parameters unless it has a length field.  That is, there cannot
255           be a parameters field without a length field and vice versa. */
256         if (JPC_MS_HASPARMS(ms->id)) {
257                 /* Get the length of the marker segment. */
258                 if (jpc_getuint16(in, &ms->len) || ms->len < 3) {
259                         jpc_ms_destroy(ms);
260                         return 0;
261                 }
262                 /* Calculate the length of the marker segment parameters. */
263                 ms->len -= 2;
264                 /* Create and prepare a temporary memory stream from which to
265                   read the marker segment parameters. */
266                 /* Note: This approach provides a simple way of ensuring that
267                   we never read beyond the end of the marker segment (even if
268                   the marker segment length is errantly set too small). */
269                 if (!(tmpstream = jas_stream_memopen(0, 0))) {
270                         jpc_ms_destroy(ms);
271                         return 0;
272                 }
273                 if (jas_stream_copy(tmpstream, in, ms->len) ||
274                   jas_stream_seek(tmpstream, 0, SEEK_SET) < 0) {
275                         jas_stream_close(tmpstream);
276                         jpc_ms_destroy(ms);
277                         return 0;
278                 }
279                 /* Get the marker segment parameters. */
280                 if ((*ms->ops->getparms)(ms, cstate, tmpstream)) {
281                         ms->ops = 0;
282                         jpc_ms_destroy(ms);
283                         jas_stream_close(tmpstream);
284                         return 0;
285                 }
286
287                 if (jas_getdbglevel() > 0) {
288                         jpc_ms_dump(ms, stderr);
289                 }
290
291                 if (JAS_CAST(ulong, jas_stream_tell(tmpstream)) != ms->len) {
292                         jas_eprintf("warning: trailing garbage in marker segment (%ld bytes)\n",
293                           ms->len - jas_stream_tell(tmpstream));
294                 }
295
296                 /* Close the temporary stream. */
297                 jas_stream_close(tmpstream);
298
299         } else {
300                 /* There are no marker segment parameters. */
301                 ms->len = 0;
302
303                 if (jas_getdbglevel() > 0) {
304                         jpc_ms_dump(ms, stderr);
305                 }
306         }
307
308         /* Update the code stream state information based on the type of
309           marker segment read. */
310         /* Note: This is a bit of a hack, but I'm not going to define another
311           type of virtual function for this one special case. */
312         if (ms->id == JPC_MS_SIZ) {
313                 cstate->numcomps = ms->parms.siz.numcomps;
314         }
315
316         return ms;
317 }
318
319 /* Write a marker segment to a stream. */
320 int jpc_putms(jas_stream_t *out, jpc_cstate_t *cstate, jpc_ms_t *ms)
321 {
322         jas_stream_t *tmpstream;
323         int len;
324
325         /* Output the marker segment type. */
326         if (jpc_putuint16(out, ms->id)) {
327                 return -1;
328         }
329
330         /* Output the marker segment length and parameters if necessary. */
331         if (ms->ops->putparms) {
332                 /* Create a temporary stream in which to buffer the
333                   parameter data. */
334                 if (!(tmpstream = jas_stream_memopen(0, 0))) {
335                         return -1;
336                 }
337                 if ((*ms->ops->putparms)(ms, cstate, tmpstream)) {
338                         jas_stream_close(tmpstream);
339                         return -1;
340                 }
341                 /* Get the number of bytes of parameter data written. */
342                 if ((len = jas_stream_tell(tmpstream)) < 0) {
343                         jas_stream_close(tmpstream);
344                         return -1;
345                 }
346                 ms->len = len;
347                 /* Write the marker segment length and parameter data to
348                   the output stream. */
349                 if (jas_stream_seek(tmpstream, 0, SEEK_SET) < 0 ||
350                   jpc_putuint16(out, ms->len + 2) ||
351                   jas_stream_copy(out, tmpstream, ms->len) < 0) {
352                         jas_stream_close(tmpstream);
353                         return -1;
354                 }
355                 /* Close the temporary stream. */
356                 jas_stream_close(tmpstream);
357         }
358
359         /* This is a bit of a hack, but I'm not going to define another
360           type of virtual function for this one special case. */
361         if (ms->id == JPC_MS_SIZ) {
362                 cstate->numcomps = ms->parms.siz.numcomps;
363         }
364
365         if (jas_getdbglevel() > 0) {
366                 jpc_ms_dump(ms, stderr);
367         }
368
369         return 0;
370 }
371
372 /******************************************************************************\
373 * Marker segment operations.
374 \******************************************************************************/
375
376 /* Create a marker segment of the specified type. */
377 jpc_ms_t *jpc_ms_create(int type)
378 {
379         jpc_ms_t *ms;
380         jpc_mstabent_t *mstabent;
381
382         if (!(ms = jas_malloc(sizeof(jpc_ms_t)))) {
383                 return 0;
384         }
385         ms->id = type;
386         ms->len = 0;
387         mstabent = jpc_mstab_lookup(ms->id);
388         ms->ops = &mstabent->ops;
389         memset(&ms->parms, 0, sizeof(jpc_msparms_t));
390         return ms;
391 }
392
393 /* Destroy a marker segment. */
394 void jpc_ms_destroy(jpc_ms_t *ms)
395 {
396         if (ms->ops && ms->ops->destroyparms) {
397                 (*ms->ops->destroyparms)(ms);
398         }
399         jas_free(ms);
400 }
401
402 /* Dump a marker segment to a stream for debugging. */
403 void jpc_ms_dump(jpc_ms_t *ms, FILE *out)
404 {
405         jpc_mstabent_t *mstabent;
406         mstabent = jpc_mstab_lookup(ms->id);
407         fprintf(out, "type = 0x%04x (%s);", ms->id, mstabent->name);
408         if (JPC_MS_HASPARMS(ms->id)) {
409                 fprintf(out, " len = %d;", ms->len + 2);
410                 if (ms->ops->dumpparms) {
411                         (*ms->ops->dumpparms)(ms, out);
412                 } else {
413                         fprintf(out, "\n");
414                 }
415         } else {
416                 fprintf(out, "\n");
417         }
418 }
419
420 /******************************************************************************\
421 * SOT marker segment operations.
422 \******************************************************************************/
423
424 static int jpc_sot_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
425 {
426         jpc_sot_t *sot = &ms->parms.sot;
427
428         /* Eliminate compiler warning about unused variables. */
429         cstate = 0;
430
431         if (jpc_getuint16(in, &sot->tileno) ||
432           jpc_getuint32(in, &sot->len) ||
433           jpc_getuint8(in, &sot->partno) ||
434           jpc_getuint8(in, &sot->numparts)) {
435                 return -1;
436         }
437         if (jas_stream_eof(in)) {
438                 return -1;
439         }
440         return 0;
441 }
442
443 static int jpc_sot_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
444 {
445         jpc_sot_t *sot = &ms->parms.sot;
446
447         /* Eliminate compiler warning about unused variables. */
448         cstate = 0;
449
450         if (jpc_putuint16(out, sot->tileno) ||
451           jpc_putuint32(out, sot->len) ||
452           jpc_putuint8(out, sot->partno) ||
453           jpc_putuint8(out, sot->numparts)) {
454                 return -1;
455         }
456         return 0;
457 }
458
459 static int jpc_sot_dumpparms(jpc_ms_t *ms, FILE *out)
460 {
461         jpc_sot_t *sot = &ms->parms.sot;
462         fprintf(out, "tileno = %d; len = %d; partno = %d; numparts = %d\n",
463           sot->tileno, sot->len, sot->partno, sot->numparts);
464         return 0;
465 }
466
467 /******************************************************************************\
468 * SIZ marker segment operations.
469 \******************************************************************************/
470
471 static void jpc_siz_destroyparms(jpc_ms_t *ms)
472 {
473         jpc_siz_t *siz = &ms->parms.siz;
474         if (siz->comps) {
475                 jas_free(siz->comps);
476         }
477 }
478
479 static int jpc_siz_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
480   jas_stream_t *in)
481 {
482         jpc_siz_t *siz = &ms->parms.siz;
483         unsigned int i;
484         uint_fast8_t tmp;
485
486         /* Eliminate compiler warning about unused variables. */
487         cstate = 0;
488
489         if (jpc_getuint16(in, &siz->caps) ||
490           jpc_getuint32(in, &siz->width) ||
491           jpc_getuint32(in, &siz->height) ||
492           jpc_getuint32(in, &siz->xoff) ||
493           jpc_getuint32(in, &siz->yoff) ||
494           jpc_getuint32(in, &siz->tilewidth) ||
495           jpc_getuint32(in, &siz->tileheight) ||
496           jpc_getuint32(in, &siz->tilexoff) ||
497           jpc_getuint32(in, &siz->tileyoff) ||
498           jpc_getuint16(in, &siz->numcomps)) {
499                 return -1;
500         }
501         if (!siz->width || !siz->height || !siz->tilewidth ||
502           !siz->tileheight || !siz->numcomps) {
503                 return -1;
504         }
505         if (!(siz->comps = jas_malloc(siz->numcomps * sizeof(jpc_sizcomp_t)))) {
506                 return -1;
507         }
508         for (i = 0; i < siz->numcomps; ++i) {
509                 if (jpc_getuint8(in, &tmp) ||
510                   jpc_getuint8(in, &siz->comps[i].hsamp) ||
511                   jpc_getuint8(in, &siz->comps[i].vsamp)) {
512                         jas_free(siz->comps);
513                         return -1;
514                 }
515                 siz->comps[i].sgnd = (tmp >> 7) & 1;
516                 siz->comps[i].prec = (tmp & 0x7f) + 1;
517         }
518         if (jas_stream_eof(in)) {
519                 jas_free(siz->comps);
520                 return -1;
521         }
522         return 0;
523 }
524
525 static int jpc_siz_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
526 {
527         jpc_siz_t *siz = &ms->parms.siz;
528         unsigned int i;
529
530         /* Eliminate compiler warning about unused variables. */
531         cstate = 0;
532
533         assert(siz->width && siz->height && siz->tilewidth &&
534           siz->tileheight && siz->numcomps);
535         if (jpc_putuint16(out, siz->caps) ||
536           jpc_putuint32(out, siz->width) ||
537           jpc_putuint32(out, siz->height) ||
538           jpc_putuint32(out, siz->xoff) ||
539           jpc_putuint32(out, siz->yoff) ||
540           jpc_putuint32(out, siz->tilewidth) ||
541           jpc_putuint32(out, siz->tileheight) ||
542           jpc_putuint32(out, siz->tilexoff) ||
543           jpc_putuint32(out, siz->tileyoff) ||
544           jpc_putuint16(out, siz->numcomps)) {
545                 return -1;
546         }
547         for (i = 0; i < siz->numcomps; ++i) {
548                 if (jpc_putuint8(out, ((siz->comps[i].sgnd & 1) << 7) |
549                   ((siz->comps[i].prec - 1) & 0x7f)) ||
550                   jpc_putuint8(out, siz->comps[i].hsamp) ||
551                   jpc_putuint8(out, siz->comps[i].vsamp)) {
552                         return -1;
553                 }
554         }
555         return 0;
556 }
557
558 static int jpc_siz_dumpparms(jpc_ms_t *ms, FILE *out)
559 {
560         jpc_siz_t *siz = &ms->parms.siz;
561         unsigned int i;
562         fprintf(out, "caps = 0x%02x;\n", siz->caps);
563         fprintf(out, "width = %d; height = %d; xoff = %d; yoff = %d;\n",
564           siz->width, siz->height, siz->xoff, siz->yoff);
565         fprintf(out, "tilewidth = %d; tileheight = %d; tilexoff = %d; "
566           "tileyoff = %d;\n", siz->tilewidth, siz->tileheight, siz->tilexoff,
567           siz->tileyoff);
568         for (i = 0; i < siz->numcomps; ++i) {
569                 fprintf(out, "prec[%d] = %d; sgnd[%d] = %d; hsamp[%d] = %d; "
570                   "vsamp[%d] = %d\n", i, siz->comps[i].prec, i,
571                   siz->comps[i].sgnd, i, siz->comps[i].hsamp, i,
572                   siz->comps[i].vsamp);
573         }
574         return 0;
575 }
576
577 /******************************************************************************\
578 * COD marker segment operations.
579 \******************************************************************************/
580
581 static void jpc_cod_destroyparms(jpc_ms_t *ms)
582 {
583         jpc_cod_t *cod = &ms->parms.cod;
584         jpc_cox_destroycompparms(&cod->compparms);
585 }
586
587 static int jpc_cod_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
588 {
589         jpc_cod_t *cod = &ms->parms.cod;
590         if (jpc_getuint8(in, &cod->csty)) {
591                 return -1;
592         }
593         if (jpc_getuint8(in, &cod->prg) ||
594           jpc_getuint16(in, &cod->numlyrs) ||
595           jpc_getuint8(in, &cod->mctrans)) {
596                 return -1;
597         }
598         if (jpc_cox_getcompparms(ms, cstate, in,
599           (cod->csty & JPC_COX_PRT) != 0, &cod->compparms)) {
600                 return -1;
601         }
602         if (jas_stream_eof(in)) {
603                 jpc_cod_destroyparms(ms);
604                 return -1;
605         }
606         return 0;
607 }
608
609 static int jpc_cod_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
610 {
611         jpc_cod_t *cod = &ms->parms.cod;
612         assert(cod->numlyrs > 0 && cod->compparms.numdlvls <= 32);
613         assert(cod->compparms.numdlvls == cod->compparms.numrlvls - 1);
614         if (jpc_putuint8(out, cod->compparms.csty) ||
615           jpc_putuint8(out, cod->prg) ||
616           jpc_putuint16(out, cod->numlyrs) ||
617           jpc_putuint8(out, cod->mctrans)) {
618                 return -1;
619         }
620         if (jpc_cox_putcompparms(ms, cstate, out,
621           (cod->csty & JPC_COX_PRT) != 0, &cod->compparms)) {
622                 return -1;
623         }
624         return 0;
625 }
626
627 static int jpc_cod_dumpparms(jpc_ms_t *ms, FILE *out)
628 {
629         jpc_cod_t *cod = &ms->parms.cod;
630         int i;
631         fprintf(out, "csty = 0x%02x;\n", cod->compparms.csty);
632         fprintf(out, "numdlvls = %d; qmfbid = %d; mctrans = %d\n",
633           cod->compparms.numdlvls, cod->compparms.qmfbid, cod->mctrans);
634         fprintf(out, "prg = %d; numlyrs = %d;\n",
635           cod->prg, cod->numlyrs);
636         fprintf(out, "cblkwidthval = %d; cblkheightval = %d; "
637           "cblksty = 0x%02x;\n", cod->compparms.cblkwidthval, cod->compparms.cblkheightval,
638           cod->compparms.cblksty);
639         if (cod->csty & JPC_COX_PRT) {
640                 for (i = 0; i < cod->compparms.numrlvls; ++i) {
641                         jas_eprintf("prcwidth[%d] = %d, prcheight[%d] = %d\n",
642                           i, cod->compparms.rlvls[i].parwidthval,
643                           i, cod->compparms.rlvls[i].parheightval);
644                 }
645         }
646         return 0;
647 }
648
649 /******************************************************************************\
650 * COC marker segment operations.
651 \******************************************************************************/
652
653 static void jpc_coc_destroyparms(jpc_ms_t *ms)
654 {
655         jpc_coc_t *coc = &ms->parms.coc;
656         jpc_cox_destroycompparms(&coc->compparms);
657 }
658
659 static int jpc_coc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
660 {
661         jpc_coc_t *coc = &ms->parms.coc;
662         uint_fast8_t tmp;
663         if (cstate->numcomps <= 256) {
664                 if (jpc_getuint8(in, &tmp)) {
665                         return -1;
666                 }
667                 coc->compno = tmp;
668         } else {
669                 if (jpc_getuint16(in, &coc->compno)) {
670                         return -1;
671                 }
672         }
673         if (jpc_getuint8(in, &coc->compparms.csty)) {
674                 return -1;
675         }
676         if (jpc_cox_getcompparms(ms, cstate, in,
677           (coc->compparms.csty & JPC_COX_PRT) != 0, &coc->compparms)) {
678                 return -1;
679         }
680         if (jas_stream_eof(in)) {
681                 return -1;
682         }
683         return 0;
684 }
685
686 static int jpc_coc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
687 {
688         jpc_coc_t *coc = &ms->parms.coc;
689         assert(coc->compparms.numdlvls <= 32);
690         if (cstate->numcomps <= 256) {
691                 if (jpc_putuint8(out, coc->compno)) {
692                         return -1;
693                 }
694         } else {
695                 if (jpc_putuint16(out, coc->compno)) {
696                         return -1;
697                 }
698         }
699         if (jpc_putuint8(out, coc->compparms.csty)) {
700                 return -1;
701         }
702         if (jpc_cox_putcompparms(ms, cstate, out,
703           (coc->compparms.csty & JPC_COX_PRT) != 0, &coc->compparms)) {
704                 return -1;
705         }
706         return 0;
707 }
708
709 static int jpc_coc_dumpparms(jpc_ms_t *ms, FILE *out)
710 {
711         jpc_coc_t *coc = &ms->parms.coc;
712         fprintf(out, "compno = %d; csty = 0x%02x; numdlvls = %d;\n",
713           coc->compno, coc->compparms.csty, coc->compparms.numdlvls);
714         fprintf(out, "cblkwidthval = %d; cblkheightval = %d; "
715           "cblksty = 0x%02x; qmfbid = %d;\n", coc->compparms.cblkwidthval,
716           coc->compparms.cblkheightval, coc->compparms.cblksty, coc->compparms.qmfbid);
717         return 0;
718 }
719 /******************************************************************************\
720 * COD/COC marker segment operation helper functions.
721 \******************************************************************************/
722
723 static void jpc_cox_destroycompparms(jpc_coxcp_t *compparms)
724 {
725         /* Eliminate compiler warning about unused variables. */
726         compparms = 0;
727 }
728
729 static int jpc_cox_getcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
730   jas_stream_t *in, int prtflag, jpc_coxcp_t *compparms)
731 {
732         uint_fast8_t tmp;
733         int i;
734
735         /* Eliminate compiler warning about unused variables. */
736         ms = 0;
737         cstate = 0;
738
739         if (jpc_getuint8(in, &compparms->numdlvls) ||
740           jpc_getuint8(in, &compparms->cblkwidthval) ||
741           jpc_getuint8(in, &compparms->cblkheightval) ||
742           jpc_getuint8(in, &compparms->cblksty) ||
743           jpc_getuint8(in, &compparms->qmfbid)) {
744                 return -1;
745         }
746         compparms->numrlvls = compparms->numdlvls + 1;
747         if (prtflag) {
748                 for (i = 0; i < compparms->numrlvls; ++i) {
749                         if (jpc_getuint8(in, &tmp)) {
750                                 jpc_cox_destroycompparms(compparms);
751                                 return -1;
752                         }
753                         compparms->rlvls[i].parwidthval = tmp & 0xf;
754                         compparms->rlvls[i].parheightval = (tmp >> 4) & 0xf;
755                 }
756 /* Sigh.  This bit should be in the same field in both COC and COD mrk segs. */
757 compparms->csty |= JPC_COX_PRT;
758         } else {
759         }
760         if (jas_stream_eof(in)) {
761                 jpc_cox_destroycompparms(compparms);
762                 return -1;
763         }
764         return 0;
765 }
766
767 static int jpc_cox_putcompparms(jpc_ms_t *ms, jpc_cstate_t *cstate,
768   jas_stream_t *out, int prtflag, jpc_coxcp_t *compparms)
769 {
770         int i;
771         assert(compparms->numdlvls <= 32);
772
773         /* Eliminate compiler warning about unused variables. */
774         ms = 0;
775         cstate = 0;
776
777         if (jpc_putuint8(out, compparms->numdlvls) ||
778           jpc_putuint8(out, compparms->cblkwidthval) ||
779           jpc_putuint8(out, compparms->cblkheightval) ||
780           jpc_putuint8(out, compparms->cblksty) ||
781           jpc_putuint8(out, compparms->qmfbid)) {
782                 return -1;
783         }
784         if (prtflag) {
785                 for (i = 0; i < compparms->numrlvls; ++i) {
786                         if (jpc_putuint8(out,
787                           ((compparms->rlvls[i].parheightval & 0xf) << 4) |
788                           (compparms->rlvls[i].parwidthval & 0xf))) {
789                                 return -1;
790                         }
791                 }
792         }
793         return 0;
794 }
795
796 /******************************************************************************\
797 * RGN marker segment operations.
798 \******************************************************************************/
799
800 static int jpc_rgn_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
801 {
802         jpc_rgn_t *rgn = &ms->parms.rgn;
803         uint_fast8_t tmp;
804         if (cstate->numcomps <= 256) {
805                 if (jpc_getuint8(in, &tmp)) {
806                         return -1;
807                 }
808                 rgn->compno = tmp;
809         } else {
810                 if (jpc_getuint16(in, &rgn->compno)) {
811                         return -1;
812                 }
813         }
814         if (jpc_getuint8(in, &rgn->roisty) ||
815           jpc_getuint8(in, &rgn->roishift)) {
816                 return -1;
817         }
818         return 0;
819 }
820
821 static int jpc_rgn_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
822 {
823         jpc_rgn_t *rgn = &ms->parms.rgn;
824         if (cstate->numcomps <= 256) {
825                 if (jpc_putuint8(out, rgn->compno)) {
826                         return -1;
827                 }
828         } else {
829                 if (jpc_putuint16(out, rgn->compno)) {
830                         return -1;
831                 }
832         }
833         if (jpc_putuint8(out, rgn->roisty) ||
834           jpc_putuint8(out, rgn->roishift)) {
835                 return -1;
836         }
837         return 0;
838 }
839
840 static int jpc_rgn_dumpparms(jpc_ms_t *ms, FILE *out)
841 {
842         jpc_rgn_t *rgn = &ms->parms.rgn;
843         fprintf(out, "compno = %d; roisty = %d; roishift = %d\n",
844           rgn->compno, rgn->roisty, rgn->roishift);
845         return 0;
846 }
847
848 /******************************************************************************\
849 * QCD marker segment operations.
850 \******************************************************************************/
851
852 static void jpc_qcd_destroyparms(jpc_ms_t *ms)
853 {
854         jpc_qcd_t *qcd = &ms->parms.qcd;
855         jpc_qcx_destroycompparms(&qcd->compparms);
856 }
857
858 static int jpc_qcd_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
859 {
860         jpc_qcxcp_t *compparms = &ms->parms.qcd.compparms;
861         return jpc_qcx_getcompparms(compparms, cstate, in, ms->len);
862 }
863
864 static int jpc_qcd_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
865 {
866         jpc_qcxcp_t *compparms = &ms->parms.qcd.compparms;
867         return jpc_qcx_putcompparms(compparms, cstate, out);
868 }
869
870 static int jpc_qcd_dumpparms(jpc_ms_t *ms, FILE *out)
871 {
872         jpc_qcd_t *qcd = &ms->parms.qcd;
873         int i;
874         fprintf(out, "qntsty = %d; numguard = %d; numstepsizes = %d\n",
875           (int) qcd->compparms.qntsty, qcd->compparms.numguard, qcd->compparms.numstepsizes);
876         for (i = 0; i < qcd->compparms.numstepsizes; ++i) {
877                 fprintf(out, "expn[%d] = 0x%04x; mant[%d] = 0x%04x;\n",
878                   i, (unsigned) JPC_QCX_GETEXPN(qcd->compparms.stepsizes[i]),
879                   i, (unsigned) JPC_QCX_GETMANT(qcd->compparms.stepsizes[i]));
880         }
881         return 0;
882 }
883
884 /******************************************************************************\
885 * QCC marker segment operations.
886 \******************************************************************************/
887
888 static void jpc_qcc_destroyparms(jpc_ms_t *ms)
889 {
890         jpc_qcc_t *qcc = &ms->parms.qcc;
891         jpc_qcx_destroycompparms(&qcc->compparms);
892 }
893
894 static int jpc_qcc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
895 {
896         jpc_qcc_t *qcc = &ms->parms.qcc;
897         uint_fast8_t tmp;
898         int len;
899         len = ms->len;
900         if (cstate->numcomps <= 256) {
901                 jpc_getuint8(in, &tmp);
902                 qcc->compno = tmp;
903                 --len;
904         } else {
905                 jpc_getuint16(in, &qcc->compno);
906                 len -= 2;
907         }
908         if (jpc_qcx_getcompparms(&qcc->compparms, cstate, in, len)) {
909                 return -1;
910         }
911         if (jas_stream_eof(in)) {
912                 jpc_qcc_destroyparms(ms);
913                 return -1;
914         }
915         return 0;
916 }
917
918 static int jpc_qcc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
919 {
920         jpc_qcc_t *qcc = &ms->parms.qcc;
921         if (cstate->numcomps <= 256) {
922                 jpc_putuint8(out, qcc->compno);
923         } else {
924                 jpc_putuint16(out, qcc->compno);
925         }
926         if (jpc_qcx_putcompparms(&qcc->compparms, cstate, out)) {
927                 return -1;
928         }
929         return 0;
930 }
931
932 static int jpc_qcc_dumpparms(jpc_ms_t *ms, FILE *out)
933 {
934         jpc_qcc_t *qcc = &ms->parms.qcc;
935         int i;
936         fprintf(out, "compno = %d; qntsty = %d; numguard = %d; "
937           "numstepsizes = %d\n", qcc->compno, qcc->compparms.qntsty, qcc->compparms.numguard,
938           qcc->compparms.numstepsizes);
939         for (i = 0; i < qcc->compparms.numstepsizes; ++i) {
940                 fprintf(out, "expn[%d] = 0x%04x; mant[%d] = 0x%04x;\n",
941                   i, (unsigned) JPC_QCX_GETEXPN(qcc->compparms.stepsizes[i]),
942                   i, (unsigned) JPC_QCX_GETMANT(qcc->compparms.stepsizes[i]));
943         }
944         return 0;
945 }
946
947 /******************************************************************************\
948 * QCD/QCC marker segment helper functions.
949 \******************************************************************************/
950
951 static void jpc_qcx_destroycompparms(jpc_qcxcp_t *compparms)
952 {
953         if (compparms->stepsizes) {
954                 jas_free(compparms->stepsizes);
955         }
956 }
957
958 static int jpc_qcx_getcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate,
959   jas_stream_t *in, uint_fast16_t len)
960 {
961         uint_fast8_t tmp;
962         int n;
963         int i;
964
965         /* Eliminate compiler warning about unused variables. */
966         cstate = 0;
967
968         n = 0;
969         jpc_getuint8(in, &tmp);
970         ++n;
971         compparms->qntsty = tmp & 0x1f;
972         compparms->numguard = (tmp >> 5) & 7;
973         switch (compparms->qntsty) {
974         case JPC_QCX_SIQNT:
975                 compparms->numstepsizes = 1;
976                 break;
977         case JPC_QCX_NOQNT:
978                 compparms->numstepsizes = (len - n);
979                 break;
980         case JPC_QCX_SEQNT:
981                 /* XXX - this is a hack */
982                 compparms->numstepsizes = (len - n) / 2;
983                 break;
984         }
985         if (compparms->numstepsizes > 0) {
986                 compparms->stepsizes = jas_malloc(compparms->numstepsizes *
987                   sizeof(uint_fast16_t));
988                 assert(compparms->stepsizes);
989                 for (i = 0; i < compparms->numstepsizes; ++i) {
990                         if (compparms->qntsty == JPC_QCX_NOQNT) {
991                                 jpc_getuint8(in, &tmp);
992                                 compparms->stepsizes[i] = JPC_QCX_EXPN(tmp >> 3);
993                         } else {
994                                 jpc_getuint16(in, &compparms->stepsizes[i]);
995                         }
996                 }
997         } else {
998                 compparms->stepsizes = 0;
999         }
1000         if (jas_stream_error(in) || jas_stream_eof(in)) {
1001                 jpc_qcx_destroycompparms(compparms);
1002                 return -1;
1003         }
1004         return 0;
1005 }
1006
1007 static int jpc_qcx_putcompparms(jpc_qcxcp_t *compparms, jpc_cstate_t *cstate,
1008   jas_stream_t *out)
1009 {
1010         int i;
1011
1012         /* Eliminate compiler warning about unused variables. */
1013         cstate = 0;
1014
1015         jpc_putuint8(out, ((compparms->numguard & 7) << 5) | compparms->qntsty);
1016         for (i = 0; i < compparms->numstepsizes; ++i) {
1017                 if (compparms->qntsty == JPC_QCX_NOQNT) {
1018                         jpc_putuint8(out, JPC_QCX_GETEXPN(
1019                           compparms->stepsizes[i]) << 3);
1020                 } else {
1021                         jpc_putuint16(out, compparms->stepsizes[i]);
1022                 }
1023         }
1024         return 0;
1025 }
1026
1027 /******************************************************************************\
1028 * SOP marker segment operations.
1029 \******************************************************************************/
1030
1031 static int jpc_sop_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1032 {
1033         jpc_sop_t *sop = &ms->parms.sop;
1034
1035         /* Eliminate compiler warning about unused variable. */
1036         cstate = 0;
1037
1038         if (jpc_getuint16(in, &sop->seqno)) {
1039                 return -1;
1040         }
1041         return 0;
1042 }
1043
1044 static int jpc_sop_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1045 {
1046         jpc_sop_t *sop = &ms->parms.sop;
1047
1048         /* Eliminate compiler warning about unused variable. */
1049         cstate = 0;
1050
1051         if (jpc_putuint16(out, sop->seqno)) {
1052                 return -1;
1053         }
1054         return 0;
1055 }
1056
1057 static int jpc_sop_dumpparms(jpc_ms_t *ms, FILE *out)
1058 {
1059         jpc_sop_t *sop = &ms->parms.sop;
1060         fprintf(out, "seqno = %d;\n", sop->seqno);
1061         return 0;
1062 }
1063
1064 /******************************************************************************\
1065 * PPM marker segment operations.
1066 \******************************************************************************/
1067
1068 static void jpc_ppm_destroyparms(jpc_ms_t *ms)
1069 {
1070         jpc_ppm_t *ppm = &ms->parms.ppm;
1071         if (ppm->data) {
1072                 jas_free(ppm->data);
1073         }
1074 }
1075
1076 static int jpc_ppm_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1077 {
1078         jpc_ppm_t *ppm = &ms->parms.ppm;
1079
1080         /* Eliminate compiler warning about unused variables. */
1081         cstate = 0;
1082
1083         ppm->data = 0;
1084
1085         if (ms->len < 1) {
1086                 goto error;
1087         }
1088         if (jpc_getuint8(in, &ppm->ind)) {
1089                 goto error;
1090         }
1091
1092         ppm->len = ms->len - 1;
1093         if (ppm->len > 0) {
1094                 if (!(ppm->data = jas_malloc(ppm->len * sizeof(unsigned char)))) {
1095                         goto error;
1096                 }
1097                 if (JAS_CAST(uint, jas_stream_read(in, ppm->data, ppm->len)) != ppm->len) {
1098                         goto error;
1099                 }
1100         } else {
1101                 ppm->data = 0;
1102         }
1103         return 0;
1104
1105 error:
1106         jpc_ppm_destroyparms(ms);
1107         return -1;
1108 }
1109
1110 static int jpc_ppm_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1111 {
1112         jpc_ppm_t *ppm = &ms->parms.ppm;
1113
1114         /* Eliminate compiler warning about unused variables. */
1115         cstate = 0;
1116
1117         if (JAS_CAST(uint, jas_stream_write(out, (char *) ppm->data, ppm->len)) != ppm->len) {
1118                 return -1;
1119         }
1120         return 0;
1121 }
1122
1123 static int jpc_ppm_dumpparms(jpc_ms_t *ms, FILE *out)
1124 {
1125         jpc_ppm_t *ppm = &ms->parms.ppm;
1126         fprintf(out, "ind=%d; len = %d;\n", ppm->ind, ppm->len);
1127         if (ppm->len > 0) {
1128                 fprintf(out, "data =\n");
1129                 jas_memdump(out, ppm->data, ppm->len);
1130         }
1131         return 0;
1132 }
1133
1134 /******************************************************************************\
1135 * PPT marker segment operations.
1136 \******************************************************************************/
1137
1138 static void jpc_ppt_destroyparms(jpc_ms_t *ms)
1139 {
1140         jpc_ppt_t *ppt = &ms->parms.ppt;
1141         if (ppt->data) {
1142                 jas_free(ppt->data);
1143         }
1144 }
1145
1146 static int jpc_ppt_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1147 {
1148         jpc_ppt_t *ppt = &ms->parms.ppt;
1149
1150         /* Eliminate compiler warning about unused variables. */
1151         cstate = 0;
1152
1153         ppt->data = 0;
1154
1155         if (ms->len < 1) {
1156                 goto error;
1157         }
1158         if (jpc_getuint8(in, &ppt->ind)) {
1159                 goto error;
1160         }
1161         ppt->len = ms->len - 1;
1162         if (ppt->len > 0) {
1163                 if (!(ppt->data = jas_malloc(ppt->len * sizeof(unsigned char)))) {
1164                         goto error;
1165                 }
1166                 if (jas_stream_read(in, (char *) ppt->data, ppt->len) != JAS_CAST(int, ppt->len)) {
1167                         goto error;
1168                 }
1169         } else {
1170                 ppt->data = 0;
1171         }
1172         return 0;
1173
1174 error:
1175         jpc_ppt_destroyparms(ms);
1176         return -1;
1177 }
1178
1179 static int jpc_ppt_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1180 {
1181         jpc_ppt_t *ppt = &ms->parms.ppt;
1182
1183         /* Eliminate compiler warning about unused variable. */
1184         cstate = 0;
1185
1186         if (jpc_putuint8(out, ppt->ind)) {
1187                 return -1;
1188         }
1189         if (jas_stream_write(out, (char *) ppt->data, ppt->len) != JAS_CAST(int, ppt->len)) {
1190                 return -1;
1191         }
1192         return 0;
1193 }
1194
1195 static int jpc_ppt_dumpparms(jpc_ms_t *ms, FILE *out)
1196 {
1197         jpc_ppt_t *ppt = &ms->parms.ppt;
1198         fprintf(out, "ind=%d; len = %d;\n", ppt->ind, ppt->len);
1199         if (ppt->len > 0) {
1200                 fprintf(out, "data =\n");
1201                 jas_memdump(out, ppt->data, ppt->len);
1202         }
1203         return 0;
1204 }
1205
1206 /******************************************************************************\
1207 * POC marker segment operations.
1208 \******************************************************************************/
1209
1210 static void jpc_poc_destroyparms(jpc_ms_t *ms)
1211 {
1212         jpc_poc_t *poc = &ms->parms.poc;
1213         if (poc->pchgs) {
1214                 jas_free(poc->pchgs);
1215         }
1216 }
1217
1218 static int jpc_poc_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1219 {
1220         jpc_poc_t *poc = &ms->parms.poc;
1221         jpc_pocpchg_t *pchg;
1222         int pchgno;
1223         uint_fast8_t tmp;
1224         poc->numpchgs = (cstate->numcomps > 256) ? (ms->len / 9) :
1225           (ms->len / 7);
1226         if (!(poc->pchgs = jas_malloc(poc->numpchgs * sizeof(jpc_pocpchg_t)))) {
1227                 goto error;
1228         }
1229         for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs; ++pchgno,
1230           ++pchg) {
1231                 if (jpc_getuint8(in, &pchg->rlvlnostart)) {
1232                         goto error;
1233                 }
1234                 if (cstate->numcomps > 256) {
1235                         if (jpc_getuint16(in, &pchg->compnostart)) {
1236                                 goto error;
1237                         }
1238                 } else {
1239                         if (jpc_getuint8(in, &tmp)) {
1240                                 goto error;
1241                         };
1242                         pchg->compnostart = tmp;
1243                 }
1244                 if (jpc_getuint16(in, &pchg->lyrnoend) ||
1245                   jpc_getuint8(in, &pchg->rlvlnoend)) {
1246                         goto error;
1247                 }
1248                 if (cstate->numcomps > 256) {
1249                         if (jpc_getuint16(in, &pchg->compnoend)) {
1250                                 goto error;
1251                         }
1252                 } else {
1253                         if (jpc_getuint8(in, &tmp)) {
1254                                 goto error;
1255                         }
1256                         pchg->compnoend = tmp;
1257                 }
1258                 if (jpc_getuint8(in, &pchg->prgord)) {
1259                         goto error;
1260                 }
1261                 if (pchg->rlvlnostart > pchg->rlvlnoend ||
1262                   pchg->compnostart > pchg->compnoend) {
1263                         goto error;
1264                 }
1265         }
1266         return 0;
1267
1268 error:
1269         jpc_poc_destroyparms(ms);
1270         return -1;
1271 }
1272
1273 static int jpc_poc_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1274 {
1275         jpc_poc_t *poc = &ms->parms.poc;
1276         jpc_pocpchg_t *pchg;
1277         int pchgno;
1278         for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs; ++pchgno,
1279           ++pchg) {
1280                 if (jpc_putuint8(out, pchg->rlvlnostart) ||
1281                   ((cstate->numcomps > 256) ?
1282                   jpc_putuint16(out, pchg->compnostart) :
1283                   jpc_putuint8(out, pchg->compnostart)) ||
1284                   jpc_putuint16(out, pchg->lyrnoend) ||
1285                   jpc_putuint8(out, pchg->rlvlnoend) ||
1286                   ((cstate->numcomps > 256) ?
1287                   jpc_putuint16(out, pchg->compnoend) :
1288                   jpc_putuint8(out, pchg->compnoend)) ||
1289                   jpc_putuint8(out, pchg->prgord)) {
1290                         return -1;
1291                 }
1292         }
1293         return 0;
1294 }
1295
1296 static int jpc_poc_dumpparms(jpc_ms_t *ms, FILE *out)
1297 {
1298         jpc_poc_t *poc = &ms->parms.poc;
1299         jpc_pocpchg_t *pchg;
1300         int pchgno;
1301         for (pchgno = 0, pchg = poc->pchgs; pchgno < poc->numpchgs;
1302           ++pchgno, ++pchg) {
1303                 fprintf(out, "po[%d] = %d; ", pchgno, pchg->prgord);
1304                 fprintf(out, "cs[%d] = %d; ce[%d] = %d; ",
1305                   pchgno, pchg->compnostart, pchgno, pchg->compnoend);
1306                 fprintf(out, "rs[%d] = %d; re[%d] = %d; ",
1307                   pchgno, pchg->rlvlnostart, pchgno, pchg->rlvlnoend);
1308                 fprintf(out, "le[%d] = %d\n", pchgno, pchg->lyrnoend);
1309         }
1310         return 0;
1311 }
1312
1313 /******************************************************************************\
1314 * CRG marker segment operations.
1315 \******************************************************************************/
1316
1317 static void jpc_crg_destroyparms(jpc_ms_t *ms)
1318 {
1319         jpc_crg_t *crg = &ms->parms.crg;
1320         if (crg->comps) {
1321                 jas_free(crg->comps);
1322         }
1323 }
1324
1325 static int jpc_crg_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1326 {
1327         jpc_crg_t *crg = &ms->parms.crg;
1328         jpc_crgcomp_t *comp;
1329         uint_fast16_t compno;
1330         crg->numcomps = cstate->numcomps;
1331         if (!(crg->comps = jas_malloc(cstate->numcomps * sizeof(uint_fast16_t)))) {
1332                 return -1;
1333         }
1334         for (compno = 0, comp = crg->comps; compno < cstate->numcomps;
1335           ++compno, ++comp) {
1336                 if (jpc_getuint16(in, &comp->hoff) ||
1337                   jpc_getuint16(in, &comp->voff)) {
1338                         jpc_crg_destroyparms(ms);
1339                         return -1;
1340                 }
1341         }
1342         return 0;
1343 }
1344
1345 static int jpc_crg_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1346 {
1347         jpc_crg_t *crg = &ms->parms.crg;
1348         int compno;
1349         jpc_crgcomp_t *comp;
1350
1351         /* Eliminate compiler warning about unused variables. */
1352         cstate = 0;
1353
1354         for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno,
1355           ++comp) {
1356                 if (jpc_putuint16(out, comp->hoff) ||
1357                   jpc_putuint16(out, comp->voff)) {
1358                         return -1;
1359                 }
1360         }
1361         return 0;
1362 }
1363
1364 static int jpc_crg_dumpparms(jpc_ms_t *ms, FILE *out)
1365 {
1366         jpc_crg_t *crg = &ms->parms.crg;
1367         int compno;
1368         jpc_crgcomp_t *comp;
1369         for (compno = 0, comp = crg->comps; compno < crg->numcomps; ++compno,
1370           ++comp) {
1371                 fprintf(out, "hoff[%d] = %d; voff[%d] = %d\n", compno,
1372                   comp->hoff, compno, comp->voff);
1373         }
1374         return 0;
1375 }
1376
1377 /******************************************************************************\
1378 * Operations for COM marker segment.
1379 \******************************************************************************/
1380
1381 static void jpc_com_destroyparms(jpc_ms_t *ms)
1382 {
1383         jpc_com_t *com = &ms->parms.com;
1384         if (com->data) {
1385                 jas_free(com->data);
1386         }
1387 }
1388
1389 static int jpc_com_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1390 {
1391         jpc_com_t *com = &ms->parms.com;
1392
1393         /* Eliminate compiler warning about unused variables. */
1394         cstate = 0;
1395
1396         if (jpc_getuint16(in, &com->regid)) {
1397                 return -1;
1398         }
1399         com->len = ms->len - 2;
1400         if (com->len > 0) {
1401                 if (!(com->data = jas_malloc(com->len))) {
1402                         return -1;
1403                 }
1404                 if (jas_stream_read(in, com->data, com->len) != JAS_CAST(int, com->len)) {
1405                         return -1;
1406                 }
1407         } else {
1408                 com->data = 0;
1409         }
1410         return 0;
1411 }
1412
1413 static int jpc_com_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1414 {
1415         jpc_com_t *com = &ms->parms.com;
1416
1417         /* Eliminate compiler warning about unused variables. */
1418         cstate = 0;
1419
1420         if (jpc_putuint16(out, com->regid)) {
1421                 return -1;
1422         }
1423         if (jas_stream_write(out, com->data, com->len) != JAS_CAST(int, com->len)) {
1424                 return -1;
1425         }
1426         return 0;
1427 }
1428
1429 static int jpc_com_dumpparms(jpc_ms_t *ms, FILE *out)
1430 {
1431         jpc_com_t *com = &ms->parms.com;
1432         unsigned int i;
1433         int printable;
1434         fprintf(out, "regid = %d;\n", com->regid);
1435         printable = 1;
1436         for (i = 0; i < com->len; ++i) {
1437                 if (!isprint(com->data[i])) {
1438                         printable = 0;
1439                         break;
1440                 }
1441         }
1442         if (printable) {
1443                 fprintf(out, "data = ");
1444                 fwrite(com->data, sizeof(char), com->len, out);
1445                 fprintf(out, "\n");
1446         }
1447         return 0;
1448 }
1449
1450 /******************************************************************************\
1451 * Operations for unknown types of marker segments.
1452 \******************************************************************************/
1453
1454 static void jpc_unk_destroyparms(jpc_ms_t *ms)
1455 {
1456         jpc_unk_t *unk = &ms->parms.unk;
1457         if (unk->data) {
1458                 jas_free(unk->data);
1459         }
1460 }
1461
1462 static int jpc_unk_getparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *in)
1463 {
1464         jpc_unk_t *unk = &ms->parms.unk;
1465
1466         /* Eliminate compiler warning about unused variables. */
1467         cstate = 0;
1468
1469         if (ms->len > 0) {
1470                 if (!(unk->data = jas_malloc(ms->len * sizeof(unsigned char)))) {
1471                         return -1;
1472                 }
1473                 if (jas_stream_read(in, (char *) unk->data, ms->len) != JAS_CAST(int, ms->len)) {
1474                         jas_free(unk->data);
1475                         return -1;
1476                 }
1477                 unk->len = ms->len;
1478         } else {
1479                 unk->data = 0;
1480                 unk->len = 0;
1481         }
1482         return 0;
1483 }
1484
1485 static int jpc_unk_putparms(jpc_ms_t *ms, jpc_cstate_t *cstate, jas_stream_t *out)
1486 {
1487         /* Eliminate compiler warning about unused variables. */
1488         cstate = 0;
1489         ms = 0;
1490         out = 0;
1491
1492         /* If this function is called, we are trying to write an unsupported
1493           type of marker segment.  Return with an error indication.  */
1494         return -1;
1495 }
1496
1497 static int jpc_unk_dumpparms(jpc_ms_t *ms, FILE *out)
1498 {
1499         unsigned int i;
1500         jpc_unk_t *unk = &ms->parms.unk;
1501         for (i = 0; i < unk->len; ++i) {
1502                 fprintf(out, "%02x ", unk->data[i]);
1503         }
1504         return 0;
1505 }
1506
1507 /******************************************************************************\
1508 * Primitive I/O operations.
1509 \******************************************************************************/
1510
1511 int jpc_getuint8(jas_stream_t *in, uint_fast8_t *val)
1512 {
1513         int c;
1514         if ((c = jas_stream_getc(in)) == EOF) {
1515                 return -1;
1516         }
1517         if (val) {
1518                 *val = c;
1519         }
1520         return 0;
1521 }
1522
1523 int jpc_putuint8(jas_stream_t *out, uint_fast8_t val)
1524 {
1525         if (jas_stream_putc(out, val & 0xff) == EOF) {
1526                 return -1;
1527         }
1528         return 0;
1529 }
1530
1531 int jpc_getuint16(jas_stream_t *in, uint_fast16_t *val)
1532 {
1533         uint_fast16_t v;
1534         int c;
1535         if ((c = jas_stream_getc(in)) == EOF) {
1536                 return -1;
1537         }
1538         v = c;
1539         if ((c = jas_stream_getc(in)) == EOF) {
1540                 return -1;
1541         }
1542         v = (v << 8) | c;
1543         if (val) {
1544                 *val = v;
1545         }
1546         return 0;
1547 }
1548
1549 int jpc_putuint16(jas_stream_t *out, uint_fast16_t val)
1550 {
1551         if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
1552           jas_stream_putc(out, val & 0xff) == EOF) {
1553                 return -1;
1554         }
1555         return 0;
1556 }
1557
1558 int jpc_getuint32(jas_stream_t *in, uint_fast32_t *val)
1559 {
1560         uint_fast32_t v;
1561         int c;
1562         if ((c = jas_stream_getc(in)) == EOF) {
1563                 return -1;
1564         }
1565         v = c;
1566         if ((c = jas_stream_getc(in)) == EOF) {
1567                 return -1;
1568         }
1569         v = (v << 8) | c;
1570         if ((c = jas_stream_getc(in)) == EOF) {
1571                 return -1;
1572         }
1573         v = (v << 8) | c;
1574         if ((c = jas_stream_getc(in)) == EOF) {
1575                 return -1;
1576         }
1577         v = (v << 8) | c;
1578         if (val) {
1579                 *val = v;
1580         }
1581         return 0;
1582 }
1583
1584 int jpc_putuint32(jas_stream_t *out, uint_fast32_t val)
1585 {
1586         if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF ||
1587           jas_stream_putc(out, (val >> 16) & 0xff) == EOF ||
1588           jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
1589           jas_stream_putc(out, val & 0xff) == EOF) {
1590                 return -1;
1591         }
1592         return 0;
1593 }
1594
1595 /******************************************************************************\
1596 * Miscellany
1597 \******************************************************************************/
1598
1599 static jpc_mstabent_t *jpc_mstab_lookup(int id)
1600 {
1601         jpc_mstabent_t *mstabent;
1602         for (mstabent = jpc_mstab;; ++mstabent) {
1603                 if (mstabent->id == id || mstabent->id < 0) {
1604                         return mstabent;
1605                 }
1606         }
1607         assert(0);
1608         return 0;
1609 }
1610
1611 int jpc_validate(jas_stream_t *in)
1612 {
1613         int n;
1614         int i;
1615         unsigned char buf[2];
1616
1617         assert(JAS_STREAM_MAXPUTBACK >= 2);
1618
1619         if ((n = jas_stream_read(in, (char *) buf, 2)) < 0) {
1620                 return -1;
1621         }
1622         for (i = n - 1; i >= 0; --i) {
1623                 if (jas_stream_ungetc(in, buf[i]) == EOF) {
1624                         return -1;
1625                 }
1626         }
1627         if (n < 2) {
1628                 return -1;
1629         }
1630         if (buf[0] == (JPC_MS_SOC >> 8) && buf[1] == (JPC_MS_SOC & 0xff)) {
1631                 return 0;
1632         }
1633         return -1;
1634 }
1635
1636 int jpc_getdata(jas_stream_t *in, jas_stream_t *out, long len)
1637 {
1638         return jas_stream_copy(out, in, len);
1639 }
1640
1641 int jpc_putdata(jas_stream_t *out, jas_stream_t *in, long len)
1642 {
1643         return jas_stream_copy(out, in, len);
1644 }