1/* 2 * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium 3 * Copyright (c) 2002-2007, Professor Benoit Macq 4 * Copyright (c) 2001-2003, David Janssens 5 * Copyright (c) 2002-2003, Yannick Verschueren 6 * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe 7 * Copyright (c) 2005, Herve Drolon, FreeImage Team 8 * Copyright (c) 2010-2011, Kaori Hagihara 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32#include "opj_includes.h" 33 34/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ 35/*@{*/ 36 37/** @name Local static functions */ 38/*@{*/ 39 40/** 41Read box headers 42@param cinfo Codec context info 43@param cio Input stream 44@param box 45@return Returns true if successful, returns false otherwise 46*/ 47static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box); 48/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/ 49/** 50Read the IHDR box - Image Header box 51@param jp2 JP2 handle 52@param cio Input buffer stream 53@return Returns true if successful, returns false otherwise 54*/ 55static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); 56static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); 57static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); 58static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); 59static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio); 60/** 61Write the FTYP box - File type box 62@param jp2 JP2 handle 63@param cio Output buffer stream 64*/ 65static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); 66/** 67Read the FTYP box - File type box 68@param jp2 JP2 handle 69@param cio Input buffer stream 70@return Returns true if successful, returns false otherwise 71*/ 72static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); 73static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); 74static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset); 75static void jp2_write_jp(opj_cio_t *cio); 76/** 77Read the JP box - JPEG 2000 signature 78@param jp2 JP2 handle 79@param cio Input buffer stream 80@return Returns true if successful, returns false otherwise 81*/ 82static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio); 83/** 84Decode the structure of a JP2 file 85@param jp2 JP2 handle 86@param cio Input buffer stream 87@param color Collector for profile, cdef and pclr data 88@return Returns true if successful, returns false otherwise 89*/ 90static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, 91 opj_jp2_color_t *color); 92/** 93Apply collected palette data 94@param color Collector for profile, cdef and pclr data 95@param image 96*/ 97static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo); 98/** 99Collect palette data 100@param jp2 JP2 handle 101@param cio Input buffer stream 102@param box 103@param color Collector for profile, cdef and pclr data 104@return Returns true if successful, returns false otherwise 105*/ 106static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, 107 opj_jp2_box_t *box, opj_jp2_color_t *color); 108/** 109Collect component mapping data 110@param jp2 JP2 handle 111@param cio Input buffer stream 112@param box 113@param color Collector for profile, cdef and pclr data 114@return Returns true if successful, returns false otherwise 115*/ 116static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, 117 opj_jp2_box_t *box, opj_jp2_color_t *color); 118/** 119Collect colour specification data 120@param jp2 JP2 handle 121@param cio Input buffer stream 122@param box 123@param color Collector for profile, cdef and pclr data 124@return Returns true if successful, returns false otherwise 125*/ 126static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, 127 opj_jp2_box_t *box, opj_jp2_color_t *color); 128/** 129Write file Index (superbox) 130@param[in] offset_jp2c offset of jp2c box 131@param[in] length_jp2c length of jp2c box 132@param[in] offset_idx offset of cidx box 133@param[in] length_idx length of cidx box 134@param[in] cio file output handle 135@return length of fidx box 136*/ 137static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); 138/** 139Write index Finder box 140@param[in] offset offset of fidx box 141@param[in] length length of fidx box 142@param[in] cio file output handle 143*/ 144static void write_iptr( int offset, int length, opj_cio_t *cio); 145/** 146Write proxy box 147@param[in] offset_jp2c offset of jp2c box 148@param[in] length_jp2c length of jp2c box 149@param[in] offset_idx offset of cidx box 150@param[in] length_idx length of cidx box 151@param[in] cio file output handle 152*/ 153static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); 154/*@}*/ 155 156/*@}*/ 157 158/* ----------------------------------------------------------------------- */ 159 160static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) { 161 box->init_pos = cio_tell(cio); 162 box->length = cio_read(cio, 4); 163 box->type = cio_read(cio, 4); 164 if (box->length == 1) { 165 if (cio_read(cio, 4) != 0) { 166 opj_event_msg(cinfo, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); 167 return OPJ_FALSE; 168 } 169 box->length = cio_read(cio, 4); 170 if (box->length == 0) 171 box->length = cio_numbytesleft(cio) + 12; 172 } 173 else if (box->length == 0) { 174 box->length = cio_numbytesleft(cio) + 8; 175 } 176 177 return OPJ_TRUE; 178} 179 180#if 0 181static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { 182 unsigned int i; 183 opj_jp2_box_t box; 184 185 box.init_pos = cio_tell(cio); 186 cio_skip(cio, 4); 187 cio_write(cio, JP2_URL, 4); /* DBTL */ 188 cio_write(cio, 0, 1); /* VERS */ 189 cio_write(cio, 0, 3); /* FLAG */ 190 191 if(Idx_file) { 192 for (i = 0; i < strlen(Idx_file); i++) { 193 cio_write(cio, Idx_file[i], 1); 194 } 195 } 196 197 box.length = cio_tell(cio) - box.init_pos; 198 cio_seek(cio, box.init_pos); 199 cio_write(cio, box.length, 4); /* L */ 200 cio_seek(cio, box.init_pos + box.length); 201} 202#endif 203 204static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { 205 opj_jp2_box_t box; 206 207 opj_common_ptr cinfo = jp2->cinfo; 208 209 if(jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { 210 opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); 211 return OPJ_FALSE; 212 } 213 if (JP2_IHDR != box.type) { 214 opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n"); 215 return OPJ_FALSE; 216 } 217 218 jp2->h = cio_read(cio, 4); /* HEIGHT */ 219 jp2->w = cio_read(cio, 4); /* WIDTH */ 220 jp2->numcomps = cio_read(cio, 2); /* NC */ 221 jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); 222 223 jp2->bpc = cio_read(cio, 1); /* BPC */ 224 225 jp2->C = cio_read(cio, 1); /* C */ 226 jp2->UnkC = cio_read(cio, 1); /* UnkC */ 227 jp2->IPR = cio_read(cio, 1); /* IPR */ 228 229 if (cio_tell(cio) - box.init_pos != box.length) { 230 opj_event_msg(cinfo, EVT_ERROR, "Error with IHDR Box\n"); 231 return OPJ_FALSE; 232 } 233 234 return OPJ_TRUE; 235} 236 237static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { 238 opj_jp2_box_t box; 239 240 box.init_pos = cio_tell(cio); 241 cio_skip(cio, 4); 242 cio_write(cio, JP2_IHDR, 4); /* IHDR */ 243 244 cio_write(cio, jp2->h, 4); /* HEIGHT */ 245 cio_write(cio, jp2->w, 4); /* WIDTH */ 246 cio_write(cio, jp2->numcomps, 2); /* NC */ 247 248 cio_write(cio, jp2->bpc, 1); /* BPC */ 249 250 cio_write(cio, jp2->C, 1); /* C : Always 7 */ 251 cio_write(cio, jp2->UnkC, 1); /* UnkC, colorspace unknown */ 252 cio_write(cio, jp2->IPR, 1); /* IPR, no intellectual property */ 253 254 box.length = cio_tell(cio) - box.init_pos; 255 cio_seek(cio, box.init_pos); 256 cio_write(cio, box.length, 4); /* L */ 257 cio_seek(cio, box.init_pos + box.length); 258} 259 260static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { 261 unsigned int i; 262 opj_jp2_box_t box; 263 264 box.init_pos = cio_tell(cio); 265 cio_skip(cio, 4); 266 cio_write(cio, JP2_BPCC, 4); /* BPCC */ 267 268 for (i = 0; i < jp2->numcomps; i++) { 269 cio_write(cio, jp2->comps[i].bpcc, 1); 270 } 271 272 box.length = cio_tell(cio) - box.init_pos; 273 cio_seek(cio, box.init_pos); 274 cio_write(cio, box.length, 4); /* L */ 275 cio_seek(cio, box.init_pos + box.length); 276} 277 278 279static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { 280 unsigned int i; 281 opj_jp2_box_t box; 282 283 opj_common_ptr cinfo = jp2->cinfo; 284 285 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { 286 opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); 287 return OPJ_FALSE; 288 } 289 if (JP2_BPCC != box.type) { 290 opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n"); 291 return OPJ_FALSE; 292 } 293 294 for (i = 0; i < jp2->numcomps; i++) { 295 jp2->comps[i].bpcc = cio_read(cio, 1); 296 } 297 298 if (cio_tell(cio) - box.init_pos != box.length) { 299 opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n"); 300 return OPJ_FALSE; 301 } 302 303 return OPJ_TRUE; 304} 305 306static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { 307 opj_jp2_box_t box; 308 309 box.init_pos = cio_tell(cio); 310 cio_skip(cio, 4); 311 cio_write(cio, JP2_COLR, 4); /* COLR */ 312 313 cio_write(cio, jp2->meth, 1); /* METH */ 314 cio_write(cio, jp2->precedence, 1); /* PRECEDENCE */ 315 cio_write(cio, jp2->approx, 1); /* APPROX */ 316 317 if(jp2->meth == 2) 318 jp2->enumcs = 0; 319 320 cio_write(cio, jp2->enumcs, 4); /* EnumCS */ 321 322 box.length = cio_tell(cio) - box.init_pos; 323 cio_seek(cio, box.init_pos); 324 cio_write(cio, box.length, 4); /* L */ 325 cio_seek(cio, box.init_pos + box.length); 326} 327 328static void jp2_free_pclr(opj_jp2_color_t *color) 329{ 330 opj_free(color->jp2_pclr->channel_sign); 331 opj_free(color->jp2_pclr->channel_size); 332 opj_free(color->jp2_pclr->entries); 333 334 if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap); 335 336 opj_free(color->jp2_pclr); color->jp2_pclr = NULL; 337} 338 339static void free_color_data(opj_jp2_color_t *color) 340{ 341 if(color->jp2_pclr) 342 { 343 jp2_free_pclr(color); 344 } 345 if(color->jp2_cdef) 346 { 347 if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); 348 opj_free(color->jp2_cdef); 349 } 350 if(color->icc_profile_buf) opj_free(color->icc_profile_buf); 351} 352 353static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo) 354{ 355 opj_image_comp_t *old_comps, *new_comps; 356 unsigned char *channel_size, *channel_sign; 357 unsigned int *entries; 358 opj_jp2_cmap_comp_t *cmap; 359 int *src, *dst; 360 unsigned int j, max; 361 unsigned short i, nr_channels, cmp, pcol; 362 int k, top_k; 363 364 channel_size = color->jp2_pclr->channel_size; 365 channel_sign = color->jp2_pclr->channel_sign; 366 entries = color->jp2_pclr->entries; 367 cmap = color->jp2_pclr->cmap; 368 nr_channels = color->jp2_pclr->nr_channels; 369 370 old_comps = image->comps; 371 new_comps = (opj_image_comp_t*) 372 opj_malloc(nr_channels * sizeof(opj_image_comp_t)); 373 374 for(i = 0; i < nr_channels; ++i) 375 { 376 pcol = cmap[i].pcol; cmp = cmap[i].cmp; 377 378 if( pcol < nr_channels ) 379 new_comps[pcol] = old_comps[cmp]; 380 else 381 { 382 opj_event_msg(cinfo, EVT_ERROR, "Error with pcol value %d (max: %d). skipping\n", pcol, nr_channels); 383 continue; 384 } 385 386 if(cmap[i].mtyp == 0) /* Direct use */ 387 { 388 old_comps[cmp].data = NULL; continue; 389 } 390/* Palette mapping: */ 391 new_comps[pcol].data = (int*) 392 opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int)); 393 new_comps[pcol].prec = channel_size[i]; 394 new_comps[pcol].sgnd = channel_sign[i]; 395 } 396 top_k = color->jp2_pclr->nr_entries - 1; 397 398 for(i = 0; i < nr_channels; ++i) 399 { 400/* Direct use: */ 401 if(cmap[i].mtyp == 0) continue; 402 403/* Palette mapping: */ 404 cmp = cmap[i].cmp; pcol = cmap[i].pcol; 405 src = old_comps[cmp].data; 406 dst = new_comps[pcol].data; 407 max = new_comps[pcol].w * new_comps[pcol].h; 408 409 for(j = 0; j < max; ++j) 410 { 411/* The index */ 412 if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; 413/* The colour */ 414 dst[j] = entries[k * nr_channels + pcol]; 415 } 416 } 417 max = image->numcomps; 418 for(i = 0; i < max; ++i) 419 { 420 if(old_comps[i].data) opj_free(old_comps[i].data); 421 } 422 opj_free(old_comps); 423 image->comps = new_comps; 424 image->numcomps = nr_channels; 425 426 jp2_free_pclr(color); 427 428}/* apply_pclr() */ 429 430static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, 431 opj_jp2_box_t *box, opj_jp2_color_t *color) 432{ 433 opj_jp2_pclr_t *jp2_pclr; 434 unsigned char *channel_size, *channel_sign; 435 unsigned int *entries; 436 unsigned short nr_entries, nr_channels; 437 unsigned short i, j; 438 unsigned char uc; 439 440 OPJ_ARG_NOT_USED(box); 441 OPJ_ARG_NOT_USED(jp2); 442 443/* Part 1, I.5.3.4: 'There shall be at most one Palette box inside 444 * a JP2 Header box' : 445*/ 446 if(color->jp2_pclr) return OPJ_FALSE; 447 448 nr_entries = (unsigned short)cio_read(cio, 2); /* NE */ 449 nr_channels = (unsigned short)cio_read(cio, 1);/* NPC */ 450 451 entries = (unsigned int*) 452 opj_malloc(nr_channels * nr_entries * sizeof(unsigned int)); 453 channel_size = (unsigned char*)opj_malloc(nr_channels); 454 channel_sign = (unsigned char*)opj_malloc(nr_channels); 455 456 jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); 457 jp2_pclr->channel_sign = channel_sign; 458 jp2_pclr->channel_size = channel_size; 459 jp2_pclr->entries = entries; 460 jp2_pclr->nr_entries = nr_entries; 461 jp2_pclr->nr_channels = nr_channels; 462 jp2_pclr->cmap = NULL; 463 464 color->jp2_pclr = jp2_pclr; 465 466 for(i = 0; i < nr_channels; ++i) 467 { 468 uc = cio_read(cio, 1); /* Bi */ 469 channel_size[i] = (uc & 0x7f) + 1; 470 channel_sign[i] = (uc & 0x80)?1:0; 471 } 472 473 for(j = 0; j < nr_entries; ++j) 474 { 475 for(i = 0; i < nr_channels; ++i) 476 { 477/* Cji */ 478 *entries++ = cio_read(cio, (channel_size[i]+7)>>3); 479 } 480 } 481 482 return OPJ_TRUE; 483}/* jp2_read_pclr() */ 484 485static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, 486 opj_jp2_box_t *box, opj_jp2_color_t *color) 487{ 488 opj_jp2_cmap_comp_t *cmap; 489 unsigned short i, nr_channels; 490 491 OPJ_ARG_NOT_USED(box); 492 OPJ_ARG_NOT_USED(jp2); 493 494/* Need nr_channels: */ 495 if(color->jp2_pclr == NULL) return OPJ_FALSE; 496 497/* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box 498 * inside a JP2 Header box' : 499*/ 500 if(color->jp2_pclr->cmap) return OPJ_FALSE; 501 502 nr_channels = color->jp2_pclr->nr_channels; 503 cmap = (opj_jp2_cmap_comp_t*) 504 opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t)); 505 506 for(i = 0; i < nr_channels; ++i) 507 { 508 cmap[i].cmp = (unsigned short)cio_read(cio, 2); 509 cmap[i].mtyp = cio_read(cio, 1); 510 cmap[i].pcol = cio_read(cio, 1); 511 512 } 513 color->jp2_pclr->cmap = cmap; 514 515 return OPJ_TRUE; 516}/* jp2_read_cmap() */ 517 518static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) 519{ 520 opj_jp2_cdef_info_t *info; 521 int color_space; 522 unsigned short i, n, cn, typ, asoc, acn; 523 524 color_space = image->color_space; 525 info = color->jp2_cdef->info; 526 n = color->jp2_cdef->n; 527 528 for(i = 0; i < n; ++i) 529 { 530/* WATCH: acn = asoc - 1 ! */ 531 if((asoc = info[i].asoc) == 0) continue; 532 533 cn = info[i].cn; typ = info[i].typ; acn = asoc - 1; 534 535 if(cn != acn) 536 { 537 opj_image_comp_t saved; 538 539 memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); 540 memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); 541 memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); 542 543 info[i].asoc = cn + 1; 544 info[acn].asoc = info[acn].cn + 1; 545 } 546 } 547 if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); 548 549 opj_free(color->jp2_cdef); color->jp2_cdef = NULL; 550 551}/* jp2_apply_cdef() */ 552 553static opj_bool jp2_read_cdef(opj_jp2_t *jp2, opj_cio_t *cio, 554 opj_jp2_box_t *box, opj_jp2_color_t *color) 555{ 556 opj_jp2_cdef_info_t *info; 557 unsigned short i, n; 558 559 OPJ_ARG_NOT_USED(box); 560 OPJ_ARG_NOT_USED(jp2); 561 562/* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box 563 * inside a JP2 Header box.' 564*/ 565 if(color->jp2_cdef) return OPJ_FALSE; 566 567 if((n = (unsigned short)cio_read(cio, 2)) == 0) return OPJ_FALSE; /* szukw000: FIXME */ 568 569 info = (opj_jp2_cdef_info_t*) 570 opj_malloc(n * sizeof(opj_jp2_cdef_info_t)); 571 572 color->jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); 573 color->jp2_cdef->info = info; 574 color->jp2_cdef->n = n; 575 576 for(i = 0; i < n; ++i) 577 { 578 info[i].cn = (unsigned short)cio_read(cio, 2); 579 info[i].typ = (unsigned short)cio_read(cio, 2); 580 info[i].asoc = (unsigned short)cio_read(cio, 2); 581 582 } 583 return OPJ_TRUE; 584}/* jp2_read_cdef() */ 585 586static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, 587 opj_jp2_box_t *box, opj_jp2_color_t *color) 588{ 589 int skip_len; 590 opj_common_ptr cinfo; 591 592/* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour 593 * Specification boxes after the first.' 594*/ 595 if(color->jp2_has_colr) return OPJ_FALSE; 596 597 cinfo = jp2->cinfo; 598 599 jp2->meth = cio_read(cio, 1); /* METH */ 600 jp2->precedence = cio_read(cio, 1); /* PRECEDENCE */ 601 jp2->approx = cio_read(cio, 1); /* APPROX */ 602 603 if (jp2->meth == 1) 604 { 605 jp2->enumcs = cio_read(cio, 4); /* EnumCS */ 606 } 607 else 608 if (jp2->meth == 2) 609 { 610/* skip PROFILE */ 611 skip_len = box->init_pos + box->length - cio_tell(cio); 612 if (skip_len < 0) 613 { 614 opj_event_msg(cinfo, EVT_ERROR, "Error with COLR box size\n"); 615 return OPJ_FALSE; 616 } 617 if(skip_len > 0) 618 { 619 unsigned char *start; 620 621 start = cio_getbp(cio); 622 color->icc_profile_buf = (unsigned char*)opj_malloc(skip_len); 623 color->icc_profile_len = skip_len; 624 625 cio_skip(cio, box->init_pos + box->length - cio_tell(cio)); 626 627 memcpy(color->icc_profile_buf, start, skip_len); 628 } 629 } 630 631 if (cio_tell(cio) - box->init_pos != box->length) 632 { 633 opj_event_msg(cinfo, EVT_ERROR, "Error with COLR Box\n"); 634 return OPJ_FALSE; 635 } 636 color->jp2_has_colr = 1; 637 638 return OPJ_TRUE; 639}/* jp2_read_colr() */ 640 641opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color) 642{ 643 opj_jp2_box_t box; 644 int jp2h_end; 645 646 opj_common_ptr cinfo = jp2->cinfo; 647 648 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 649 do { 650 if (JP2_JP2H != box.type) 651 { 652 if (box.type == JP2_JP2C) 653 { 654 opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); 655 return OPJ_FALSE; 656 } 657 cio_skip(cio, box.length - 8); 658 659 if(cio->bp >= cio->end) return OPJ_FALSE; 660 661 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 662 } 663 } while(JP2_JP2H != box.type); 664 665 if (!jp2_read_ihdr(jp2, cio)) 666 return OPJ_FALSE; 667 jp2h_end = box.init_pos + box.length; 668 669 if (jp2->bpc == 255) 670 { 671 if (!jp2_read_bpcc(jp2, cio)) 672 return OPJ_FALSE; 673 } 674 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 675 676 while(cio_tell(cio) < jp2h_end) 677 { 678 if(box.type == JP2_COLR) 679 { 680 if( !jp2_read_colr(jp2, cio, &box, color)) 681 { 682 cio_seek(cio, box.init_pos + 8); 683 cio_skip(cio, box.length - 8); 684 } 685 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 686 continue; 687 } 688 if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef) 689 { 690 if( !jp2_read_cdef(jp2, cio, &box, color)) 691 { 692 cio_seek(cio, box.init_pos + 8); 693 cio_skip(cio, box.length - 8); 694 } 695 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 696 continue; 697 } 698 if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef) 699 { 700 if( !jp2_read_pclr(jp2, cio, &box, color)) 701 { 702 cio_seek(cio, box.init_pos + 8); 703 cio_skip(cio, box.length - 8); 704 } 705 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 706 continue; 707 } 708 if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef) 709 { 710 if( !jp2_read_cmap(jp2, cio, &box, color)) 711 { 712 cio_seek(cio, box.init_pos + 8); 713 cio_skip(cio, box.length - 8); 714 } 715 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 716 continue; 717 } 718 cio_seek(cio, box.init_pos + 8); 719 cio_skip(cio, box.length - 8); 720 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 721 722 }/* while(cio_tell(cio) < box_end) */ 723 724 cio_seek(cio, jp2h_end); 725 726 /* Part 1, I.5.3.3 : 'must contain at least one' */ 727 return (color->jp2_has_colr == 1); 728 729}/* jp2_read_jp2h() */ 730 731opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, 732 opj_codestream_info_t *cstr_info) 733{ 734 opj_common_ptr cinfo; 735 opj_image_t *image = NULL; 736 opj_jp2_color_t color; 737 738 if(!jp2 || !cio) 739 { 740 return NULL; 741 } 742 memset(&color, 0, sizeof(opj_jp2_color_t)); 743 cinfo = jp2->cinfo; 744 745/* JP2 decoding */ 746 if(!jp2_read_struct(jp2, cio, &color)) 747 { 748 free_color_data(&color); 749 opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); 750 return NULL; 751 } 752 753/* J2K decoding */ 754 image = j2k_decode(jp2->j2k, cio, cstr_info); 755 756 if(!image) 757 { 758 free_color_data(&color); 759 opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); 760 return NULL; 761 } 762 763 if (!jp2->ignore_pclr_cmap_cdef){ 764 765 /* Set Image Color Space */ 766 if (jp2->enumcs == 16) 767 image->color_space = CLRSPC_SRGB; 768 else if (jp2->enumcs == 17) 769 image->color_space = CLRSPC_GRAY; 770 else if (jp2->enumcs == 18) 771 image->color_space = CLRSPC_SYCC; 772 else 773 image->color_space = CLRSPC_UNKNOWN; 774 775 if(color.jp2_cdef) 776 { 777 jp2_apply_cdef(image, &color); 778 } 779 if(color.jp2_pclr) 780 { 781/* Part 1, I.5.3.4: Either both or none : */ 782 if( !color.jp2_pclr->cmap) 783 jp2_free_pclr(&color); 784 else 785 jp2_apply_pclr(&color, image, cinfo); 786 } 787 if(color.icc_profile_buf) 788 { 789 image->icc_profile_buf = color.icc_profile_buf; 790 color.icc_profile_buf = NULL; 791 image->icc_profile_len = color.icc_profile_len; 792 } 793 } 794 795 return image; 796 797}/* opj_jp2_decode() */ 798 799 800void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { 801 opj_jp2_box_t box; 802 803 box.init_pos = cio_tell(cio); 804 cio_skip(cio, 4); 805 cio_write(cio, JP2_JP2H, 4); /* JP2H */ 806 807 jp2_write_ihdr(jp2, cio); 808 809 if (jp2->bpc == 255) { 810 jp2_write_bpcc(jp2, cio); 811 } 812 jp2_write_colr(jp2, cio); 813 814 box.length = cio_tell(cio) - box.init_pos; 815 cio_seek(cio, box.init_pos); 816 cio_write(cio, box.length, 4); /* L */ 817 cio_seek(cio, box.init_pos + box.length); 818} 819 820static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { 821 unsigned int i; 822 opj_jp2_box_t box; 823 824 box.init_pos = cio_tell(cio); 825 cio_skip(cio, 4); 826 cio_write(cio, JP2_FTYP, 4); /* FTYP */ 827 828 cio_write(cio, jp2->brand, 4); /* BR */ 829 cio_write(cio, jp2->minversion, 4); /* MinV */ 830 831 for (i = 0; i < jp2->numcl; i++) { 832 cio_write(cio, jp2->cl[i], 4); /* CL */ 833 } 834 835 box.length = cio_tell(cio) - box.init_pos; 836 cio_seek(cio, box.init_pos); 837 cio_write(cio, box.length, 4); /* L */ 838 cio_seek(cio, box.init_pos + box.length); 839} 840 841static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { 842 int i; 843 opj_jp2_box_t box; 844 845 opj_common_ptr cinfo = jp2->cinfo; 846 847 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { 848 opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); 849 return OPJ_FALSE; 850 } 851 if (JP2_FTYP != box.type) { 852 opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n"); 853 return OPJ_FALSE; 854 } 855 856 jp2->brand = cio_read(cio, 4); /* BR */ 857 jp2->minversion = cio_read(cio, 4); /* MinV */ 858 jp2->numcl = (box.length - 16) / 4; 859 jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int)); 860 861 for (i = 0; i < (int)jp2->numcl; i++) { 862 jp2->cl[i] = cio_read(cio, 4); /* CLi */ 863 } 864 865 if (cio_tell(cio) - box.init_pos != box.length) { 866 opj_event_msg(cinfo, EVT_ERROR, "Error with FTYP Box\n"); 867 return OPJ_FALSE; 868 } 869 870 return OPJ_TRUE; 871} 872 873static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { 874 unsigned int j2k_codestream_offset, j2k_codestream_length; 875 opj_jp2_box_t box; 876 877 opj_j2k_t *j2k = jp2->j2k; 878 879 box.init_pos = cio_tell(cio); 880 cio_skip(cio, 4); 881 cio_write(cio, JP2_JP2C, 4); /* JP2C */ 882 883 /* J2K encoding */ 884 j2k_codestream_offset = cio_tell(cio); 885 if(!j2k_encode(j2k, cio, image, cstr_info)) { 886 opj_event_msg(j2k->cinfo, EVT_ERROR, "Failed to encode image\n"); 887 return 0; 888 } 889 j2k_codestream_length = cio_tell(cio) - j2k_codestream_offset; 890 891 jp2->j2k_codestream_offset = j2k_codestream_offset; 892 jp2->j2k_codestream_length = j2k_codestream_length; 893 894 box.length = 8 + jp2->j2k_codestream_length; 895 cio_seek(cio, box.init_pos); 896 cio_write(cio, box.length, 4); /* L */ 897 cio_seek(cio, box.init_pos + box.length); 898 899 return box.length; 900} 901 902static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) { 903 opj_jp2_box_t box; 904 905 opj_common_ptr cinfo = jp2->cinfo; 906 907 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { 908 opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); 909 return OPJ_FALSE; 910 } 911 do { 912 if(JP2_JP2C != box.type) { 913 cio_skip(cio, box.length - 8); 914 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; 915 } 916 } while(JP2_JP2C != box.type); 917 918 *j2k_codestream_offset = cio_tell(cio); 919 *j2k_codestream_length = box.length - 8; 920 921 return OPJ_TRUE; 922} 923 924static void jp2_write_jp(opj_cio_t *cio) { 925 opj_jp2_box_t box; 926 927 box.init_pos = cio_tell(cio); 928 cio_skip(cio, 4); 929 cio_write(cio, JP2_JP, 4); /* JP2 signature */ 930 cio_write(cio, 0x0d0a870a, 4); 931 932 box.length = cio_tell(cio) - box.init_pos; 933 cio_seek(cio, box.init_pos); 934 cio_write(cio, box.length, 4); /* L */ 935 cio_seek(cio, box.init_pos + box.length); 936} 937 938static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) { 939 opj_jp2_box_t box; 940 941 opj_common_ptr cinfo = jp2->cinfo; 942 943 if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { 944 opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); 945 return OPJ_FALSE; 946 } 947 if (JP2_JP != box.type) { 948 opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n"); 949 return OPJ_FALSE; 950 } 951 if (0x0d0a870a != cio_read(cio, 4)) { 952 opj_event_msg(cinfo, EVT_ERROR, "Error with JP Marker\n"); 953 return OPJ_FALSE; 954 } 955 if (cio_tell(cio) - box.init_pos != box.length) { 956 opj_event_msg(cinfo, EVT_ERROR, "Error with JP Box size\n"); 957 return OPJ_FALSE; 958 } 959 960 return OPJ_TRUE; 961} 962 963 964static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, 965 opj_jp2_color_t *color) { 966 if (!jp2_read_jp(jp2, cio)) 967 return OPJ_FALSE; 968 if (!jp2_read_ftyp(jp2, cio)) 969 return OPJ_FALSE; 970 if (!jp2_read_jp2h(jp2, cio, color)) 971 return OPJ_FALSE; 972 if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset)) 973 return OPJ_FALSE; 974 975 return OPJ_TRUE; 976} 977 978 979static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) 980{ 981 int len, lenp; 982 983 lenp = cio_tell( cio); 984 cio_skip( cio, 4); /* L [at the end] */ 985 cio_write( cio, JPIP_FIDX, 4); /* IPTR */ 986 987 write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio); 988 989 len = cio_tell( cio)-lenp; 990 cio_seek( cio, lenp); 991 cio_write( cio, len, 4); /* L */ 992 cio_seek( cio, lenp+len); 993 994 return len; 995} 996 997static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) 998{ 999 int len, lenp; 1000 1001 lenp = cio_tell( cio); 1002 cio_skip( cio, 4); /* L [at the end] */ 1003 cio_write( cio, JPIP_PRXY, 4); /* IPTR */ 1004 1005 cio_write( cio, offset_jp2c, 8); /* OOFF */ 1006 cio_write( cio, length_jp2c, 4); /* OBH part 1 */ 1007 cio_write( cio, JP2_JP2C, 4); /* OBH part 2 */ 1008 1009 cio_write( cio, 1,1); /* NI */ 1010 1011 cio_write( cio, offset_idx, 8); /* IOFF */ 1012 cio_write( cio, length_idx, 4); /* IBH part 1 */ 1013 cio_write( cio, JPIP_CIDX, 4); /* IBH part 2 */ 1014 1015 len = cio_tell( cio)-lenp; 1016 cio_seek( cio, lenp); 1017 cio_write( cio, len, 4); /* L */ 1018 cio_seek( cio, lenp+len); 1019} 1020 1021static void write_iptr( int offset, int length, opj_cio_t *cio) 1022{ 1023 int len, lenp; 1024 1025 lenp = cio_tell( cio); 1026 cio_skip( cio, 4); /* L [at the end] */ 1027 cio_write( cio, JPIP_IPTR, 4); /* IPTR */ 1028 1029 cio_write( cio, offset, 8); 1030 cio_write( cio, length, 8); 1031 1032 len = cio_tell( cio)-lenp; 1033 cio_seek( cio, lenp); 1034 cio_write( cio, len, 4); /* L */ 1035 cio_seek( cio, lenp+len); 1036} 1037 1038 1039/* ----------------------------------------------------------------------- */ 1040/* JP2 decoder interface */ 1041/* ----------------------------------------------------------------------- */ 1042 1043opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) { 1044 opj_jp2_t *jp2 = (opj_jp2_t*) opj_calloc(1, sizeof(opj_jp2_t)); 1045 if(jp2) { 1046 jp2->cinfo = cinfo; 1047 /* create the J2K codec */ 1048 jp2->j2k = j2k_create_decompress(cinfo); 1049 if(jp2->j2k == NULL) { 1050 jp2_destroy_decompress(jp2); 1051 return NULL; 1052 } 1053 } 1054 return jp2; 1055} 1056 1057void jp2_destroy_decompress(opj_jp2_t *jp2) { 1058 if(jp2) { 1059 /* destroy the J2K codec */ 1060 j2k_destroy_decompress(jp2->j2k); 1061 1062 if(jp2->comps) { 1063 opj_free(jp2->comps); 1064 } 1065 if(jp2->cl) { 1066 opj_free(jp2->cl); 1067 } 1068 opj_free(jp2); 1069 } 1070} 1071 1072void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) { 1073 /* setup the J2K codec */ 1074 j2k_setup_decoder(jp2->j2k, parameters); 1075 /* further JP2 initializations go here */ 1076 jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; 1077} 1078 1079/* ----------------------------------------------------------------------- */ 1080/* JP2 encoder interface */ 1081/* ----------------------------------------------------------------------- */ 1082 1083opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo) { 1084 opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t)); 1085 if(jp2) { 1086 jp2->cinfo = cinfo; 1087 /* create the J2K codec */ 1088 jp2->j2k = j2k_create_compress(cinfo); 1089 if(jp2->j2k == NULL) { 1090 jp2_destroy_compress(jp2); 1091 return NULL; 1092 } 1093 } 1094 return jp2; 1095} 1096 1097void jp2_destroy_compress(opj_jp2_t *jp2) { 1098 if(jp2) { 1099 /* destroy the J2K codec */ 1100 j2k_destroy_compress(jp2->j2k); 1101 1102 if(jp2->comps) { 1103 opj_free(jp2->comps); 1104 } 1105 if(jp2->cl) { 1106 opj_free(jp2->cl); 1107 } 1108 opj_free(jp2); 1109 } 1110} 1111 1112void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image) { 1113 int i; 1114 int depth_0, sign; 1115 1116 if(!jp2 || !parameters || !image) 1117 return; 1118 1119 /* setup the J2K codec */ 1120 /* ------------------- */ 1121 1122 /* Check if number of components respects standard */ 1123 if (image->numcomps < 1 || image->numcomps > 16384) { 1124 opj_event_msg(jp2->cinfo, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n"); 1125 return; 1126 } 1127 1128 j2k_setup_encoder(jp2->j2k, parameters, image); 1129 1130 /* setup the JP2 codec */ 1131 /* ------------------- */ 1132 1133 /* Profile box */ 1134 1135 jp2->brand = JP2_JP2; /* BR */ 1136 jp2->minversion = 0; /* MinV */ 1137 jp2->numcl = 1; 1138 jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int)); 1139 jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ 1140 1141 /* Image Header box */ 1142 1143 jp2->numcomps = image->numcomps; /* NC */ 1144 jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); 1145 jp2->h = image->y1 - image->y0; /* HEIGHT */ 1146 jp2->w = image->x1 - image->x0; /* WIDTH */ 1147 /* BPC */ 1148 depth_0 = image->comps[0].prec - 1; 1149 sign = image->comps[0].sgnd; 1150 jp2->bpc = depth_0 + (sign << 7); 1151 for (i = 1; i < image->numcomps; i++) { 1152 int depth = image->comps[i].prec - 1; 1153 sign = image->comps[i].sgnd; 1154 if (depth_0 != depth) 1155 jp2->bpc = 255; 1156 } 1157 jp2->C = 7; /* C : Always 7 */ 1158 jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ 1159 jp2->IPR = 0; /* IPR, no intellectual property */ 1160 1161 /* BitsPerComponent box */ 1162 1163 for (i = 0; i < image->numcomps; i++) { 1164 jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); 1165 } 1166 jp2->meth = 1; 1167 if (image->color_space == 1) 1168 jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2.1 */ 1169 else if (image->color_space == 2) 1170 jp2->enumcs = 17; /* greyscale */ 1171 else if (image->color_space == 3) 1172 jp2->enumcs = 18; /* YUV */ 1173 jp2->precedence = 0; /* PRECEDENCE */ 1174 jp2->approx = 0; /* APPROX */ 1175 1176 jp2->jpip_on = parameters->jpip_on; 1177} 1178 1179opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { 1180 1181 int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, len_cidx, end_pos, pos_fidx, len_fidx; 1182 pos_jp2c = pos_iptr = -1; /* remove a warning */ 1183 1184 /* JP2 encoding */ 1185 1186 /* JPEG 2000 Signature box */ 1187 jp2_write_jp(cio); 1188 /* File Type box */ 1189 jp2_write_ftyp(jp2, cio); 1190 /* JP2 Header box */ 1191 jp2_write_jp2h(jp2, cio); 1192 1193 if( jp2->jpip_on){ 1194 pos_iptr = cio_tell( cio); 1195 cio_skip( cio, 24); /* IPTR further ! */ 1196 1197 pos_jp2c = cio_tell( cio); 1198 } 1199 1200 /* J2K encoding */ 1201 if(!(len_jp2c = jp2_write_jp2c( jp2, cio, image, cstr_info))){ 1202 opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n"); 1203 return OPJ_FALSE; 1204 } 1205 1206 if( jp2->jpip_on){ 1207 pos_cidx = cio_tell( cio); 1208 1209 len_cidx = write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8); 1210 1211 pos_fidx = cio_tell( cio); 1212 len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, len_cidx, cio); 1213 1214 end_pos = cio_tell( cio); 1215 1216 cio_seek( cio, pos_iptr); 1217 write_iptr( pos_fidx, len_fidx, cio); 1218 1219 cio_seek( cio, end_pos); 1220 } 1221 1222 return OPJ_TRUE; 1223} 1224