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