diff options
Diffstat (limited to 'xicc/xmatrix.c')
-rw-r--r-- | xicc/xmatrix.c | 205 |
1 files changed, 137 insertions, 68 deletions
diff --git a/xicc/xmatrix.c b/xicc/xmatrix.c index a194314..53db237 100644 --- a/xicc/xmatrix.c +++ b/xicc/xmatrix.c @@ -42,9 +42,9 @@ #define XSHAPE_OFFG 0.1 /* Input offset weights when ord 0 is gamma */ #define XSHAPE_OFFS 1.0 /* Input offset weights when ord 0 is shaper */ -#define XSHAPE_HW01 0.002 /* 0 & 1 harmonic weights */ -#define XSHAPE_HBREAK 4 /* Harmonic that has HWBR */ -#define XSHAPE_HWBR 0.8 /* Base weight of harmonics HBREAK up */ +#define XSHAPE_HW01 0.01 /* 0 & 1 harmonic weights */ +#define XSHAPE_HBREAK 3 /* Harmonic that has HWBR */ +#define XSHAPE_HWBR 0.5 /* Base weight of harmonics HBREAK up */ #define XSHAPE_HWINC 0.5 /* Increase in weight for each harmonic above HWBR */ #define XSHAPE_GAMTHR 0.01 /* Input threshold for linear slope below gamma power */ @@ -309,8 +309,8 @@ int dir /* 0 = fwd, 1 = bwd */ else xicc_enum_viewcond(xicp, &p->vc, -1, NULL, 0, NULL); /* Use a default */ p->cam = new_icxcam(cam_default); - p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, p->vc.Yf, - p->vc.Fxyz, XICC_USE_HK); + p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, + p->vc.Yf, p->vc.Yg, p->vc.Gxyz, XICC_USE_HK); } else { p->cam = NULL; } @@ -560,7 +560,6 @@ double *v /* Pointer to parameters */ tt = v[11 + f]; if (f == 0 && p->shape0gam) tt -= 1.0; /* default is linear */ - tt *= tt; /* Weigh to suppress ripples */ if (f <= 1) { /* Use XSHAPE_HW01 */ w = XSHAPE_HW01; @@ -568,15 +567,15 @@ double *v /* Pointer to parameters */ double bl = (f - 1.0)/(XSHAPE_HBREAK - 1.0); w = (1.0 - bl) * XSHAPE_HW01 + bl * XSHAPE_HWBR * p->smooth; } else { /* Use XSHAPE_HWBR * smooth */ - w = XSHAPE_HWBR + (f-XSHAPE_HBREAK) * XSHAPE_HWINC; - w *= p->smooth; + w = XSHAPE_HWBR + (f-XSHAPE_HBREAK) * XSHAPE_HWINC * p->smooth; } + tt *= tt; tparam += w * tt; } return XSHAPE_MAG * tparam; } - /* Input ffset value */ + /* Input offset value */ if (p->shape0gam) w = XSHAPE_OFFG; else @@ -603,7 +602,6 @@ double *v /* Pointer to parameters */ w = (1.0 - bl) * XSHAPE_HW01 + bl * XSHAPE_HWBR * p->smooth; } else { w = XSHAPE_HWBR + (f-XSHAPE_HBREAK) * XSHAPE_HWINC * p->smooth; - w *= p->smooth; } for (g = 0; g < 3; g++) { tt = v[15 + 3 * f + g]; @@ -863,6 +861,10 @@ double scale /* Scale device values */ os->v[3] = 0.2; os->v[4] = 0.8; os->v[5] = 0.1; os->v[6] = 0.02; os->v[7] = 0.15; os->v[8] = 1.3; + /* We try and take a homomorphic approach here, in an attempt */ + /* to avoid getting trapped at a local minimum when a full */ + /* set of shaper parameters are in play. */ + /* Do a first pass just setting the matrix values */ os->isLinear = 1; os->isGamma = 1; @@ -889,17 +891,43 @@ double scale /* Scale device values */ #endif /* NEVER */ /* Now optimize again with shaper or gamma curves */ - if (!isLinear || isGamma) { + if (!isLinear) { + double scgamma; /* Start from linear, which is what was assumed for the matrix fit, */ - /* and fit first with a single shared curve. */ + /* and fit with a single shared gamma curve. */ os->isShTRC = 1; - if (isGamma) { /* Just gamma curve */ - os->isLinear = 0; - os->isGamma = 1; - os->optdim = 10; - os->v[9] = 1.0; /* Linear */ - } else { /* Creating input curves */ + os->isLinear = 0; + os->isGamma = 1; + os->optdim = 10; + os->v[9] = 1.0; /* Linear */ + + /* Set search area to starting values */ + for (j = 0; j < os->optdim; j++) + os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */ + + if (os->verb) + printf("Creating matrix and single gamma curve...\n"); + + if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits, + mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0) + warning("Powell failed to converge, residual error = %f",rerr); + + scgamma = os->v[9]; + if (isShTRC && !isGamma) { + +#ifndef NEVER + if (os->verb) { + printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]); + printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]); + printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]); + printf("Gamma = %f\n",os->v[9]); + } +#endif /* NEVER */ + + /* Do final optimisation using full curve capability */ + /* and fit first with a single shared curve. */ + os->isShTRC = 1; os->isLinear = 0; os->isGamma = 0; os->optdim = 9 + 2 + os->norders; /* Matrix, offset + orders */ @@ -911,71 +939,96 @@ double scale /* Scale device values */ os->v[11] = 0.0; /* 0th Harmonic */ for (i = 12; i < os->optdim; i++) os->v[i] = 0.0; /* Higher orders */ - } - /* Set search area to starting values */ - for (j = 0; j < os->optdim; j++) - os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */ + /* Set search area to starting values */ + for (j = 0; j < os->optdim; j++) + os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */ - if (os->verb) - printf("Creating matrix and single curve...\n"); + if (os->verb) + printf("Creating matrix and single shaper curve...\n"); - if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits, - mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0) - warning("Powell failed to converge, residual error = %f",rerr); + if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits, + mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0) + warning("Powell failed to converge, residual error = %f",rerr); + + scgamma = os->v[9]; + + } + + /* For multiple curves, continue fitting */ + if (!isShTRC) { + double mcgamma[3]; #ifndef NEVER - if (os->verb) { - printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]); - printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]); - printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]); - if (isGamma) { /* Creating input curves */ + if (os->verb) { + printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]); + printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]); + printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]); printf("Gamma = %f\n",os->v[9]); - } else { /* Creating input curves */ - printf("Input offset = %f\n",os->v[9]); - printf("Output offset = %f\n",os->v[10]); - for (j = 0; j < os->norders; j++) { - if (shape0gam && j == 0) - printf("gamma = %f\n", os->v[11 + j]); - else - printf("%d harmonics = %f\n",j, os->v[11 + j]); - } } - } #endif /* NEVER */ - /* Now do the final optimisation with all curves */ - if (!isShTRC) { + /* Fit matrix + multi gamma curves */ os->isShTRC = 0; - if (isGamma) { /* Just gamma curves */ - os->isLinear = 0; - os->isGamma = 1; - os->optdim = 12; - os->v[9] = os->v[10] = os->v[11] = 1.0; /* Linear */ - } else { /* Creating input curves */ - os->isLinear = 0; - os->isGamma = 0; - os->optdim = 9 + 6 + 3 * os->norders; /* Matrix, offset + orders */ - os->v[9] = os->v[10] = os->v[11] = 0.0; /* Input offset */ - os->v[12] = os->v[13] = os->v[14] = 0.0; /* Output offset */ - if (shape0gam) - os->v[15] = os->v[16] = os->v[17] = 1.0; /* Gamma */ - else - os->v[15] = os->v[16] = os->v[17] = 0.0; /* 0th Harmonic */ - for (i = 18; i < os->optdim; i++) - os->v[i] = 0.0; /* Higher orders */ - } + os->isLinear = 0; + os->isGamma = 1; + os->optdim = 12; + os->v[9] = os->v[10] = os->v[11] = scgamma; /* Single curve value */ /* Set search area to starting values */ for (j = 0; j < os->optdim; j++) os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */ if (os->verb) - printf("Creating matrix and curves...\n"); + printf("Creating matrix and gamma curves...\n"); if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits, mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0) warning("Powell failed to converge, residual error = %f",rerr); + + + mcgamma[0] = os->v[9]; + mcgamma[1] = os->v[10]; + mcgamma[2] = os->v[11]; + + if (!isGamma) { + +#ifndef NEVER + if (os->verb) { + printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]); + printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]); + printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]); + printf("Gamma = %f %f %f\n",os->v[9], os->v[10], os->v[11]); + } +#endif /* NEVER */ + + /* Do final curves */ + os->isShTRC = 0; + os->isLinear = 0; + os->isGamma = 0; + os->optdim = 9 + 6 + 3 * os->norders; /* Matrix, offset + orders */ + os->v[9] = os->v[10] = os->v[11] = 0.0; /* Input offset */ + os->v[12] = os->v[13] = os->v[14] = 0.0; /* Output offset */ + if (shape0gam) { + os->v[15] = mcgamma[0]; + os->v[16] = mcgamma[1]; + os->v[17] = mcgamma[2]; + } else + os->v[15] = os->v[16] = os->v[17] = 0.0; /* 0th Harmonic */ + for (i = 18; i < os->optdim; i++) + os->v[i] = 0.0; /* Higher orders */ + + /* Set search area to starting values */ + for (j = 0; j < os->optdim; j++) + os->sa[j] = 0.1; /* Matrix, Gamma, Offsets, harmonics */ + + if (os->verb) + printf("Creating matrix and curves...\n"); + + if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits, + mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0) + warning("Powell failed to converge, residual error = %f",rerr); + } } } if (os->clipprims) { /* Clip -ve primaries */ @@ -991,7 +1044,7 @@ double scale /* Scale device values */ printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]); printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]); if (!isLinear) { /* Creating input curves */ - if (isGamma) { /* Creating input curves */ + if (os->isGamma) { /* Creating input curves */ if (isShTRC) printf("Gamma = %f\n",os->v[9]); else @@ -1531,7 +1584,7 @@ double smooth /* Curve smoothing, nominally 1.0 */ } /* If we are going to auto scale the WP to avoid clipping */ - /* values above the WP: (not important for matrix profiles ?) */ + /* values above the WP: (not so important for matrix profiles ?) */ if ((p->flags & ICX_SET_WHITE_US) == ICX_SET_WHITE_US) { double tw[3], bw[3]; icmXYZNumber _wp; @@ -1813,12 +1866,28 @@ double smooth /* Curve smoothing, nominally 1.0 */ /* Matrix values */ { icmXYZArray *wor, *wog, *wob; + double mat[3][3]; wor = pmlu->redColrnt; wog = pmlu->greenColrnt; wob = pmlu->blueColrnt; - wor->data[0].X = os.v[0]; wor->data[0].Y = os.v[3]; wor->data[0].Z = os.v[6]; - wog->data[0].X = os.v[1]; wog->data[0].Y = os.v[4]; wog->data[0].Z = os.v[7]; - wob->data[0].X = os.v[2]; wob->data[0].Y = os.v[5]; wob->data[0].Z = os.v[8]; + + /* Copy to mat[RGB][XYZ] */ + mat[0][0] = os.v[0]; + mat[0][1] = os.v[3]; + mat[0][2] = os.v[6]; + mat[1][0] = os.v[1]; + mat[1][1] = os.v[4]; + mat[1][2] = os.v[7]; + mat[2][0] = os.v[2]; + mat[2][1] = os.v[5]; + mat[2][2] = os.v[8]; + + /* Make sure rounding doesn't wreck white point */ + quantizeRGBprimsS15Fixed16(mat); + + wor->data[0].X = mat[0][0]; wor->data[0].Y = mat[0][1]; wor->data[0].Z = mat[0][2]; + wog->data[0].X = mat[1][0]; wog->data[0].Y = mat[1][1]; wog->data[0].Z = mat[1][2]; + wob->data[0].X = mat[2][0]; wob->data[0].Y = mat[2][1]; wob->data[0].Z = mat[2][2]; /* Load into pmlu matrix and inverse ??? */ } |