1 /* 2 * Copyright (c) 2002-2003 Michael David Adams. 3 * All rights reserved. 4 */ 5 6 /* __START_OF_JASPER_LICENSE__ 7 * 8 * JasPer License Version 2.0 9 * 10 * Copyright (c) 2001-2006 Michael David Adams 11 * Copyright (c) 1999-2000 Image Power, Inc. 12 * Copyright (c) 1999-2000 The University of British Columbia 13 * 14 * All rights reserved. 15 * 16 * Permission is hereby granted, free of charge, to any person (the 17 * "User") obtaining a copy of this software and associated documentation 18 * files (the "Software"), to deal in the Software without restriction, 19 * including without limitation the rights to use, copy, modify, merge, 20 * publish, distribute, and/or sell copies of the Software, and to permit 21 * persons to whom the Software is furnished to do so, subject to the 22 * following conditions: 23 * 24 * 1. The above copyright notices and this permission notice (which 25 * includes the disclaimer below) shall be included in all copies or 26 * substantial portions of the Software. 27 * 28 * 2. The name of a copyright holder shall not be used to endorse or 29 * promote products derived from the Software without specific prior 30 * written permission. 31 * 32 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS 33 * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER 34 * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 35 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 36 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 37 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO 38 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 39 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 40 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 41 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 42 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE 43 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE 44 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. 45 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS 46 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL 47 * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS 48 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE 49 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE 50 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL 51 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, 52 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL 53 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH 54 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, 55 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH 56 * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY 57 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. 58 * 59 * __END_OF_JASPER_LICENSE__ 60 */ 61 62 /* 63 * Color Management 64 * 65 * $Id: jas_cm.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $ 66 */ 67 68 #include <jasper/jas_config.h> 69 #include <math.h> 70 #include <stdlib.h> 71 #include <assert.h> 72 #include <jasper/jas_cm.h> 73 #include <jasper/jas_icc.h> 74 #include <jasper/jas_init.h> 75 #include <jasper/jas_stream.h> 76 #include <jasper/jas_malloc.h> 77 #include <jasper/jas_math.h> 78 79 static jas_cmprof_t *jas_cmprof_create(void); 80 static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *); 81 static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x); 82 83 static void jas_cmpxform_destroy(jas_cmpxform_t *pxform); 84 static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform); 85 86 static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform); 87 static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in, 88 jas_cmreal_t *out, int cnt); 89 90 static int jas_cmputint(long **bufptr, int sgnd, int prec, long val); 91 static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val); 92 static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, 93 jas_cmpxformseq_t *othpxformseq); 94 static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, 95 int, int); 96 static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n); 97 98 static int mono(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **pxformseq); 99 static int triclr(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq); 100 101 static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq); 102 static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i); 103 static jas_cmpxformseq_t *jas_cmpxformseq_create(void); 104 static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq); 105 static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]); 106 static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, 107 int i, jas_cmpxform_t *pxform); 108 109 #define SEQFWD(intent) (intent) 110 #define SEQREV(intent) (4 + (intent)) 111 #define SEQSIM(intent) (8 + (intent)) 112 #define SEQGAM 12 113 114 #define fwdpxformseq(prof, intent) \ 115 (((prof)->pxformseqs[SEQFWD(intent)]) ? \ 116 ((prof)->pxformseqs[SEQFWD(intent)]) : \ 117 ((prof)->pxformseqs[SEQFWD(0)])) 118 119 #define revpxformseq(prof, intent) \ 120 (((prof)->pxformseqs[SEQREV(intent)]) ? \ 121 ((prof)->pxformseqs[SEQREV(intent)]) : \ 122 ((prof)->pxformseqs[SEQREV(0)])) 123 124 #define simpxformseq(prof, intent) \ 125 (((prof)->pxformseqs[SEQSIM(intent)]) ? \ 126 ((prof)->pxformseqs[SEQSIM(intent)]) : \ 127 ((prof)->pxformseqs[SEQSIM(0)])) 128 129 #define gampxformseq(prof) ((prof)->pxformseqs[SEQGAM]) 130 131 static int icctoclrspc(int iccclrspc, int refflag); 132 static jas_cmpxform_t *jas_cmpxform_create0(void); 133 static jas_cmpxform_t *jas_cmpxform_createshapmat(void); 134 static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut); 135 static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv); 136 137 static jas_cmpxformops_t shapmat_ops = {jas_cmshapmat_destroy, jas_cmshapmat_apply, 0}; 138 static jas_cmprof_t *jas_cmprof_createsycc(void); 139 140 /******************************************************************************\ 141 * Color profile class. 142 \******************************************************************************/ 143 144 jas_cmprof_t *jas_cmprof_createfromclrspc(int clrspc) 145 { 146 jas_iccprof_t *iccprof; 147 jas_cmprof_t *prof; 148 149 iccprof = 0; 150 prof = 0; 151 switch (clrspc) { 152 case JAS_CLRSPC_SYCBCR: 153 if (!(prof = jas_cmprof_createsycc())) 154 goto error; 155 break; 156 default: 157 if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) 158 goto error; 159 if (!(prof = jas_cmprof_createfromiccprof(iccprof))) 160 goto error; 161 jas_iccprof_destroy(iccprof); 162 iccprof = 0; 163 if (!jas_clrspc_isgeneric(clrspc)) 164 prof->clrspc = clrspc; 165 break; 166 } 167 return prof; 168 error: 169 if (iccprof) 170 jas_iccprof_destroy(iccprof); 171 return 0; 172 } 173 174 static jas_cmprof_t *jas_cmprof_createsycc() 175 { 176 jas_cmprof_t *prof; 177 jas_cmpxform_t *fwdpxform; 178 jas_cmpxform_t *revpxform; 179 jas_cmshapmat_t *fwdshapmat; 180 jas_cmshapmat_t *revshapmat; 181 int i; 182 int j; 183 184 if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) 185 goto error; 186 prof->clrspc = JAS_CLRSPC_SYCBCR; 187 assert(prof->numchans == 3 && prof->numrefchans == 3); 188 assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ); 189 if (!(fwdpxform = jas_cmpxform_createshapmat())) 190 goto error; 191 fwdpxform->numinchans = 3; 192 fwdpxform->numoutchans = 3; 193 fwdshapmat = &fwdpxform->data.shapmat; 194 fwdshapmat->mono = 0; 195 fwdshapmat->order = 0; 196 fwdshapmat->useluts = 0; 197 fwdshapmat->usemat = 1; 198 fwdshapmat->mat[0][0] = 1.0; 199 fwdshapmat->mat[0][1] = 0.0; 200 fwdshapmat->mat[0][2] = 1.402; 201 fwdshapmat->mat[1][0] = 1.0; 202 fwdshapmat->mat[1][1] = -0.34413; 203 fwdshapmat->mat[1][2] = -0.71414; 204 fwdshapmat->mat[2][0] = 1.0; 205 fwdshapmat->mat[2][1] = 1.772; 206 fwdshapmat->mat[2][2] = 0.0; 207 fwdshapmat->mat[0][3] = -0.5 * (1.402); 208 fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414); 209 fwdshapmat->mat[2][3] = -0.5 * (1.772); 210 if (!(revpxform = jas_cmpxform_createshapmat())) 211 goto error; 212 revpxform->numinchans = 3; 213 revpxform->numoutchans = 3; 214 revshapmat = &revpxform->data.shapmat; 215 revshapmat->mono = 0; 216 revshapmat->order = 1; 217 revshapmat->useluts = 0; 218 revshapmat->usemat = 1; 219 jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat); 220 221 for (i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) { 222 j = SEQFWD(i); 223 if (prof->pxformseqs[j]) { 224 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0, 225 fwdpxform)) 226 goto error; 227 } 228 j = SEQREV(i); 229 if (prof->pxformseqs[j]) { 230 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 231 -1, revpxform)) 232 goto error; 233 } 234 } 235 236 jas_cmpxform_destroy(fwdpxform); 237 jas_cmpxform_destroy(revpxform); 238 return prof; 239 error: 240 return 0; 241 } 242 243 jas_cmprof_t *jas_cmprof_createfromiccprof(jas_iccprof_t *iccprof) 244 { 245 jas_cmprof_t *prof; 246 jas_icchdr_t icchdr; 247 jas_cmpxformseq_t *fwdpxformseq; 248 jas_cmpxformseq_t *revpxformseq; 249 250 prof = 0; 251 fwdpxformseq = 0; 252 revpxformseq = 0; 253 254 if (!(prof = jas_cmprof_create())) 255 goto error; 256 jas_iccprof_gethdr(iccprof, &icchdr); 257 if (!(prof->iccprof = jas_iccprof_copy(iccprof))) 258 goto error; 259 prof->clrspc = icctoclrspc(icchdr.colorspc, 0); 260 prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1); 261 prof->numchans = jas_clrspc_numchans(prof->clrspc); 262 prof->numrefchans = jas_clrspc_numchans(prof->refclrspc); 263 264 if (prof->numchans == 1) { 265 if (mono(prof->iccprof, 0, &fwdpxformseq)) 266 goto error; 267 if (mono(prof->iccprof, 1, &revpxformseq)) 268 goto error; 269 } else if (prof->numchans == 3) { 270 if (triclr(prof->iccprof, 0, &fwdpxformseq)) 271 goto error; 272 if (triclr(prof->iccprof, 1, &revpxformseq)) 273 goto error; 274 } 275 prof->pxformseqs[SEQFWD(0)] = fwdpxformseq; 276 prof->pxformseqs[SEQREV(0)] = revpxformseq; 277 278 #if 0 279 if (prof->numchans > 1) { 280 lut(prof->iccprof, 0, PER, &pxformseq); 281 pxformseqs_set(prof, SEQFWD(PER), pxformseq); 282 lut(prof->iccprof, 1, PER, &pxformseq); 283 pxformseqs_set(prof, SEQREV(PER), pxformseq); 284 lut(prof->iccprof, 0, CLR, &pxformseq); 285 pxformseqs_set(prof, SEQREV(CLR), pxformseq); 286 lut(prof->iccprof, 1, CLR, &pxformseq); 287 pxformseqs_set(prof, SEQREV(CLR), pxformseq); 288 lut(prof->iccprof, 0, SAT, &pxformseq); 289 pxformseqs_set(prof, SEQREV(SAT), pxformseq); 290 lut(prof->iccprof, 1, SAT, &pxformseq); 291 pxformseqs_set(prof, SEQREV(SAT), pxformseq); 292 } 293 #endif 294 295 return prof; 296 297 error: 298 if (fwdpxformseq) { 299 jas_cmpxformseq_destroy(fwdpxformseq); 300 } 301 if (revpxformseq) { 302 jas_cmpxformseq_destroy(revpxformseq); 303 } 304 if (prof) { 305 jas_cmprof_destroy(prof); 306 } 307 308 return 0; 309 } 310 311 static jas_cmprof_t *jas_cmprof_create() 312 { 313 int i; 314 jas_cmprof_t *prof; 315 if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) 316 return 0; 317 memset(prof, 0, sizeof(jas_cmprof_t)); 318 prof->iccprof = 0; 319 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) 320 prof->pxformseqs[i] = 0; 321 return prof; 322 } 323 324 void jas_cmprof_destroy(jas_cmprof_t *prof) 325 { 326 int i; 327 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { 328 if (prof->pxformseqs[i]) { 329 jas_cmpxformseq_destroy(prof->pxformseqs[i]); 330 prof->pxformseqs[i] = 0; 331 } 332 } 333 if (prof->iccprof) 334 jas_iccprof_destroy(prof->iccprof); 335 jas_free(prof); 336 } 337 338 jas_cmprof_t *jas_cmprof_copy(jas_cmprof_t *prof) 339 { 340 jas_cmprof_t *newprof; 341 int i; 342 343 if (!(newprof = jas_cmprof_create())) 344 goto error; 345 newprof->clrspc = prof->clrspc; 346 newprof->numchans = prof->numchans; 347 newprof->refclrspc = prof->refclrspc; 348 newprof->numrefchans = prof->numrefchans; 349 newprof->iccprof = jas_iccprof_copy(prof->iccprof); 350 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { 351 if (prof->pxformseqs[i]) { 352 if (!(newprof->pxformseqs[i] = jas_cmpxformseq_copy(prof->pxformseqs[i]))) 353 goto error; 354 } 355 } 356 return newprof; 357 error: 358 return 0; 359 } 360 361 /******************************************************************************\ 362 * Transform class. 363 \******************************************************************************/ 364 365 jas_cmxform_t *jas_cmxform_create(jas_cmprof_t *inprof, jas_cmprof_t *outprof, 366 jas_cmprof_t *prfprof, int op, int intent, int optimize) 367 { 368 jas_cmxform_t *xform; 369 jas_cmpxformseq_t *inpxformseq; 370 jas_cmpxformseq_t *outpxformseq; 371 jas_cmpxformseq_t *altoutpxformseq; 372 jas_cmpxformseq_t *prfpxformseq; 373 int prfintent; 374 375 /* Avoid compiler warnings about unused parameters. */ 376 optimize = 0; 377 378 prfintent = intent; 379 380 if (!(xform = jas_malloc(sizeof(jas_cmxform_t)))) 381 goto error; 382 if (!(xform->pxformseq = jas_cmpxformseq_create())) 383 goto error; 384 385 switch (op) { 386 case JAS_CMXFORM_OP_FWD: 387 inpxformseq = fwdpxformseq(inprof, intent); 388 outpxformseq = revpxformseq(outprof, intent); 389 if (!inpxformseq || !outpxformseq) 390 goto error; 391 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || 392 jas_cmpxformseq_appendcnvt(xform->pxformseq, 393 inprof->refclrspc, outprof->refclrspc) || 394 jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) 395 goto error; 396 xform->numinchans = jas_clrspc_numchans(inprof->clrspc); 397 xform->numoutchans = jas_clrspc_numchans(outprof->clrspc); 398 break; 399 case JAS_CMXFORM_OP_REV: 400 outpxformseq = fwdpxformseq(outprof, intent); 401 inpxformseq = revpxformseq(inprof, intent); 402 if (!outpxformseq || !inpxformseq) 403 goto error; 404 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || 405 jas_cmpxformseq_appendcnvt(xform->pxformseq, 406 outprof->refclrspc, inprof->refclrspc) || 407 jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) 408 goto error; 409 xform->numinchans = jas_clrspc_numchans(outprof->clrspc); 410 xform->numoutchans = jas_clrspc_numchans(inprof->clrspc); 411 break; 412 case JAS_CMXFORM_OP_PROOF: 413 assert(prfprof); 414 inpxformseq = fwdpxformseq(inprof, intent); 415 prfpxformseq = fwdpxformseq(prfprof, prfintent); 416 if (!inpxformseq || !prfpxformseq) 417 goto error; 418 outpxformseq = simpxformseq(outprof, intent); 419 altoutpxformseq = 0; 420 if (!outpxformseq) { 421 outpxformseq = revpxformseq(outprof, intent); 422 altoutpxformseq = fwdpxformseq(outprof, intent); 423 if (!outpxformseq || !altoutpxformseq) 424 goto error; 425 } 426 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || 427 jas_cmpxformseq_appendcnvt(xform->pxformseq, 428 inprof->refclrspc, outprof->refclrspc)) 429 goto error; 430 if (altoutpxformseq) { 431 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || 432 jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) 433 goto error; 434 } else { 435 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) 436 goto error; 437 } 438 if (jas_cmpxformseq_appendcnvt(xform->pxformseq, 439 outprof->refclrspc, inprof->refclrspc) || 440 jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) 441 goto error; 442 xform->numinchans = jas_clrspc_numchans(inprof->clrspc); 443 xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc); 444 break; 445 case JAS_CMXFORM_OP_GAMUT: 446 inpxformseq = fwdpxformseq(inprof, intent); 447 outpxformseq = gampxformseq(outprof); 448 if (!inpxformseq || !outpxformseq) 449 goto error; 450 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || 451 jas_cmpxformseq_appendcnvt(xform->pxformseq, 452 inprof->refclrspc, outprof->refclrspc) || 453 jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) 454 goto error; 455 xform->numinchans = jas_clrspc_numchans(inprof->clrspc); 456 xform->numoutchans = 1; 457 break; 458 } 459 return xform; 460 error: 461 return 0; 462 } 463 464 #define APPLYBUFSIZ 2048 465 int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out) 466 { 467 jas_cmcmptfmt_t *fmt; 468 jas_cmreal_t buf[2][APPLYBUFSIZ]; 469 jas_cmpxformseq_t *pxformseq; 470 int i; 471 int j; 472 int width; 473 int height; 474 int total; 475 int n; 476 jas_cmreal_t *inbuf; 477 jas_cmreal_t *outbuf; 478 jas_cmpxform_t *pxform; 479 long *dataptr; 480 int maxchans; 481 int bufmax; 482 int m; 483 int bias; 484 jas_cmreal_t scale; 485 long v; 486 jas_cmreal_t *bufptr; 487 488 if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts) 489 goto error; 490 491 fmt = &in->cmptfmts[0]; 492 width = fmt->width; 493 height = fmt->height; 494 for (i = 1; i < xform->numinchans; ++i) { 495 fmt = &in->cmptfmts[i]; 496 if (fmt->width != width || fmt->height != height) { 497 goto error; 498 } 499 } 500 for (i = 0; i < xform->numoutchans; ++i) { 501 fmt = &out->cmptfmts[i]; 502 if (fmt->width != width || fmt->height != height) { 503 goto error; 504 } 505 } 506 507 maxchans = 0; 508 pxformseq = xform->pxformseq; 509 for (i = 0; i < pxformseq->numpxforms; ++i) { 510 pxform = pxformseq->pxforms[i]; 511 if (pxform->numinchans > maxchans) { 512 maxchans = pxform->numinchans; 513 } 514 if (pxform->numoutchans > maxchans) { 515 maxchans = pxform->numoutchans; 516 } 517 } 518 bufmax = APPLYBUFSIZ / maxchans; 519 assert(bufmax > 0); 520 521 total = width * height; 522 n = 0; 523 while (n < total) { 524 525 inbuf = &buf[0][0]; 526 m = JAS_MIN(total - n, bufmax); 527 528 for (i = 0; i < xform->numinchans; ++i) { 529 fmt = &in->cmptfmts[i]; 530 scale = (double)((1 << fmt->prec) - 1); 531 bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0; 532 dataptr = &fmt->buf[n]; 533 bufptr = &inbuf[i]; 534 for (j = 0; j < m; ++j) { 535 if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v)) 536 goto error; 537 *bufptr = (v - bias) / scale; 538 bufptr += xform->numinchans; 539 } 540 } 541 542 inbuf = &buf[0][0]; 543 outbuf = inbuf; 544 for (i = 0; i < pxformseq->numpxforms; ++i) { 545 pxform = pxformseq->pxforms[i]; 546 if (pxform->numoutchans > pxform->numinchans) { 547 outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0]; 548 } else { 549 outbuf = inbuf; 550 } 551 if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) 552 goto error; 553 inbuf = outbuf; 554 } 555 556 for (i = 0; i < xform->numoutchans; ++i) { 557 fmt = &out->cmptfmts[i]; 558 scale = (double)((1 << fmt->prec) - 1); 559 bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0; 560 bufptr = &outbuf[i]; 561 dataptr = &fmt->buf[n]; 562 for (j = 0; j < m; ++j) { 563 v = (*bufptr) * scale + bias; 564 bufptr += xform->numoutchans; 565 if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v)) 566 goto error; 567 } 568 } 569 570 n += m; 571 } 572 573 return 0; 574 error: 575 return -1; 576 } 577 578 void jas_cmxform_destroy(jas_cmxform_t *xform) 579 { 580 if (xform->pxformseq) 581 jas_cmpxformseq_destroy(xform->pxformseq); 582 jas_free(xform); 583 } 584 585 /******************************************************************************\ 586 * Primitive transform sequence class. 587 \******************************************************************************/ 588 589 static jas_cmpxformseq_t *jas_cmpxformseq_create() 590 { 591 jas_cmpxformseq_t *pxformseq; 592 pxformseq = 0; 593 if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) 594 goto error; 595 pxformseq->pxforms = 0; 596 pxformseq->numpxforms = 0; 597 pxformseq->maxpxforms = 0; 598 if (jas_cmpxformseq_resize(pxformseq, 16)) 599 goto error; 600 return pxformseq; 601 error: 602 if (pxformseq) 603 jas_cmpxformseq_destroy(pxformseq); 604 return 0; 605 } 606 607 static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq) 608 { 609 jas_cmpxformseq_t *newpxformseq; 610 611 if (!(newpxformseq = jas_cmpxformseq_create())) 612 goto error; 613 if (jas_cmpxformseq_append(newpxformseq, pxformseq)) 614 goto error; 615 return newpxformseq; 616 error: 617 return 0; 618 } 619 620 static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq) 621 { 622 while (pxformseq->numpxforms > 0) 623 jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1); 624 if (pxformseq->pxforms) 625 jas_free(pxformseq->pxforms); 626 jas_free(pxformseq); 627 } 628 629 static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i) 630 { 631 assert(i >= 0 && i < pxformseq->numpxforms); 632 if (i != pxformseq->numpxforms - 1) 633 abort(); 634 jas_cmpxform_destroy(pxformseq->pxforms[i]); 635 pxformseq->pxforms[i] = 0; 636 --pxformseq->numpxforms; 637 return 0; 638 } 639 640 static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, 641 int dstclrspc, int srcclrspc) 642 { 643 if (dstclrspc == srcclrspc) 644 return 0; 645 abort(); 646 /* Avoid compiler warnings about unused parameters. */ 647 pxformseq = 0; 648 return -1; 649 } 650 651 static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, 652 int i, jas_cmpxform_t *pxform) 653 { 654 jas_cmpxform_t *tmppxform; 655 int n; 656 if (i < 0) 657 i = pxformseq->numpxforms; 658 assert(i >= 0 && i <= pxformseq->numpxforms); 659 if (pxformseq->numpxforms >= pxformseq->maxpxforms) { 660 if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + 661 16)) 662 goto error; 663 } 664 assert(pxformseq->numpxforms < pxformseq->maxpxforms); 665 if (!(tmppxform = jas_cmpxform_copy(pxform))) 666 goto error; 667 n = pxformseq->numpxforms - i; 668 if (n > 0) { 669 memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i], 670 n * sizeof(jas_cmpxform_t *)); 671 } 672 pxformseq->pxforms[i] = tmppxform; 673 ++pxformseq->numpxforms; 674 return 0; 675 error: 676 return -1; 677 } 678 679 static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, 680 jas_cmpxformseq_t *othpxformseq) 681 { 682 int n; 683 int i; 684 jas_cmpxform_t *pxform; 685 jas_cmpxform_t *othpxform; 686 n = pxformseq->numpxforms + othpxformseq->numpxforms; 687 if (n > pxformseq->maxpxforms) { 688 if (jas_cmpxformseq_resize(pxformseq, n)) 689 goto error; 690 } 691 for (i = 0; i < othpxformseq->numpxforms; ++i) { 692 othpxform = othpxformseq->pxforms[i]; 693 if (!(pxform = jas_cmpxform_copy(othpxform))) 694 goto error; 695 pxformseq->pxforms[pxformseq->numpxforms] = pxform; 696 ++pxformseq->numpxforms; 697 } 698 return 0; 699 error: 700 return -1; 701 } 702 703 static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n) 704 { 705 jas_cmpxform_t **p; 706 assert(n >= pxformseq->numpxforms); 707 p = jas_realloc2(pxformseq->pxforms, n, sizeof(jas_cmpxform_t *)); 708 if (!p) { 709 return -1; 710 } 711 pxformseq->pxforms = p; 712 pxformseq->maxpxforms = n; 713 return 0; 714 } 715 716 /******************************************************************************\ 717 * Primitive transform class. 718 \******************************************************************************/ 719 720 static jas_cmpxform_t *jas_cmpxform_create0() 721 { 722 jas_cmpxform_t *pxform; 723 if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) 724 return 0; 725 memset(pxform, 0, sizeof(jas_cmpxform_t)); 726 pxform->refcnt = 0; 727 pxform->ops = 0; 728 return pxform; 729 } 730 731 static void jas_cmpxform_destroy(jas_cmpxform_t *pxform) 732 { 733 if (--pxform->refcnt <= 0) { 734 (*pxform->ops->destroy)(pxform); 735 jas_free(pxform); 736 } 737 } 738 739 static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform) 740 { 741 ++pxform->refcnt; 742 return pxform; 743 } 744 745 /******************************************************************************\ 746 * Shaper matrix class. 747 \******************************************************************************/ 748 749 static jas_cmpxform_t *jas_cmpxform_createshapmat() 750 { 751 int i; 752 int j; 753 jas_cmpxform_t *pxform; 754 jas_cmshapmat_t *shapmat; 755 if (!(pxform = jas_cmpxform_create0())) 756 return 0; 757 pxform->ops = &shapmat_ops; 758 shapmat = &pxform->data.shapmat; 759 shapmat->mono = 0; 760 shapmat->order = 0; 761 shapmat->useluts = 0; 762 shapmat->usemat = 0; 763 for (i = 0; i < 3; ++i) 764 jas_cmshapmatlut_init(&shapmat->luts[i]); 765 for (i = 0; i < 3; ++i) { 766 for (j = 0; j < 4; ++j) 767 shapmat->mat[i][j] = 0.0; 768 } 769 ++pxform->refcnt; 770 return pxform; 771 } 772 773 static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform) 774 { 775 jas_cmshapmat_t *shapmat = &pxform->data.shapmat; 776 int i; 777 for (i = 0; i < 3; ++i) 778 jas_cmshapmatlut_cleanup(&shapmat->luts[i]); 779 } 780 781 static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in, 782 jas_cmreal_t *out, int cnt) 783 { 784 jas_cmshapmat_t *shapmat = &pxform->data.shapmat; 785 jas_cmreal_t *src; 786 jas_cmreal_t *dst; 787 jas_cmreal_t a0; 788 jas_cmreal_t a1; 789 jas_cmreal_t a2; 790 jas_cmreal_t b0; 791 jas_cmreal_t b1; 792 jas_cmreal_t b2; 793 src = in; 794 dst = out; 795 if (!shapmat->mono) { 796 while (--cnt >= 0) { 797 a0 = *src++; 798 a1 = *src++; 799 a2 = *src++; 800 if (!shapmat->order && shapmat->useluts) { 801 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 802 a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1); 803 a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2); 804 } 805 if (shapmat->usemat) { 806 b0 = shapmat->mat[0][0] * a0 807 + shapmat->mat[0][1] * a1 808 + shapmat->mat[0][2] * a2 809 + shapmat->mat[0][3]; 810 b1 = shapmat->mat[1][0] * a0 811 + shapmat->mat[1][1] * a1 812 + shapmat->mat[1][2] * a2 813 + shapmat->mat[1][3]; 814 b2 = shapmat->mat[2][0] * a0 815 + shapmat->mat[2][1] * a1 816 + shapmat->mat[2][2] * a2 817 + shapmat->mat[2][3]; 818 a0 = b0; 819 a1 = b1; 820 a2 = b2; 821 } 822 if (shapmat->order && shapmat->useluts) { 823 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 824 a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1); 825 a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2); 826 } 827 *dst++ = a0; 828 *dst++ = a1; 829 *dst++ = a2; 830 } 831 } else { 832 if (!shapmat->order) { 833 while (--cnt >= 0) { 834 a0 = *src++; 835 if (shapmat->useluts) 836 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 837 a2 = a0 * shapmat->mat[2][0]; 838 a1 = a0 * shapmat->mat[1][0]; 839 a0 = a0 * shapmat->mat[0][0]; 840 *dst++ = a0; 841 *dst++ = a1; 842 *dst++ = a2; 843 } 844 } else { 845 while (--cnt >= 0) { 846 a0 = *src++; 847 src++; 848 src++; 849 a0 = a0 * shapmat->mat[0][0]; 850 if (shapmat->useluts) 851 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 852 *dst++ = a0; 853 } 854 } 855 } 856 857 return 0; 858 } 859 860 static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut) 861 { 862 lut->data = 0; 863 lut->size = 0; 864 } 865 866 static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut) 867 { 868 if (lut->data) { 869 jas_free(lut->data); 870 lut->data = 0; 871 } 872 lut->size = 0; 873 } 874 875 static double gammafn(double x, double gamma) 876 { 877 if (x == 0.0) 878 return 0.0; 879 return pow(x, gamma); 880 } 881 882 static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv) 883 { 884 jas_cmreal_t gamma; 885 int i; 886 gamma = 0; 887 jas_cmshapmatlut_cleanup(lut); 888 if (curv->numents == 0) { 889 lut->size = 2; 890 if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) 891 goto error; 892 lut->data[0] = 0.0; 893 lut->data[1] = 1.0; 894 } else if (curv->numents == 1) { 895 lut->size = 256; 896 if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) 897 goto error; 898 gamma = curv->ents[0] / 256.0; 899 for (i = 0; i < lut->size; ++i) { 900 lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma); 901 } 902 } else { 903 lut->size = curv->numents; 904 if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t)))) 905 goto error; 906 for (i = 0; i < lut->size; ++i) { 907 lut->data[i] = curv->ents[i] / 65535.0; 908 } 909 } 910 return 0; 911 error: 912 return -1; 913 } 914 915 static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x) 916 { 917 jas_cmreal_t t; 918 int lo; 919 int hi; 920 t = x * (lut->size - 1); 921 lo = floor(t); 922 if (lo < 0) 923 return lut->data[0]; 924 hi = ceil(t); 925 if (hi >= lut->size) 926 return lut->data[lut->size - 1]; 927 return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]); 928 } 929 930 static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, 931 jas_cmshapmatlut_t *lut, int n) 932 { 933 int i; 934 int j; 935 int k; 936 jas_cmreal_t ax; 937 jas_cmreal_t ay; 938 jas_cmreal_t bx; 939 jas_cmreal_t by; 940 jas_cmreal_t sx; 941 jas_cmreal_t sy; 942 assert(n >= 2); 943 if (invlut->data) { 944 jas_free(invlut->data); 945 invlut->data = 0; 946 } 947 /* The sample values should be nondecreasing. */ 948 for (i = 1; i < lut->size; ++i) { 949 if (lut->data[i - 1] > lut->data[i]) { 950 assert(0); 951 return -1; 952 } 953 } 954 if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t)))) 955 return -1; 956 invlut->size = n; 957 for (i = 0; i < invlut->size; ++i) { 958 sy = ((double) i) / (invlut->size - 1); 959 sx = 1.0; 960 for (j = 0; j < lut->size; ++j) { 961 ay = lut->data[j]; 962 if (sy == ay) { 963 for (k = j + 1; k < lut->size; ++k) { 964 by = lut->data[k]; 965 if (by != sy) 966 break; 967 #if 0 968 assert(0); 969 #endif 970 } 971 if (k < lut->size) { 972 --k; 973 ax = ((double) j) / (lut->size - 1); 974 bx = ((double) k) / (lut->size - 1); 975 sx = (ax + bx) / 2.0; 976 } 977 break; 978 } 979 if (j < lut->size - 1) { 980 by = lut->data[j + 1]; 981 if (sy > ay && sy < by) { 982 ax = ((double) j) / (lut->size - 1); 983 bx = ((double) j + 1) / (lut->size - 1); 984 sx = ax + 985 (sy - ay) / (by - ay) * (bx - ax); 986 break; 987 } 988 } 989 } 990 invlut->data[i] = sx; 991 } 992 #if 0 993 for (i=0;i<lut->size;++i) 994 jas_eprintf("lut[%d]=%f ", i, lut->data[i]); 995 for (i=0;i<invlut->size;++i) 996 jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]); 997 #endif 998 return 0; 999 } 1000 1001 static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]) 1002 { 1003 jas_cmreal_t d; 1004 d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1]) 1005 - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0]) 1006 + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]); 1007 #if 0 1008 jas_eprintf("delta=%f\n", d); 1009 #endif 1010 if (JAS_ABS(d) < 1e-6) 1011 return -1; 1012 out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d; 1013 out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d; 1014 out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d; 1015 out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d; 1016 out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d; 1017 out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d; 1018 out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d; 1019 out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d; 1020 out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d; 1021 out[0][3] = -in[0][3]; 1022 out[1][3] = -in[1][3]; 1023 out[2][3] = -in[2][3]; 1024 #if 0 1025 jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", 1026 in[0][0], in[0][1], in[0][2], in[0][3], 1027 in[1][0], in[1][1], in[1][2], in[1][3], 1028 in[2][0], in[2][1], in[2][2], in[2][3]); 1029 jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", 1030 out[0][0], out[0][1], out[0][2], out[0][3], 1031 out[1][0], out[1][1], out[1][2], out[1][3], 1032 out[2][0], out[2][1], out[2][2], out[2][3]); 1033 #endif 1034 return 0; 1035 } 1036 1037 /******************************************************************************\ 1038 * 1039 \******************************************************************************/ 1040 1041 static int icctoclrspc(int iccclrspc, int refflag) 1042 { 1043 if (refflag) { 1044 switch (iccclrspc) { 1045 case JAS_ICC_COLORSPC_XYZ: 1046 return JAS_CLRSPC_CIEXYZ; 1047 case JAS_ICC_COLORSPC_LAB: 1048 return JAS_CLRSPC_CIELAB; 1049 default: 1050 abort(); 1051 break; 1052 } 1053 } else { 1054 switch (iccclrspc) { 1055 case JAS_ICC_COLORSPC_YCBCR: 1056 return JAS_CLRSPC_GENYCBCR; 1057 case JAS_ICC_COLORSPC_RGB: 1058 return JAS_CLRSPC_GENRGB; 1059 case JAS_ICC_COLORSPC_GRAY: 1060 return JAS_CLRSPC_GENGRAY; 1061 default: 1062 abort(); 1063 break; 1064 } 1065 } 1066 } 1067 1068 static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) 1069 { 1070 jas_iccattrval_t *graytrc; 1071 jas_cmshapmat_t *shapmat; 1072 jas_cmpxform_t *pxform; 1073 jas_cmpxformseq_t *pxformseq; 1074 jas_cmshapmatlut_t lut; 1075 1076 jas_cmshapmatlut_init(&lut); 1077 if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) || 1078 graytrc->type != JAS_ICC_TYPE_CURV) 1079 goto error; 1080 if (!(pxform = jas_cmpxform_createshapmat())) 1081 goto error; 1082 shapmat = &pxform->data.shapmat; 1083 if (!(pxformseq = jas_cmpxformseq_create())) 1084 goto error; 1085 if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) 1086 goto error; 1087 1088 pxform->numinchans = 1; 1089 pxform->numoutchans = 3; 1090 1091 shapmat->mono = 1; 1092 shapmat->useluts = 1; 1093 shapmat->usemat = 1; 1094 if (!op) { 1095 shapmat->order = 0; 1096 shapmat->mat[0][0] = 0.9642; 1097 shapmat->mat[1][0] = 1.0; 1098 shapmat->mat[2][0] = 0.8249; 1099 if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv)) 1100 goto error; 1101 } else { 1102 shapmat->order = 1; 1103 shapmat->mat[0][0] = 1.0 / 0.9642; 1104 shapmat->mat[1][0] = 1.0; 1105 shapmat->mat[2][0] = 1.0 / 0.8249; 1106 jas_cmshapmatlut_init(&lut); 1107 if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) 1108 goto error; 1109 if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size)) 1110 goto error; 1111 jas_cmshapmatlut_cleanup(&lut); 1112 } 1113 jas_iccattrval_destroy(graytrc); 1114 jas_cmpxform_destroy(pxform); 1115 *retpxformseq = pxformseq; 1116 return 0; 1117 error: 1118 return -1; 1119 } 1120 1121 static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) 1122 { 1123 int i; 1124 jas_iccattrval_t *trcs[3]; 1125 jas_iccattrval_t *cols[3]; 1126 jas_cmshapmat_t *shapmat; 1127 jas_cmpxform_t *pxform; 1128 jas_cmpxformseq_t *pxformseq; 1129 jas_cmreal_t mat[3][4]; 1130 jas_cmshapmatlut_t lut; 1131 1132 pxform = 0; 1133 pxformseq = 0; 1134 for (i = 0; i < 3; ++i) { 1135 trcs[i] = 0; 1136 cols[i] = 0; 1137 } 1138 jas_cmshapmatlut_init(&lut); 1139 1140 if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) || 1141 !(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) || 1142 !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) || 1143 !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) || 1144 !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) || 1145 !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL))) 1146 goto error; 1147 for (i = 0; i < 3; ++i) { 1148 if (trcs[i]->type != JAS_ICC_TYPE_CURV || 1149 cols[i]->type != JAS_ICC_TYPE_XYZ) 1150 goto error; 1151 } 1152 if (!(pxform = jas_cmpxform_createshapmat())) 1153 goto error; 1154 pxform->numinchans = 3; 1155 pxform->numoutchans = 3; 1156 shapmat = &pxform->data.shapmat; 1157 if (!(pxformseq = jas_cmpxformseq_create())) 1158 goto error; 1159 if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) 1160 goto error; 1161 shapmat->mono = 0; 1162 shapmat->useluts = 1; 1163 shapmat->usemat = 1; 1164 if (!op) { 1165 shapmat->order = 0; 1166 for (i = 0; i < 3; ++i) { 1167 shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0; 1168 shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0; 1169 shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0; 1170 } 1171 for (i = 0; i < 3; ++i) 1172 shapmat->mat[i][3] = 0.0; 1173 for (i = 0; i < 3; ++i) { 1174 if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv)) 1175 goto error; 1176 } 1177 } else { 1178 shapmat->order = 1; 1179 for (i = 0; i < 3; ++i) { 1180 mat[0][i] = cols[i]->data.xyz.x / 65536.0; 1181 mat[1][i] = cols[i]->data.xyz.y / 65536.0; 1182 mat[2][i] = cols[i]->data.xyz.z / 65536.0; 1183 } 1184 for (i = 0; i < 3; ++i) 1185 mat[i][3] = 0.0; 1186 if (jas_cmshapmat_invmat(shapmat->mat, mat)) 1187 goto error; 1188 for (i = 0; i < 3; ++i) { 1189 jas_cmshapmatlut_init(&lut); 1190 if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv)) 1191 goto error; 1192 if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size)) 1193 goto error; 1194 jas_cmshapmatlut_cleanup(&lut); 1195 } 1196 } 1197 for (i = 0; i < 3; ++i) { 1198 jas_iccattrval_destroy(trcs[i]); 1199 jas_iccattrval_destroy(cols[i]); 1200 } 1201 jas_cmpxform_destroy(pxform); 1202 *retpxformseq = pxformseq; 1203 return 0; 1204 1205 error: 1206 1207 for (i = 0; i < 3; ++i) { 1208 if (trcs[i]) { 1209 jas_iccattrval_destroy(trcs[i]); 1210 } 1211 if (cols[i]) { 1212 jas_iccattrval_destroy(cols[i]); 1213 } 1214 } 1215 if (pxformseq) { 1216 jas_cmpxformseq_destroy(pxformseq); 1217 } 1218 if (pxform) { 1219 jas_cmpxform_destroy(pxform); 1220 } 1221 1222 return -1; 1223 } 1224 1225 static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val) 1226 { 1227 long v; 1228 int m; 1229 v = **bufptr; 1230 if (sgnd) { 1231 m = (1 << (prec - 1)); 1232 if (v < -m || v >= m) 1233 return -1; 1234 } else { 1235 if (v < 0 || v >= (1 << prec)) 1236 return -1; 1237 } 1238 ++(*bufptr); 1239 *val = v; 1240 return 0; 1241 } 1242 1243 static int jas_cmputint(long **bufptr, int sgnd, int prec, long val) 1244 { 1245 int m; 1246 if (sgnd) { 1247 m = (1 << (prec - 1)); 1248 if (val < -m || val >= m) 1249 return -1; 1250 } else { 1251 if (val < 0 || val >= (1 << prec)) 1252 return -1; 1253 } 1254 **bufptr = val; 1255 ++(*bufptr); 1256 return 0; 1257 } 1258 1259 int jas_clrspc_numchans(int clrspc) 1260 { 1261 switch (jas_clrspc_fam(clrspc)) { 1262 case JAS_CLRSPC_FAM_XYZ: 1263 case JAS_CLRSPC_FAM_LAB: 1264 case JAS_CLRSPC_FAM_RGB: 1265 case JAS_CLRSPC_FAM_YCBCR: 1266 return 3; 1267 break; 1268 case JAS_CLRSPC_FAM_GRAY: 1269 return 1; 1270 break; 1271 default: 1272 abort(); 1273 break; 1274 } 1275 } 1276 1277 jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof) 1278 { 1279 return jas_iccprof_copy(prof->iccprof); 1280 } 1281