jas_cm.c (34364B)
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) 1999-2000 Image Power, Inc. 11 * Copyright (c) 1999-2000 The University of British Columbia 12 * Copyright (c) 2001-2003 Michael David Adams 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 1918 2005-07-24 14:12:08Z baford $ 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 #if 0 162 jas_iccprof_destroy(iccprof); 163 #else 164 prof->iccprof = iccprof; 165 #endif 166 if (!jas_clrspc_isgeneric(clrspc)) 167 prof->clrspc = clrspc; 168 break; 169 } 170 return prof; 171 error: 172 if (iccprof) 173 jas_iccprof_destroy(iccprof); 174 return 0; 175 } 176 177 static jas_cmprof_t *jas_cmprof_createsycc() 178 { 179 jas_cmprof_t *prof; 180 jas_cmpxform_t *fwdpxform; 181 jas_cmpxform_t *revpxform; 182 jas_cmshapmat_t *fwdshapmat; 183 jas_cmshapmat_t *revshapmat; 184 int i; 185 int j; 186 187 if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) 188 goto error; 189 prof->clrspc = JAS_CLRSPC_SYCBCR; 190 assert(prof->numchans == 3 && prof->numrefchans == 3); 191 assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ); 192 if (!(fwdpxform = jas_cmpxform_createshapmat())) 193 goto error; 194 fwdpxform->numinchans = 3; 195 fwdpxform->numoutchans = 3; 196 fwdshapmat = &fwdpxform->data.shapmat; 197 fwdshapmat->mono = 0; 198 fwdshapmat->order = 0; 199 fwdshapmat->useluts = 0; 200 fwdshapmat->usemat = 1; 201 fwdshapmat->mat[0][0] = 1.0; 202 fwdshapmat->mat[0][1] = 0.0; 203 fwdshapmat->mat[0][2] = 1.402; 204 fwdshapmat->mat[1][0] = 1.0; 205 fwdshapmat->mat[1][1] = -0.34413; 206 fwdshapmat->mat[1][2] = -0.71414; 207 fwdshapmat->mat[2][0] = 1.0; 208 fwdshapmat->mat[2][1] = 1.772; 209 fwdshapmat->mat[2][2] = 0.0; 210 fwdshapmat->mat[0][3] = -0.5 * (1.402); 211 fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414); 212 fwdshapmat->mat[2][3] = -0.5 * (1.772); 213 if (!(revpxform = jas_cmpxform_createshapmat())) 214 goto error; 215 revpxform->numinchans = 3; 216 revpxform->numoutchans = 3; 217 revshapmat = &revpxform->data.shapmat; 218 revshapmat->mono = 0; 219 revshapmat->order = 1; 220 revshapmat->useluts = 0; 221 revshapmat->usemat = 1; 222 jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat); 223 224 for (i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) { 225 j = SEQFWD(i); 226 if (prof->pxformseqs[j]) { 227 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0, 228 fwdpxform)) 229 goto error; 230 } 231 j = SEQREV(i); 232 if (prof->pxformseqs[j]) { 233 if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 234 -1, revpxform)) 235 goto error; 236 } 237 } 238 239 jas_cmpxform_destroy(fwdpxform); 240 jas_cmpxform_destroy(revpxform); 241 return prof; 242 error: 243 return 0; 244 } 245 246 jas_cmprof_t *jas_cmprof_createfromiccprof(jas_iccprof_t *iccprof) 247 { 248 jas_cmprof_t *prof; 249 jas_icchdr_t icchdr; 250 jas_cmpxformseq_t *fwdpxformseq; 251 jas_cmpxformseq_t *revpxformseq; 252 253 if (!(prof = jas_cmprof_create())) 254 goto error; 255 jas_iccprof_gethdr(iccprof, &icchdr); 256 if (!(prof->iccprof = jas_iccprof_copy(iccprof))) 257 goto error; 258 prof->clrspc = icctoclrspc(icchdr.colorspc, 0); 259 prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1); 260 prof->numchans = jas_clrspc_numchans(prof->clrspc); 261 prof->numrefchans = jas_clrspc_numchans(prof->refclrspc); 262 263 if (prof->numchans == 1) { 264 if (mono(prof->iccprof, 0, &fwdpxformseq)) 265 goto error; 266 if (mono(prof->iccprof, 1, &revpxformseq)) 267 goto error; 268 } else if (prof->numchans == 3) { 269 if (triclr(prof->iccprof, 0, &fwdpxformseq)) 270 goto error; 271 if (triclr(prof->iccprof, 1, &revpxformseq)) 272 goto error; 273 } 274 prof->pxformseqs[SEQFWD(0)] = fwdpxformseq; 275 prof->pxformseqs[SEQREV(0)] = revpxformseq; 276 277 #if 0 278 if (prof->numchans > 1) { 279 lut(prof->iccprof, 0, PER, &pxformseq); 280 pxformseqs_set(prof, SEQFWD(PER), pxformseq); 281 lut(prof->iccprof, 1, PER, &pxformseq); 282 pxformseqs_set(prof, SEQREV(PER), pxformseq); 283 lut(prof->iccprof, 0, CLR, &pxformseq); 284 pxformseqs_set(prof, SEQREV(CLR), pxformseq); 285 lut(prof->iccprof, 1, CLR, &pxformseq); 286 pxformseqs_set(prof, SEQREV(CLR), pxformseq); 287 lut(prof->iccprof, 0, SAT, &pxformseq); 288 pxformseqs_set(prof, SEQREV(SAT), pxformseq); 289 lut(prof->iccprof, 1, SAT, &pxformseq); 290 pxformseqs_set(prof, SEQREV(SAT), pxformseq); 291 } 292 #endif 293 294 return prof; 295 error: 296 return 0; 297 } 298 299 static jas_cmprof_t *jas_cmprof_create() 300 { 301 int i; 302 jas_cmprof_t *prof; 303 if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) 304 return 0; 305 memset(prof, 0, sizeof(jas_cmprof_t)); 306 prof->iccprof = 0; 307 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) 308 prof->pxformseqs[i] = 0; 309 return prof; 310 } 311 312 void jas_cmprof_destroy(jas_cmprof_t *prof) 313 { 314 int i; 315 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { 316 if (prof->pxformseqs[i]) { 317 jas_cmpxformseq_destroy(prof->pxformseqs[i]); 318 prof->pxformseqs[i] = 0; 319 } 320 } 321 if (prof->iccprof) 322 jas_iccprof_destroy(prof->iccprof); 323 jas_free(prof); 324 } 325 326 jas_cmprof_t *jas_cmprof_copy(jas_cmprof_t *prof) 327 { 328 jas_cmprof_t *newprof; 329 int i; 330 331 if (!(newprof = jas_cmprof_create())) 332 goto error; 333 newprof->clrspc = prof->clrspc; 334 newprof->numchans = prof->numchans; 335 newprof->refclrspc = prof->refclrspc; 336 newprof->numrefchans = prof->numrefchans; 337 newprof->iccprof = jas_iccprof_copy(prof->iccprof); 338 for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { 339 if (prof->pxformseqs[i]) { 340 if (!(newprof->pxformseqs[i] = jas_cmpxformseq_copy(prof->pxformseqs[i]))) 341 goto error; 342 } 343 } 344 return newprof; 345 error: 346 return 0; 347 } 348 349 /******************************************************************************\ 350 * Transform class. 351 \******************************************************************************/ 352 353 jas_cmxform_t *jas_cmxform_create(jas_cmprof_t *inprof, jas_cmprof_t *outprof, 354 jas_cmprof_t *prfprof, int op, int intent, int optimize) 355 { 356 jas_cmxform_t *xform; 357 jas_cmpxformseq_t *inpxformseq; 358 jas_cmpxformseq_t *outpxformseq; 359 jas_cmpxformseq_t *altoutpxformseq; 360 jas_cmpxformseq_t *prfpxformseq; 361 int prfintent; 362 363 /* Avoid compiler warnings about unused parameters. */ 364 optimize = 0; 365 366 prfintent = intent; 367 368 if (!(xform = jas_malloc(sizeof(jas_cmxform_t)))) 369 goto error; 370 if (!(xform->pxformseq = jas_cmpxformseq_create())) 371 goto error; 372 373 switch (op) { 374 case JAS_CMXFORM_OP_FWD: 375 inpxformseq = fwdpxformseq(inprof, intent); 376 outpxformseq = revpxformseq(outprof, intent); 377 if (!inpxformseq || !outpxformseq) 378 goto error; 379 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || 380 jas_cmpxformseq_appendcnvt(xform->pxformseq, 381 inprof->refclrspc, outprof->refclrspc) || 382 jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) 383 goto error; 384 xform->numinchans = jas_clrspc_numchans(inprof->clrspc); 385 xform->numoutchans = jas_clrspc_numchans(outprof->clrspc); 386 break; 387 case JAS_CMXFORM_OP_REV: 388 outpxformseq = fwdpxformseq(outprof, intent); 389 inpxformseq = revpxformseq(inprof, intent); 390 if (!outpxformseq || !inpxformseq) 391 goto error; 392 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || 393 jas_cmpxformseq_appendcnvt(xform->pxformseq, 394 outprof->refclrspc, inprof->refclrspc) || 395 jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) 396 goto error; 397 xform->numinchans = jas_clrspc_numchans(outprof->clrspc); 398 xform->numoutchans = jas_clrspc_numchans(inprof->clrspc); 399 break; 400 case JAS_CMXFORM_OP_PROOF: 401 assert(prfprof); 402 inpxformseq = fwdpxformseq(inprof, intent); 403 prfpxformseq = fwdpxformseq(prfprof, prfintent); 404 if (!inpxformseq || !prfpxformseq) 405 goto error; 406 outpxformseq = simpxformseq(outprof, intent); 407 altoutpxformseq = 0; 408 if (!outpxformseq) { 409 outpxformseq = revpxformseq(outprof, intent); 410 altoutpxformseq = fwdpxformseq(outprof, intent); 411 if (!outpxformseq || !altoutpxformseq) 412 goto error; 413 } 414 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || 415 jas_cmpxformseq_appendcnvt(xform->pxformseq, 416 inprof->refclrspc, outprof->refclrspc)) 417 goto error; 418 if (altoutpxformseq) { 419 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || 420 jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) 421 goto error; 422 } else { 423 if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) 424 goto error; 425 } 426 if (jas_cmpxformseq_appendcnvt(xform->pxformseq, 427 outprof->refclrspc, inprof->refclrspc) || 428 jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) 429 goto error; 430 xform->numinchans = jas_clrspc_numchans(inprof->clrspc); 431 xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc); 432 break; 433 case JAS_CMXFORM_OP_GAMUT: 434 inpxformseq = fwdpxformseq(inprof, intent); 435 outpxformseq = gampxformseq(outprof); 436 if (!inpxformseq || !outpxformseq) 437 goto error; 438 if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || 439 jas_cmpxformseq_appendcnvt(xform->pxformseq, 440 inprof->refclrspc, outprof->refclrspc) || 441 jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) 442 goto error; 443 xform->numinchans = jas_clrspc_numchans(inprof->clrspc); 444 xform->numoutchans = 1; 445 break; 446 } 447 return xform; 448 error: 449 return 0; 450 } 451 452 #define APPLYBUFSIZ 2048 453 int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out) 454 { 455 jas_cmcmptfmt_t *fmt; 456 jas_cmreal_t buf[2][APPLYBUFSIZ]; 457 jas_cmpxformseq_t *pxformseq; 458 int i; 459 int j; 460 int width; 461 int height; 462 int total; 463 int n; 464 jas_cmreal_t *inbuf; 465 jas_cmreal_t *outbuf; 466 jas_cmpxform_t *pxform; 467 long *dataptr; 468 int maxchans; 469 int bufmax; 470 int m; 471 int bias; 472 jas_cmreal_t scale; 473 long v; 474 jas_cmreal_t *bufptr; 475 476 if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts) 477 goto error; 478 479 fmt = &in->cmptfmts[0]; 480 width = fmt->width; 481 height = fmt->height; 482 for (i = 1; i < xform->numinchans; ++i) { 483 fmt = &in->cmptfmts[i]; 484 if (fmt->width != width || fmt->height != height) { 485 goto error; 486 } 487 } 488 for (i = 0; i < xform->numoutchans; ++i) { 489 fmt = &out->cmptfmts[i]; 490 if (fmt->width != width || fmt->height != height) { 491 goto error; 492 } 493 } 494 495 maxchans = 0; 496 pxformseq = xform->pxformseq; 497 for (i = 0; i < pxformseq->numpxforms; ++i) { 498 pxform = pxformseq->pxforms[i]; 499 if (pxform->numinchans > maxchans) { 500 maxchans = pxform->numinchans; 501 } 502 if (pxform->numoutchans > maxchans) { 503 maxchans = pxform->numoutchans; 504 } 505 } 506 bufmax = APPLYBUFSIZ / maxchans; 507 assert(bufmax > 0); 508 509 total = width * height; 510 n = 0; 511 while (n < total) { 512 513 inbuf = &buf[0][0]; 514 m = JAS_MIN(total - n, bufmax); 515 516 for (i = 0; i < xform->numinchans; ++i) { 517 fmt = &in->cmptfmts[i]; 518 scale = (double)((1 << fmt->prec) - 1); 519 bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0; 520 dataptr = &fmt->buf[n]; 521 bufptr = &inbuf[i]; 522 for (j = 0; j < m; ++j) { 523 if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v)) 524 goto error; 525 *bufptr = (v - bias) / scale; 526 bufptr += xform->numinchans; 527 } 528 } 529 530 inbuf = &buf[0][0]; 531 outbuf = inbuf; 532 for (i = 0; i < pxformseq->numpxforms; ++i) { 533 pxform = pxformseq->pxforms[i]; 534 if (pxform->numoutchans > pxform->numinchans) { 535 outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0]; 536 } else { 537 outbuf = inbuf; 538 } 539 if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) 540 goto error; 541 inbuf = outbuf; 542 } 543 544 for (i = 0; i < xform->numoutchans; ++i) { 545 fmt = &out->cmptfmts[i]; 546 scale = (double)((1 << fmt->prec) - 1); 547 bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0; 548 bufptr = &outbuf[i]; 549 dataptr = &fmt->buf[n]; 550 for (j = 0; j < m; ++j) { 551 v = (*bufptr) * scale + bias; 552 bufptr += xform->numoutchans; 553 if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v)) 554 goto error; 555 } 556 } 557 558 n += m; 559 } 560 561 return 0; 562 error: 563 return -1; 564 } 565 566 void jas_cmxform_destroy(jas_cmxform_t *xform) 567 { 568 if (xform->pxformseq) 569 jas_cmpxformseq_destroy(xform->pxformseq); 570 jas_free(xform); 571 } 572 573 /******************************************************************************\ 574 * Primitive transform sequence class. 575 \******************************************************************************/ 576 577 static jas_cmpxformseq_t *jas_cmpxformseq_create() 578 { 579 jas_cmpxformseq_t *pxformseq; 580 pxformseq = 0; 581 if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) 582 goto error; 583 pxformseq->pxforms = 0; 584 pxformseq->numpxforms = 0; 585 pxformseq->maxpxforms = 0; 586 if (jas_cmpxformseq_resize(pxformseq, 16)) 587 goto error; 588 return pxformseq; 589 error: 590 if (pxformseq) 591 jas_cmpxformseq_destroy(pxformseq); 592 return 0; 593 } 594 595 static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq) 596 { 597 jas_cmpxformseq_t *newpxformseq; 598 599 if (!(newpxformseq = jas_cmpxformseq_create())) 600 goto error; 601 if (jas_cmpxformseq_append(newpxformseq, pxformseq)) 602 goto error; 603 return newpxformseq; 604 error: 605 return 0; 606 } 607 608 static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq) 609 { 610 while (pxformseq->numpxforms > 0) 611 jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1); 612 if (pxformseq->pxforms) 613 jas_free(pxformseq->pxforms); 614 jas_free(pxformseq); 615 } 616 617 static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i) 618 { 619 assert(i >= 0 && i < pxformseq->numpxforms); 620 if (i != pxformseq->numpxforms - 1) 621 abort(); 622 jas_cmpxform_destroy(pxformseq->pxforms[i]); 623 pxformseq->pxforms[i] = 0; 624 --pxformseq->numpxforms; 625 return 0; 626 } 627 628 static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, 629 int dstclrspc, int srcclrspc) 630 { 631 if (dstclrspc == srcclrspc) 632 return 0; 633 abort(); 634 /* Avoid compiler warnings about unused parameters. */ 635 pxformseq = 0; 636 return -1; 637 } 638 639 static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, 640 int i, jas_cmpxform_t *pxform) 641 { 642 jas_cmpxform_t *tmppxform; 643 int n; 644 if (i < 0) 645 i = pxformseq->numpxforms; 646 assert(i >= 0 && i <= pxformseq->numpxforms); 647 if (pxformseq->numpxforms >= pxformseq->maxpxforms) { 648 if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + 649 16)) 650 goto error; 651 } 652 assert(pxformseq->numpxforms < pxformseq->maxpxforms); 653 if (!(tmppxform = jas_cmpxform_copy(pxform))) 654 goto error; 655 n = pxformseq->numpxforms - i; 656 if (n > 0) { 657 memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i], 658 n * sizeof(jas_cmpxform_t *)); 659 } 660 pxformseq->pxforms[i] = tmppxform; 661 ++pxformseq->numpxforms; 662 return 0; 663 error: 664 return -1; 665 } 666 667 static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, 668 jas_cmpxformseq_t *othpxformseq) 669 { 670 int n; 671 int i; 672 jas_cmpxform_t *pxform; 673 jas_cmpxform_t *othpxform; 674 n = pxformseq->numpxforms + othpxformseq->numpxforms; 675 if (n > pxformseq->maxpxforms) { 676 if (jas_cmpxformseq_resize(pxformseq, n)) 677 goto error; 678 } 679 for (i = 0; i < othpxformseq->numpxforms; ++i) { 680 othpxform = othpxformseq->pxforms[i]; 681 if (!(pxform = jas_cmpxform_copy(othpxform))) 682 goto error; 683 pxformseq->pxforms[pxformseq->numpxforms] = pxform; 684 ++pxformseq->numpxforms; 685 } 686 return 0; 687 error: 688 return -1; 689 } 690 691 static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n) 692 { 693 jas_cmpxform_t **p; 694 assert(n >= pxformseq->numpxforms); 695 p = (!pxformseq->pxforms) ? jas_malloc(n * sizeof(jas_cmpxform_t *)) : 696 jas_realloc(pxformseq->pxforms, n * sizeof(jas_cmpxform_t *)); 697 if (!p) { 698 return -1; 699 } 700 pxformseq->pxforms = p; 701 pxformseq->maxpxforms = n; 702 return 0; 703 } 704 705 /******************************************************************************\ 706 * Primitive transform class. 707 \******************************************************************************/ 708 709 static jas_cmpxform_t *jas_cmpxform_create0() 710 { 711 jas_cmpxform_t *pxform; 712 if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) 713 return 0; 714 memset(pxform, 0, sizeof(jas_cmpxform_t)); 715 pxform->refcnt = 0; 716 pxform->ops = 0; 717 return pxform; 718 } 719 720 static void jas_cmpxform_destroy(jas_cmpxform_t *pxform) 721 { 722 if (--pxform->refcnt <= 0) { 723 (*pxform->ops->destroy)(pxform); 724 jas_free(pxform); 725 } 726 } 727 728 static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform) 729 { 730 ++pxform->refcnt; 731 return pxform; 732 } 733 734 /******************************************************************************\ 735 * Shaper matrix class. 736 \******************************************************************************/ 737 738 static jas_cmpxform_t *jas_cmpxform_createshapmat() 739 { 740 int i; 741 int j; 742 jas_cmpxform_t *pxform; 743 jas_cmshapmat_t *shapmat; 744 if (!(pxform = jas_cmpxform_create0())) 745 return 0; 746 pxform->ops = &shapmat_ops; 747 shapmat = &pxform->data.shapmat; 748 shapmat->mono = 0; 749 shapmat->order = 0; 750 shapmat->useluts = 0; 751 shapmat->usemat = 0; 752 for (i = 0; i < 3; ++i) 753 jas_cmshapmatlut_init(&shapmat->luts[i]); 754 for (i = 0; i < 3; ++i) { 755 for (j = 0; j < 4; ++j) 756 shapmat->mat[i][j] = 0.0; 757 } 758 ++pxform->refcnt; 759 return pxform; 760 } 761 762 static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform) 763 { 764 jas_cmshapmat_t *shapmat = &pxform->data.shapmat; 765 int i; 766 for (i = 0; i < 3; ++i) 767 jas_cmshapmatlut_cleanup(&shapmat->luts[i]); 768 } 769 770 static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in, 771 jas_cmreal_t *out, int cnt) 772 { 773 jas_cmshapmat_t *shapmat = &pxform->data.shapmat; 774 jas_cmreal_t *src; 775 jas_cmreal_t *dst; 776 jas_cmreal_t a0; 777 jas_cmreal_t a1; 778 jas_cmreal_t a2; 779 jas_cmreal_t b0; 780 jas_cmreal_t b1; 781 jas_cmreal_t b2; 782 src = in; 783 dst = out; 784 if (!shapmat->mono) { 785 while (--cnt >= 0) { 786 a0 = *src++; 787 a1 = *src++; 788 a2 = *src++; 789 if (!shapmat->order && shapmat->useluts) { 790 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 791 a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1); 792 a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2); 793 } 794 if (shapmat->usemat) { 795 b0 = shapmat->mat[0][0] * a0 796 + shapmat->mat[0][1] * a1 797 + shapmat->mat[0][2] * a2 798 + shapmat->mat[0][3]; 799 b1 = shapmat->mat[1][0] * a0 800 + shapmat->mat[1][1] * a1 801 + shapmat->mat[1][2] * a2 802 + shapmat->mat[1][3]; 803 b2 = shapmat->mat[2][0] * a0 804 + shapmat->mat[2][1] * a1 805 + shapmat->mat[2][2] * a2 806 + shapmat->mat[2][3]; 807 a0 = b0; 808 a1 = b1; 809 a2 = b2; 810 } 811 if (shapmat->order && shapmat->useluts) { 812 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 813 a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1); 814 a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2); 815 } 816 *dst++ = a0; 817 *dst++ = a1; 818 *dst++ = a2; 819 } 820 } else { 821 if (!shapmat->order) { 822 while (--cnt >= 0) { 823 a0 = *src++; 824 if (shapmat->useluts) 825 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 826 a2 = a0 * shapmat->mat[2][0]; 827 a1 = a0 * shapmat->mat[1][0]; 828 a0 = a0 * shapmat->mat[0][0]; 829 *dst++ = a0; 830 *dst++ = a1; 831 *dst++ = a2; 832 } 833 } else { 834 assert(0); 835 while (--cnt >= 0) { 836 a0 = *src++; 837 src++; 838 src++; 839 a0 = a0 * shapmat->mat[0][0]; 840 if (shapmat->useluts) 841 a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); 842 *dst++ = a0; 843 } 844 } 845 } 846 847 return 0; 848 } 849 850 static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut) 851 { 852 lut->data = 0; 853 lut->size = 0; 854 } 855 856 static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut) 857 { 858 if (lut->data) { 859 jas_free(lut->data); 860 lut->data = 0; 861 } 862 lut->size = 0; 863 } 864 865 static double gammafn(double x, double gamma) 866 { 867 if (x == 0.0) 868 return 0.0; 869 return pow(x, gamma); 870 } 871 872 static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv) 873 { 874 jas_cmreal_t gamma; 875 int i; 876 gamma = 0; 877 jas_cmshapmatlut_cleanup(lut); 878 if (curv->numents == 0) { 879 lut->size = 2; 880 if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t)))) 881 goto error; 882 lut->data[0] = 0.0; 883 lut->data[1] = 1.0; 884 } else if (curv->numents == 1) { 885 lut->size = 256; 886 if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t)))) 887 goto error; 888 gamma = curv->ents[0] / 256.0; 889 for (i = 0; i < lut->size; ++i) { 890 lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma); 891 } 892 } else { 893 lut->size = curv->numents; 894 if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t)))) 895 goto error; 896 for (i = 0; i < lut->size; ++i) { 897 lut->data[i] = curv->ents[i] / 65535.0; 898 } 899 } 900 return 0; 901 error: 902 return -1; 903 } 904 905 static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x) 906 { 907 jas_cmreal_t t; 908 int lo; 909 int hi; 910 t = x * (lut->size - 1); 911 lo = floor(t); 912 if (lo < 0) 913 return lut->data[0]; 914 hi = ceil(t); 915 if (hi >= lut->size) 916 return lut->data[lut->size - 1]; 917 return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]); 918 } 919 920 static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, 921 jas_cmshapmatlut_t *lut, int n) 922 { 923 int i; 924 int j; 925 int k; 926 jas_cmreal_t ax; 927 jas_cmreal_t ay; 928 jas_cmreal_t bx; 929 jas_cmreal_t by; 930 jas_cmreal_t sx; 931 jas_cmreal_t sy; 932 assert(n >= 2); 933 if (invlut->data) { 934 jas_free(invlut->data); 935 invlut->data = 0; 936 } 937 /* The sample values should be nondecreasing. */ 938 for (i = 1; i < lut->size; ++i) { 939 if (lut->data[i - 1] > lut->data[i]) { 940 assert(0); 941 return -1; 942 } 943 } 944 if (!(invlut->data = jas_malloc(n * sizeof(jas_cmreal_t)))) 945 return -1; 946 invlut->size = n; 947 for (i = 0; i < invlut->size; ++i) { 948 sy = ((double) i) / (invlut->size - 1); 949 sx = 1.0; 950 for (j = 0; j < lut->size; ++j) { 951 ay = lut->data[j]; 952 if (sy == ay) { 953 for (k = j + 1; k < lut->size; ++k) { 954 by = lut->data[k]; 955 if (by != sy) 956 break; 957 #if 0 958 assert(0); 959 #endif 960 } 961 if (k < lut->size) { 962 --k; 963 ax = ((double) j) / (lut->size - 1); 964 bx = ((double) k) / (lut->size - 1); 965 sx = (ax + bx) / 2.0; 966 } 967 break; 968 } 969 if (j < lut->size - 1) { 970 by = lut->data[j + 1]; 971 if (sy > ay && sy < by) { 972 ax = ((double) j) / (lut->size - 1); 973 bx = ((double) j + 1) / (lut->size - 1); 974 sx = ax + 975 (sy - ay) / (by - ay) * (bx - ax); 976 break; 977 } 978 } 979 } 980 invlut->data[i] = sx; 981 } 982 #if 0 983 for (i=0;i<lut->size;++i) 984 fprintf(stderr, "lut[%d]=%f ", i, lut->data[i]); 985 for (i=0;i<invlut->size;++i) 986 fprintf(stderr, "invlut[%d]=%f ", i, invlut->data[i]); 987 #endif 988 return 0; 989 } 990 991 static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]) 992 { 993 jas_cmreal_t d; 994 d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1]) 995 - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0]) 996 + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]); 997 #if 0 998 fprintf(stderr, "delta=%f\n", d); 999 #endif 1000 if (JAS_ABS(d) < 1e-6) 1001 return -1; 1002 out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d; 1003 out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d; 1004 out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d; 1005 out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d; 1006 out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d; 1007 out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d; 1008 out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d; 1009 out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d; 1010 out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d; 1011 out[0][3] = -in[0][3]; 1012 out[1][3] = -in[1][3]; 1013 out[2][3] = -in[2][3]; 1014 #if 0 1015 fprintf(stderr, "[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", 1016 in[0][0], in[0][1], in[0][2], in[0][3], 1017 in[1][0], in[1][1], in[1][2], in[1][3], 1018 in[2][0], in[2][1], in[2][2], in[2][3]); 1019 fprintf(stderr, "[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", 1020 out[0][0], out[0][1], out[0][2], out[0][3], 1021 out[1][0], out[1][1], out[1][2], out[1][3], 1022 out[2][0], out[2][1], out[2][2], out[2][3]); 1023 #endif 1024 return 0; 1025 } 1026 1027 /******************************************************************************\ 1028 * 1029 \******************************************************************************/ 1030 1031 static int icctoclrspc(int iccclrspc, int refflag) 1032 { 1033 if (refflag) { 1034 switch (iccclrspc) { 1035 case JAS_ICC_COLORSPC_XYZ: 1036 return JAS_CLRSPC_CIEXYZ; 1037 case JAS_ICC_COLORSPC_LAB: 1038 return JAS_CLRSPC_CIELAB; 1039 default: 1040 abort(); 1041 break; 1042 } 1043 } else { 1044 switch (iccclrspc) { 1045 case JAS_ICC_COLORSPC_YCBCR: 1046 return JAS_CLRSPC_GENYCBCR; 1047 case JAS_ICC_COLORSPC_RGB: 1048 return JAS_CLRSPC_GENRGB; 1049 case JAS_ICC_COLORSPC_GRAY: 1050 return JAS_CLRSPC_GENGRAY; 1051 default: 1052 abort(); 1053 break; 1054 } 1055 } 1056 } 1057 1058 static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) 1059 { 1060 jas_iccattrval_t *graytrc; 1061 jas_cmshapmat_t *shapmat; 1062 jas_cmpxform_t *pxform; 1063 jas_cmpxformseq_t *pxformseq; 1064 jas_cmshapmatlut_t lut; 1065 1066 jas_cmshapmatlut_init(&lut); 1067 if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) || 1068 graytrc->type != JAS_ICC_TYPE_CURV) 1069 goto error; 1070 if (!(pxform = jas_cmpxform_createshapmat())) 1071 goto error; 1072 shapmat = &pxform->data.shapmat; 1073 if (!(pxformseq = jas_cmpxformseq_create())) 1074 goto error; 1075 if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) 1076 goto error; 1077 1078 pxform->numinchans = 1; 1079 pxform->numoutchans = 3; 1080 1081 shapmat->mono = 1; 1082 shapmat->useluts = 1; 1083 shapmat->usemat = 1; 1084 if (!op) { 1085 shapmat->order = 0; 1086 shapmat->mat[0][0] = 0.9642; 1087 shapmat->mat[1][0] = 1.0; 1088 shapmat->mat[2][0] = 0.8249; 1089 if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv)) 1090 goto error; 1091 } else { 1092 shapmat->order = 1; 1093 shapmat->mat[0][0] = 1.0 / 0.9642; 1094 shapmat->mat[1][0] = 1.0; 1095 shapmat->mat[2][0] = 1.0 / 0.8249; 1096 jas_cmshapmatlut_init(&lut); 1097 if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) 1098 goto error; 1099 if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size)) 1100 goto error; 1101 jas_cmshapmatlut_cleanup(&lut); 1102 } 1103 jas_iccattrval_destroy(graytrc); 1104 jas_cmpxform_destroy(pxform); 1105 *retpxformseq = pxformseq; 1106 return 0; 1107 error: 1108 return -1; 1109 } 1110 1111 static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) 1112 { 1113 int i; 1114 jas_iccattrval_t *trcs[3]; 1115 jas_iccattrval_t *cols[3]; 1116 jas_cmshapmat_t *shapmat; 1117 jas_cmpxform_t *pxform; 1118 jas_cmpxformseq_t *pxformseq; 1119 jas_cmreal_t mat[3][4]; 1120 jas_cmshapmatlut_t lut; 1121 jas_cmshapmatlut_init(&lut); 1122 for (i = 0; i < 3; ++i) { 1123 trcs[i] = 0; 1124 cols[i] = 0; 1125 } 1126 if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) || 1127 !(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) || 1128 !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) || 1129 !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) || 1130 !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) || 1131 !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL))) 1132 goto error; 1133 for (i = 0; i < 3; ++i) { 1134 if (trcs[i]->type != JAS_ICC_TYPE_CURV || 1135 cols[i]->type != JAS_ICC_TYPE_XYZ) 1136 goto error; 1137 } 1138 if (!(pxform = jas_cmpxform_createshapmat())) 1139 goto error; 1140 pxform->numinchans = 3; 1141 pxform->numoutchans = 3; 1142 shapmat = &pxform->data.shapmat; 1143 if (!(pxformseq = jas_cmpxformseq_create())) 1144 goto error; 1145 if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) 1146 goto error; 1147 shapmat->mono = 0; 1148 shapmat->useluts = 1; 1149 shapmat->usemat = 1; 1150 if (!op) { 1151 shapmat->order = 0; 1152 for (i = 0; i < 3; ++i) { 1153 shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0; 1154 shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0; 1155 shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0; 1156 } 1157 for (i = 0; i < 3; ++i) 1158 shapmat->mat[i][3] = 0.0; 1159 for (i = 0; i < 3; ++i) { 1160 if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv)) 1161 goto error; 1162 } 1163 } else { 1164 shapmat->order = 1; 1165 for (i = 0; i < 3; ++i) { 1166 mat[0][i] = cols[i]->data.xyz.x / 65536.0; 1167 mat[1][i] = cols[i]->data.xyz.y / 65536.0; 1168 mat[2][i] = cols[i]->data.xyz.z / 65536.0; 1169 } 1170 for (i = 0; i < 3; ++i) 1171 mat[i][3] = 0.0; 1172 if (jas_cmshapmat_invmat(shapmat->mat, mat)) 1173 goto error; 1174 for (i = 0; i < 3; ++i) { 1175 jas_cmshapmatlut_init(&lut); 1176 if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv)) 1177 goto error; 1178 if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size)) 1179 goto error; 1180 jas_cmshapmatlut_cleanup(&lut); 1181 } 1182 } 1183 for (i = 0; i < 3; ++i) { 1184 jas_iccattrval_destroy(trcs[i]); 1185 jas_iccattrval_destroy(cols[i]); 1186 } 1187 jas_cmpxform_destroy(pxform); 1188 *retpxformseq = pxformseq; 1189 return 0; 1190 error: 1191 return -1; 1192 } 1193 1194 static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val) 1195 { 1196 long v; 1197 int m; 1198 v = **bufptr; 1199 if (sgnd) { 1200 m = (1 << (prec - 1)); 1201 if (v < -m || v >= m) 1202 return -1; 1203 } else { 1204 if (v < 0 || v >= (1 << prec)) 1205 return -1; 1206 } 1207 ++(*bufptr); 1208 *val = v; 1209 return 0; 1210 } 1211 1212 static int jas_cmputint(long **bufptr, int sgnd, int prec, long val) 1213 { 1214 int m; 1215 if (sgnd) { 1216 m = (1 << (prec - 1)); 1217 if (val < -m || val >= m) 1218 return -1; 1219 } else { 1220 if (val < 0 || val >= (1 << prec)) 1221 return -1; 1222 } 1223 **bufptr = val; 1224 ++(*bufptr); 1225 return 0; 1226 } 1227 1228 int jas_clrspc_numchans(int clrspc) 1229 { 1230 switch (jas_clrspc_fam(clrspc)) { 1231 case JAS_CLRSPC_FAM_XYZ: 1232 case JAS_CLRSPC_FAM_LAB: 1233 case JAS_CLRSPC_FAM_RGB: 1234 case JAS_CLRSPC_FAM_YCBCR: 1235 return 3; 1236 break; 1237 case JAS_CLRSPC_FAM_GRAY: 1238 return 1; 1239 break; 1240 default: 1241 abort(); 1242 break; 1243 } 1244 } 1245 1246 jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof) 1247 { 1248 return jas_iccprof_copy(prof->iccprof); 1249 }