jp2_cod.c (23138B)
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) 1999-2000 Image Power, Inc. 13 * Copyright (c) 1999-2000 The University of British Columbia 14 * Copyright (c) 2001-2003 Michael David Adams 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 * JP2 Library 66 * 67 * $Id: jp2_cod.c 1918 2005-07-24 14:12:08Z baford $ 68 */ 69 70 /******************************************************************************\ 71 * Includes. 72 \******************************************************************************/ 73 74 #include <assert.h> 75 #include <stdlib.h> 76 77 #include "jasper/jas_stream.h" 78 #include "jasper/jas_malloc.h" 79 #include "jasper/jas_debug.h" 80 81 #include "jp2_cod.h" 82 83 /******************************************************************************\ 84 * Function prototypes. 85 \******************************************************************************/ 86 87 #define ONES(n) ((1 << (n)) - 1) 88 89 jp2_boxinfo_t *jp2_boxinfolookup(int type); 90 91 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val); 92 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val); 93 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val); 94 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val); 95 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val); 96 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val); 97 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val); 98 static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val); 99 100 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val); 101 102 jp2_box_t *jp2_box_get(jas_stream_t *in); 103 void jp2_box_dump(jp2_box_t *box, FILE *out); 104 105 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in); 106 static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out); 107 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in); 108 static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out); 109 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in); 110 static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out); 111 static void jp2_bpcc_destroy(jp2_box_t *box); 112 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in); 113 static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out); 114 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in); 115 static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out); 116 static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out); 117 static void jp2_colr_destroy(jp2_box_t *box); 118 static void jp2_cdef_destroy(jp2_box_t *box); 119 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in); 120 static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out); 121 static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out); 122 static void jp2_cmap_destroy(jp2_box_t *box); 123 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in); 124 static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out); 125 static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out); 126 static void jp2_pclr_destroy(jp2_box_t *box); 127 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in); 128 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out); 129 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out); 130 131 /******************************************************************************\ 132 * Local data. 133 \******************************************************************************/ 134 135 jp2_boxinfo_t jp2_boxinfos[] = { 136 {JP2_BOX_JP, "JP", 0, 137 {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}}, 138 {JP2_BOX_FTYP, "FTYP", 0, 139 {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}}, 140 {JP2_BOX_JP2H, "JP2H", JP2_BOX_SUPER, 141 {0, 0, 0, 0, 0}}, 142 {JP2_BOX_IHDR, "IHDR", 0, 143 {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}}, 144 {JP2_BOX_BPCC, "BPCC", 0, 145 {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}}, 146 {JP2_BOX_COLR, "COLR", 0, 147 {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}}, 148 {JP2_BOX_PCLR, "PCLR", 0, 149 {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}}, 150 {JP2_BOX_CMAP, "CMAP", 0, 151 {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}}, 152 {JP2_BOX_CDEF, "CDEF", 0, 153 {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}}, 154 {JP2_BOX_RES, "RES", JP2_BOX_SUPER, 155 {0, 0, 0, 0, 0}}, 156 {JP2_BOX_RESC, "RESC", 0, 157 {0, 0, 0, 0, 0}}, 158 {JP2_BOX_RESD, "RESD", 0, 159 {0, 0, 0, 0, 0}}, 160 {JP2_BOX_JP2C, "JP2C", JP2_BOX_NODATA, 161 {0, 0, 0, 0, 0}}, 162 {JP2_BOX_JP2I, "JP2I", 0, 163 {0, 0, 0, 0, 0}}, 164 {JP2_BOX_XML, "XML", 0, 165 {0, 0, 0, 0, 0}}, 166 {JP2_BOX_UUID, "UUID", 0, 167 {0, 0, 0, 0, 0}}, 168 {JP2_BOX_UINF, "UINF", JP2_BOX_SUPER, 169 {0, 0, 0, 0, 0}}, 170 {JP2_BOX_ULST, "ULST", 0, 171 {0, 0, 0, 0, 0}}, 172 {JP2_BOX_URL, "URL", 0, 173 {0, 0, 0, 0, 0}}, 174 {0, 0, 0, {0, 0, 0, 0, 0}}, 175 }; 176 177 jp2_boxinfo_t jp2_boxinfo_unk = { 178 0, "Unknown", 0, {0, 0, 0, 0, 0} 179 }; 180 181 /******************************************************************************\ 182 * Box constructor. 183 \******************************************************************************/ 184 185 jp2_box_t *jp2_box_create(int type) 186 { 187 jp2_box_t *box; 188 jp2_boxinfo_t *boxinfo; 189 190 if (!(box = jas_malloc(sizeof(jp2_box_t)))) { 191 return 0; 192 } 193 memset(box, 0, sizeof(jp2_box_t)); 194 box->type = type; 195 box->len = 0; 196 if (!(boxinfo = jp2_boxinfolookup(type))) { 197 return 0; 198 } 199 box->info = boxinfo; 200 box->ops = &boxinfo->ops; 201 return box; 202 } 203 204 /******************************************************************************\ 205 * Box destructor. 206 \******************************************************************************/ 207 208 void jp2_box_destroy(jp2_box_t *box) 209 { 210 if (box->ops->destroy) { 211 (*box->ops->destroy)(box); 212 } 213 jas_free(box); 214 } 215 216 static void jp2_bpcc_destroy(jp2_box_t *box) 217 { 218 jp2_bpcc_t *bpcc = &box->data.bpcc; 219 if (bpcc->bpcs) { 220 jas_free(bpcc->bpcs); 221 bpcc->bpcs = 0; 222 } 223 } 224 225 static void jp2_cdef_destroy(jp2_box_t *box) 226 { 227 jp2_cdef_t *cdef = &box->data.cdef; 228 if (cdef->ents) { 229 jas_free(cdef->ents); 230 cdef->ents = 0; 231 } 232 } 233 234 /******************************************************************************\ 235 * Box input. 236 \******************************************************************************/ 237 238 jp2_box_t *jp2_box_get(jas_stream_t *in) 239 { 240 jp2_box_t *box; 241 jp2_boxinfo_t *boxinfo; 242 jas_stream_t *tmpstream; 243 uint_fast32_t len; 244 uint_fast64_t extlen; 245 bool dataflag; 246 247 box = 0; 248 tmpstream = 0; 249 250 if (!(box = jas_malloc(sizeof(jp2_box_t)))) { 251 goto error; 252 } 253 box->ops = &jp2_boxinfo_unk.ops; 254 if (jp2_getuint32(in, &len) || jp2_getuint32(in, &box->type)) { 255 goto error; 256 } 257 boxinfo = jp2_boxinfolookup(box->type); 258 box->info = boxinfo; 259 box->ops = &boxinfo->ops; 260 box->len = len; 261 if (box->len == 1) { 262 if (jp2_getuint64(in, &extlen)) { 263 goto error; 264 } 265 box->len = extlen; 266 } 267 if (box->len != 0 && box->len < 8) { 268 goto error; 269 } 270 271 dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA)); 272 273 if (dataflag) { 274 if (!(tmpstream = jas_stream_memopen(0, 0))) { 275 goto error; 276 } 277 if (jas_stream_copy(tmpstream, in, box->len - JP2_BOX_HDRLEN)) { 278 goto error; 279 } 280 jas_stream_rewind(tmpstream); 281 282 if (box->ops->getdata) { 283 if ((*box->ops->getdata)(box, tmpstream)) { 284 goto error; 285 } 286 } 287 jas_stream_close(tmpstream); 288 } 289 290 #if 0 291 jp2_box_dump(box, stderr); 292 #endif 293 294 return box; 295 abort(); 296 297 error: 298 if (box) { 299 jp2_box_destroy(box); 300 } 301 if (tmpstream) { 302 jas_stream_close(tmpstream); 303 } 304 return 0; 305 } 306 307 void jp2_box_dump(jp2_box_t *box, FILE *out) 308 { 309 jp2_boxinfo_t *boxinfo; 310 boxinfo = jp2_boxinfolookup(box->type); 311 assert(boxinfo); 312 313 fprintf(out, "JP2 box: "); 314 fprintf(out, "type=%c%s%c (0x%08x); length=%d\n", '"', boxinfo->name, 315 '"', (int)box->type, (int)box->len); 316 if (box->ops->dumpdata) { 317 (*box->ops->dumpdata)(box, out); 318 } 319 } 320 321 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in) 322 { 323 jp2_jp_t *jp = &box->data.jp; 324 if (jp2_getuint32(in, &jp->magic)) { 325 return -1; 326 } 327 return 0; 328 } 329 330 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in) 331 { 332 jp2_ftyp_t *ftyp = &box->data.ftyp; 333 unsigned int i; 334 if (jp2_getuint32(in, &ftyp->majver) || jp2_getuint32(in, &ftyp->minver)) { 335 return -1; 336 } 337 ftyp->numcompatcodes = ((box->len - JP2_BOX_HDRLEN) - 8) / 4; 338 if (ftyp->numcompatcodes > JP2_FTYP_MAXCOMPATCODES) { 339 return -1; 340 } 341 for (i = 0; i < ftyp->numcompatcodes; ++i) { 342 if (jp2_getuint32(in, &ftyp->compatcodes[i])) { 343 return -1; 344 } 345 } 346 return 0; 347 } 348 349 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in) 350 { 351 jp2_ihdr_t *ihdr = &box->data.ihdr; 352 if (jp2_getuint32(in, &ihdr->height) || jp2_getuint32(in, &ihdr->width) || 353 jp2_getuint16(in, &ihdr->numcmpts) || jp2_getuint8(in, &ihdr->bpc) || 354 jp2_getuint8(in, &ihdr->comptype) || jp2_getuint8(in, &ihdr->csunk) || 355 jp2_getuint8(in, &ihdr->ipr)) { 356 return -1; 357 } 358 return 0; 359 } 360 361 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in) 362 { 363 jp2_bpcc_t *bpcc = &box->data.bpcc; 364 unsigned int i; 365 bpcc->numcmpts = box->len - JP2_BOX_HDRLEN; 366 if (!(bpcc->bpcs = jas_malloc(bpcc->numcmpts * sizeof(uint_fast8_t)))) { 367 return -1; 368 } 369 for (i = 0; i < bpcc->numcmpts; ++i) { 370 if (jp2_getuint8(in, &bpcc->bpcs[i])) { 371 return -1; 372 } 373 } 374 return 0; 375 } 376 377 static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out) 378 { 379 jp2_colr_t *colr = &box->data.colr; 380 fprintf(out, "method=%d; pri=%d; approx=%d\n", (int)colr->method, (int)colr->pri, (int)colr->approx); 381 switch (colr->method) { 382 case JP2_COLR_ENUM: 383 fprintf(out, "csid=%d\n", (int)colr->csid); 384 break; 385 case JP2_COLR_ICC: 386 jas_memdump(out, colr->iccp, colr->iccplen); 387 break; 388 } 389 } 390 391 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) 392 { 393 jp2_colr_t *colr = &box->data.colr; 394 colr->csid = 0; 395 colr->iccp = 0; 396 colr->iccplen = 0; 397 398 if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) || 399 jp2_getuint8(in, &colr->approx)) { 400 return -1; 401 } 402 switch (colr->method) { 403 case JP2_COLR_ENUM: 404 if (jp2_getuint32(in, &colr->csid)) { 405 return -1; 406 } 407 break; 408 case JP2_COLR_ICC: 409 colr->iccplen = box->len - JP2_BOX_HDRLEN - 3; 410 if (!(colr->iccp = jas_malloc(colr->iccplen * sizeof(uint_fast8_t)))) { 411 return -1; 412 } 413 if (jas_stream_read(in, colr->iccp, colr->iccplen) != colr->iccplen) { 414 return -1; 415 } 416 break; 417 } 418 return 0; 419 } 420 421 static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out) 422 { 423 jp2_cdef_t *cdef = &box->data.cdef; 424 unsigned int i; 425 for (i = 0; i < cdef->numchans; ++i) { 426 fprintf(out, "channo=%d; type=%d; assoc=%d\n", 427 (int)cdef->ents[i].channo, (int)cdef->ents[i].type, (int)cdef->ents[i].assoc); 428 } 429 } 430 431 static void jp2_colr_destroy(jp2_box_t *box) 432 { 433 jp2_colr_t *colr = &box->data.colr; 434 if (colr->iccp) { 435 jas_free(colr->iccp); 436 } 437 } 438 439 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in) 440 { 441 jp2_cdef_t *cdef = &box->data.cdef; 442 jp2_cdefchan_t *chan; 443 unsigned int channo; 444 if (jp2_getuint16(in, &cdef->numchans)) { 445 return -1; 446 } 447 if (!(cdef->ents = jas_malloc(cdef->numchans * sizeof(jp2_cdefchan_t)))) { 448 return -1; 449 } 450 for (channo = 0; channo < cdef->numchans; ++channo) { 451 chan = &cdef->ents[channo]; 452 if (jp2_getuint16(in, &chan->channo) || jp2_getuint16(in, &chan->type) || 453 jp2_getuint16(in, &chan->assoc)) { 454 return -1; 455 } 456 } 457 return 0; 458 } 459 460 /******************************************************************************\ 461 * Box output. 462 \******************************************************************************/ 463 464 int jp2_box_put(jp2_box_t *box, jas_stream_t *out) 465 { 466 jas_stream_t *tmpstream; 467 bool extlen; 468 bool dataflag; 469 470 tmpstream = 0; 471 472 dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA)); 473 474 if (dataflag) { 475 tmpstream = jas_stream_memopen(0, 0); 476 if (box->ops->putdata) { 477 if ((*box->ops->putdata)(box, tmpstream)) { 478 goto error; 479 } 480 } 481 box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN; 482 jas_stream_rewind(tmpstream); 483 } 484 extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0; 485 if (jp2_putuint32(out, extlen ? 1 : box->len)) { 486 goto error; 487 } 488 if (jp2_putuint32(out, box->type)) { 489 goto error; 490 } 491 if (extlen) { 492 if (jp2_putuint64(out, box->len)) { 493 goto error; 494 } 495 } 496 497 if (dataflag) { 498 if (jas_stream_copy(out, tmpstream, box->len - JP2_BOX_HDRLEN)) { 499 goto error; 500 } 501 jas_stream_close(tmpstream); 502 } 503 504 return 0; 505 abort(); 506 507 error: 508 509 if (tmpstream) { 510 jas_stream_close(tmpstream); 511 } 512 return -1; 513 } 514 515 static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out) 516 { 517 jp2_jp_t *jp = &box->data.jp; 518 if (jp2_putuint32(out, jp->magic)) { 519 return -1; 520 } 521 return 0; 522 } 523 524 static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out) 525 { 526 jp2_ftyp_t *ftyp = &box->data.ftyp; 527 unsigned int i; 528 if (jp2_putuint32(out, ftyp->majver) || jp2_putuint32(out, ftyp->minver)) { 529 return -1; 530 } 531 for (i = 0; i < ftyp->numcompatcodes; ++i) { 532 if (jp2_putuint32(out, ftyp->compatcodes[i])) { 533 return -1; 534 } 535 } 536 return 0; 537 } 538 539 static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out) 540 { 541 jp2_ihdr_t *ihdr = &box->data.ihdr; 542 if (jp2_putuint32(out, ihdr->height) || jp2_putuint32(out, ihdr->width) || 543 jp2_putuint16(out, ihdr->numcmpts) || jp2_putuint8(out, ihdr->bpc) || 544 jp2_putuint8(out, ihdr->comptype) || jp2_putuint8(out, ihdr->csunk) || 545 jp2_putuint8(out, ihdr->ipr)) { 546 return -1; 547 } 548 return 0; 549 } 550 551 static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out) 552 { 553 jp2_bpcc_t *bpcc = &box->data.bpcc; 554 unsigned int i; 555 for (i = 0; i < bpcc->numcmpts; ++i) { 556 if (jp2_putuint8(out, bpcc->bpcs[i])) { 557 return -1; 558 } 559 } 560 return 0; 561 } 562 563 static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out) 564 { 565 jp2_colr_t *colr = &box->data.colr; 566 if (jp2_putuint8(out, colr->method) || jp2_putuint8(out, colr->pri) || 567 jp2_putuint8(out, colr->approx)) { 568 return -1; 569 } 570 switch (colr->method) { 571 case JP2_COLR_ENUM: 572 if (jp2_putuint32(out, colr->csid)) { 573 return -1; 574 } 575 break; 576 case JP2_COLR_ICC: 577 if (jas_stream_write(out, colr->iccp, 578 JAS_CAST(int, colr->iccplen)) != JAS_CAST(int, colr->iccplen)) 579 return -1; 580 break; 581 } 582 return 0; 583 } 584 585 static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out) 586 { 587 jp2_cdef_t *cdef = &box->data.cdef; 588 unsigned int i; 589 jp2_cdefchan_t *ent; 590 591 if (jp2_putuint16(out, cdef->numchans)) { 592 return -1; 593 } 594 595 for (i = 0; i < cdef->numchans; ++i) { 596 ent = &cdef->ents[i]; 597 if (jp2_putuint16(out, ent->channo) || 598 jp2_putuint16(out, ent->type) || 599 jp2_putuint16(out, ent->assoc)) { 600 return -1; 601 } 602 } 603 return 0; 604 } 605 606 /******************************************************************************\ 607 * Input operations for primitive types. 608 \******************************************************************************/ 609 610 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val) 611 { 612 int c; 613 if ((c = jas_stream_getc(in)) == EOF) { 614 return -1; 615 } 616 if (val) { 617 *val = c; 618 } 619 return 0; 620 } 621 622 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val) 623 { 624 uint_fast16_t v; 625 int c; 626 if ((c = jas_stream_getc(in)) == EOF) { 627 return -1; 628 } 629 v = c; 630 if ((c = jas_stream_getc(in)) == EOF) { 631 return -1; 632 } 633 v = (v << 8) | c; 634 if (val) { 635 *val = v; 636 } 637 return 0; 638 } 639 640 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val) 641 { 642 uint_fast32_t v; 643 int c; 644 if ((c = jas_stream_getc(in)) == EOF) { 645 return -1; 646 } 647 v = c; 648 if ((c = jas_stream_getc(in)) == EOF) { 649 return -1; 650 } 651 v = (v << 8) | c; 652 if ((c = jas_stream_getc(in)) == EOF) { 653 return -1; 654 } 655 v = (v << 8) | c; 656 if ((c = jas_stream_getc(in)) == EOF) { 657 return -1; 658 } 659 v = (v << 8) | c; 660 if (val) { 661 *val = v; 662 } 663 return 0; 664 } 665 666 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val) 667 { 668 in = 0; 669 val = 0; 670 abort(); 671 } 672 673 /******************************************************************************\ 674 * Output operations for primitive types. 675 \******************************************************************************/ 676 677 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val) 678 { 679 if (jas_stream_putc(out, val & 0xff) == EOF) { 680 return -1; 681 } 682 return 0; 683 } 684 685 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val) 686 { 687 if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF || 688 jas_stream_putc(out, val & 0xff) == EOF) { 689 return -1; 690 } 691 return 0; 692 } 693 694 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val) 695 { 696 if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF || 697 jas_stream_putc(out, (val >> 16) & 0xff) == EOF || 698 jas_stream_putc(out, (val >> 8) & 0xff) == EOF || 699 jas_stream_putc(out, val & 0xff) == EOF) { 700 return -1; 701 } 702 return 0; 703 } 704 705 static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val) 706 { 707 if (jp2_putuint32(out, (val >> 32) & 0xffffffffUL) || 708 jp2_putuint32(out, val & 0xffffffffUL)) { 709 return -1; 710 } 711 return 0; 712 } 713 714 /******************************************************************************\ 715 * Miscellaneous code. 716 \******************************************************************************/ 717 718 jp2_boxinfo_t *jp2_boxinfolookup(int type) 719 { 720 jp2_boxinfo_t *boxinfo; 721 for (boxinfo = jp2_boxinfos; boxinfo->name; ++boxinfo) { 722 if (boxinfo->type == type) { 723 return boxinfo; 724 } 725 } 726 return &jp2_boxinfo_unk; 727 } 728 729 730 731 732 733 static void jp2_cmap_destroy(jp2_box_t *box) 734 { 735 jp2_cmap_t *cmap = &box->data.cmap; 736 if (cmap->ents) { 737 jas_free(cmap->ents); 738 } 739 } 740 741 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in) 742 { 743 jp2_cmap_t *cmap = &box->data.cmap; 744 jp2_cmapent_t *ent; 745 unsigned int i; 746 747 cmap->numchans = (box->len - JP2_BOX_HDRLEN) / 4; 748 if (!(cmap->ents = jas_malloc(cmap->numchans * sizeof(jp2_cmapent_t)))) { 749 return -1; 750 } 751 for (i = 0; i < cmap->numchans; ++i) { 752 ent = &cmap->ents[i]; 753 if (jp2_getuint16(in, &ent->cmptno) || 754 jp2_getuint8(in, &ent->map) || 755 jp2_getuint8(in, &ent->pcol)) { 756 return -1; 757 } 758 } 759 760 return 0; 761 } 762 763 static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out) 764 { 765 /* Eliminate compiler warning about unused variables. */ 766 box = 0; 767 out = 0; 768 769 return -1; 770 } 771 772 static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out) 773 { 774 jp2_cmap_t *cmap = &box->data.cmap; 775 unsigned int i; 776 jp2_cmapent_t *ent; 777 fprintf(out, "numchans = %d\n", (int) cmap->numchans); 778 for (i = 0; i < cmap->numchans; ++i) { 779 ent = &cmap->ents[i]; 780 fprintf(out, "cmptno=%d; map=%d; pcol=%d\n", 781 (int) ent->cmptno, (int) ent->map, (int) ent->pcol); 782 } 783 } 784 785 static void jp2_pclr_destroy(jp2_box_t *box) 786 { 787 jp2_pclr_t *pclr = &box->data.pclr; 788 if (pclr->lutdata) { 789 jas_free(pclr->lutdata); 790 } 791 if (pclr->bpc) 792 jas_free(pclr->bpc); 793 } 794 795 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in) 796 { 797 jp2_pclr_t *pclr = &box->data.pclr; 798 int lutsize; 799 unsigned int i; 800 unsigned int j; 801 int_fast32_t x; 802 803 pclr->lutdata = 0; 804 805 if (jp2_getuint16(in, &pclr->numlutents) || 806 jp2_getuint8(in, &pclr->numchans)) { 807 return -1; 808 } 809 lutsize = pclr->numlutents * pclr->numchans; 810 if (!(pclr->lutdata = jas_malloc(lutsize * sizeof(int_fast32_t)))) { 811 return -1; 812 } 813 if (!(pclr->bpc = jas_malloc(pclr->numchans * sizeof(uint_fast8_t)))) { 814 return -1; 815 } 816 for (i = 0; i < pclr->numchans; ++i) { 817 if (jp2_getuint8(in, &pclr->bpc[i])) { 818 return -1; 819 } 820 } 821 for (i = 0; i < pclr->numlutents; ++i) { 822 for (j = 0; j < pclr->numchans; ++j) { 823 if (jp2_getint(in, (pclr->bpc[j] & 0x80) != 0, 824 (pclr->bpc[j] & 0x7f) + 1, &x)) { 825 return -1; 826 } 827 pclr->lutdata[i * pclr->numchans + j] = x; 828 } 829 } 830 return 0; 831 } 832 833 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out) 834 { 835 #if 0 836 jp2_pclr_t *pclr = &box->data.pclr; 837 #endif 838 /* Eliminate warning about unused variable. */ 839 box = 0; 840 out = 0; 841 return -1; 842 } 843 844 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out) 845 { 846 jp2_pclr_t *pclr = &box->data.pclr; 847 unsigned int i; 848 int j; 849 fprintf(out, "numents=%d; numchans=%d\n", (int) pclr->numlutents, 850 (int) pclr->numchans); 851 for (i = 0; i < pclr->numlutents; ++i) { 852 for (j = 0; j < pclr->numchans; ++j) { 853 fprintf(out, "LUT[%d][%d]=%d\n", i, j, (int)pclr->lutdata[i * pclr->numchans + j]); 854 } 855 } 856 } 857 858 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) 859 { 860 int c; 861 int i; 862 uint_fast32_t v; 863 int m; 864 865 m = (n + 7) / 8; 866 867 v = 0; 868 for (i = 0; i < m; ++i) { 869 if ((c = jas_stream_getc(in)) == EOF) { 870 return -1; 871 } 872 v = (v << 8) | c; 873 } 874 v &= ONES(n); 875 if (s) { 876 int sb; 877 sb = v & (1 << (8 * m - 1)); 878 *val = ((~v) + 1) & ONES(8 * m); 879 if (sb) { 880 *val = -*val; 881 } 882 } else { 883 *val = v; 884 } 885 886 return 0; 887 } 888 889 jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo) 890 { 891 unsigned int i; 892 jp2_cdefchan_t *cdefent; 893 for (i = 0; i < cdef->numchans; ++i) { 894 cdefent = &cdef->ents[i]; 895 if (cdefent->channo == JAS_CAST(unsigned int, channo)) { 896 return cdefent; 897 } 898 } 899 return 0; 900 }