test: frgmnt16.c Source File

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

# frgmnt16.c

Go to the documentation of this file.

    00001 /*
    00002         File:           LHFragment16.c
    00003
    00004         Contains:       ALUT stuff (16 bit) for Color Sync
    00005
    00006         Version:
    00007
    00008         Written by:     H.Siegeritz
    00009
    00010         Copyright:      © 1993-1997 by Heidelberger Druckmaschinen AG, all rights reserved.
    00011
    00012 */
    00013
    00014 #ifndef LHGeneralIncs_h
    00015 #include "General.h"
    00016 #endif
    00017
    00018 #if GENERATING68K
    00019 /*      #include <ConditionalMacros.h> */
    00020
    00021         #define CM_Doub extended
    00022         extern CM_Doub pow(CM_Doub _x,CM_Doub _y);
    00023 #else
    00024         #define CM_Doub double
    00025         #include <math.h>
    00026 #endif
    00027
    00028 #ifndef LHFragment_h
    00029 #include "Fragment.h"
    00030 #endif
    00031
    00032 #ifndef LHStdConversionLuts_h
    00033 #include "StdConv.h"
    00034 #endif
    00035
    00036 #if ! realThing
    00037 #ifdef DEBUG_OUTPUT
    00038 #define kThisFile kLHFragment16ID
    00039 #endif
    00040 #endif
    00041
    00042
    00043 /*-----prototypes for local functions-----*/
    00044 void
    00045 Fill_inverseGamma_ushort_ALUT   ( unsigned short *usALUT, char addrBits,
    00046                                                                   unsigned short gamma_u8_8);
    00047
    00048 /* ______________________________________________________________________
    00049
    00050         CMError
    00051                 Fill_inverse_ushort_ALUT_from_CurveTag( icCurveType             *pCurveTag,
    00052                                                                                                 unsigned short  *usALUT,
    00053                                                                                                 char                    addrBits )
    00054         Abstract:
    00055                 extracts output luts out of cmSigCurveType tag and converts them
    00056                 to desired format: (2 ^ addrBits) values in a range from 0 to 65535
    00057                 NOTE: not-monotone CurveTags are manipulated
    00058                 NOTE: Memory for the LUT has to be allocated before !
    00059
    00060         Params:
    00061                 pCurveTag               (in)            extract input LUT from this
    00062                 usALUT                  (in/out)        result LUT
    00063                 addrBits                (in)            2 ^ addrBits values are requested
    00064
    00065         Return:
    00066                 noErr           successful
    00067
    00068    _____________________________________________________________________ */
    00069 CMError
    00070 Fill_inverse_ushort_ALUT_from_CurveTag( icCurveType             *pCurveTag,
    00071                                                                                 unsigned short  *usALUT,
    00072                                                                                 char                    addrBits )
    00073 {
    00074         unsigned long   i, inCount, outCount, clipIndex, ulFactor;
    00075         unsigned long   intpFirst, intpLast, halfStep, ulAux, target;
    00076         short                   monot;
    00077         unsigned short  *inCurve, *usPtr, *stopPtr;
    00078         double                  flFactor;
    00079 #ifdef DEBUG_OUTPUT
    00080         OSErr err=noErr;
    00081 #endif
    00082         LH_START_PROC("Fill_inverse_ushort_ALUT_from_CurveTag")
    00083
    00084     if( pCurveTag->base.sig != icSigCurveType   /* 'curv' */
    00085          || addrBits > 15 )
    00086          {
    00087 #ifdef DEBUG_OUTPUT
    00088                 if ( DebugCheck(kThisFile, kDebugErrorInfo) )
    00089                         DebugPrint("¥ Fill_inverse_ushort_ALUT_from_CurveTag ERROR:   addrBits= %d\n",addrBits);
    00090 #endif
    00091                 return(cmparamErr);
    00092          }
    00093
    00094         outCount  = 1 << addrBits;
    00095         clipIndex = outCount - 1;
    00096
    00097                 /*---special cases:---*/
    00098
    00099         if(pCurveTag->curve.count == 0)         /*---identity---*/
    00100         {
    00101                 ulFactor = ((unsigned long)65535 << 16) / clipIndex;            /* use all 32 bits */
    00102
    00103                 for(i=0; i<clipIndex; i++)
    00104                         usALUT[i] = (unsigned short)((i * ulFactor + 32767) >> 16);
    00105
    00106                 for(i=clipIndex; i<outCount; i++)
    00107                         usALUT[i] = 0xFFFF;
    00108
    00109                 return(noErr);
    00110         }
    00111         else if(pCurveTag->curve.count == 1)    /*---gamma curve---*/
    00112         {
    00113                 Fill_inverseGamma_ushort_ALUT(usALUT, addrBits, pCurveTag->curve.data[0]);
    00114                 return(noErr);
    00115         }
    00116
    00117                 /*---ordinary case:---*/
    00118
    00119         inCount = pCurveTag->curve.count;
    00120         inCurve = pCurveTag->curve.data;
    00121
    00122                  /* exact matching factor needed for special values: */
    00123         flFactor = (double)clipIndex / 65535.;
    00124
    00125         halfStep = clipIndex >> 1;              /* lessen computation incorrectness */
    00126
    00127                                 /* ascending or descending ? */
    00128         for(monot=0, i=1; i<inCount; i++)
    00129         {
    00130                 if(inCurve[i-1] < inCurve[i])
    00131                         monot++;
    00132                 else if(inCurve[i-1] > inCurve[i])
    00133                         monot--;
    00134         }
    00135
    00136         if(monot >= 0)  /* curve seems to be ascending */
    00137         {
    00138                 for(i=1; i<inCount; i++)
    00139                         if(inCurve[i-1] > inCurve[i])
    00140                                 inCurve[i] = inCurve[i-1];      /* correct not-invertible parts */
    00141
    00142                 intpFirst = (unsigned long)(inCurve[0] * flFactor + 0.9999);
    00143                 intpLast  = (unsigned long)(inCurve[inCount-1] * flFactor);
    00144
    00145                 for(i=0; i<intpFirst; i++)                      /* fill lacking area low */
    00146                         usALUT[i] = 0;
    00147                 for(i=intpLast+1; i<outCount; i++)      /* fill lacking area high */
    00148                         usALUT[i] = 0xFFFF;
    00149
    00150                         /* interpolate remaining values: */
    00151                 usPtr   = inCurve;
    00152                 stopPtr = inCurve + inCount - 2; /* stops incrementation */
    00153
    00154                 for(i=intpFirst; i<=intpLast; i++)
    00155                 {
    00156                         target = (0x0FFFF * i + halfStep)  / clipIndex;
    00157                         while(*(usPtr+1) < target && usPtr < stopPtr)
    00158                                 usPtr++;                                        /* find interval */
    00159
    00160                         ulAux = ((unsigned long)(usPtr - inCurve) << 16) / (inCount - 1);
    00161                         if(*(usPtr+1) != *usPtr)
    00162                         {
    00163                                 ulAux += ((target - (unsigned long)*usPtr) << 16)
    00164                                           / ( (*(usPtr+1) - *usPtr) * (inCount - 1) );
    00165
    00166                                 if(ulAux & 0x10000)   /* *(usPtr+1) was required */
    00167                                         ulAux = 0xFFFF;
    00168                         }
    00169
    00170                         usALUT[i] = (unsigned short)ulAux;
    00171                 }
    00172         }
    00173         else                    /* curve seems to be descending */
    00174         {
    00175                 for(i=1; i<inCount; i++)
    00176                         if(inCurve[i-1] < inCurve[i])
    00177                                 inCurve[i] = inCurve[i-1];      /* correct not-invertible parts */
    00178
    00179                 intpFirst = (unsigned long)(inCurve[inCount-1] * flFactor + 0.9999);
    00180                 intpLast  = (unsigned long)(inCurve[0] * flFactor);
    00181
    00182                 for(i=0; i<intpFirst; i++)                      /* fill lacking area low */
    00183                         usALUT[i] = 0xFFFF;
    00184                 for(i=intpLast+1; i<outCount; i++)      /* fill lacking area high */
    00185                         usALUT[i] = 0;
    00186
    00187                         /* interpolate remaining values: */
    00188                 usPtr   = inCurve + inCount - 1;
    00189                 stopPtr = inCurve + 1;          /* stops decrementation */
    00190
    00191                 for(i=intpFirst; i<=intpLast; i++)
    00192                 {
    00193                         target = (0x0FFFF * i + halfStep)  / clipIndex;
    00194                         while(*(usPtr-1) < target && usPtr > stopPtr)
    00195                                 usPtr--;                                        /* find interval */
    00196
    00197                         ulAux = ((unsigned long)(usPtr-1 - inCurve) << 16) / (inCount - 1);
    00198                         if(*(usPtr-1) != *usPtr)
    00199                         {
    00200                                 ulAux += (((unsigned long)*(usPtr-1) - target) << 16)
    00201                                           / ( (*(usPtr-1) - *usPtr) * (inCount - 1) );
    00202
    00203                                 if(ulAux & 0x10000)
    00204                                         ulAux = 0xFFFF;
    00205                         }
    00206
    00207                         usALUT[i] = (unsigned short)ulAux;
    00208                 }
    00209         }
    00210
    00211
    00212         LH_END_PROC("Fill_inverse_ushort_ALUT_from_CurveTag")
    00213         return(noErr);
    00214 }
    00215
    00216 /*   _____________________________________________________________________ */
    00217
    00218 void
    00219 Fill_inverseGamma_ushort_ALUT(  unsigned short  *usALUT,
    00220                                                                 char                    addrBits,
    00221                                                                 unsigned short  gamma_u8_8 )
    00222 {
    00223         unsigned long   i, j, outCount, step, stopit;
    00224         long                    leftVal, Diff, lAux;
    00225         CM_Doub                 invGamma, x, xFactor;
    00226         long                    clipIndex;
    00227 #ifdef DEBUG_OUTPUT
    00228         OSErr err = noErr;
    00229 #endif
    00230         LH_START_PROC("Fill_inverseGamma_ushort_ALUT")
    00231
    00232         outCount = 0x1 << addrBits;
    00233
    00234         invGamma  = 256. / (CM_Doub)gamma_u8_8;
    00235         clipIndex = outCount - 1;
    00236         xFactor   = 1. / (CM_Doub)clipIndex;
    00237
    00238         if(addrBits <= 6)               /* up to 64 - 2 float.computations */
    00239                 step = 1;
    00240         else
    00241                 step = 0x1 << (addrBits - 6);           /* more would take too long */
    00242
    00243         usALUT[0]          = 0;                 /* these two... */
    00244         usALUT[outCount-1] = 0xFFFF;    /* ...are fixed */
    00245
    00246         for(i=step; i<outCount-1; i+=step)
    00247         {
    00248                 x = (CM_Doub)i * xFactor;
    00249                 if(x > 1.)
    00250                         x = 1.;         /* clipping in the end of ALUT */
    00251
    00252                 usALUT[i] = (unsigned short)( pow(x,invGamma) * 65535.0 + 0.5);
    00253         }
    00254
    00255                 /*---fill intervals - except for last, which is odd:---*/
    00256         for(i=0; i<outCount-step; i+=step)
    00257         {
    00258                 leftVal = (long)usALUT[i];
    00259                 Diff    = (long)usALUT[i + step] - leftVal;
    00260
    00261                 for(j=1; j<step; j++)
    00262                 {
    00263                         lAux = ( (Diff * j << 8) / step + 128 ) >> 8;
    00264
    00265                         usALUT[i + j] = (unsigned short)(leftVal + lAux);
    00266                 }
    00267         }
    00268
    00269                 /*---fill last interval:---*/
    00270         i       = outCount - step;
    00271         leftVal = (long)usALUT[i];
    00272         Diff    = 0x0FFFF - leftVal;    /* 0xFFFF for 1.0 */
    00273
    00274         for(j=1; j<step-1; j++)         /* stops here if step <= 2 */
    00275         {
    00276                 lAux = ( (Diff * j << 8) / (step - 1) + 128 ) >> 8;
    00277
    00278                 usALUT[i + j] = (unsigned short)(leftVal + lAux);
    00279         }
    00280
    00281                 /*--overwrite sensitive values depending on Gamma:--*/
    00282         if(addrBits > 6 && invGamma < 1.0)              /* ...if lower part is difficult */
    00283         {
    00284                 stopit = 0x1 << (addrBits - 6);
    00285
    00286                 for(i=1; i<stopit; i++)
    00287                 {
    00288                         x         = (CM_Doub)i * xFactor;
    00289                         usALUT[i] = (unsigned short)( pow(x,invGamma) * 65535.0);
    00290                 }
    00291         }
    00292
    00293         LH_END_PROC("Fill_inverseGamma_ushort_ALUT")
    00294 }
    00295
    00296 /* ______________________________________________________________________
    00297
    00298         CMError
    00299         Fill_ushort_ALUTs_from_lut8Tag( CMLutParamPtr   theLutData,
    00300                                                                         Ptr                             profileALuts,
    00301                                                                         char                    addrBits )
    00302         Abstract:
    00303                 extracts output luts out of CMLut8Type tag and converts them
    00304                 to desired format: (2 ^ addrBits) values in a range from 0 to 65535
    00305
    00306         Params:
    00307                 theLutData                      (in/out)        Ptr to structure that holds all the luts...
    00308                 profileALuts            (in)            Ptr to the profile's output luts
    00309                 addrBits                        (in)            2 ^ addrBits values are requested
    00310
    00311         Return:
    00312                 noErr           successful
    00313
    00314    _____________________________________________________________________ */
    00315 CMError
    00316 Fill_ushort_ALUTs_from_lut8Tag( CMLutParamPtr   theLutData,
    00317                                                                 Ptr                             profileALuts,
    00318                                                                 char                    addrBits )
    00319 {
    00320         long                    i, j;
    00321         unsigned char   *curOutLut;
    00322         unsigned char   *profAluts = (unsigned char *)profileALuts;
    00323         unsigned short  *curALUT;
    00324         long                    count, clipIndex;
    00325         long                    factor, fract, baseInd, lAux, leftVal, rightVal;
    00326         OSErr                   err = noErr;
    00327         LUT_DATA_TYPE   localAlut = nil;
    00328         unsigned short  *localAlutPtr;
    00329         long                    theAlutSize;
    00330
    00331         LH_START_PROC("Fill_ushort_ALUTs_from_lut8Tag")
    00332
    00333         count     = 1 << addrBits;                                              /* addrBits is always >= 8 */
    00334         clipIndex = count - 1;
    00335
    00336         theAlutSize = theLutData->colorLutOutDim * count * sizeof(unsigned short);
    00337         localAlut   = ALLOC_DATA(theAlutSize + 2, &err);
    00338         if (err)
    00339                 goto CleanupAndExit;
    00340
    00341         LOCK_DATA(localAlut);
    00342         localAlutPtr = (unsigned short *)DATA_2_PTR(localAlut);
    00343
    00344         factor = ((255 << 12) + clipIndex/2) / clipIndex;               /* for adjusting the indices */
    00345
    00346         for(i=0; i<theLutData->colorLutOutDim; i++)
    00347         {
    00348                 curOutLut = profAluts + (i << 8);               /* these are unsigned char's */
    00349                 curALUT   = localAlutPtr + i * count;   /* these are unsigned short's */
    00350
    00351                 for(j=0; j<=clipIndex-1; j++)
    00352                 {
    00353                         lAux    = j * factor;
    00354                         baseInd = (unsigned long)lAux >> 12;
    00355                         fract   = lAux & 0x0FFF;
    00356
    00357                         leftVal = (long)curOutLut[baseInd];
    00358                         leftVal = (leftVal << 8) + leftVal;             /* 0xFF -> 0xFFFF */
    00359
    00360                         if(fract)
    00361                         {
    00362                                 rightVal = (long)curOutLut[baseInd + 1];
    00363                                 rightVal = (rightVal << 8) + rightVal;          /* 0xFF -> 0xFFFF */
    00364
    00365                                 lAux = rightVal - leftVal;
    00366                                 lAux = (lAux * fract + 0x0800) >> 12;
    00367
    00368                                 curALUT[j] = (unsigned short)(leftVal + lAux);
    00369                         }
    00370                         else
    00371                                 curALUT[j] = (unsigned short)leftVal;
    00372                 }
    00373
    00374                 leftVal = (long)curOutLut[255];
    00375                 leftVal = (leftVal << 8) + leftVal;             /* 0xFF -> 0xFFFF */
    00376                 curALUT[j] = (unsigned short)leftVal;
    00377
    00378                 for(j=clipIndex+1; j<count; j++)                /* unused indices, clip these */
    00379                         curALUT[j] = curALUT[clipIndex];
    00380         }
    00381
    00382         UNLOCK_DATA(localAlut);
    00383         theLutData->outputLut = localAlut;
    00384         localAlut = nil;
    00385 CleanupAndExit:
    00386         localAlut = DISPOSE_IF_DATA(localAlut);
    00387
    00388         LH_END_PROC("Fill_ushort_ALUTs_from_lut8Tag")
    00389         return err;
    00390 }
    00391
    00392 /* ______________________________________________________________________
    00393
    00394         CMError
    00395         Fill_ushort_ALUTs_from_lut16Tag(CMLutParamPtr   theLutData,
    00396                                                                         Ptr                             profileALuts,
    00397                                                                         char                    addrBits,
    00398                                                                     long                        outputTableEntries )
    00399         Abstract:
    00400                 extracts output luts out of CMLut16Type tag and converts them
    00401                 to desired format: (2 ^ addrBits) values in a range from 0 to 65535
    00402
    00403         Params:
    00404                 theLutData                      (in/out)        Ptr to structure that holds all the luts...
    00405                 profileALuts            (in)            Ptr to the profile's output luts
    00406                 addrBits                        (in)            2 ^ addrBits values are requested
    00407                 outputTableEntries      (in)            number of entries in the output lut (up to 4096)
    00408
    00409         Return:
    00410                 noErr           successful
    00411
    00412    _____________________________________________________________________ */
    00413 CMError
    00414 Fill_ushort_ALUTs_from_lut16Tag(CMLutParamPtr   theLutData,
    00415                                                                 Ptr                             profileALuts,
    00416                                                                 char                    addrBits,
    00417                                                             long                        outputTableEntries )
    00418 {
    00419         long                    i;
    00420         unsigned short  *curOutLut;
    00421         unsigned short  *curALUT;
    00422         unsigned long   ulIndFactor, j;
    00423         long                    count, clipIndex, outTabLen;
    00424         long                    fract, baseInd, lAux, leftVal, rightVal;
    00425         unsigned short  *profALUTs = (unsigned short *)profileALuts;
    00426         OSErr                   err = noErr;
    00427         LUT_DATA_TYPE   localAlut = nil;
    00428         unsigned short  *localAlutPtr;
    00429         long                    theAlutSize;
    00430
    00431         LH_START_PROC("Fill_ushort_ALUTs_from_lut16Tag")
    00432
    00433         count     = 1 << addrBits;                                              /* addrBits is always >= 8 */
    00434         clipIndex = count - 1;
    00435
    00436         theAlutSize = theLutData->colorLutOutDim * count * sizeof(unsigned short);
    00437         localAlut   = ALLOC_DATA(theAlutSize + 2, &err);
    00438         if (err)
    00439                 goto CleanupAndExit;
    00440
    00441         outTabLen = outputTableEntries;                 /* <= 4096 acc. to the spec */
    00442         if(outTabLen > 4096)
    00443         {
    00444                 err = cmparamErr;
    00445                 goto CleanupAndExit;
    00446         }
    00447
    00448         ulIndFactor = (((unsigned long)outTabLen - 1) << 20)
    00449                                 / (unsigned long)clipIndex;                             /* for adjusting the indices */
    00450
    00451         LOCK_DATA(localAlut);
    00452         localAlutPtr = (unsigned short *)DATA_2_PTR(localAlut);
    00453
    00454         for(i=0; i<theLutData->colorLutOutDim; i++)
    00455         {
    00456                 curOutLut = profALUTs + i * outTabLen;
    00457                 curALUT   = localAlutPtr + i * count;
    00458
    00459                 for(j=0; j<=(unsigned long)clipIndex; j++)
    00460                 {
    00461                         lAux    = (long)( (j * ulIndFactor + 16) >> 5 );                /* n.b: j is unsigned long ! */
    00462                         baseInd = (unsigned long)lAux >> 15;
    00463                         fract   = lAux & 0x7FFF;        /* 15 bits for interpolation */
    00464
    00465                         if(fract)
    00466                         {
    00467                                 leftVal  = (long)curOutLut[baseInd];
    00468                                 rightVal = (long)curOutLut[baseInd + 1];
    00469
    00470                                 lAux = rightVal - leftVal;
    00471                                 lAux = (lAux * fract + 16383) >> 15;
    00472
    00473                                 curALUT[j] = (unsigned short)(leftVal + lAux);
    00474                         }
    00475                         else
    00476                                 curALUT[j] = curOutLut[baseInd];
    00477                 }
    00478
    00479                 for(j=clipIndex+1; j<(unsigned long)count; j++)         /* unused indices, clip these */
    00480                         curALUT[j] = curALUT[clipIndex];
    00481         }
    00482
    00483         UNLOCK_DATA(localAlut);
    00484         theLutData->outputLut = localAlut;
    00485         localAlut = nil;
    00486 CleanupAndExit:
    00487         localAlut = DISPOSE_IF_DATA(localAlut);
    00488
    00489         LH_END_PROC("Fill_ushort_ALUTs_from_lut16Tag")
    00490         return err;
    00491 }
    00492
    00493 /* ______________________________________________________________________
    00494
    00495         CMError
    00496                 DoAbsoluteShiftForPCS_Cube16(   unsigned short  *theCube,
    00497                                                                                 long                    count,
    00498                                                                                 CMProfileRef    theProfile,
    00499                                                                                 Boolean                 pcsIsXYZ,
    00500                                                                                 Boolean                 afterInput )
    00501         Abstract:
    00502                 Performs color shift necessary for absolute colorimetry. Data of
    00503                 the cube points are in linear XYZ (16 bit) or in Lab (16 bit).
    00504                 Either conversion just after entering PCS or before leaving PCS (inverse
    00505                 operation). NOTE: for devices with colorant matrices this operation is
    00506                 done much faster by manipulating the matrix.
    00507
    00508         Params:
    00509                 theCube                 (in/out)        cube grid points
    00510                 count                   (in)            number of points
    00511                 theProfile              (in)            contains media white point
    00512                 pcsIsXYZ                (in)            XYZ/Lab, saves one file access to profile
    00513                 afterInput              (in)            direct or inverse operation
    00514
    00515         Return:
    00516                 noErr                   successful
    00517    _____________________________________________________________________ */
    00518 CMError DoAbsoluteShiftForPCS_Cube16(   unsigned short  *theCube,
    00519                                                                                 long                    count,
    00520                                                                                 CMProfileRef    theProfile,
    00521                                                                                 Boolean                 pcsIsXYZ,
    00522                                                                                 Boolean                 afterInput )
    00523 {
    00524         unsigned long           i, uLong;
    00525         unsigned short          *usPtr;
    00526    CMError                              err = noErr;
    00527         unsigned long           elementSize;
    00528         icXYZType                       curMediaWhite;
    00529         double                          xFactor, yFactor, zFactor;
    00530         unsigned long           intFactorX, intFactorY, intFactorZ;
    00531         unsigned long           roundX, roundY, roundZ;
    00532         unsigned long           shiftX, shiftY, shiftZ;
    00533
    00534         LH_START_PROC("DoAbsoluteShiftForPCS_Cube16")
    00535
    00536         elementSize = sizeof(icXYZType);
    00537         err = CMGetProfileElement(theProfile, icSigMediaWhitePointTag, &elementSize, &curMediaWhite);
    00538 #ifdef IntelMode
    00539    SwapLongOffset( &curMediaWhite.base.sig, 0, 4 );
    00540    SwapLongOffset( &curMediaWhite, (LONG)((char*)&curMediaWhite.data.data[0]-(char*)&curMediaWhite), elementSize );
    00541 #endif
    00542         if(err)
    00543         {
    00544                 if(err == cmElementTagNotFound)         /* take D50 and do nothing */
    00545                         return(noErr);
    00546                 else
    00547                         return(err);
    00548         }
    00549
    00550                 /*--- preliminary matching factors: ---*/
    00551         xFactor = ((double)curMediaWhite.data.data[0].X) / 65536. / 0.9642;
    00552         if(xFactor > 100.)
    00553                 xFactor = 100.;                 /* evil profile */
    00554         else if(xFactor < 0.01)
    00555                 xFactor = 0.01;
    00556
    00557         yFactor = ((double)curMediaWhite.data.data[0].Y) / 65536.;
    00558         if(yFactor > 100.)
    00559                 yFactor = 100.;
    00560         else if(yFactor < 0.01)
    00561                 yFactor = 0.01;
    00562
    00563         zFactor = ((double)curMediaWhite.data.data[0].Z) / 65536. / 0.8249;
    00564         if(zFactor > 100.)
    00565                 zFactor = 100.;
    00566         else if(zFactor < 0.01)
    00567                 zFactor = 0.01;
    00568
    00569         if( ( xFactor < 1.+1.E-3 && xFactor > 1.-1.E-3 ) &&
    00570                 ( yFactor < 1.+1.E-3 && yFactor > 1.-1.E-3 ) &&
    00571                 ( zFactor < 1.+1.E-3 && zFactor > 1.-1.E-3 ) )
    00572                         return noErr; /* do nothing if MediaWhite is D50 */
    00573
    00574         if(!afterInput)         /* back to device space (for example with B2A1 table) */
    00575         {
    00576                 xFactor = 1. / xFactor;
    00577                 yFactor = 1. / yFactor;
    00578                 zFactor = 1. / zFactor;
    00579         }
    00580
    00581                 /*--- integer factors for speed: ---*/
    00582         intFactorX = (unsigned long)(xFactor * 65536. * 64.);   /* probably too long... */
    00583         intFactorY = (unsigned long)(yFactor * 65536. * 64.);   /* ...adding 22 bits    */
    00584         intFactorZ = (unsigned long)(zFactor * 65536. * 64.);
    00585
    00586         roundX = roundY = roundZ = 0x1FFFFF;    /* 2^21 - 1 */
    00587         shiftX = shiftY = shiftZ = 22;
    00588
    00589         while(intFactorX & 0xFFFF0000)  /* stay within 16 bits to prevent product overflow */
    00590         {
    00591                 intFactorX >>= 1;
    00592                 roundX     >>= 1;
    00593                 shiftX      -= 1;
    00594         }
    00595
    00596         while(intFactorY & 0xFFFF0000)
    00597         {
    00598                 intFactorY >>= 1;
    00599                 roundY     >>= 1;
    00600                 shiftY      -= 1;
    00601         }
    00602
    00603         while(intFactorZ & 0xFFFF0000)
    00604         {
    00605                 intFactorZ >>= 1;
    00606                 roundZ     >>= 1;
    00607                 shiftZ      -= 1;
    00608         }
    00609
    00610                 /*--- perform matching: ---*/
    00611         if(!pcsIsXYZ)           /* 16 bit linear Lab  to XYZ before and afterwards */
    00612                 Lab2XYZ_forCube16(theCube, count);
    00613
    00614         usPtr = theCube;
    00615
    00616         for(i=0; i<(unsigned long)count; i++)
    00617         {
    00618                 uLong = ((unsigned long)(*usPtr) * intFactorX + roundX) >> shiftX;
    00619                 if(uLong > 0x0FFFF)
    00620                         uLong = 0xFFFF;                         /* clip to 2.0 */
    00621                 *usPtr++ = (unsigned short)uLong;
    00622
    00623                 uLong = ((unsigned long)(*usPtr) * intFactorY + roundY) >> shiftY;
    00624                 if(uLong > 0x0FFFF)
    00625                         uLong = 0xFFFF;
    00626                 *usPtr++ = (unsigned short)uLong;
    00627
    00628                 uLong = ((unsigned long)(*usPtr) * intFactorZ + roundZ) >> shiftZ;
    00629                 if(uLong > 0x0FFFF)
    00630                         uLong = 0xFFFF;
    00631                 *usPtr++ = (unsigned short)uLong;
    00632         }
    00633
    00634         if(!pcsIsXYZ)           /* back to 16 bit Lab */
    00635                 XYZ2Lab_forCube16(theCube, count);
    00636
    00637
    00638         LH_END_PROC("DoAbsoluteShiftForPCS_Cube16")
    00639         return(noErr);
    00640 }