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 Software License
11 *
12 * IMAGE POWER JPEG-2000 PUBLIC LICENSE
13 * ************************************
14 *
15 * GRANT:
16 *
17 * Permission is hereby granted, free of charge, to any person (the "User")
18 * obtaining a copy of this software and associated documentation, to deal
19 * in the JasPer Software without restriction, including without limitation
20 * the right to use, copy, modify, merge, publish, distribute, sublicense,
21 * and/or sell copies of the JasPer Software (in source and binary forms),
22 * and to permit persons to whom the JasPer Software is furnished to do so,
23 * provided further that the License Conditions below are met.
24 *
25 * License Conditions
26 * ******************
27 *
28 * A. Redistributions of source code must retain the above copyright notice,
29 * and this list of conditions, and the following disclaimer.
30 *
31 * B. Redistributions in binary form must reproduce the above copyright
32 * notice, and this list of conditions, and the following disclaimer in
33 * the documentation and/or other materials provided with the distribution.
34 *
35 * C. Neither the name of Image Power, Inc. nor any other contributor
36 * (including, but not limited to, the University of British Columbia and
37 * Michael David Adams) may be used to endorse or promote products derived
38 * from this software without specific prior written permission.
39 *
40 * D. User agrees that it shall not commence any action against Image Power,
41 * Inc., the University of British Columbia, Michael David Adams, or any
42 * other contributors (collectively "Licensors") for infringement of any
43 * intellectual property rights ("IPR") held by the User in respect of any
44 * technology that User owns or has a right to license or sublicense and
45 * which is an element required in order to claim compliance with ISO/IEC
46 * 15444-1 (i.e., JPEG-2000 Part 1). "IPR" means all intellectual property
47 * rights worldwide arising under statutory or common law, and whether
48 * or not perfected, including, without limitation, all (i) patents and
49 * patent applications owned or licensable by User; (ii) rights associated
50 * with works of authorship including copyrights, copyright applications,
51 * copyright registrations, mask work rights, mask work applications,
52 * mask work registrations; (iii) rights relating to the protection of
53 * trade secrets and confidential information; (iv) any right analogous
54 * to those set forth in subsections (i), (ii), or (iii) and any other
55 * proprietary rights relating to intangible property (other than trademark,
56 * trade dress, or service mark rights); and (v) divisions, continuations,
57 * renewals, reissues and extensions of the foregoing (as and to the extent
58 * applicable) now existing, hereafter filed, issued or acquired.
59 *
60 * E. If User commences an infringement action against any Licensor(s) then
61 * such Licensor(s) shall have the right to terminate User's license and
62 * all sublicenses that have been granted hereunder by User to other parties.
63 *
64 * F. This software is for use only in hardware or software products that
65 * are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1). No license
66 * or right to this Software is granted for products that do not comply
67 * with ISO/IEC 15444-1. The JPEG-2000 Part 1 standard can be purchased
68 * from the ISO.
69 *
70 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
71 * NO USE OF THE JASPER SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
72 * THIS DISCLAIMER. THE JASPER SOFTWARE IS PROVIDED BY THE LICENSORS AND
73 * CONTRIBUTORS UNDER THIS LICENSE ON AN ``AS-IS'' BASIS, WITHOUT WARRANTY
74 * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
75 * WARRANTIES THAT THE JASPER SOFTWARE IS FREE OF DEFECTS, IS MERCHANTABLE,
76 * IS FIT FOR A PARTICULAR PURPOSE OR IS NON-INFRINGING. THOSE INTENDING
77 * TO USE THE JASPER SOFTWARE OR MODIFICATIONS THEREOF FOR USE IN HARDWARE
78 * OR SOFTWARE PRODUCTS ARE ADVISED THAT THEIR USE MAY INFRINGE EXISTING
79 * PATENTS, COPYRIGHTS, TRADEMARKS, OR OTHER INTELLECTUAL PROPERTY RIGHTS.
80 * THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE JASPER SOFTWARE
81 * IS WITH THE USER. SHOULD ANY PART OF THE JASPER SOFTWARE PROVE DEFECTIVE
82 * IN ANY RESPECT, THE USER (AND NOT THE INITIAL DEVELOPERS, THE UNIVERSITY
83 * OF BRITISH COLUMBIA, IMAGE POWER, INC., MICHAEL DAVID ADAMS, OR ANY
84 * OTHER CONTRIBUTOR) SHALL ASSUME THE COST OF ANY NECESSARY SERVICING,
85 * REPAIR OR CORRECTION. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY,
86 * WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE
87 * INITIAL DEVELOPER, THE UNIVERSITY OF BRITISH COLUMBIA, IMAGE POWER, INC.,
88 * MICHAEL DAVID ADAMS, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE
89 * JASPER SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO
90 * THE USER OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
91 * CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION,
92 * DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR
93 * MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF
94 * SUCH PARTY HAD BEEN INFORMED, OR OUGHT TO HAVE KNOWN, OF THE POSSIBILITY
95 * OF SUCH DAMAGES. THE JASPER SOFTWARE AND UNDERLYING TECHNOLOGY ARE NOT
96 * FAULT-TOLERANT AND ARE NOT DESIGNED, MANUFACTURED OR INTENDED FOR USE OR
97 * RESALE AS ON-LINE CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING
98 * FAIL-SAFE PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES,
99 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT
100 * LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
101 * JASPER SOFTWARE OR UNDERLYING TECHNOLOGY OR PRODUCT COULD LEAD DIRECTLY
102 * TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE
103 * ("HIGH RISK ACTIVITIES"). LICENSOR SPECIFICALLY DISCLAIMS ANY EXPRESS
104 * OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. USER WILL NOT
105 * KNOWINGLY USE, DISTRIBUTE OR RESELL THE JASPER SOFTWARE OR UNDERLYING
106 * TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS
107 * CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE
108 * NOTICE SPECIFIED IN THIS SECTION.
109 *
110 * __END_OF_JASPER_LICENSE__
111 */
112
113 /*
114 * JP2 Library
115 *
116 * $Id$
117 */
118
119 /******************************************************************************\
120 * Includes.
121 \******************************************************************************/
122
123 #include <assert.h>
124 #include <stdlib.h>
125
126 #include "netpbm/pm_c_util.h"
127
128 #include "jasper/jas_stream.h"
129 #include "jasper/jas_malloc.h"
130 #include "jasper/jas_debug.h"
131
132 #include "jp2_cod.h"
133
134 /******************************************************************************\
135 * Function prototypes.
136 \******************************************************************************/
137
138 #define ONES(n) ((1 << (n)) - 1)
139
140 jp2_boxinfo_t *jp2_boxinfolookup(int type);
141
142 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val);
143 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val);
144 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val);
145 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val);
146 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val);
147 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val);
148 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val);
149
150 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val);
151
152 jp2_box_t *jp2_box_get(jas_stream_t *in);
153 void jp2_box_dump(jp2_box_t *box, FILE *out);
154
155 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in);
156 static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out);
157 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in);
158 static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out);
159 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in);
160 static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out);
161 static void jp2_bpcc_destroy(jp2_box_t *box);
162 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in);
163 static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out);
164 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in);
165 static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out);
166 static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out);
167 static void jp2_colr_destroy(jp2_box_t *box);
168 static void jp2_cdef_destroy(jp2_box_t *box);
169 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in);
170 static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out);
171 static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out);
172 static void jp2_cmap_destroy(jp2_box_t *box);
173 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in);
174 static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out);
175 static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out);
176 static void jp2_pclr_destroy(jp2_box_t *box);
177 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in);
178 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out);
179 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out);
180
181 /******************************************************************************\
182 * Local data.
183 \******************************************************************************/
184
185 jp2_boxinfo_t jp2_boxinfos[] = {
186 {JP2_BOX_JP, "JP", 0,
187 {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}},
188 {JP2_BOX_FTYP, "FTYP", 0,
189 {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}},
190 {JP2_BOX_JP2H, "JP2H", JP2_BOX_SUPER,
191 {0, 0, 0, 0, 0}},
192 {JP2_BOX_IHDR, "IHDR", 0,
193 {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}},
194 {JP2_BOX_BPCC, "BPCC", 0,
195 {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}},
196 {JP2_BOX_COLR, "COLR", 0,
197 {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}},
198 {JP2_BOX_PCLR, "PCLR", 0,
199 {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}},
200 {JP2_BOX_CMAP, "CMAP", 0,
201 {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}},
202 {JP2_BOX_CDEF, "CDEF", 0,
203 {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}},
204 {JP2_BOX_RES, "RES", JP2_BOX_SUPER,
205 {0, 0, 0, 0, 0}},
206 {JP2_BOX_RESC, "RESC", 0,
207 {0, 0, 0, 0, 0}},
208 {JP2_BOX_RESD, "RESD", 0,
209 {0, 0, 0, 0, 0}},
210 {JP2_BOX_JP2C, "JP2C", JP2_BOX_NODATA,
211 {0, 0, 0, 0, 0}},
212 {JP2_BOX_JP2I, "JP2I", 0,
213 {0, 0, 0, 0, 0}},
214 {JP2_BOX_XML, "XML", 0,
215 {0, 0, 0, 0, 0}},
216 {JP2_BOX_UUID, "UUID", 0,
217 {0, 0, 0, 0, 0}},
218 {JP2_BOX_UINF, "UINF", JP2_BOX_SUPER,
219 {0, 0, 0, 0, 0}},
220 {JP2_BOX_ULST, "ULST", 0,
221 {0, 0, 0, 0, 0}},
222 {JP2_BOX_URL, "URL", 0,
223 {0, 0, 0, 0, 0}},
224 {0, 0, 0, {0, 0, 0, 0, 0}},
225 };
226
227 jp2_boxinfo_t jp2_boxinfo_unk = {
228 0, "Unknown", 0, {0, 0, 0, 0}
229 };
230
231 /******************************************************************************\
232 * Box constructor.
233 \******************************************************************************/
234
jp2_box_create(int type)235 jp2_box_t *jp2_box_create(int type)
236 {
237 jp2_box_t *box;
238 jp2_boxinfo_t *boxinfo;
239
240 if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
241 return 0;
242 }
243 memset(box, 0, sizeof(jp2_box_t));
244 box->type = type;
245 box->len = 0;
246 if (!(boxinfo = jp2_boxinfolookup(type))) {
247 return 0;
248 }
249 box->info = boxinfo;
250 box->ops = &boxinfo->ops;
251 return box;
252 }
253
254 /******************************************************************************\
255 * Box destructor.
256 \******************************************************************************/
257
jp2_box_destroy(jp2_box_t * box)258 void jp2_box_destroy(jp2_box_t *box)
259 {
260 if (box->ops->destroy) {
261 (*box->ops->destroy)(box);
262 }
263 jas_free(box);
264 }
265
jp2_bpcc_destroy(jp2_box_t * box)266 static void jp2_bpcc_destroy(jp2_box_t *box)
267 {
268 jp2_bpcc_t *bpcc = &box->data.bpcc;
269 if (bpcc->bpcs) {
270 jas_free(bpcc->bpcs);
271 bpcc->bpcs = 0;
272 }
273 }
274
jp2_cdef_destroy(jp2_box_t * box)275 static void jp2_cdef_destroy(jp2_box_t *box)
276 {
277 jp2_cdef_t *cdef = &box->data.cdef;
278 if (cdef->ents) {
279 jas_free(cdef->ents);
280 cdef->ents = 0;
281 }
282 }
283
284 /******************************************************************************\
285 * Box input.
286 \******************************************************************************/
287
jp2_box_get(jas_stream_t * in)288 jp2_box_t *jp2_box_get(jas_stream_t *in)
289 {
290 jp2_box_t *box;
291 jp2_boxinfo_t *boxinfo;
292 jas_stream_t *tmpstream;
293 uint_fast32_t len;
294 uint_fast64_t extlen;
295 bool dataflag;
296
297 box = 0;
298 tmpstream = 0;
299
300 if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
301 goto error;
302 }
303 box->ops = &jp2_boxinfo_unk.ops;
304 if (jp2_getuint32(in, &len) || jp2_getuint32(in, &box->type)) {
305 goto error;
306 }
307 boxinfo = jp2_boxinfolookup(box->type);
308 box->info = boxinfo;
309 box->ops = &boxinfo->ops;
310 box->len = len;
311 if (box->len == 1) {
312 if (jp2_getuint64(in, &extlen)) {
313 goto error;
314 }
315 box->len = extlen;
316 }
317 if (box->len != 0 && box->len < 8) {
318 goto error;
319 }
320
321 dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA));
322
323 if (dataflag) {
324 if (!(tmpstream = jas_stream_memopen(0, 0))) {
325 goto error;
326 }
327 if (jas_stream_copy(tmpstream, in, box->len - JP2_BOX_HDRLEN)) {
328 goto error;
329 }
330 jas_stream_rewind(tmpstream);
331
332 if (box->ops->getdata) {
333 if ((*box->ops->getdata)(box, tmpstream)) {
334 goto error;
335 }
336 }
337 jas_stream_close(tmpstream);
338 }
339
340 if (jas_getdbglevel() > 0) {
341 jp2_box_dump(box, stderr);
342 }
343 return box;
344 abort();
345
346 error:
347 if (box) {
348 jp2_box_destroy(box);
349 }
350 if (tmpstream) {
351 jas_stream_close(tmpstream);
352 }
353 return 0;
354 }
355
jp2_box_dump(jp2_box_t * box,FILE * out)356 void jp2_box_dump(jp2_box_t *box, FILE *out)
357 {
358 jp2_boxinfo_t *boxinfo;
359 boxinfo = jp2_boxinfolookup(box->type);
360 assert(boxinfo);
361
362 fprintf(out, "JP2 box: ");
363 fprintf(out, "type=%c%s%c (0x%08x); length=%d\n", '"', boxinfo->name,
364 '"', (unsigned int) box->type, (int)box->len);
365 if (box->ops->dumpdata) {
366 (*box->ops->dumpdata)(box, out);
367 }
368 }
369
jp2_jp_getdata(jp2_box_t * box,jas_stream_t * in)370 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in)
371 {
372 jp2_jp_t *jp = &box->data.jp;
373 if (jp2_getuint32(in, &jp->magic)) {
374 return -1;
375 }
376 return 0;
377 }
378
jp2_ftyp_getdata(jp2_box_t * box,jas_stream_t * in)379 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in)
380 {
381 jp2_ftyp_t *ftyp = &box->data.ftyp;
382 int i;
383 if (jp2_getuint32(in, &ftyp->majver) || jp2_getuint32(in, &ftyp->minver)) {
384 return -1;
385 }
386 ftyp->numcompatcodes = ((box->len - JP2_BOX_HDRLEN) - 8) / 4;
387 if (ftyp->numcompatcodes > JP2_FTYP_MAXCOMPATCODES) {
388 return -1;
389 }
390 for (i = 0; i < ftyp->numcompatcodes; ++i) {
391 if (jp2_getuint32(in, &ftyp->compatcodes[i])) {
392 return -1;
393 }
394 }
395 return 0;
396 }
397
jp2_ihdr_getdata(jp2_box_t * box,jas_stream_t * in)398 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in)
399 {
400 jp2_ihdr_t *ihdr = &box->data.ihdr;
401 if (jp2_getuint32(in, &ihdr->height) || jp2_getuint32(in, &ihdr->width) ||
402 jp2_getuint16(in, &ihdr->numcmpts) || jp2_getuint8(in, &ihdr->bpc) ||
403 jp2_getuint8(in, &ihdr->comptype) || jp2_getuint8(in, &ihdr->csunk) ||
404 jp2_getuint8(in, &ihdr->ipr)) {
405 return -1;
406 }
407 return 0;
408 }
409
jp2_bpcc_getdata(jp2_box_t * box,jas_stream_t * in)410 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in)
411 {
412 jp2_bpcc_t *bpcc = &box->data.bpcc;
413 int i;
414 bpcc->numcmpts = box->len - JP2_BOX_HDRLEN;
415 if (!(bpcc->bpcs = jas_malloc(bpcc->numcmpts * sizeof(uint_fast8_t)))) {
416 return -1;
417 }
418 for (i = 0; i < bpcc->numcmpts; ++i) {
419 if (jp2_getuint8(in, &bpcc->bpcs[i])) {
420 return -1;
421 }
422 }
423 return 0;
424 }
425
jp2_colr_dumpdata(jp2_box_t * box,FILE * out)426 static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out)
427 {
428 jp2_colr_t *colr = &box->data.colr;
429 fprintf(out, "method=%d; pri=%d; approx=%d\n", (int)colr->method, (int)colr->pri, (int)colr->approx);
430 switch (colr->method) {
431 case JP2_COLR_ENUM:
432 fprintf(out, "csid=%d\n", (int)colr->csid);
433 break;
434 case JP2_COLR_ICC:
435 jas_memdump(out, colr->iccp, colr->iccplen);
436 break;
437 }
438 }
439
jp2_colr_getdata(jp2_box_t * box,jas_stream_t * in)440 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in)
441 {
442 jp2_colr_t *colr = &box->data.colr;
443 colr->csid = 0;
444 colr->iccp = 0;
445 colr->iccplen = 0;
446
447 if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) ||
448 jp2_getuint8(in, &colr->approx)) {
449 return -1;
450 }
451 switch (colr->method) {
452 case JP2_COLR_ENUM:
453 if (jp2_getuint32(in, &colr->csid)) {
454 return -1;
455 }
456 break;
457 case JP2_COLR_ICC:
458 colr->iccplen = box->len - JP2_BOX_HDRLEN - 3;
459 if (!(colr->iccp = jas_malloc(colr->iccplen * sizeof(uint_fast8_t)))) {
460 return -1;
461 }
462 if (jas_stream_read(in, colr->iccp, colr->iccplen) != colr->iccplen) {
463 return -1;
464 }
465 break;
466 }
467 return 0;
468 }
469
jp2_cdef_dumpdata(jp2_box_t * box,FILE * out)470 static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out)
471 {
472 jp2_cdef_t *cdef = &box->data.cdef;
473 int i;
474 for (i = 0; i < cdef->numchans; ++i) {
475 fprintf(out, "channo=%d; type=%d; assoc=%d\n",
476 (int)cdef->ents[i].channo, (int)cdef->ents[i].type,
477 (int)cdef->ents[i].assoc);
478 }
479 }
480
jp2_colr_destroy(jp2_box_t * box)481 static void jp2_colr_destroy(jp2_box_t *box)
482 {
483 jp2_colr_t *colr = &box->data.colr;
484 if (colr->iccp) {
485 free(colr->iccp);
486 }
487 }
488
jp2_cdef_getdata(jp2_box_t * box,jas_stream_t * in)489 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in)
490 {
491 jp2_cdef_t *cdef = &box->data.cdef;
492 jp2_cdefchan_t *chan;
493 int channo;
494 if (jp2_getuint16(in, &cdef->numchans)) {
495 return -1;
496 }
497 if (!(cdef->ents = jas_malloc(cdef->numchans * sizeof(jp2_cdefchan_t)))) {
498 return -1;
499 }
500 for (channo = 0; channo < cdef->numchans; ++channo) {
501 chan = &cdef->ents[channo];
502 if (jp2_getuint16(in, &chan->channo) || jp2_getuint16(in, &chan->type) ||
503 jp2_getuint16(in, &chan->assoc)) {
504 return -1;
505 }
506 }
507 return 0;
508 }
509
510 /******************************************************************************\
511 * Box output.
512 \******************************************************************************/
513
jp2_box_put(jp2_box_t * box,jas_stream_t * out)514 int jp2_box_put(jp2_box_t *box, jas_stream_t *out)
515 {
516 jas_stream_t *tmpstream;
517 bool dataflag;
518
519 tmpstream = 0;
520
521 dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA));
522
523 if (dataflag) {
524 tmpstream = jas_stream_memopen(0, 0);
525 if (box->ops->putdata) {
526 if ((*box->ops->putdata)(box, tmpstream)) {
527 goto error;
528 }
529 }
530 box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN;
531 jas_stream_rewind(tmpstream);
532 }
533 /* There was code here in official Jasper to handle 64 bit lengths,
534 but it was based on determining whether box->len fits in 32 bits.
535 But box->len is a 32 bit data type, so it fits in 32 bits by
536 definition. Either this encoder is incapable of making boxes with
537 lengths that don't fit in 32 bits, or it passes invalid values of
538 box->len to us. We assume the former because it's easier.
539 */
540 if (jp2_putuint32(out, box->len)) {
541 goto error;
542 }
543 if (jp2_putuint32(out, box->type)) {
544 goto error;
545 }
546
547 if (dataflag) {
548 if (jas_stream_copy(out, tmpstream, box->len - JP2_BOX_HDRLEN)) {
549 goto error;
550 }
551 jas_stream_close(tmpstream);
552 }
553
554 return 0;
555 abort();
556
557 error:
558
559 if (tmpstream) {
560 jas_stream_close(tmpstream);
561 }
562 return -1;
563 }
564
jp2_jp_putdata(jp2_box_t * box,jas_stream_t * out)565 static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out)
566 {
567 jp2_jp_t *jp = &box->data.jp;
568 if (jp2_putuint32(out, jp->magic)) {
569 return -1;
570 }
571 return 0;
572 }
573
jp2_ftyp_putdata(jp2_box_t * box,jas_stream_t * out)574 static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out)
575 {
576 jp2_ftyp_t *ftyp = &box->data.ftyp;
577 int i;
578 if (jp2_putuint32(out, ftyp->majver) || jp2_putuint32(out, ftyp->minver)) {
579 return -1;
580 }
581 for (i = 0; i < ftyp->numcompatcodes; ++i) {
582 if (jp2_putuint32(out, ftyp->compatcodes[i])) {
583 return -1;
584 }
585 }
586 return 0;
587 }
588
jp2_ihdr_putdata(jp2_box_t * box,jas_stream_t * out)589 static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out)
590 {
591 jp2_ihdr_t *ihdr = &box->data.ihdr;
592 if (jp2_putuint32(out, ihdr->height) || jp2_putuint32(out, ihdr->width) ||
593 jp2_putuint16(out, ihdr->numcmpts) || jp2_putuint8(out, ihdr->bpc) ||
594 jp2_putuint8(out, ihdr->comptype) || jp2_putuint8(out, ihdr->csunk) ||
595 jp2_putuint8(out, ihdr->ipr)) {
596 return -1;
597 }
598 return 0;
599 }
600
jp2_bpcc_putdata(jp2_box_t * box,jas_stream_t * out)601 static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out)
602 {
603 jp2_bpcc_t *bpcc = &box->data.bpcc;
604 int i;
605 for (i = 0; i < bpcc->numcmpts; ++i) {
606 if (jp2_putuint8(out, bpcc->bpcs[i])) {
607 return -1;
608 }
609 }
610 return 0;
611 }
612
jp2_colr_putdata(jp2_box_t * box,jas_stream_t * out)613 static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out)
614 {
615 jp2_colr_t *colr = &box->data.colr;
616 if (jp2_putuint8(out, colr->method) || jp2_putuint8(out, colr->pri) ||
617 jp2_putuint8(out, colr->approx)) {
618 return -1;
619 }
620 switch (colr->method) {
621 case JP2_COLR_ENUM:
622 if (jp2_putuint32(out, colr->csid)) {
623 return -1;
624 }
625 break;
626 case JP2_COLR_ICC:
627 /* XXX - not implemented */
628 abort();
629 break;
630 }
631 return 0;
632 }
633
jp2_cdef_putdata(jp2_box_t * box,jas_stream_t * out)634 static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out)
635 {
636 jp2_cdef_t *cdef = &box->data.cdef;
637 int i;
638 jp2_cdefchan_t *ent;
639
640 if (jp2_putuint16(out, cdef->numchans)) {
641 return -1;
642 }
643
644 for (i = 0; i < cdef->numchans; ++i) {
645 ent = &cdef->ents[i];
646 if (jp2_putuint16(out, ent->channo) ||
647 jp2_putuint16(out, ent->type) ||
648 jp2_putuint16(out, ent->assoc)) {
649 return -1;
650 }
651 }
652 return 0;
653 }
654
655 /******************************************************************************\
656 * Input operations for primitive types.
657 \******************************************************************************/
658
jp2_getuint8(jas_stream_t * in,uint_fast8_t * val)659 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val)
660 {
661 int c;
662 if ((c = jas_stream_getc(in)) == EOF) {
663 return -1;
664 }
665 if (val) {
666 *val = c;
667 }
668 return 0;
669 }
670
jp2_getuint16(jas_stream_t * in,uint_fast16_t * val)671 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val)
672 {
673 uint_fast16_t v;
674 int c;
675 if ((c = jas_stream_getc(in)) == EOF) {
676 return -1;
677 }
678 v = c;
679 if ((c = jas_stream_getc(in)) == EOF) {
680 return -1;
681 }
682 v = (v << 8) | c;
683 if (val) {
684 *val = v;
685 }
686 return 0;
687 }
688
jp2_getuint32(jas_stream_t * in,uint_fast32_t * val)689 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val)
690 {
691 uint_fast32_t v;
692 int c;
693 if ((c = jas_stream_getc(in)) == EOF) {
694 return -1;
695 }
696 v = c;
697 if ((c = jas_stream_getc(in)) == EOF) {
698 return -1;
699 }
700 v = (v << 8) | c;
701 if ((c = jas_stream_getc(in)) == EOF) {
702 return -1;
703 }
704 v = (v << 8) | c;
705 if ((c = jas_stream_getc(in)) == EOF) {
706 return -1;
707 }
708 v = (v << 8) | c;
709 if (val) {
710 *val = v;
711 }
712 return 0;
713 }
714
jp2_getuint64(jas_stream_t * in,uint_fast64_t * val)715 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val)
716 {
717 abort();
718 }
719
720 /******************************************************************************\
721 * Output operations for primitive types.
722 \******************************************************************************/
723
jp2_putuint8(jas_stream_t * out,uint_fast8_t val)724 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val)
725 {
726 if (jas_stream_putc(out, val & 0xff) == EOF) {
727 return -1;
728 }
729 return 0;
730 }
731
jp2_putuint16(jas_stream_t * out,uint_fast16_t val)732 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val)
733 {
734 if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
735 jas_stream_putc(out, val & 0xff) == EOF) {
736 return -1;
737 }
738 return 0;
739 }
740
jp2_putuint32(jas_stream_t * out,uint_fast32_t val)741 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val)
742 {
743 if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF ||
744 jas_stream_putc(out, (val >> 16) & 0xff) == EOF ||
745 jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
746 jas_stream_putc(out, val & 0xff) == EOF) {
747 return -1;
748 }
749 return 0;
750 }
751
752 /******************************************************************************\
753 * Miscellaneous code.
754 \******************************************************************************/
755
jp2_boxinfolookup(int type)756 jp2_boxinfo_t *jp2_boxinfolookup(int type)
757 {
758 jp2_boxinfo_t *boxinfo;
759 for (boxinfo = jp2_boxinfos; boxinfo->name; ++boxinfo) {
760 if (boxinfo->type == type) {
761 return boxinfo;
762 }
763 }
764 return &jp2_boxinfo_unk;
765 }
766
767
768
769
770
jp2_cmap_destroy(jp2_box_t * box)771 static void jp2_cmap_destroy(jp2_box_t *box)
772 {
773 jp2_cmap_t *cmap = &box->data.cmap;
774 if (cmap->ents) {
775 jas_free(cmap->ents);
776 }
777 }
778
jp2_cmap_getdata(jp2_box_t * box,jas_stream_t * in)779 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in)
780 {
781 jp2_cmap_t *cmap = &box->data.cmap;
782 jp2_cmapent_t *ent;
783 int i;
784
785 cmap->numchans = (box->len - JP2_BOX_HDRLEN) / 4;
786 if (!(cmap->ents = jas_malloc(cmap->numchans * sizeof(jp2_cmapent_t)))) {
787 return -1;
788 }
789 for (i = 0; i < cmap->numchans; ++i) {
790 ent = &cmap->ents[i];
791 if (jp2_getuint16(in, &ent->cmptno) ||
792 jp2_getuint8(in, &ent->map) ||
793 jp2_getuint8(in, &ent->pcol)) {
794 return -1;
795 }
796 }
797
798 return 0;
799 }
800
jp2_cmap_putdata(jp2_box_t * box,jas_stream_t * out)801 static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out)
802 {
803 return -1;
804 }
805
jp2_cmap_dumpdata(jp2_box_t * box,FILE * out)806 static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out)
807 {
808 jp2_cmap_t *cmap = &box->data.cmap;
809 int i;
810 jp2_cmapent_t *ent;
811 fprintf(stderr, "numchans = %d\n", (int) cmap->numchans);
812 for (i = 0; i < cmap->numchans; ++i) {
813 ent = &cmap->ents[i];
814 fprintf(stderr, "cmptno=%d; map=%d; pcol=%d\n",
815 (int) ent->cmptno, (int) ent->map, (int) ent->pcol);
816 }
817 }
818
jp2_pclr_destroy(jp2_box_t * box)819 static void jp2_pclr_destroy(jp2_box_t *box)
820 {
821 jp2_pclr_t *pclr = &box->data.pclr;
822 if (pclr->lutdata) {
823 jas_free(pclr->lutdata);
824 }
825 }
826
jp2_pclr_getdata(jp2_box_t * box,jas_stream_t * in)827 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in)
828 {
829 jp2_pclr_t *pclr = &box->data.pclr;
830 int lutsize;
831 int i;
832 int j;
833 int_fast32_t x;
834
835 pclr->lutdata = 0;
836
837 if (jp2_getuint16(in, &pclr->numlutents) ||
838 jp2_getuint8(in, &pclr->numchans)) {
839 return -1;
840 }
841 lutsize = pclr->numlutents * pclr->numchans;
842 if (!(pclr->lutdata = jas_malloc(lutsize * sizeof(int_fast32_t)))) {
843 return -1;
844 }
845 if (!(pclr->bpc = jas_malloc(pclr->numchans * sizeof(uint_fast8_t)))) {
846 return -1;
847 }
848 for (i = 0; i < pclr->numchans; ++i) {
849 if (jp2_getuint8(in, &pclr->bpc[i])) {
850 return -1;
851 }
852 }
853 for (i = 0; i < pclr->numlutents; ++i) {
854 for (j = 0; j < pclr->numchans; ++j) {
855 if (jp2_getint(in, (pclr->bpc[j] & 0x80) != 0,
856 (pclr->bpc[j] & 0x7f) + 1, &x)) {
857 return -1;
858 }
859 pclr->lutdata[i * pclr->numchans + j] = x;
860 }
861 }
862 return 0;
863 }
864
jp2_pclr_putdata(jp2_box_t * box,jas_stream_t * out)865 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out)
866 {
867 /* This code from official Jasper must be part of unfinished work.
868 It generates an unused variable warning.
869 jp2_pclr_t *pclr = &box->data.pclr;
870 */
871 return -1;
872 }
873
jp2_pclr_dumpdata(jp2_box_t * box,FILE * out)874 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out)
875 {
876 jp2_pclr_t *pclr = &box->data.pclr;
877 int i;
878 int j;
879 fprintf(out, "numents=%d; numchans=%d\n", (int) pclr->numlutents,
880 (int) pclr->numchans);
881 for (i = 0; i < pclr->numlutents; ++i) {
882 for (j = 0; j < pclr->numchans; ++j) {
883 fprintf(out, "LUT[%d][%d]=%d\n", i, j,
884 (int)pclr->lutdata[i * pclr->numchans + j]);
885 }
886 }
887 }
888
jp2_getint(jas_stream_t * in,int s,int n,int_fast32_t * val)889 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val)
890 {
891 int c;
892 int i;
893 uint_fast32_t v;
894 int m;
895
896 m = (n + 7) / 8;
897
898 v = 0;
899 for (i = 0; i < m; ++i) {
900 if ((c = jas_stream_getc(in)) == EOF) {
901 return -1;
902 }
903 v = (v << 8) | c;
904 }
905 v &= ONES(n);
906 if (s) {
907 int sb;
908 sb = v & (1 << (8 * m - 1));
909 *val = ((~v) + 1) & ONES(8 * m);
910 if (sb) {
911 *val = -*val;
912 }
913 } else {
914 *val = v;
915 }
916
917 return 0;
918 }
919
jp2_cdef_lookup(jp2_cdef_t * cdef,int channo)920 jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo)
921 {
922 int i;
923 jp2_cdefchan_t *cdefent;
924 for (i = 0; i < cdef->numchans; ++i) {
925 cdefent = &cdef->ents[i];
926 if (cdefent->channo == channo) {
927 return cdefent;
928 }
929 }
930 return 0;
931 }
932