1 /* 2 * Copyright (c) 1999-2000 Image Power, Inc. and the University of 3 * British Columbia. 4 * Copyright (c) 2001-2003 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_enc.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 "jasper/jas_malloc.h" 81 #include "jasper/jas_image.h" 82 #include "jasper/jas_stream.h" 83 #include "jasper/jas_cm.h" 84 #include "jasper/jas_icc.h" 85 #include "jp2_cod.h" 86 87 static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype); 88 static int clrspctojp2(jas_clrspc_t clrspc); 89 90 /******************************************************************************\ 91 * Functions. 92 \******************************************************************************/ 93 94 int jp2_write_header(jas_image_t *image, jas_stream_t *out) 95 { 96 jp2_box_t *box; 97 jp2_ftyp_t *ftyp; 98 jp2_ihdr_t *ihdr; 99 jas_stream_t *tmpstream; 100 int allcmptssame; 101 jp2_bpcc_t *bpcc; 102 long len; 103 uint_fast16_t cmptno; 104 jp2_colr_t *colr; 105 jp2_cdefchan_t *cdefchanent; 106 jp2_cdef_t *cdef; 107 int i; 108 uint_fast32_t typeasoc; 109 jas_iccprof_t *iccprof; 110 jas_stream_t *iccstream; 111 int pos; 112 int needcdef; 113 int prec; 114 int sgnd; 115 116 box = 0; 117 tmpstream = 0; 118 119 allcmptssame = 1; 120 sgnd = jas_image_cmptsgnd(image, 0); 121 prec = jas_image_cmptprec(image, 0); 122 for (i = 1; i < jas_image_numcmpts(image); ++i) { 123 if (jas_image_cmptsgnd(image, i) != sgnd || 124 jas_image_cmptprec(image, i) != prec) { 125 allcmptssame = 0; 126 break; 127 } 128 } 129 130 /* Output the signature box. */ 131 132 if (!(box = jp2_box_create(JP2_BOX_JP))) { 133 goto error; 134 } 135 box->data.jp.magic = JP2_JP_MAGIC; 136 if (jp2_box_put(box, out)) { 137 goto error; 138 } 139 jp2_box_destroy(box); 140 box = 0; 141 142 /* Output the file type box. */ 143 144 if (!(box = jp2_box_create(JP2_BOX_FTYP))) { 145 goto error; 146 } 147 ftyp = &box->data.ftyp; 148 ftyp->majver = JP2_FTYP_MAJVER; 149 ftyp->minver = JP2_FTYP_MINVER; 150 ftyp->numcompatcodes = 1; 151 ftyp->compatcodes[0] = JP2_FTYP_COMPATCODE; 152 if (jp2_box_put(box, out)) { 153 goto error; 154 } 155 jp2_box_destroy(box); 156 box = 0; 157 158 /* 159 * Generate the data portion of the JP2 header box. 160 * We cannot simply output the header for this box 161 * since we do not yet know the correct value for the length 162 * field. 163 */ 164 165 if (!(tmpstream = jas_stream_memopen(0, 0))) { 166 goto error; 167 } 168 169 /* Generate image header box. */ 170 171 if (!(box = jp2_box_create(JP2_BOX_IHDR))) { 172 goto error; 173 } 174 ihdr = &box->data.ihdr; 175 ihdr->width = jas_image_width(image); 176 ihdr->height = jas_image_height(image); 177 ihdr->numcmpts = jas_image_numcmpts(image); 178 ihdr->bpc = allcmptssame ? JP2_SPTOBPC(jas_image_cmptsgnd(image, 0), 179 jas_image_cmptprec(image, 0)) : JP2_IHDR_BPCNULL; 180 ihdr->comptype = JP2_IHDR_COMPTYPE; 181 ihdr->csunk = 0; 182 ihdr->ipr = 0; 183 if (jp2_box_put(box, tmpstream)) { 184 goto error; 185 } 186 jp2_box_destroy(box); 187 box = 0; 188 189 /* Generate bits per component box. */ 190 191 if (!allcmptssame) { 192 if (!(box = jp2_box_create(JP2_BOX_BPCC))) { 193 goto error; 194 } 195 bpcc = &box->data.bpcc; 196 bpcc->numcmpts = jas_image_numcmpts(image); 197 if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts, 198 sizeof(uint_fast8_t)))) { 199 goto error; 200 } 201 for (cmptno = 0; cmptno < bpcc->numcmpts; ++cmptno) { 202 bpcc->bpcs[cmptno] = JP2_SPTOBPC(jas_image_cmptsgnd(image, 203 cmptno), jas_image_cmptprec(image, cmptno)); 204 } 205 if (jp2_box_put(box, tmpstream)) { 206 goto error; 207 } 208 jp2_box_destroy(box); 209 box = 0; 210 } 211 212 /* Generate color specification box. */ 213 214 if (!(box = jp2_box_create(JP2_BOX_COLR))) { 215 goto error; 216 } 217 colr = &box->data.colr; 218 switch (jas_image_clrspc(image)) { 219 case JAS_CLRSPC_SRGB: 220 case JAS_CLRSPC_SYCBCR: 221 case JAS_CLRSPC_SGRAY: 222 colr->method = JP2_COLR_ENUM; 223 colr->csid = clrspctojp2(jas_image_clrspc(image)); 224 colr->pri = JP2_COLR_PRI; 225 colr->approx = 0; 226 break; 227 default: 228 colr->method = JP2_COLR_ICC; 229 colr->pri = JP2_COLR_PRI; 230 colr->approx = 0; 231 iccprof = jas_iccprof_createfromcmprof(jas_image_cmprof(image)); 232 assert(iccprof); 233 iccstream = jas_stream_memopen(0, 0); 234 assert(iccstream); 235 if (jas_iccprof_save(iccprof, iccstream)) 236 abort(); 237 if ((pos = jas_stream_tell(iccstream)) < 0) 238 abort(); 239 colr->iccplen = pos; 240 colr->iccp = jas_malloc(pos); 241 assert(colr->iccp); 242 jas_stream_rewind(iccstream); 243 if (jas_stream_read(iccstream, colr->iccp, colr->iccplen) != colr->iccplen) 244 abort(); 245 jas_stream_close(iccstream); 246 jas_iccprof_destroy(iccprof); 247 break; 248 } 249 if (jp2_box_put(box, tmpstream)) { 250 goto error; 251 } 252 jp2_box_destroy(box); 253 box = 0; 254 255 needcdef = 1; 256 switch (jas_clrspc_fam(jas_image_clrspc(image))) { 257 case JAS_CLRSPC_FAM_RGB: 258 if (jas_image_cmpttype(image, 0) == 259 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R) && 260 jas_image_cmpttype(image, 1) == 261 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G) && 262 jas_image_cmpttype(image, 2) == 263 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)) 264 needcdef = 0; 265 break; 266 case JAS_CLRSPC_FAM_YCBCR: 267 if (jas_image_cmpttype(image, 0) == 268 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y) && 269 jas_image_cmpttype(image, 1) == 270 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB) && 271 jas_image_cmpttype(image, 2) == 272 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR)) 273 needcdef = 0; 274 break; 275 case JAS_CLRSPC_FAM_GRAY: 276 if (jas_image_cmpttype(image, 0) == 277 JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y)) 278 needcdef = 0; 279 break; 280 default: 281 abort(); 282 break; 283 } 284 285 if (needcdef) { 286 if (!(box = jp2_box_create(JP2_BOX_CDEF))) { 287 goto error; 288 } 289 cdef = &box->data.cdef; 290 cdef->numchans = jas_image_numcmpts(image); 291 cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t)); 292 for (i = 0; i < jas_image_numcmpts(image); ++i) { 293 cdefchanent = &cdef->ents[i]; 294 cdefchanent->channo = i; 295 typeasoc = jp2_gettypeasoc(jas_image_clrspc(image), jas_image_cmpttype(image, i)); 296 cdefchanent->type = typeasoc >> 16; 297 cdefchanent->assoc = typeasoc & 0x7fff; 298 } 299 if (jp2_box_put(box, tmpstream)) { 300 goto error; 301 } 302 jp2_box_destroy(box); 303 box = 0; 304 } 305 306 /* Determine the total length of the JP2 header box. */ 307 308 len = jas_stream_tell(tmpstream); 309 jas_stream_rewind(tmpstream); 310 311 /* 312 * Output the JP2 header box and all of the boxes which it contains. 313 */ 314 315 if (!(box = jp2_box_create(JP2_BOX_JP2H))) { 316 goto error; 317 } 318 box->len = len + JP2_BOX_HDRLEN(false); 319 if (jp2_box_put(box, out)) { 320 goto error; 321 } 322 jp2_box_destroy(box); 323 box = 0; 324 325 if (jas_stream_copy(out, tmpstream, len)) { 326 goto error; 327 } 328 329 jas_stream_close(tmpstream); 330 tmpstream = 0; 331 332 return 0; 333 abort(); 334 335 error: 336 337 if (box) { 338 jp2_box_destroy(box); 339 } 340 if (tmpstream) { 341 jas_stream_close(tmpstream); 342 } 343 return -1; 344 } 345 346 int jp2_write_codestream(jas_image_t *image, jas_stream_t *out, char *optstr) 347 { 348 jp2_box_t *box; 349 char buf[4096]; 350 uint_fast32_t overhead; 351 352 /* 353 * Output the contiguous code stream box. 354 */ 355 356 if (!(box = jp2_box_create(JP2_BOX_JP2C))) { 357 goto error; 358 } 359 box->len = 0; 360 if (jp2_box_put(box, out)) { 361 goto error; 362 } 363 jp2_box_destroy(box); 364 box = 0; 365 366 /* Output the JPEG-2000 code stream. */ 367 368 overhead = jas_stream_getrwcount(out); 369 sprintf(buf, "%s\n_jp2overhead=%lu\n", (optstr ? optstr : ""), 370 (unsigned long) overhead); 371 372 if (jpc_encode(image, out, buf)) { 373 goto error; 374 } 375 376 return 0; 377 abort(); 378 379 error: 380 381 if (box) { 382 jp2_box_destroy(box); 383 } 384 return -1; 385 } 386 387 int jp2_encode(jas_image_t *image, jas_stream_t *out, char *optstr) 388 { 389 if (jp2_write_header(image, out) < 0) 390 return -1; 391 if (jp2_write_codestream(image, out, optstr) < 0) 392 return -1; 393 394 return 0; 395 } 396 397 int jp2_encode_uuid(jas_image_t *image, jas_stream_t *out, 398 char *optstr, jp2_box_t *uuid) 399 { 400 if (jp2_write_header(image, out) < 0) 401 return -1; 402 if (uuid) { 403 if (jp2_box_put(uuid, out)) 404 return -1; 405 } 406 if (jp2_write_codestream(image, out, optstr) < 0) 407 return -1; 408 409 return 0; 410 } 411 412 static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype) 413 { 414 int type; 415 int asoc; 416 417 if (ctype & JAS_IMAGE_CT_OPACITY) { 418 type = JP2_CDEF_TYPE_OPACITY; 419 asoc = JP2_CDEF_ASOC_ALL; 420 goto done; 421 } 422 423 type = JP2_CDEF_TYPE_UNSPEC; 424 asoc = JP2_CDEF_ASOC_NONE; 425 switch (jas_clrspc_fam(colorspace)) { 426 case JAS_CLRSPC_FAM_RGB: 427 switch (JAS_IMAGE_CT_COLOR(ctype)) { 428 case JAS_IMAGE_CT_RGB_R: 429 type = JP2_CDEF_TYPE_COLOR; 430 asoc = JP2_CDEF_RGB_R; 431 break; 432 case JAS_IMAGE_CT_RGB_G: 433 type = JP2_CDEF_TYPE_COLOR; 434 asoc = JP2_CDEF_RGB_G; 435 break; 436 case JAS_IMAGE_CT_RGB_B: 437 type = JP2_CDEF_TYPE_COLOR; 438 asoc = JP2_CDEF_RGB_B; 439 break; 440 } 441 break; 442 case JAS_CLRSPC_FAM_YCBCR: 443 switch (JAS_IMAGE_CT_COLOR(ctype)) { 444 case JAS_IMAGE_CT_YCBCR_Y: 445 type = JP2_CDEF_TYPE_COLOR; 446 asoc = JP2_CDEF_YCBCR_Y; 447 break; 448 case JAS_IMAGE_CT_YCBCR_CB: 449 type = JP2_CDEF_TYPE_COLOR; 450 asoc = JP2_CDEF_YCBCR_CB; 451 break; 452 case JAS_IMAGE_CT_YCBCR_CR: 453 type = JP2_CDEF_TYPE_COLOR; 454 asoc = JP2_CDEF_YCBCR_CR; 455 break; 456 } 457 break; 458 case JAS_CLRSPC_FAM_GRAY: 459 type = JP2_CDEF_TYPE_COLOR; 460 asoc = JP2_CDEF_GRAY_Y; 461 break; 462 } 463 464 done: 465 return (type << 16) | asoc; 466 } 467 468 static int clrspctojp2(jas_clrspc_t clrspc) 469 { 470 switch (clrspc) { 471 case JAS_CLRSPC_SRGB: 472 return JP2_COLR_SRGB; 473 case JAS_CLRSPC_SYCBCR: 474 return JP2_COLR_SYCC; 475 case JAS_CLRSPC_SGRAY: 476 return JP2_COLR_SGRAY; 477 default: 478 abort(); 479 break; 480 } 481 } 482