jas_cm.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       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 }