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 01366 /*----------------------------------------------------------------------------------------- E */ 01367 tempELutHdl = ALLOC_DATA(adr_bereich_elut * 3 * sizeof(unsigned short) + 2, &err); /* +2 extra space for Interpolation */ 01368 if(err) 01369 goto CleanupAndExit; 01370 LOCK_DATA(tempELutHdl); 01371 tempELut = (unsigned short *)DATA_2_PTR(tempELutHdl); 01372 01373 01374 /*----------------------------------------------------------------------------------------- X */ 01375 if(cube32Flag) 01376 gridPoints = 32; /* for cube grid */ 01377 else 01378 gridPoints = 16; 01379 totalCount = gridPoints * gridPoints * gridPoints; 01380 totalCount += 1 + gridPoints + gridPoints * gridPoints; /* extra space for Interpolation */ 01381 01382 #ifdef ALLOW_MMX 01383 totalCount+=3; /* +1 for MMX 4 Byte access */ 01384 #endif 01385 01386 tempXLutHdl = ALLOC_DATA(totalCount, &err); 01387 if(err) 01388 goto CleanupAndExit; 01389 LOCK_DATA(tempXLutHdl); 01390 tempXLut = (unsigned char *)DATA_2_PTR(tempXLutHdl); 01391 01392 01393 /*----------------------------------------------------------------------------------------- A */ 01394 tempALutHdl = ALLOC_DATA(adr_bereich_alut + 1, &err); /* +1 extra space for Interpolation */ 01395 if(err) 01396 goto CleanupAndExit; 01397 LOCK_DATA(tempALutHdl); 01398 tempALut = (unsigned char *)DATA_2_PTR(tempALutHdl); 01399 01400 /*---------fill 3 ELUTs for X, Y, Z (256 u.shorts each):--------------------*/ 01401 /* linear curve with clipping, slope makes white value become */ 01402 /* max * 30.5/31 or max * 14.5/15, that is half of the last XLUT interval */ 01403 if(cube32Flag) 01404 dFactor = 30.5 / 31.; 01405 else 01406 dFactor = 14.5 / 15.; 01407 01408 maxOut = ((1L << (16 /*usedBits*/ - 8) ) * 256 * (gridPoints - 1)) / gridPoints; 01409 01410 for(i=0; i<3; i++) /* X, Y, Z ELUTs */ 01411 { 01412 if(i == 0) 01413 lFactor = (long)( dFactor * 2. * maxOut * 256. / 255. / 0.9642 );/* X, adjust D50 */ 01414 else if(i == 1) 01415 lFactor = (long)( dFactor * 2. * maxOut * 256. / 255.); /* Y */ 01416 else 01417 lFactor = (long)( dFactor * 2. * maxOut * 256. / 255. / 0.8249);/* Z, adjust D50 */ 01418 01419 usPtr = tempELut + 256 * i; 01420 for(j=0; j<256; j++) 01421 { 01422 k = (j * lFactor + 127) >> 8; 01423 if(k > maxOut) 01424 k = maxOut; /* max. ELUT value */ 01425 01426 *usPtr++ = (unsigned short)k; 01427 } 01428 } 01429 01430 /*------ RGB to XYZ matrix in the range 0.0 to 1.0 -----*/ 01431 /* floating point for accurate inversion */ 01432 XYZmatrix[0][0] = (double)pRedXYZ->data.data[0].X; 01433 XYZmatrix[1][0] = (double)pRedXYZ->data.data[0].Y; 01434 XYZmatrix[2][0] = (double)pRedXYZ->data.data[0].Z; 01435 01436 XYZmatrix[0][1] = (double)pGreenXYZ->data.data[0].X; 01437 XYZmatrix[1][1] = (double)pGreenXYZ->data.data[0].Y; 01438 XYZmatrix[2][1] = (double)pGreenXYZ->data.data[0].Z; 01439 01440 XYZmatrix[0][2] = (double)pBlueXYZ->data.data[0].X; 01441 XYZmatrix[1][2] = (double)pBlueXYZ->data.data[0].Y; 01442 XYZmatrix[2][2] = (double)pBlueXYZ->data.data[0].Z; 01443 01444 /*--- grey with R = G = B (D50 adjustment is done by the ELUTs) ----*/ 01445 for(i=0; i<3; i++) 01446 { 01447 sum = XYZmatrix[i][0] + XYZmatrix[i][1] + XYZmatrix[i][2]; 01448 if(sum < 0.1) 01449 sum = 0.1; /* prevent from div. by 0 (bad profiles) */ 01450 01451 for(j=0; j<3; j++) 01452 XYZmatrix[i][j] /= sum; 01453 } 01454 01455 /*---XYZ to RGB matrix:---*/ 01456 if(!doubMatrixInvert(XYZmatrix, RGBmatrix)) 01457 { 01458 err = cmparamErr; 01459 goto CleanupAndExit; 01460 } 01461 01462 for(i=0; i<3; i++) /* create integer format for speed, */ 01463 for(j=0; j<3; j++) /* 1.0 becomes 2^13, works for coeff. up to 8. */ 01464 longMat[3*i + j] = (long)(RGBmatrix[i][j] * 8192.); 01465 01466 /*-----grid levels for cube grid in XYZ (16 bit) so ----*/ 01467 /* that white is at half of last interval, so the last */ 01468 /* value is white * 15/14.5 or white * 31/30.5 */ 01469 if(cube32Flag) 01470 dFactor = 32768. / 30.5 * 31. / (gridPoints - 1); 01471 else 01472 dFactor = 32768. / 14.5 * 15. / (gridPoints - 1); 01473 01474 for(i=0; i<gridPoints; i++) /* n.b: 32 is max. possible gridPoints */ 01475 Levels[i] = (unsigned short)(i * dFactor + 0.5); 01476 01477 /*----special treatment of first and last plane for speed:----*/ 01478 planeCount = gridPoints * gridPoints; 01479 XPtr = tempXLut; 01480 for(i=0; i<planeCount; i++) 01481 *XPtr++ = 255; /* out of gamut */ 01482 01483 XPtr = tempXLut + (gridPoints - 1) * planeCount; 01484 for(i=0; i<planeCount; i++) 01485 *XPtr++ = 255; /* out of gamut */ 01486 01487 *tempXLut = 0; /* set black (white is between last 2 planes) */ 01488 01489 /*----second to second last plane must be computed:-----*/ 01490 /* transform points to RGB and judge in/out */ 01491 XPtr = tempXLut + planeCount; 01492 01493 for(i=1; i<gridPoints-1; i++) 01494 for(j=0; j<gridPoints; j++) 01495 for(k=0; k<gridPoints; k++) 01496 { 01497 longX = (long)Levels[i]; /* X */ 01498 longY = (long)Levels[j]; /* Y */ 01499 longZ = (long)Levels[k]; /* Z */ 01500 01501 /* matrix coeff: 2^13 is 1.0 , XYZ values: 1.0 or 100. is 2^15 ; */ 01502 /* -> mask for products < 0 and >= 2^28 is used for in/out checking */ 01503 01504 longR = longX * longMat[0] + longY * longMat[1] + longZ * longMat[2]; 01505 if(longR & 0xF0000000) 01506 *XPtr++ = 255; /* out of gamut */ 01507 else 01508 { 01509 longG = longX * longMat[3] + longY * longMat[4] + longZ * longMat[5]; 01510 if(longG & 0xF0000000) 01511 *XPtr++ = 255; /* out of gamut */ 01512 else 01513 { 01514 longB = longX * longMat[6] + longY * longMat[7] + longZ * longMat[8]; 01515 if(longB & 0xF0000000) 01516 *XPtr++ = 255; /* out of gamut */ 01517 else 01518 *XPtr++ = 0; /* in gamut */ 01519 } 01520 } 01521 } 01522 01523 /*---fill Boolean output LUT, adr_bereich_alut Bytes, 4 at one time with long:---*/ 01524 lPtr = (long *)(tempALut); 01525 j = adr_bereich_alut/4/2 + 8; /* slightly more than 50 % */ 01526 for(i=0; i<j; i++) /* slightly more than 50 % */ 01527 *(lPtr + i) = 0; /* in gamut */ 01528 k = adr_bereich_alut/4; 01529 for(i=j; i<k; i++) 01530 *(lPtr + i) = 0xFFFFFFFF; /* out of gamut */ 01531 01532 UNLOCK_DATA(tempELutHdl); 01533 UNLOCK_DATA(tempXLutHdl); 01534 UNLOCK_DATA(tempALutHdl); 01535 theLutData->colorLut = tempXLutHdl; tempXLutHdl = nil; 01536 theLutData->inputLut = tempELutHdl; tempELutHdl = nil; 01537 theLutData->outputLut = tempALutHdl; tempALutHdl = nil; 01538 01539 CleanupAndExit: 01540 tempELutHdl = DISPOSE_IF_DATA(tempELutHdl); 01541 tempXLutHdl = DISPOSE_IF_DATA(tempXLutHdl); 01542 tempALutHdl = DISPOSE_IF_DATA(tempALutHdl); 01543 LH_END_PROC("MakeGamut16or32ForMonitor") 01544 return (err); 01545 } 01546

Generated on Sat May 15 19:40:03 2004 for test by doxygen 1.3.7