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