📄 cmsgamma.c
字号:
c[2] = (-4 * lambda - d[1] * c[1] * e[1]) / d[2]; e[2] = lambda / d[2]; z[2] = w[2] * y[2] - c[1] * z[1]; for (i = 3; i < m - 1; i++) { i1 = i - 1; i2 = i - 2; d[i]= w[i] + 6 * lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2]; c[i] = (-4 * lambda -d[i1] * c[i1] * e[i1])/ d[i]; e[i] = lambda / d[i]; z[i] = w[i] * y[i] - c[i1] * z[i1] - e[i2] * z[i2]; } i1 = m - 2; i2 = m - 3; d[m - 1] = w[m - 1] + 5 * lambda -c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2]; c[m - 1] = (-2 * lambda - d[i1] * c[i1] * e[i1]) / d[m - 1]; z[m - 1] = w[m - 1] * y[m - 1] - c[i1] * z[i1] - e[i2] * z[i2]; i1 = m - 1; i2 = m - 2; d[m] = w[m] + lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2]; z[m] = (w[m] * y[m] - c[i1] * z[i1] - e[i2] * z[i2]) / d[m]; z[m - 1] = z[m - 1] / d[m - 1] - c[m - 1] * z[m]; for (i = m - 2; 1<= i; i--) z[i] = z[i] / d[i] - c[i] * z[i + 1] - e[i] * z[i + 2];}// Smooths a curve sampled at regular intervalsBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda){ vec w, y, z; int i, nItems, Zeros, Poles; if (cmsIsLinear(Tab->GammaTable, Tab->nEntries)) return FALSE; // Nothing to do nItems = Tab -> nEntries; if (nItems > MAX_KNOTS) { cmsSignalError(LCMS_ERRC_ABORTED, "cmsSmoothGamma: too many points."); return FALSE; } ZeroMemory(w, nItems * sizeof(float)); ZeroMemory(y, nItems * sizeof(float)); ZeroMemory(z, nItems * sizeof(float)); for (i=0; i < nItems; i++) { y[i+1] = (float) Tab -> GammaTable[i]; w[i+1] = 1.0; } smooth2(w, y, z, (float) lambda, nItems); // Do some reality - checking... Zeros = Poles = 0; for (i=nItems; i > 1; --i) { if (z[i] == 0.) Zeros++; if (z[i] >= 65535.) Poles++; if (z[i] < z[i-1]) return FALSE; // Non-Monotonic } if (Zeros > (nItems / 3)) return FALSE; // Degenerated, mostly zeros if (Poles > (nItems / 3)) return FALSE; // Degenerated, mostly poles // Seems ok for (i=0; i < nItems; i++) { // Clamp to WORD float v = z[i+1]; if (v < 0) v = 0; if (v > 65535.) v = 65535.; Tab -> GammaTable[i] = (WORD) floor(v + .5); } return TRUE;}// Check if curve is exponential, return gamma if so.double LCMSEXPORT cmsEstimateGammaEx(LPWORD GammaTable, int nEntries, double Thereshold){ double gamma, sum, sum2; double n, x, y, Std; int i; sum = sum2 = n = 0; // Does exclude endpoints for (i=1; i < nEntries - 1; i++) { x = (double) i / (nEntries - 1); y = (double) GammaTable[i] / 65535.; // Avoid 7% on lower part to prevent // artifacts due to linear ramps if (y > 0. && y < 1. && x > 0.07) { gamma = log(y) / log(x); sum += gamma; sum2 += gamma * gamma; n++; } } // Take a look on SD to see if gamma isn't exponential at all Std = sqrt((n * sum2 - sum * sum) / (n*(n-1))); if (Std > Thereshold) return -1.0; return (sum / n); // The mean}double LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t){ return cmsEstimateGammaEx(t->GammaTable, t->nEntries, 0.7);}// -----------------------------------------------------------------Sampled curves// Allocate a empty curveLPSAMPLEDCURVE cmsAllocSampledCurve(int nItems){ LPSAMPLEDCURVE pOut; pOut = (LPSAMPLEDCURVE) malloc(sizeof(SAMPLEDCURVE)); if (pOut == NULL) return NULL; if((pOut->Values = (double *) malloc(nItems * sizeof(double))) == NULL) { free(pOut); return NULL; } pOut->nItems = nItems; ZeroMemory(pOut->Values, nItems * sizeof(double)); return pOut;}void cmsFreeSampledCurve(LPSAMPLEDCURVE p){ free((LPVOID) p -> Values); free((LPVOID) p);}// Does duplicate a sampled curveLPSAMPLEDCURVE cmsDupSampledCurve(LPSAMPLEDCURVE p){ LPSAMPLEDCURVE out; out = cmsAllocSampledCurve(p -> nItems); if (!out) return NULL; CopyMemory(out ->Values, p ->Values, p->nItems * sizeof(double)); return out;}// Take min, max of curvevoid cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max){ int i; *Min = 65536.; *Max = 0.; for (i=0; i < p -> nItems; i++) { double v = p -> Values[i]; if (v < *Min) *Min = v; if (v > *Max) *Max = v; } if (*Min < 0) *Min = 0; if (*Max > 65535.0) *Max = 65535.0;}// Clamps to Min, Maxvoid cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max){ int i; for (i=0; i < p -> nItems; i++) { double v = p -> Values[i]; if (v < Min) v = Min; if (v > Max) v = Max; p -> Values[i] = v; }}// Smooths a curve sampled at regular intervalsBOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda){ vec w, y, z; int i, nItems; nItems = Tab -> nItems; if (nItems > MAX_KNOTS) { cmsSignalError(LCMS_ERRC_ABORTED, "cmsSmoothSampledCurve: too many points."); return FALSE; } ZeroMemory(w, nItems * sizeof(float)); ZeroMemory(y, nItems * sizeof(float)); ZeroMemory(z, nItems * sizeof(float)); for (i=0; i < nItems; i++) { float value = (float) Tab -> Values[i]; y[i+1] = value; w[i+1] = (float) ((value < 0.0) ? 0 : 1); } smooth2(w, y, z, (float) lambda, nItems); for (i=0; i < nItems; i++) { Tab -> Values[i] = z[i+1];; } return TRUE;}// Scale a value v, within domain Min .. Max // to a domain 0..(nPoints-1)staticdouble ScaleVal(double v, double Min, double Max, int nPoints){ double a, b; if (v <= Min) return 0; if (v >= Max) return (nPoints-1); a = (double) (nPoints - 1) / (Max - Min); b = a * Min; return (a * v) - b;}// Does rescale a sampled curve to fit in a 0..(nPoints-1) domainvoid cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints){ int i; for (i=0; i < p -> nItems; i++) { double v = p -> Values[i]; p -> Values[i] = ScaleVal(v, Min, Max, nPoints); }}// Joins two sampled curves for X and Y. Curves should be sorted.LPSAMPLEDCURVE cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints){ int i, j; LPSAMPLEDCURVE out; double MinX, MinY, MaxX, MaxY; double x, y, x1, y1, x2, y2, a, b; out = cmsAllocSampledCurve(nResultingPoints); if (out == NULL) return NULL; if (X -> nItems != Y -> nItems) { cmsSignalError(LCMS_ERRC_ABORTED, "cmsJoinSampledCurves: invalid curve."); cmsFreeSampledCurve(out); return NULL; } // Get endpoints of sampled curves cmsEndpointsOfSampledCurve(X, &MinX, &MaxX); cmsEndpointsOfSampledCurve(Y, &MinY, &MaxY); // Set our points out ->Values[0] = MinY; for (i=1; i < nResultingPoints; i++) { // Scale t to x domain x = (i * (MaxX - MinX) / (nResultingPoints-1)) + MinX; // Find interval in which j is within (always up, // since fn should be monotonic at all) j = 1; while ((j < X ->nItems - 1) && X ->Values[j] < x) j++; // Now x is within X[j-1], X[j] x1 = X ->Values[j-1]; x2 = X ->Values[j]; y1 = Y ->Values[j-1]; y2 = Y ->Values[j]; // Interpolate the value a = (y1 - y2) / (x1 - x2); b = y1 - a * x1; y = a* x + b; out ->Values[i] = y; } cmsClampSampledCurve(out, MinY, MaxY); return out;}// Convert between curve typesLPGAMMATABLE cmsConvertSampledCurveToGamma(LPSAMPLEDCURVE Sampled, double Max){ LPGAMMATABLE Gamma; int i, nPoints; nPoints = Sampled ->nItems; Gamma = cmsAllocGamma(nPoints); for (i=0; i < nPoints; i++) { Gamma->GammaTable[i] = (WORD) floor(ScaleVal(Sampled ->Values[i], 0, Max, 65536) + .5); } return Gamma;}// Inverse of anteriorLPSAMPLEDCURVE cmsConvertGammaToSampledCurve(LPGAMMATABLE Gamma, int nPoints){ LPSAMPLEDCURVE Sampled; L16PARAMS L16; int i; WORD wQuant, wValIn; if (nPoints > 4096) { cmsSignalError(LCMS_ERRC_ABORTED, "cmsConvertGammaToSampledCurve: too many points (max=4096)"); return NULL; } cmsCalcL16Params(Gamma -> nEntries, &L16); Sampled = cmsAllocSampledCurve(nPoints); for (i=0; i < nPoints; i++) { wQuant = _cmsQuantizeVal(i, nPoints); wValIn = cmsLinearInterpLUT16(wQuant, Gamma ->GammaTable, &L16); Sampled ->Values[i] = (float) wValIn; } return Sampled;}// Smooth endpoints (used in Black/White compensation)BOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries){ vec w, y, z; int i, Zeros, Poles;#ifdef DEBUG ASAVE(Table, nEntries, "nonsmt.txt");#endif if (cmsIsLinear(Table, nEntries)) return FALSE; // Nothing to do if (nEntries > MAX_KNOTS) { cmsSignalError(LCMS_ERRC_ABORTED, "_cmsSmoothEndpoints: too many points."); return FALSE; } ZeroMemory(w, nEntries * sizeof(float)); ZeroMemory(y, nEntries * sizeof(float)); ZeroMemory(z, nEntries * sizeof(float)); for (i=0; i < nEntries; i++) { y[i+1] = (float) Table[i]; w[i+1] = 1.0; } w[1] = 65535.0; w[nEntries] = 65535.0; smooth2(w, y, z, (float) nEntries, nEntries); // Do some reality - checking... Zeros = Poles = 0; for (i=nEntries; i > 1; --i) { if (z[i] == 0.) Zeros++; if (z[i] >= 65535.) Poles++; if (z[i] < z[i-1]) return FALSE; // Non-Monotonic } if (Zeros > (nEntries / 3)) return FALSE; // Degenerated, mostly zeros if (Poles > (nEntries / 3)) return FALSE; // Degenerated, mostly poles // Seems ok for (i=0; i < nEntries; i++) { // Clamp to WORD float v = z[i+1]; if (v < 0) v = 0; if (v > 65535.) v = 65535.; Table[i] = (WORD) floor(v + .5); } return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -