test: fragment.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# fragment.c

Go to the documentation of this file.

    00001 /*
    00002         File:           LHFragment.c
    00003
    00004         Contains:       Test fragment for Color Sync
    00005
    00006         Written by:     H.Siegeritz
    00007
    00008         Copyright:      © 1993-1997 by Heidelberger Druckmaschinen AG, all rights reserved.
    00009
    00010 */
    00011
    00012 #ifndef LHGeneralIncs_h
    00013 #include "General.h"
    00014 #endif
    00015
    00016 #if GENERATING68K
    00017 /*      #include <ConditionalMacros.h> */
    00018
    00019         #define CM_Doub extended
    00020         extern CM_Doub pow(CM_Doub _x,CM_Doub _y);
    00021 #else
    00022         #define CM_Doub double
    00023         #include <math.h>
    00024 #endif
    00025
    00026 #ifndef LHFragment_h
    00027 #include "Fragment.h"
    00028 #endif
    00029
    00030 #ifndef LHStdConversionLuts_h
    00031 #include "StdConv.h"
    00032 #endif
    00033
    00034 #if ! realThing
    00035 #ifdef DEBUG_OUTPUT
    00036 #define kThisFile kLHFragmentID
    00037 #endif
    00038 #endif
    00039
    00040
    00041 /*-----prototypes for local functions-----*/
    00042
    00043 void    InvLut1dExceptions(unsigned short *inCurve, unsigned long inCount,
    00044                                 unsigned short *outCurve, UINT8 AdressBits);
    00045 CMError Fill_ushort_ELUT_Gamma(unsigned short *usELUT, char addrBits, char usedBits,
    00046                                                                                         long gridPoints, unsigned short gamma_u8_8);
    00047 void    Fill_inverseGamma_byte_ALUT(unsigned char *ucALUT, char addrBits,
    00048                                                                                                         unsigned short gamma_u8_8);
    00049
    00050 /* ______________________________________________________________________
    00051
    00052         icCurveType     *
    00053                 InvertLut1d(icCurveType *LookUpTable,
    00054                     UINT8               AdressBits);
    00055         Abstract:
    00056                 allocates memory and inverts Lut
    00057                 NOTE: not-monotone LookUpTables are manipulated
    00058                 areas without values in LookUpTable are set 0 resp. 0xFFFF
    00059
    00060         Params:
    00061                 LookUpTable     (in)    LUT to be inverted
    00062                 AdressBits      (in)    curve with 2 ^ AdressBits values
    00063
    00064         Return:
    00065                 Ptr to icCurveType              successful
    00066                 nil                                             Error
    00067
    00068    _____________________________________________________________________ */
    00069 icCurveType     *
    00070 InvertLut1d ( icCurveType *LookUpTable,
    00071                           UINT8 AdressBits)
    00072 {
    00073         unsigned long   i, inCount, outCount;
    00074         unsigned long   intpFirst, intpLast, halfStep, ulAux, target;
    00075         short                   monot;
    00076         unsigned short  *inCurve, *outCurve, *usPtr, *stopPtr;
    00077         icCurveType             *outCMcurve = nil;
    00078         double                  flFactor;
    00079         OSErr                   err = noErr;
    00080
    00081         LH_START_PROC("InvertLut1d")
    00082
    00083         if( LookUpTable->base.sig != icSigCurveType     /* 'curv' */ || AdressBits > 15 )
    00084                 goto CleanupAndExit;
    00085
    00086         inCount  = LookUpTable->curve.count;
    00087         inCurve  = LookUpTable->curve.data;
    00088         outCount = 0x1 << AdressBits;
    00089
    00090         outCMcurve = (icCurveType *)SmartNewPtr( sizeof(OSType)
    00091                                                                           + 2 * sizeof(unsigned long)
    00092                                                                           + outCount * sizeof(unsigned short), &err );
    00093         if(err)
    00094                 goto CleanupAndExit;
    00095
    00096         outCurve = (unsigned short *)outCMcurve->curve.data;
    00097
    00098         outCMcurve->base.sig    = icSigCurveType;       /* 'curv' */
    00099         outCMcurve->base.reserved[0] = 0x00;
    00100         outCMcurve->base.reserved[1] = 0x00;
    00101         outCMcurve->base.reserved[2] = 0x00;
    00102         outCMcurve->base.reserved[3] = 0x00;
    00103         outCMcurve->curve.count = outCount;
    00104
    00105         if(inCount < 2)         /* 0 or 1 point in LUT */
    00106         {
    00107                 InvLut1dExceptions(inCurve, inCount, outCurve, AdressBits);
    00108                 goto CleanupAndExit;
    00109         }
    00110
    00111                  /* exact matching factor for special values: */
    00112         flFactor = (double)(outCount - 1) / 65535.;
    00113         halfStep = outCount >> 1;               /* lessen computation incorrectness */
    00114
    00115                                 /* ascending or descending ? */
    00116         for(monot=0, i=1; i<inCount; i++)
    00117         {
    00118                 if(inCurve[i-1] < inCurve[i])
    00119                         monot++;
    00120                 else if(inCurve[i-1] > inCurve[i])
    00121                         monot--;
    00122         }
    00123
    00124         if(monot >= 0)  /* curve seems to be ascending */
    00125         {
    00126                 for(i=1; i<inCount; i++)
    00127                         if(inCurve[i-1] > inCurve[i])
    00128                                 inCurve[i] = inCurve[i-1];
    00129
    00130                 intpFirst = (unsigned long)(inCurve[0] * flFactor + 0.9999);
    00131                 intpLast  = (unsigned long)(inCurve[inCount-1] * flFactor);
    00132
    00133                 for(i=0; i<intpFirst; i++)                      /* fill lacking area low */
    00134                         outCurve[i] = 0;
    00135                 for(i=intpLast+1; i<outCount; i++)      /* fill lacking area high */
    00136                         outCurve[i] = 0xFFFF;
    00137
    00138                         /* interpolate remaining values: */
    00139                 usPtr   = inCurve;
    00140                 stopPtr = inCurve + inCount - 2; /* stops incrementation */
    00141
    00142                 for(i=intpFirst; i<=intpLast; i++)
    00143                 {
    00144                         target = (0x0FFFF * i + halfStep)  / (outCount - 1);
    00145                         while(*(usPtr+1) < target && usPtr < stopPtr)
    00146                                 usPtr++;                                        /* find interval */
    00147
    00148                         ulAux = ((unsigned long)(usPtr - inCurve) << 16) / (inCount - 1);
    00149                         if(*(usPtr+1) != *usPtr)
    00150                         {
    00151                                 ulAux += ((target - (unsigned long)*usPtr) << 16)
    00152                                           / ( (*(usPtr+1) - *usPtr) * (inCount - 1) );
    00153
    00154                                 if(ulAux & 0x10000)   /* *(usPtr+1) was required */
    00155                                         ulAux = 0xFFFF;
    00156                         }
    00157
    00158                         outCurve[i] = (unsigned short)ulAux;
    00159                 }
    00160         }
    00161         else                    /* curve seems to be descending */
    00162         {
    00163                 for(i=1; i<inCount; i++)
    00164                         if(inCurve[i-1] < inCurve[i])
    00165                                 inCurve[i] = inCurve[i-1];
    00166
    00167                 intpFirst = (unsigned long)(inCurve[inCount-1] * flFactor + 0.9999);
    00168                 intpLast  = (unsigned long)(inCurve[0] * flFactor);
    00169
    00170                 for(i=0; i<intpFirst; i++)                      /* fill lacking area low */
    00171                         outCurve[i] = 0xFFFF;
    00172                 for(i=intpLast+1; i<outCount; i++)      /* fill lacking area high */
    00173                         outCurve[i] = 0;
    00174
    00175                         /* interpolate remaining values: */
    00176                 usPtr   = inCurve + inCount - 1;
    00177                 stopPtr = inCurve + 1;          /* stops decrementation */
    00178
    00179                 for(i=intpFirst; i<=intpLast; i++)
    00180                 {
    00181                         target = (0x0FFFF * i + halfStep)  / (outCount - 1);
    00182                         while(*(usPtr-1) < target && usPtr > stopPtr)
    00183                                 usPtr--;                                        /* find interval */
    00184
    00185                         ulAux = ((unsigned long)(usPtr-1 - inCurve) << 16) / (inCount - 1);
    00186                         if(*(usPtr-1) != *usPtr)
    00187                         {
    00188                                 ulAux += (((unsigned long)*(usPtr-1) - target) << 16)
    00189                                           / ( (*(usPtr-1) - *usPtr) * (inCount - 1) );
    00190
    00191                                 if(ulAux & 0x10000)
    00192                                         ulAux = 0x0FFFF;
    00193                         }
    00194
    00195                         outCurve[i] = (unsigned short)ulAux;
    00196                 }
    00197         }
    00198 CleanupAndExit:
    00199         LH_END_PROC("InvertLut1d")
    00200         return(outCMcurve);
    00201 }
    00202
    00203 /* ______________________________________________________________________
    00204
    00205         void
    00206                 InvLut1dExceptions(     unsigned short  *inCurve,
    00207                                                         unsigned long   inCount,
    00208                                                         unsigned short  *outCurve,
    00209                             UINT8                       AdressBits )
    00210         Abstract:
    00211                 handles identity and gamma case for LUT inversion
    00212
    00213         Params:
    00214                 inCurve         (in)    pseudo LUT to be inverted
    00215                 inCount         (in)    count of values, 0 (identity) or 1 (gamma)
    00216                 outCurve        (out)   inverted LUT
    00217                 AdressBits      (in)    2^n values are requested
    00218
    00219         Return:
    00220                 void
    00221
    00222    _____________________________________________________________________ */
    00223 void
    00224 InvLut1dExceptions      ( unsigned short *      inCurve,
    00225                                           unsigned long         inCount,
    00226                                           unsigned short *      outCurve,
    00227                                           UINT8                         AdressBits)
    00228 {
    00229         unsigned long   i, outCount, step, oldstep, stopit;
    00230         UINT8                   shiftBits;
    00231         CM_Doub                 invGamma, x, xFactor;
    00232 #ifdef DEBUG_OUTPUT
    00233         CMError                 err = noErr;
    00234 #endif
    00235
    00236         LH_START_PROC("InvLut1dExceptions")
    00237         outCount = 0x1 << AdressBits;
    00238
    00239         if(inCount == 0)        /* identity */
    00240         {
    00241                 shiftBits = 16 - AdressBits;
    00242
    00243                 for(i=0; i<outCount; i++)
    00244                         outCurve[i] = (unsigned short)( (i << shiftBits)
    00245                                                                                   + (i >> AdressBits) );
    00246         }
    00247         else            /* inCount == 1 , gamma */
    00248         {
    00249                 invGamma = 256. / (CM_Doub)inCurve[0];
    00250                 xFactor  = 1. / (CM_Doub)(outCount - 1);
    00251
    00252                 if(AdressBits <= 6)             /* up to 64 - 2 float.computations */
    00253                         step = 1;
    00254                 else
    00255                         step = 0x1 << (AdressBits - 6);         /* would take too long */
    00256
    00257                 outCurve[0]          = 0;
    00258                 outCurve[outCount-1] = 0xFFFF;
    00259
    00260                 for(i=step; i<outCount-1; i+=step)
    00261                 {
    00262                         x = (CM_Doub)i * xFactor;
    00263                         outCurve[i] = (unsigned short)( pow(x,invGamma) * 65535.0);
    00264                 }
    00265
    00266                 while(step > 1)         /* fill remaining values successively */
    00267                 {
    00268                         oldstep = step;
    00269                         step  >>= 1;
    00270
    00271                         stopit = outCount - step;       /* last value afterwards */
    00272
    00273                         for(i=step; i<stopit; i+=oldstep)
    00274                                 outCurve[i] = (unsigned short)( ((long)outCurve[i - step]
    00275                                                                                 + (long)outCurve[i + step]) >> 1 );
    00276
    00277                         if(step != 1)
    00278                                 outCurve[stopit] = (unsigned short)
    00279                                                         ( ((long)outCurve[stopit - step] + 0x0FFFF) >> 1 );
    00280                 }
    00281
    00282                         /* overwrite sensitive values depending on Gamma */
    00283                 if(AdressBits > 6 && invGamma < 1.0)    /* lower part is difficult */
    00284                 {
    00285                         stopit = 0x1 << (AdressBits - 6);
    00286
    00287                         for(i=1; i<stopit; i++)
    00288                         {
    00289                                 x = (CM_Doub)i * xFactor;
    00290                                 outCurve[i] = (unsigned short)( pow(x,invGamma) * 65535.0);
    00291                         }
    00292                 }
    00293         }
    00294         LH_END_PROC("InvLut1dExceptions")
    00295 }
    00296
    00297 /* ______________________________________________________________________
    00298
    00299         CMError
    00300                 CombiMatrix(icXYZType   *srcColorantData[3],
    00301                                         icXYZType       *destColorantData[3],
    00302                                         double          resMatrix[3][3])
    00303         Abstract:
    00304                 inverts the 2nd matrix, multiplies it with the 1rst and
    00305                 puts the result in resMatrix
    00306
    00307         Params:
    00308                 srcColorantData         (in)            RGB colorants
    00309                 destColorantData        (in)            RGB colorants
    00310                 resMatrix                       (in/out)
    00311
    00312         Return:
    00313                 noErr           successful
    00314
    00315    _____________________________________________________________________ */
    00316 CMError
    00317 CombiMatrix     ( icXYZType srcColorantData[3],
    00318                           icXYZType destColorantData[3],
    00319                           double resMatrix[3][3] )
    00320 {
    00321         short           i, j;
    00322         double          straightMat[3][3], invMat[3][3];
    00323         CMError         err = noErr;
    00324
    00325         LH_START_PROC("CombiMatrix")
    00326                 /* RGB -> XYZ for first profile: */
    00327         straightMat[0][0] = (double)srcColorantData[0].data.data[0].X;
    00328         straightMat[1][0] = (double)srcColorantData[0].data.data[0].Y;
    00329         straightMat[2][0] = (double)srcColorantData[0].data.data[0].Z;
    00330
    00331         straightMat[0][1] = (double)srcColorantData[1].data.data[0].X;
    00332         straightMat[1][1] = (double)srcColorantData[1].data.data[0].Y;
    00333         straightMat[2][1] = (double)srcColorantData[1].data.data[0].Z;
    00334
    00335         straightMat[0][2] = (double)srcColorantData[2].data.data[0].X;
    00336         straightMat[1][2] = (double)srcColorantData[2].data.data[0].Y;
    00337         straightMat[2][2] = (double)srcColorantData[2].data.data[0].Z;
    00338
    00339                 /* RGB -> XYZ for 2nd profile, store in resMatrix prelim.: */
    00340         resMatrix[0][0] = (double)destColorantData[0].data.data[0].X;
    00341         resMatrix[1][0] = (double)destColorantData[0].data.data[0].Y;
    00342         resMatrix[2][0] = (double)destColorantData[0].data.data[0].Z;
    00343
    00344         resMatrix[0][1] = (double)destColorantData[1].data.data[0].X;
    00345         resMatrix[1][1] = (double)destColorantData[1].data.data[0].Y;
    00346         resMatrix[2][1] = (double)destColorantData[1].data.data[0].Z;
    00347
    00348         resMatrix[0][2] = (double)destColorantData[2].data.data[0].X;
    00349         resMatrix[1][2] = (double)destColorantData[2].data.data[0].Y;
    00350         resMatrix[2][2] = (double)destColorantData[2].data.data[0].Z;
    00351
    00352         if( !doubMatrixInvert(resMatrix, invMat) )
    00353         {
    00354 #ifdef DEBUG_OUTPUT
    00355         if ( DebugCheck(kThisFile, kDebugErrorInfo) )
    00356             DebugPrint("¥ CombiMatrix-Error: doubMatrixInvert failed \n");
    00357 #endif
    00358                 err = cmparamErr;
    00359                 goto CleanupAndExit;
    00360         }
    00361
    00362         for(i=0; i<3; i++)
    00363                 for(j=0; j<3; j++)
    00364                         resMatrix[i][j] = straightMat[i][0] * invMat[0][j]
    00365                                                         + straightMat[i][1] * invMat[1][j]
    00366                                                         + straightMat[i][2] * invMat[2][j];
    00367 CleanupAndExit:
    00368         LH_END_PROC("CombiMatrix")
    00369         return err;
    00370 }
    00371
    00372 /* ______________________________________________________________________
    00373
    00374         Boolean
    00375                 doubMatrixInvert(double MatHin[3][3],
    00376                                                  double MatRueck[3][3])
    00377         Abstract:
    00378                 inverts MatHin matrix and puts the result in MatRueck
    00379
    00380         Params:
    00381                 MatHin                  (in)                    3 * 3 double matrix
    00382                 MatRueck                (in/out)                3 * 3 double matrix
    00383
    00384         Return:
    00385         TRUE            successful
    00386
    00387    _____________________________________________________________________ */
    00388 Boolean
    00389 doubMatrixInvert(double MatHin[3][3], double MatRueck[3][3])
    00390 {
    00391         double  detm, hilf1, hilf2, hilf3, hilf4, hilf5, hilf6;
    00392         double  *a;
    00393         Boolean success = TRUE;
    00394 #ifdef DEBUG_OUTPUT
    00395         CMError err=noErr;
    00396 #endif
    00397         LH_START_PROC("doubMatrixInvert")
    00398         a = (double *)MatHin;
    00399
    00400         hilf1 = a[0] * a[4];
    00401         hilf2 = a[1] * a[5];
    00402         hilf3 = a[2] * a[3];
    00403         hilf4 = a[2] * a[4];
    00404         hilf5 = a[1] * a[3];
    00405         hilf6 = a[0] * a[5];
    00406
    00407         detm = hilf1 * a[8] + hilf2 * a[6]
    00408                  + hilf3 * a[7] - hilf4 * a[6]
    00409                  - hilf5 * a[8] - hilf6 * a[7];
    00410
    00411         /*      if(fabs(detm) < 1.E-9) */
    00412         if ( (detm < 1.E-9) && (detm > -1.E-9) )
    00413         success = FALSE;
    00414         else
    00415         {
    00416                 detm = 1. / detm;
    00417
    00418                 MatRueck[0][0] = (a[4] * a[8] - a[5] * a[7]) * detm;
    00419                 MatRueck[0][1] = (a[7] * a[2] - a[8] * a[1]) * detm;
    00420                 MatRueck[0][2] = (hilf2       - hilf4      ) * detm;
    00421
    00422                 MatRueck[1][0] = (a[5] * a[6] - a[3] * a[8]) * detm;
    00423                 MatRueck[1][1] = (a[8] * a[0] - a[6] * a[2]) * detm;
    00424                 MatRueck[1][2] = (hilf3       - hilf6      ) * detm;
    00425
    00426                 MatRueck[2][0] = (a[3] * a[7] - a[4] * a[6]) * detm;
    00427                 MatRueck[2][1] = (a[6] * a[1] - a[7] * a[0]) * detm;
    00428                 MatRueck[2][2] = (hilf1       - hilf5      ) * detm;
    00429         }
    00430
    00431         LH_END_PROC("doubMatrixInvert")
    00432     return(success);
    00433 }
    00434
    00435 /* ______________________________________________________________________
    00436         CMError
    00437                 Fill_ushort_ELUT_from_CurveTag( icCurveType             *pCurveTag,
    00438                                                                                 unsigned short  *usELUT,
    00439                                                                                 char                    addrBits,
    00440                                                                                 char                    usedBits,
    00441                                                                                 long                    gridPoints )
    00442         Abstract:
    00443                 extracts input luts out of cmSigCurveType tag and converts it
    00444                 to desired format: (2 ^ addrBits) values in a range from
    00445                 0 to (2 ^ usedBits) - (gridPoints ^ 2)
    00446                 NOTE: Memory for the LUTs has to be allocated before !
    00447
    00448         Params:
    00449                 pCurveTag               (in)            extract input LUT from this
    00450                 usELUT                  (in/out)        result LUT
    00451                 addrBits                (in)            2 ^ addrBits values are requested
    00452                 usedBits                (in)            used bits in u.short
    00453                 gridPoints              (in)            used for interpolation
    00454
    00455         Return:
    00456                 noErr           successful
    00457
    00458    _____________________________________________________________________ */
    00459 CMError
    00460 Fill_ushort_ELUT_from_CurveTag ( icCurveType    *pCurveTag,
    00461                                                                  unsigned short *usELUT,
    00462                                                                  char                   addrBits,
    00463                                                                  char                   usedBits,
    00464                                                                  long                   gridPoints)
    00465 {
    00466         long                    i, count, indFactor, outFactor, baseInd, maxOut;
    00467         long                    fract, lAux, diff, outRound, outShift, interpRound, interpShift;
    00468         unsigned short  *usCurv;
    00469         double                  dFactor;
    00470         CMError                 err = noErr;
    00471
    00472         LH_START_PROC("Fill_ushort_ELUT_from_CurveTag")
    00473                 /*---special cases:---*/
    00474
    00475         if(pCurveTag->curve.count == 0)         /* identity curve */
    00476         {
    00477                 err = Fill_ushort_ELUT_identical(usELUT, addrBits, usedBits, gridPoints);
    00478                 goto CleanupAndExit;
    00479         }
    00480
    00481         if(pCurveTag->curve.count == 1)         /* Gamma  curve */
    00482         {
    00483                 err = Fill_ushort_ELUT_Gamma(usELUT, addrBits, usedBits, gridPoints, pCurveTag->curve.data[0]);
    00484                 goto CleanupAndExit;
    00485         }
    00486                 /*---ordinary case:---*/
    00487
    00488         if(addrBits > 15)
    00489         {
    00490                 err = cmparamErr;       /* would lead to overflow */
    00491                 goto CleanupAndExit;
    00492         }
    00493
    00494         count     = 1 << addrBits;
    00495         indFactor = ((pCurveTag->curve.count - 1) << 18) / (count - 1); /* for adjusting indices */
    00496
    00497         if(usedBits < 8)
    00498         {
    00499                 err = cmparamErr;
    00500                 goto CleanupAndExit;
    00501         }
    00502
    00503         if(gridPoints == 0)
    00504                 maxOut = 65535;
    00505         else
    00506                 maxOut = ((1L << (usedBits - 8) ) * 256 * (gridPoints - 1)) / gridPoints;
    00507
    00508                 /*-----find factor for the values that fits in 15 bits------*/
    00509                 /* (product with 16 bit number must fit in 31 bit uns.long)     */
    00510                 /* n.b: 512 <= maxOut <= 65535  in all possible cases           */
    00511
    00512         dFactor  = (double)maxOut / 65535.;             /* 65535 is max. curve value */
    00513         dFactor *= 4194304.;                                    /* same as << 22, certainly too much */
    00514
    00515         outFactor = (long)dFactor;
    00516         outRound  = (1L << 21) - 1;
    00517         outShift  = 22;
    00518         while(outFactor & 0xFFF8000)    /* stay within 15 bits to prevent product overflow */
    00519         {
    00520                 outFactor >>= 1;
    00521                 outRound  >>= 1;
    00522                 outShift   -= 1;
    00523         }
    00524
    00525         interpRound = outRound >> 1;    /* with interpolation we have an additional...  */
    00526         interpShift = outShift  - 1;    /* ... >> 1 because we must add two nunmbers    */
    00527
    00528         usCurv = pCurveTag->curve.data;
    00529
    00530         for(i=0; i<count; i++)
    00531         {
    00532                 lAux    = (i * indFactor+4) >> 3;
    00533                 baseInd = (unsigned long)lAux >> 15;
    00534                 fract   = lAux & 0x7FFF;                /* 15 bits for interpolation */
    00535
    00536                 if(fract)               /* interpolation necessary ? */
    00537                 {
    00538                         lAux = (long)usCurv[baseInd] * outFactor >> 1;
    00539
    00540                         diff = (long)usCurv[baseInd+1] - (long)usCurv[baseInd];
    00541                         diff = (diff * outFactor >> 15) * fract >> 1;
    00542
    00543                         usELUT[i] = (unsigned short)( (lAux + diff + interpRound) >> interpShift );
    00544                 }
    00545                 else
    00546                         usELUT[i] = (unsigned short)( ((long)usCurv[baseInd]
    00547                                                                                                 * outFactor + outRound) >> outShift );
    00548         }
    00549
    00550 CleanupAndExit:
    00551         LH_END_PROC("Fill_ushort_ELUT_from_CurveTag")
    00552         return(noErr);
    00553 }
    00554
    00555 /* ______________________________________________________________________
    00556    _____________________________________________________________________ */
    00557 CMError
    00558 Fill_ushort_ELUT_identical      ( UINT16 *usELUT,
    00559                                                           char addrBits,
    00560                                                           char usedBits,
    00561                                                           long gridPoints )
    00562 {
    00563         long            i, count, factor, maxOut;
    00564         UINT16          *myWPtr;
    00565 #ifdef DEBUG_OUTPUT
    00566         CMError err = noErr;
    00567 #endif
    00568         LH_START_PROC("Fill_ushort_ELUT_identical")
    00569
    00570         count  = 1 << addrBits;
    00571
    00572         if(gridPoints == 0)
    00573                 maxOut = 65535;
    00574         else
    00575                 maxOut = ((1L << (usedBits - 8) ) * 256 * (gridPoints - 1)) / gridPoints;
    00576
    00577         factor = (maxOut << 14) / (count - 1);
    00578
    00579         myWPtr = usELUT;
    00580         for(i=0; i<count; i++)
    00581                 *myWPtr++ = (UINT16)((i * factor + 0x2000) >> 14);
    00582
    00583         LH_END_PROC("Fill_ushort_ELUT_identical")
    00584         return(noErr);
    00585 }
    00586
    00587 /* ______________________________________________________________________
    00588    _____________________________________________________________________ */
    00589 CMError
    00590 Fill_ushort_ELUT_Gamma  ( unsigned short*       usELUT,
    00591                                                   char                          addrBits,
    00592                                                   char                          usedBits,
    00593                                                   long                          gridPoints,
    00594                                                   unsigned short        gamma_u8_8 )
    00595 {
    00596         unsigned long   i, j, outCount, step, stopit;
    00597         CM_Doub                 gamma, x, xFactor;
    00598         long                    leftVal, Diff, lAux, maxOut;
    00599 #ifdef DEBUG_OUTPUT
    00600         CMError                 err=noErr;
    00601 #endif
    00602
    00603         LH_START_PROC("Fill_ushort_ELUT_Gamma")
    00604         outCount = 0x1 << addrBits;
    00605         if(gridPoints == 0)
    00606                 maxOut = 65535;
    00607         else
    00608                 maxOut = ((1L << (usedBits - 8) ) * 256 * (gridPoints - 1)) / gridPoints;
    00609
    00610         gamma   = ((CM_Doub)gamma_u8_8 * 3.90625E-3);   /* / 256.0 */
    00611         xFactor = 1. / (CM_Doub)(outCount - 1);
    00612
    00613         if(addrBits <= 6)               /* up to 64 - 2 float.computations */
    00614                 step = 1;
    00615         else
    00616                 step = 0x1 << (addrBits - 6);           /* would take too long */
    00617
    00618         usELUT[0]          = 0;
    00619     usELUT[outCount-1] = (UINT16)maxOut;
    00620
    00621         for(i=step; i<outCount-1; i+=step)
    00622         {
    00623                 x         = (CM_Doub)i * xFactor;
    00624                 usELUT[i] = (unsigned short)( pow(x,gamma) * maxOut);
    00625         }
    00626
    00627                 /*---fill intervals - except for last, which is odd:---*/
    00628         for(i=0; i<outCount-step; i+=step)
    00629         {
    00630                 leftVal = (long)usELUT[i];
    00631                 Diff    = (long)usELUT[i + step] - leftVal;
    00632
    00633                 for(j=1; j<step; j++)
    00634                 {
    00635                         lAux = ( (Diff * j << 8) / step + 128 ) >> 8;
    00636
    00637                         usELUT[i + j] = (unsigned short)(leftVal + lAux);
    00638                 }
    00639         }
    00640
    00641                 /*---fill last interval:---*/
    00642         i       = outCount - step;
    00643         leftVal = (long)usELUT[i];
    00644         Diff    = maxOut - leftVal;             /* maxOut for 1.0 */
    00645
    00646         for(j=1; j<step-1; j++)         /* stops here if step <= 2 */
    00647         {
    00648                 lAux = ( (Diff * j << 8) / (step - 1) + 128 ) >> 8;
    00649
    00650                 usELUT[i + j] = (unsigned short)(leftVal + lAux);
    00651         }
    00652
    00653                 /* overwrite sensitive values depending on Gamma */
    00654         if(addrBits > 6 && gamma < 1.0) /* lower part is difficult */
    00655         {
    00656                 stopit = 0x1 << (addrBits - 6);
    00657
    00658                 for(i=1; i<stopit; i++)
    00659                 {
    00660                         x = (CM_Doub)i * xFactor;
    00661                         usELUT[i] = (unsigned short)( pow(x,gamma) * maxOut);
    00662                 }
    00663         }
    00664
    00665         LH_END_PROC("Fill_ushort_ELUT_Gamma")
    00666         return(noErr);
    00667 }
    00668
    00669
    00670 /* ______________________________________________________________________
    00671
    00672         CMError
    00673                 Fill_inverse_byte_ALUT_from_CurveTag(   icCurveType             *pCurveTag,
    00674                                                                                                 unsigned char   *ucALUT,
    00675                                                                                                 char                    addrBits )
    00676         Abstract:
    00677                 extracts output luts out of cmSigCurveType tag and converts them
    00678                 to desired format: (2 ^ addrBits) values in a range from 0 to 255
    00679                 NOTE: not-monotone CurveTags are manipulated
    00680                 NOTE: Memory for the LUT has to be allocated before !
    00681
    00682         Params:
    00683                 pCurveTag               (in)            extract input LUT from this
    00684                 ucALUT                  (in/out)        result LUT
    00685                 addrBits                (in)            2 ^ addrBits values are requested
    00686
    00687         Return:
    00688                 noErr           successful
    00689
    00690    _____________________________________________________________________ */
    00691 CMError
    00692 Fill_inverse_byte_ALUT_from_CurveTag    ( icCurveType   *pCurveTag,
    00693                                                                                   unsigned char *ucALUT,
    00694                                                                                   char                  addrBits )
    00695 {
    00696         unsigned long   i, inCount, outCount;
    00697         unsigned long   intpFirst, intpLast, halfStep, ulAux, target;
    00698         short                   monot;
    00699         unsigned short  *inCurve, *usPtr, *stopPtr;
    00700         double                  flFactor;
    00701         char                    baseShift;
    00702         unsigned long   clipIndex;
    00703         CMError                 err = noErr;
    00704
    00705         LH_START_PROC("Fill_inverse_byte_ALUT_from_CurveTag")
    00706
    00707     if( pCurveTag->base.sig != icSigCurveType   /* 'curv' */
    00708      || addrBits > 15 )
    00709     {
    00710 #ifdef DEBUG_OUTPUT
    00711         if ( DebugCheck(kThisFile, kDebugErrorInfo) )
    00712             DebugPrint("¥ Fill_inverse_byte_ALUT_from_CurveTag ERROR:  addrBits = %d\n",addrBits);
    00713 #endif
    00714                 err = cmparamErr;
    00715                 goto CleanupAndExit;
    00716         }
    00717
    00718         outCount = 0x1 << addrBits;
    00719
    00720                 /*---special cases:---*/
    00721
    00722         if(pCurveTag->curve.count == 0)         /*---identity---*/
    00723         {
    00724                 baseShift = addrBits - 8;               /* >= 0, we need at least 256 values */
    00725
    00726                 for(i=0; i<outCount; i++)
    00727                         ucALUT[i] = (unsigned char)(i >> baseShift);
    00728
    00729                 goto CleanupAndExit;
    00730         }
    00731         else if(pCurveTag->curve.count == 1)    /*---gamma curve---*/
    00732         {
    00733                 Fill_inverseGamma_byte_ALUT(ucALUT, addrBits, pCurveTag->curve.data[0]);
    00734                 goto CleanupAndExit;
    00735         }
    00736
    00737                 /*---ordinary case:---*/
    00738
    00739         inCount = pCurveTag->curve.count;
    00740         inCurve = pCurveTag->curve.data;
    00741
    00742                  /* exact matching factor needed for special values: */
    00743         clipIndex = (1 << addrBits) - (1 << (addrBits - 8)); /* max XLUT output with 10 bit is at 1020, not at1023 */
    00744         flFactor  = (double)clipIndex / 65535.;
    00745
    00746         halfStep = outCount >> 1;               /* lessen computation incorrectness */
    00747
    00748                                 /* ascending or descending ? */
    00749         for(monot=0, i=1; i<inCount; i++)
    00750         {
    00751                 if(inCurve[i-1] < inCurve[i])
    00752                         monot++;
    00753                 else if(inCurve[i-1] > inCurve[i])
    00754                         monot--;
    00755         }
    00756
    00757         if(monot >= 0)  /* curve seems to be ascending */
    00758         {
    00759                 for(i=1; i<inCount; i++)
    00760                         if(inCurve[i-1] > inCurve[i])
    00761                                 inCurve[i] = inCurve[i-1];
    00762
    00763                 intpFirst = (unsigned long)(inCurve[0] * flFactor + 0.9999);
    00764                 intpLast  = (unsigned long)(inCurve[inCount-1] * flFactor);
    00765
    00766                 for(i=0; i<intpFirst; i++)                      /* fill lacking area low */
    00767                         ucALUT[i] = 0;
    00768                 for(i=intpLast+1; i<outCount; i++)      /* fill lacking area high */
    00769                         ucALUT[i] = 0xFF;
    00770
    00771                         /* interpolate remaining values: */
    00772                 usPtr   = inCurve;
    00773                 stopPtr = inCurve + inCount - 2; /* stops incrementation */
    00774
    00775                 for(i=intpFirst; i<=intpLast; i++)
    00776                 {
    00777                         target = (0x0FFFF * i + halfStep)  / (outCount - 1);
    00778                         while(*(usPtr+1) < target && usPtr < stopPtr)
    00779                                 usPtr++;                                        /* find interval */
    00780
    00781                         ulAux = ((unsigned long)(usPtr - inCurve) << 16) / (inCount - 1);
    00782                         if(*(usPtr+1) != *usPtr)
    00783                         {
    00784                                 ulAux += ((target - (unsigned long)*usPtr) << 16)
    00785                                           / ( (*(usPtr+1) - *usPtr) * (inCount - 1) );
    00786
    00787                                 if(ulAux & 0x10000)   /* *(usPtr+1) was required */
    00788                                         ulAux = 0x0FFFF;
    00789                         }
    00790
    00791                         ucALUT[i] = (unsigned char)(ulAux >> 8);
    00792                 }
    00793         }
    00794         else                    /* curve seems to be descending */
    00795         {
    00796                 for(i=1; i<inCount; i++)
    00797                         if(inCurve[i-1] < inCurve[i])
    00798                                 inCurve[i] = inCurve[i-1];
    00799
    00800                 intpFirst = (unsigned long)(inCurve[inCount-1] * flFactor + 0.9999);
    00801                 intpLast  = (unsigned long)(inCurve[0] * flFactor);
    00802
    00803                 for(i=0; i<intpFirst; i++)                      /* fill lacking area low */
    00804                         ucALUT[i] = 0xFF;
    00805                 for(i=intpLast+1; i<outCount; i++)      /* fill lacking area high */
    00806                         ucALUT[i] = 0;
    00807
    00808                         /* interpolate remaining values: */
    00809                 usPtr   = inCurve + inCount - 1;
    00810                 stopPtr = inCurve + 1;          /* stops decrementation */
    00811
    00812                 for(i=intpFirst; i<=intpLast; i++)
    00813                 {
    00814                         target = (0x0FFFF * i + halfStep)  / (outCount - 1);
    00815                         while(*(usPtr-1) < target && usPtr > stopPtr)
    00816                                 usPtr--;                                        /* find interval */
    00817
    00818                         ulAux = ((unsigned long)(usPtr-1 - inCurve) << 16) / (inCount - 1);
    00819                         if(*(usPtr-1) != *usPtr)
    00820                         {
    00821                                 ulAux += (((unsigned long)*(usPtr-1) - target) << 16)
    00822                                           / ( (*(usPtr-1) - *usPtr) * (inCount - 1) );
    00823
    00824                                 if(ulAux & 0x10000)
    00825                                         ulAux = 0x0FFFF;
    00826                         }
    00827
    00828             ucALUT[i] = (unsigned char)(ulAux >> 8);
    00829                 }
    00830         }
    00831
    00832 CleanupAndExit:
    00833         LH_END_PROC("Fill_inverse_byte_ALUT_from_CurveTag")
    00834         return(noErr);
    00835 }
    00836
    00837 /*   _____________________________________________________________________ */
    00838 void
    00839 Fill_inverseGamma_byte_ALUT ( unsigned char     *       ucALUT,
    00840                                                           char                          addrBits,
    00841                                                           unsigned short        gamma_u8_8 )
    00842 {
    00843         unsigned long   i, j, outCount, step, stopit;
    00844         long                    leftVal, Diff, lAux;
    00845         CM_Doub                 invGamma, x, xFactor;
    00846     unsigned long       clipIndex;
    00847 #ifdef DEBUG_OUTPUT
    00848         CMError                 err=noErr;
    00849 #endif
    00850
    00851         LH_START_PROC("Fill_inverseGamma_byte_ALUT")
    00852
    00853         outCount = 0x1 << addrBits;
    00854
    00855         invGamma  = 256. / (CM_Doub)gamma_u8_8;
    00856         clipIndex = (1 << addrBits) - (1 << (addrBits - 8)); /* max XLUT output with 10 bit is at 1020, not at1023 */
    00857         xFactor   = 1. / (CM_Doub)clipIndex;
    00858
    00859         if(addrBits <= 6)               /* up to 64 - 2 float.computations */
    00860                 step = 1;
    00861         else
    00862                 step = 0x1 << (addrBits - 6);           /* more would take too long */
    00863
    00864         ucALUT[0]          = 0;                 /* these two... */
    00865         ucALUT[outCount-1] = 0xFF;              /* ...are fixed */
    00866
    00867         for(i=step; i<outCount-1; i+=step)
    00868         {
    00869                 x = (CM_Doub)i * xFactor;
    00870                 if(x > 1.)
    00871                         x = 1.;         /* clipping in the end of ALUT */
    00872
    00873                 ucALUT[i] = (unsigned char)( pow(x,invGamma) * 255.0 + 0.5);
    00874         }
    00875
    00876                 /*---fill intervals - except for last, which is odd:---*/
    00877         for(i=0; i<outCount-step; i+=step)
    00878         {
    00879                 leftVal = (long)ucALUT[i];
    00880                 Diff    = (long)ucALUT[i + step] - leftVal;
    00881
    00882                 for(j=1; j<step; j++)
    00883                 {
    00884                         lAux = ( (Diff * j << 8) / step + 128 ) >> 8;
    00885
    00886                         ucALUT[i + j] = (unsigned char)(leftVal + lAux);
    00887                 }
    00888         }
    00889
    00890                 /*---fill last interval:---*/
    00891         i       = outCount - step;
    00892         leftVal = (long)ucALUT[i];
    00893         Diff    = 0x0FF - leftVal;      /* 0xFF for 1.0 */
    00894
    00895         for(j=1; j<step-1; j++)         /* stops here if step <= 2 */
    00896         {
    00897                 lAux = ( (Diff * j << 8) / (step - 1) + 128 ) >> 8;
    00898
    00899                 ucALUT[i + j] = (unsigned char)(leftVal + lAux);
    00900         }
    00901
    00902                 /*--overwrite sensitive values depending on Gamma:--*/
    00903         if(addrBits > 6 && invGamma < 1.0)              /* ...if lower part is difficult */
    00904         {
    00905                 stopit = 0x1 << (addrBits - 6);
    00906
    00907                 for(i=1; i<stopit; i++)
    00908                 {
    00909                         x         = (CM_Doub)i * xFactor;
    00910                         ucALUT[i] = (unsigned char)( pow(x,invGamma) * 255.0);
    00911                 }
    00912         }
    00913         LH_END_PROC("Fill_inverseGamma_byte_ALUT")
    00914 }
    00915
    00916 /* ______________________________________________________________________
    00917
    00918         CMError
    00919         Fill_ushort_ELUTs_from_lut8Tag ( CMLutParamPtr  theLutData,
    00920                                                                          Ptr                    profileELuts,
    00921                                                                          char                   addrBits,
    00922                                                                          char                   usedBits,
    00923                                                                          long                   gridPoints )
    00924         Abstract:
    00925                 extracts input luts out of CMlut8Type tag and converts them
    00926                 to desired format: (2 ^ addrBits) values in a range from
    00927                 0 to (2 ^ usedBits) - (gridPoints ^ 2)
    00928
    00929         Params:
    00930                 theLutData                      (in/out)        Ptr to structure that holds all the luts...
    00931                 profileELuts            (in)            Ptr to the profile's input luts
    00932                 addrBits                        (in)            2 ^ addrBits values are requested
    00933                 usedBits                        (in)            used bits in u.short
    00934                 gridPoints                      (in)            used for interpolation
    00935
    00936         Return:
    00937                 noErr           successful
    00938
    00939    _____________________________________________________________________ */
    00940 CMError
    00941 Fill_ushort_ELUTs_from_lut8Tag ( CMLutParamPtr  theLutData,
    00942                                                                  Ptr                    profileELuts,
    00943                                                                  char                   addrBits,
    00944                                                                  char                   usedBits,
    00945                                                                  long                   gridPoints )
    00946 {
    00947         long                    i, j, maxOut;
    00948         UINT8                   *curInLut;
    00949         UINT16                  *curELUT;
    00950         long                    count, indFactor, outFactor, baseInd, fract, lAux, diff;
    00951         LUT_DATA_TYPE   localElut = nil;
    00952         UINT16                  *localElutPtr;
    00953         OSErr                   err = noErr;
    00954         long                    theElutSize;
    00955
    00956         LH_START_PROC("Fill_ushort_ELUTs_from_lut8Tag")
    00957
    00958         count       = 1 << addrBits;
    00959         theElutSize = theLutData->colorLutInDim * count * sizeof (UINT16);
    00960         localElut   = ALLOC_DATA(theElutSize + 2, &err);
    00961         if (err)
    00962                 goto CleanupAndExit;
    00963
    00964         indFactor = (255 << 12) / (count - 1);  /* for adjusting indices */
    00965
    00966         if(gridPoints == 0)
    00967                 maxOut = 65535;
    00968         else
    00969                 maxOut = ((1L << (usedBits - 8) ) * 256 * (gridPoints - 1)) / gridPoints;
    00970         outFactor = (maxOut << 12) / 255;                       /* 255 is max. value from mft1 output lut */
    00971
    00972         LOCK_DATA(localElut);
    00973         localElutPtr = (UINT16*)DATA_2_PTR(localElut);
    00974         for(i=0; i<theLutData->colorLutInDim; i++)
    00975         {
    00976                 curInLut = (UINT8*)profileELuts + (i << 8);
    00977                 curELUT  = localElutPtr + i * count;
    00978
    00979                 for(j=0; j<count; j++)
    00980                 {
    00981                         lAux    = j * indFactor;
    00982                         baseInd = lAux >> 12;
    00983                         fract   = (lAux & 0x0FFF) >> 4; /* leaves 8 bits for interpolation as with distortion */
    00984
    00985                         if(fract && baseInd != 255)             /* interpolation necessary ? */
    00986                         {
    00987                                 lAux = (long)curInLut[baseInd] * outFactor >> 6;
    00988
    00989                                 diff = (long)curInLut[baseInd+1] - (long)curInLut[baseInd];
    00990                                 diff = (diff * outFactor >> 6) * fract >> 8;
    00991
    00992                                 curELUT[j] = (UINT16)( (lAux + diff + 32) >> 6 );
    00993                         }
    00994                         else
    00995                                 curELUT[j] = (UINT16)( ((long)curInLut[baseInd]
    00996                                                                                                         * outFactor + 0x0800) >> 12 );
    00997                 }
    00998         }
    00999         UNLOCK_DATA(localElut);
    01000         theLutData->inputLut = localElut;
    01001         localElut = nil;
    01002 CleanupAndExit:
    01003         localElut = DISPOSE_IF_DATA(localElut);
    01004         LH_END_PROC("Fill_ushort_ELUTs_from_lut8Tag")
    01005         return err;
    01006 }
    01007
    01008 /* ______________________________________________________________________
    01009
    01010         CMError
    01011         Fill_byte_ALUTs_from_lut8Tag( CMLutParamPtr     theLutData,
    01012                                                                   Ptr                   profileALuts,
    01013                                                                   char                  addrBits )
    01014         Abstract:
    01015                 extracts output luts out of CMLut8Type tag and converts them
    01016                 to desired format: (2 ^ addrBits) values in a range from 0 to 255
    01017
    01018         Params:
    01019                 theLutData                      (in/out)        Ptr to structure that holds all the luts...
    01020                 profileALuts            (in)            Ptr to the profile's output luts
    01021                 addrBits                        (in)            2 ^ addrBits values are requested
    01022
    01023         Return:
    01024                 noErr           successful
    01025
    01026    _____________________________________________________________________ */
    01027 CMError
    01028 Fill_byte_ALUTs_from_lut8Tag( CMLutParamPtr     theLutData,
    01029                                                           Ptr                   profileALuts,
    01030                                                           char                  addrBits )
    01031 {
    01032         long                    i, j;
    01033         UINT8                   *curOutLut;
    01034         UINT8                   *profAluts = (UINT8*)profileALuts;
    01035         UINT8                   *curALUT;
    01036         long                    count, clipIndex;
    01037         long                    factor, fract, baseInd, lAux;
    01038         OSErr                   err = noErr;
    01039         LUT_DATA_TYPE   localAlut = nil;
    01040         UINT8                   *localAlutPtr;
    01041         long                    theAlutSize;
    01042
    01043         LH_START_PROC("Fill_byte_ALUTs_from_lut8Tag")
    01044
    01045         count     = 1 << addrBits;                                                              /* addrBits is always >= 8 */
    01046         clipIndex = (1 << addrBits) - (1 << (addrBits - 8));    /* max XLUT output with 10 bit is at 1020, not at1023 */
    01047
    01048         theAlutSize = theLutData->colorLutOutDim * count;
    01049         localAlut   = ALLOC_DATA(theAlutSize + 1, &err);
    01050         if (err)
    01051                 goto CleanupAndExit;
    01052
    01053         LOCK_DATA(localAlut);
    01054         localAlutPtr = (UINT8*)DATA_2_PTR(localAlut);
    01055
    01056         factor = (255 << 12) / clipIndex;               /* for adjusting the indices */
    01057
    01058         for(i=0; i<theLutData->colorLutOutDim; i++)
    01059         {
    01060                 curOutLut = profAluts + (i << 8);
    01061                 curALUT   = localAlutPtr + i * count;
    01062
    01063                 for(j=0; j<=clipIndex; j++)
    01064                 {
    01065                         lAux    = j * factor;
    01066                         baseInd = lAux >> 12;
    01067                         fract   = lAux & 0x0FFF;
    01068
    01069                         if(fract)
    01070                         {
    01071                                 lAux = (long)curOutLut[baseInd + 1] - (long)curOutLut[baseInd];
    01072                                 lAux = (lAux * fract + 0x0800) >> 12;
    01073
    01074                                 curALUT[j] = (UINT8)((long)curOutLut[baseInd] + lAux);
    01075                         }
    01076                         else
    01077                                 curALUT[j] = curOutLut[baseInd];
    01078                 }
    01079
    01080                 for(j=clipIndex+1; j<count; j++)                /* unused indices, clip these */
    01081                         curALUT[j] = curALUT[clipIndex];
    01082         }
    01083
    01084         UNLOCK_DATA(localAlut);
    01085         theLutData->outputLut = localAlut;
    01086         localAlut = nil;
    01087 CleanupAndExit:
    01088         localAlut = DISPOSE_IF_DATA(localAlut);
    01089         LH_END_PROC("Fill_byte_ALUTs_from_lut8Tag")
    01090         return err;
    01091 }
    01092
    01093 /* ______________________________________________________________________
    01094
    01095         CMError
    01096         Fill_ushort_ELUTs_from_lut16Tag( CMLutParamPtr  theLutData,
    01097                                                                          Ptr                    profileELuts,
    01098                                                                          char                   addrBits,
    01099                                                                          char                   usedBits,
    01100                                                                          long                   gridPoints,
    01101                                                                          long                   inputTableEntries )
    01102
    01103         Abstract:
    01104                 extracts input luts out of CMLut16Type tag and converts them
    01105                 to desired format: (2 ^ addrBits) values in a range from
    01106                 0 to (2 ^ usedBits) - (gridPoints ^ 2)
    01107
    01108         Params:
    01109                 theLutData                      (in/out)        Ptr to structure that holds all the luts...
    01110                 profileELuts            (in)            Ptr to the profile's input luts
    01111                 addrBits                        (in)            2 ^ addrBits values are requested
    01112                 usedBits                        (in)            used bits in u.short
    01113                 gridPoints                      (in)            used for interpolation
    01114                 inputTableEntries       (in)            number of entries in the input lut (up to 4096)
    01115
    01116         Return:
    01117                 noErr           successful
    01118
    01119    _____________________________________________________________________ */
    01120 CMError
    01121 Fill_ushort_ELUTs_from_lut16Tag( CMLutParamPtr  theLutData,
    01122                                                                  Ptr                    profileELuts,
    01123                                                                  char                   addrBits,
    01124                                                                  char                   usedBits,
    01125                                                                  long                   gridPoints,
    01126                                                                  long                   inputTableEntries )
    01127 {
    01128         long                    i, j, inTabLen, maxOut;
    01129         UINT16                  *curInLut;
    01130         UINT16                  *curELUT;
    01131         UINT16                  *profELUT = (UINT16*)profileELuts;
    01132         long                    count, outFactor, fract, lAux, diff;
    01133         long                    baseInd, indFactor;
    01134         long                    outRound, outShift, interpRound, interpShift;
    01135         double                  dFactor;
    01136         long                    theElutSize;
    01137         LUT_DATA_TYPE   localElut = nil;
    01138         UINT16                  *localElutPtr;
    01139         OSErr                   err = noErr;
    01140
    01141         LH_START_PROC("Fill_ushort_ELUTs_from_lut16Tag")
    01142
    01143         count     = 1 << addrBits;
    01144         inTabLen  = inputTableEntries;
    01145
    01146         theElutSize = theLutData->colorLutInDim * count * sizeof (UINT16);
    01147         localElut   = ALLOC_DATA(theElutSize + 2, &err);
    01148         if(err)
    01149                 goto CleanupAndExit;
    01150
    01151         indFactor = ((inTabLen - 1) << 18) / (count - 1);       /* for adjusting indices */
    01152
    01153         if(gridPoints == 0)
    01154                 maxOut = 65535;
    01155         else
    01156                 maxOut = ((1L << (usedBits - 8) ) * 256 * (gridPoints - 1)) / gridPoints;
    01157
    01158                 /*-----find factor for the values that fits in 15 bits------*/
    01159                 /* (product with 16 bit number must fit in 31 bit uns.long)     */
    01160                 /* n.b: 512 <= maxOut <= 65535  in all possible cases           */
    01161
    01162         dFactor  = (double)maxOut / 65535.;             /* 65535 is max. curve value */
    01163         dFactor *= 4194304.;                                    /* same as << 22, certainly too much */
    01164
    01165         outFactor = (long)dFactor;
    01166         outRound  = (1L << 21) - 1;
    01167         outShift  = 22;
    01168         while(outFactor & 0xFFF8000)    /* stay within 15 bits to prevent product overflow */
    01169         {
    01170                 outFactor >>= 1;
    01171                 outRound  >>= 1;
    01172                 outShift   -= 1;
    01173         }
    01174
    01175         interpRound = outRound >> 1;    /* with interpolation we have an additional...  */
    01176         interpShift = outShift  - 1;    /* ... >> 1 because we must add two nunmbers    */
    01177
    01178         LOCK_DATA(localElut);
    01179         localElutPtr = (UINT16*)DATA_2_PTR(localElut);
    01180
    01181         for(i=0; i<theLutData->colorLutInDim; i++)
    01182         {
    01183                 curInLut = profELUT + (i * inTabLen);
    01184                 curELUT  = localElutPtr + (i * count);
    01185
    01186                 for(j=0; j<count; j++)
    01187                 {
    01188                         lAux    = (j * indFactor+4) >> 3;
    01189                         baseInd = (unsigned long)lAux >> 15;
    01190                         fract   = lAux & 0x7FFF;        /* 15 bits for interpolation */
    01191
    01192                         if(fract)               /* interpolation necessary ? */
    01193                         {
    01194                                 lAux = (long)curInLut[baseInd] * outFactor >> 1;
    01195
    01196                                 diff = (long)curInLut[baseInd+1] - (long)curInLut[baseInd];
    01197                                 diff = ((diff * outFactor >> 15) * fract) >> 1;
    01198
    01199                                 curELUT[j] = (UINT16)( (lAux + diff + interpRound) >> interpShift );
    01200                         }
    01201                         else
    01202                                 curELUT[j] = (UINT16)( ((long)curInLut[baseInd] * outFactor
    01203                                                                                                         + outRound) >> outShift );
    01204                 }
    01205         }
    01206         UNLOCK_DATA(localElut);
    01207         theLutData->inputLut = localElut;
    01208         localElut = nil;
    01209 CleanupAndExit:
    01210         localElut = DISPOSE_IF_DATA(localElut);
    01211         LH_END_PROC("Fill_ushort_ELUTs_from_lut16Tag")
    01212         return err;
    01213 }
    01214
    01215 /* ______________________________________________________________________
    01216
    01217         CMError
    01218         Fill_byte_ALUTs_from_lut16Tag(  CMLutParamPtr   theLutData,
    01219                                                                         Ptr                             profileALuts,
    01220                                                                         char                    addrBits,
    01221                                                                     long                        outputTableEntries )
    01222         Abstract:
    01223                 extracts output luts out of CMLut16Type tag and converts them
    01224                 to desired format: (2 ^ addrBits) values in a range from 0 to 255
    01225
    01226         Params:
    01227                 theLutData                      (in/out)        Ptr to structure that holds all the luts...
    01228                 profileALuts            (in)            Ptr to the profile's output luts
    01229                 addrBits                        (in)            2 ^ addrBits values are requested
    01230                 outputTableEntries      (in)            number of entries in the output lut (up to 4096)
    01231
    01232         Return:
    01233                 noErr           successful
    01234
    01235    _____________________________________________________________________ */
    01236 CMError
    01237 Fill_byte_ALUTs_from_lut16Tag(  CMLutParamPtr   theLutData,
    01238                                                                 Ptr                             profileALuts,
    01239                                                                 char                    addrBits,
    01240                                                             long                        outputTableEntries )
    01241 {
    01242         long                    i, j;
    01243         UINT16                  *curOutLut;
    01244         UINT8                   *curALUT;
    01245         long                    count, clipIndex, outTabLen;
    01246         long                    indFactor, fract, baseInd, lAux;
    01247         UINT16                  *profALUTs = (UINT16*)profileALuts;
    01248         OSErr                   err = noErr;
    01249         LUT_DATA_TYPE   localAlut = nil;
    01250         UINT8                   *localAlutPtr;
    01251         long                    theAlutSize;
    01252
    01253         LH_START_PROC("Fill_byte_ALUTs_from_lut16Tag")
    01254
    01255         count     = 1 << addrBits;                                                              /* addrBits is always >= 8 */
    01256         clipIndex = (1 << addrBits) - (1 << (addrBits - 8));    /* max XLUT output with 10 bit is at 1020, not at1023 */
    01257
    01258         theAlutSize = theLutData->colorLutOutDim * count;
    01259         localAlut   = ALLOC_DATA(theAlutSize + 1, &err);
    01260         if (err)
    01261                 goto CleanupAndExit;
    01262
    01263         outTabLen = outputTableEntries;                                 /* <= 4096 */
    01264         indFactor = ((outTabLen - 1) << 18) / clipIndex;        /* for adjusting the indices */
    01265
    01266         LOCK_DATA(localAlut);
    01267         localAlutPtr = (UINT8*)DATA_2_PTR(localAlut);
    01268
    01269         for(i=0; i<theLutData->colorLutOutDim; i++)
    01270         {
    01271                 curOutLut = profALUTs + i * outTabLen;
    01272                 curALUT   = localAlutPtr + i * count;
    01273
    01274                 for(j=0; j<=clipIndex; j++)
    01275                 {
    01276                         lAux    = (j * indFactor+32) >> 6;
    01277                         baseInd = lAux >> 12;
    01278                         fract   = lAux & 0x0FFF;
    01279
    01280                         if(fract)
    01281                         {
    01282                                 lAux = (long)curOutLut[baseInd + 1] - (long)curOutLut[baseInd];
    01283                                 lAux = (lAux * fract + 0x0800) >> 12;
    01284
    01285                                 curALUT[j] = (UINT8)(((long)curOutLut[baseInd] + lAux) >> 8);
    01286                         }
    01287                         else
    01288                                 curALUT[j] = curOutLut[baseInd] >> 8;
    01289                 }
    01290
    01291                 for(j=clipIndex+1; j<count; j++)                /* unused indices, clip these */
    01292                         curALUT[j] = curALUT[clipIndex];
    01293         }
    01294
    01295         UNLOCK_DATA(localAlut);
    01296         theLutData->outputLut = localAlut;
    01297         localAlut = nil;
    01298 CleanupAndExit:
    01299         localAlut = DISPOSE_IF_DATA(localAlut);
    01300
    01301         LH_END_PROC("Fill_byte_ALUTs_from_lut16Tag")
    01302         return err;
    01303 }
    01304
    01305 /* ______________________________________________________________________
    01306
    01307         CMError
    01308                 MakeGamut16or32ForMonitor(      icXYZType               *pRedXYZ,
    01309                                                                         icXYZType               *pGreenXYZ,
    01310                                                                         icXYZType               *pBlueXYZ,
    01311                                                                         unsigned short  **ppELUTs,
    01312                                    UINT8                        **ppXLUT,
    01313                                    UINT8                        **ppALUT,
    01314                                                                         Boolean                 cube32Flag )
    01315         Abstract:
    01316                 Computes 3 ELUTs, XLUT and ALUT for gamut checking out of the
    01317                 3 monitor primaries. Color space is XYZ
    01318                 NOTE: Memory for the ELUTs, XLUt and ALUT is allocated here !
    01319
    01320         Params:
    01321                 pRedXYZ                 (in)            -> red primary of monitor
    01322                 pGreenXYZ               (in)            -> green primary of monitor
    01323                 pBlueXYZ                (in)            -> blue primary of monitor
    01324                 ppELUTs                 (out)           3 input LUTs
    01325                 ppXLUT                  (out)           3 dimensional byte Lut (32^3)
    01326                 ppALUT                  (out)           Boolean output LUT (1024 bytes)
    01327         cube32Flag              (in)            TRUE: 32*32*32 points, FALSE: 16*16*16 points
    01328
    01329         Return:
    01330                 noErr           successful
    01331
    01332    _____________________________________________________________________ */
    01333
    01334 CMError MakeGamut16or32ForMonitor       (       icXYZType               *pRedXYZ,
    01335                                                                                 icXYZType               *pGreenXYZ,
    01336                                                                                 icXYZType               *pBlueXYZ,
    01337                                                                                 CMLutParamPtr   theLutData,
    01338                                                                                 Boolean                 cube32Flag )
    01339
    01340 {
    01341         double                  XYZmatrix[3][3], RGBmatrix[3][3];
    01342         double                  sum, dFactor;
    01343         long                    i, j, k, gridPoints, planeCount, totalCount, longMat[9];
    01344         long                    longX, longY, longZ, longR, longG, longB;
    01345         long                    *lPtr, lFactor, maxOut;
    01346         unsigned short  *usPtr;
    01347         unsigned char   *XPtr;
    01348         LUT_DATA_TYPE   tempXLutHdl     = nil;
    01349         LUT_DATA_TYPE   tempELutHdl     = nil;
    01350         LUT_DATA_TYPE   tempALutHdl     = nil;
    01351         unsigned char   *tempXLut       = nil;
    01352         unsigned char   *tempALut       = nil;
    01353         unsigned short  *tempELut       = nil;
    01354         unsigned short  Levels[32];
    01355         OSErr                   err = noErr;
    01356
    01357         LH_START_PROC("MakeGamut16or32ForMonitor")
    01358
    01359         if(theLutData->inputLut != nil || theLutData->colorLut != nil || theLutData->outputLut != nil)
    01360         {
    01361                 err = cmparamErr;
    01362                 goto CleanupAndExit;
    01363         }
    01364
    01365         /*----------------------------------------------------------------------------------------- E */
    01366         tempELutHdl = ALLOC_DATA(256 * 3 * sizeof(unsigned short), &err);
    01367         if(err)
    01368                 goto CleanupAndExit;
    01369         LOCK_DATA(tempELutHdl);
    01370         tempELut = (unsigned short *)DATA_2_PTR(tempELutHdl);
    01371
    01372         /*----------------------------------------------------------------------------------------- X */
    01373         if(cube32Flag)
    01374                 gridPoints = 32;                        /* for cube grid */
    01375         else
    01376                 gridPoints = 16;
    01377         totalCount = gridPoints * gridPoints * gridPoints;
    01378
    01379         tempXLutHdl = ALLOC_DATA(totalCount, &err);
    01380         if(err)
    01381                 goto CleanupAndExit;
    01382         LOCK_DATA(tempXLutHdl);
    01383         tempXLut = (unsigned char *)DATA_2_PTR(tempXLutHdl);
    01384
    01385         /*----------------------------------------------------------------------------------------- A */
    01386         tempALutHdl = ALLOC_DATA(adr_bereich_alut, &err);
    01387         if(err)
    01388                 goto CleanupAndExit;
    01389         LOCK_DATA(tempALutHdl);
    01390         tempALut = (unsigned char *)DATA_2_PTR(tempALutHdl);
    01391
    01392                 /*---------fill 3 ELUTs for X, Y, Z (256 u.shorts each):--------------------*/
    01393                 /* linear curve with clipping, slope makes white value  become                          */
    01394                 /* max * 30.5/31 or max * 14.5/15, that is half of the last XLUT interval       */
    01395         if(cube32Flag)
    01396                 dFactor = 30.5 / 31.;
    01397         else
    01398                 dFactor = 14.5 / 15.;
    01399
    01400         maxOut = ((1L << (16 /*usedBits*/ - 8) ) * 256 * (gridPoints - 1)) / gridPoints;
    01401
    01402         for(i=0; i<3; i++)              /* X, Y, Z ELUTs */
    01403         {
    01404                 if(i == 0)
    01405                         lFactor = (long)( dFactor * 2. * maxOut * 256. / 255. / 0.9642 );/* X, adjust D50 */
    01406                 else if(i == 1)
    01407                         lFactor = (long)( dFactor * 2. * maxOut * 256. / 255.);                 /* Y */
    01408                 else
    01409                         lFactor = (long)( dFactor * 2. * maxOut * 256. / 255. / 0.8249);/* Z, adjust D50 */
    01410
    01411                 usPtr = tempELut + 256 * i;
    01412                 for(j=0; j<256; j++)
    01413                 {
    01414                         k = (j * lFactor + 127) >> 8;
    01415                         if(k > maxOut)
    01416                                 k = maxOut;             /* max. ELUT value */
    01417
    01418                         *usPtr++ = (unsigned short)k;
    01419                 }
    01420         }
    01421
    01422                 /*------ RGB to XYZ matrix in the range 0.0 to 1.0 -----*/
    01423                 /* floating point for accurate inversion                                */
    01424         XYZmatrix[0][0] = (double)pRedXYZ->data.data[0].X;
    01425         XYZmatrix[1][0] = (double)pRedXYZ->data.data[0].Y;
    01426         XYZmatrix[2][0] = (double)pRedXYZ->data.data[0].Z;
    01427
    01428         XYZmatrix[0][1] = (double)pGreenXYZ->data.data[0].X;
    01429         XYZmatrix[1][1] = (double)pGreenXYZ->data.data[0].Y;
    01430         XYZmatrix[2][1] = (double)pGreenXYZ->data.data[0].Z;
    01431
    01432         XYZmatrix[0][2] = (double)pBlueXYZ->data.data[0].X;
    01433         XYZmatrix[1][2] = (double)pBlueXYZ->data.data[0].Y;
    01434         XYZmatrix[2][2] = (double)pBlueXYZ->data.data[0].Z;
    01435
    01436                 /*--- grey with R = G = B (D50 adjustment is done by the ELUTs) ----*/
    01437         for(i=0; i<3; i++)
    01438         {
    01439                 sum = XYZmatrix[i][0] + XYZmatrix[i][1] + XYZmatrix[i][2];
    01440                 if(sum < 0.1)
    01441                         sum = 0.1;      /* prevent from div. by 0 (bad profiles) */
    01442
    01443                 for(j=0; j<3; j++)
    01444                         XYZmatrix[i][j] /= sum;
    01445         }
    01446
    01447                 /*---XYZ to RGB matrix:---*/
    01448         if(!doubMatrixInvert(XYZmatrix, RGBmatrix))
    01449         {
    01450                 err = cmparamErr;
    01451                 goto CleanupAndExit;
    01452         }
    01453
    01454         for(i=0; i<3; i++)                              /* create integer format for speed, */
    01455                 for(j=0; j<3; j++)                      /* 1.0 becomes 2^13, works for coeff. up to 8. */
    01456                         longMat[3*i + j] = (long)(RGBmatrix[i][j] * 8192.);
    01457
    01458                 /*-----grid levels for cube grid in XYZ (16 bit) so ----*/
    01459                 /* that white is at half of last interval, so the last  */
    01460                 /* value is white * 15/14.5 or white * 31/30.5                  */
    01461         if(cube32Flag)
    01462                 dFactor = 32768. / 30.5 * 31. / (gridPoints - 1);
    01463         else
    01464                 dFactor = 32768. / 14.5 * 15. / (gridPoints - 1);
    01465
    01466         for(i=0; i<gridPoints; i++)                     /* n.b: 32 is max. possible gridPoints */
    01467                 Levels[i] = (unsigned short)(i * dFactor + 0.5);
    01468
    01469                 /*----special treatment of first and last plane for speed:----*/
    01470         planeCount = gridPoints * gridPoints;
    01471         XPtr       = tempXLut;
    01472         for(i=0; i<planeCount; i++)
    01473                 *XPtr++ = 255;          /* out of gamut */
    01474
    01475         XPtr = tempXLut + (gridPoints - 1) * planeCount;
    01476         for(i=0; i<planeCount; i++)
    01477                 *XPtr++ = 255;          /* out of gamut */
    01478
    01479         *tempXLut = 0;  /* set black (white is between last 2 planes) */
    01480
    01481                 /*----second to second last plane must be computed:-----*/
    01482                 /*  transform points to RGB and judge in/out                    */
    01483         XPtr = tempXLut + planeCount;
    01484
    01485         for(i=1; i<gridPoints-1; i++)
    01486                 for(j=0; j<gridPoints; j++)
    01487                         for(k=0; k<gridPoints; k++)
    01488                         {
    01489                                 longX = (long)Levels[i];                /* X */
    01490                                 longY = (long)Levels[j];                /* Y */
    01491                                 longZ = (long)Levels[k];                /* Z */
    01492
    01493                                         /* matrix coeff: 2^13 is 1.0 , XYZ values: 1.0 or 100. is 2^15 ;        */
    01494                                         /* -> mask for products < 0 and >= 2^28 is used for in/out checking     */
    01495
    01496                                 longR = longX * longMat[0] + longY * longMat[1] + longZ * longMat[2];
    01497                                 if(longR & 0xF0000000)
    01498                                         *XPtr++ = 255;          /* out of gamut */
    01499                                 else
    01500                                 {
    01501                                         longG = longX * longMat[3] + longY * longMat[4] + longZ * longMat[5];
    01502                                         if(longG & 0xF0000000)
    01503                                                 *XPtr++ = 255;          /* out of gamut */
    01504                                         else
    01505                                         {
    01506                                                 longB = longX * longMat[6] + longY * longMat[7] + longZ * longMat[8];
    01507                                                 if(longB & 0xF0000000)
    01508                                                         *XPtr++ = 255;          /* out of gamut */
    01509                                                 else
    01510                                                         *XPtr++ = 0;            /* in gamut */
    01511                                         }
    01512                                 }
    01513                         }
    01514
    01515                 /*---fill Boolean output LUT, adr_bereich_alut Bytes, 4 at one time with long:---*/
    01516         lPtr = (long *)(tempALut);
    01517         j = adr_bereich_alut/4/2 + 8;   /* slightly more than 50 % */
    01518         for(i=0; i<j; i++)                              /* slightly more than 50 % */
    01519                 *(lPtr + i) = 0;                        /* in gamut */
    01520         k = adr_bereich_alut/4;
    01521         for(i=j; i<k; i++)
    01522                 *(lPtr + i) = 0xFFFFFFFF;       /* out of gamut */
    01523
    01524         UNLOCK_DATA(tempELutHdl);
    01525         UNLOCK_DATA(tempXLutHdl);
    01526         UNLOCK_DATA(tempALutHdl);
    01527         theLutData->colorLut    = tempXLutHdl;  tempXLutHdl = nil;
    01528         theLutData->inputLut    = tempELutHdl;  tempELutHdl = nil;
    01529         theLutData->outputLut   = tempALutHdl;  tempALutHdl = nil;
    01530
    01531 CleanupAndExit:
    01532         tempELutHdl = DISPOSE_IF_DATA(tempELutHdl);
    01533         tempXLutHdl = DISPOSE_IF_DATA(tempXLutHdl);
    01534         tempALutHdl = DISPOSE_IF_DATA(tempALutHdl);
    01535         LH_END_PROC("MakeGamut16or32ForMonitor")
    01536         return (err);
    01537 }
    01538