Skip to content

Instantly share code, notes, and snippets.

@kevinlekiller
Last active May 26, 2019 11:47
Show Gist options
  • Save kevinlekiller/89c8ba84f6716d52a6b4b4204a42f5f7 to your computer and use it in GitHub Desktop.
Save kevinlekiller/89c8ba84f6716d52a6b4b4204a42f5f7 to your computer and use it in GitHub Desktop.
Patch for https://www.argyllcms.com/ dispcal to add 20 point grayscale RGB calibration (can be used for 10 point also).
--- Argyll_V2.1.1/spectro/dispcal.c 2019-04-29 12:33:26.000000000 -0400
+++ Argyll_V2.1.1_20point/spectro/dispcal.c 2019-05-26 07:40:16.662940045 -0400
@@ -3105,7 +3105,7 @@
int c;
/* Print the menue of adjustments */
- printf("\nPress 1 .. 7\n");
+ printf("\nPress 1 .. 7 or a .. u\n");
printf("1) Black level (CRT: Offset/Brightness)\n");
printf("2) White point (Color temperature, R,G,B, Gain/Contrast)\n");
printf("3) White level (CRT: Gain/Contrast, LCD: Brightness/Backlight)\n");
@@ -3114,6 +3114,10 @@
printf("6) Measure and set ambient for viewing condition adjustment\n");
printf("7) Continue on to calibration\n");
printf("8) Exit\n");
+ printf("a) 0pct Grayscale point (R,G,B)\n");
+ for (int i = 98; i < 118; i++) {
+ printf("%c) %dpct Grayscale point (R,G,B)\n", (char) i, (i - 97) * 5);
+ }
empty_con_chars();
c = next_con_char();
@@ -3804,7 +3808,157 @@
printf("Exiting\n");
dr->del(dr);
exit(0);
- }
+ } else {
+ if (c > 118 || c < 97) {
+ continue;
+ }
+ col tcols[3];
+ double lpoint = (((double) c - 97.0) * 5.0) / 100.0;
+ tcols[0].r = tcols[0].g = tcols[0].b = lpoint;
+ tcols[1].r = tcols[1].g = tcols[1].b = ((1.0 - lpoint) / 2.0) + lpoint;
+ tcols[2].r = tcols[2].g = tcols[2].b = 1.0;
+ int ff;
+ double tYxy[3]; /* Target white chromaticities */
+ icmXYZNumber tXYZ; /* Target white as XYZ */
+ double tLab[3]; /* Target white as Lab or UCS */
+ double mgamma, tar1, dev1;
+ double Lab[3]; /* Last measured point Lab */
+
+ printf("Doing some initial measurements\n");
+
+ if (rgbch == 0) { /* Figure the RGB chromaticities */
+ col ccols[3] = {
+ { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 }
+ };
+ if ((rv = dr->read(dr, ccols, 3, 0, 0, 1, 0, instClamp)) != 0) {
+ dr->del(dr);
+ error("display read failed with '%s'\n",disprd_err(rv));
+ }
+ if (verb) {
+ printf("Red = XYZ %6.3f %6.3f %6.3f\n",ccols[0].XYZ[0],
+ ccols[0].XYZ[1], ccols[0].XYZ[2]);
+ printf("Green = XYZ %6.3f %6.3f %6.3f\n",ccols[1].XYZ[0],
+ ccols[1].XYZ[1], ccols[1].XYZ[2]);
+ printf("Blue = XYZ %6.3f %6.3f %6.3f\n",ccols[2].XYZ[0],
+ ccols[2].XYZ[1], ccols[2].XYZ[2]);
+ }
+ for (i = 0; i < 3; i++)
+ icmAry2Ary(rgbXYZ[i], ccols[i].XYZ);
+ rgbch = 1;
+ }
+ /* Do an initial set of readings to set 1% output mark */
+ if ((rv = dr->read(dr, tcols, 3, 0, 0, 1, 0, instClamp)) != 0) {
+ dr->del(dr);
+ error("display read failed with '%s'\n",disprd_err(rv));
+ }
+ if (verb) {
+ printf("Low = XYZ %6.4f %6.4f %6.4f\n",tcols[0].XYZ[0],
+ tcols[0].XYZ[1], tcols[0].XYZ[2]);
+ printf("Med = XYZ %6.3f %6.3f %6.3f\n",tcols[1].XYZ[0],
+ tcols[1].XYZ[1], tcols[1].XYZ[2]);
+ printf("High = XYZ %6.3f %6.3f %6.3f\n",tcols[2].XYZ[0],
+ tcols[2].XYZ[1], tcols[2].XYZ[2]);
+ }
+
+ /* Advertised Gamma - Gross curve shape */
+ mgamma = pop_gamma(tcols[0].XYZ[1], tcols[1].XYZ[1], tcols[2].XYZ[1]);
+
+ dev1 = pow(lpoint, 1.0/mgamma);
+ tcols[1].r = tcols[1].g = tcols[1].b = dev1;
+
+ /* Figure out the target white chromaticity */
+ if (wpx > 0.0 || wpy > 0.0) { /* xy coordinates */
+ tYxy[0] = 1.0;
+ tYxy[1] = wpx;
+ tYxy[2] = wpy;
+
+ } else if (temp > 0.0) { /* Daylight color temperature */
+ double XYZ[3];
+ if (planckian)
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0);
+ else
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0);
+ if (rv != 0)
+ error("Failed to compute XYZ of target color temperature %f\n",temp);
+ icmXYZ2Yxy(tYxy, XYZ);
+ } else { /* Native white */
+ icmXYZ2Yxy(tYxy, tcols[2].XYZ);
+ }
+
+ printf("\nAdjust R,G & B offsets to get target x,y. Press space when done.\n");
+ printf(" Target x %.4f , y %.4f \n", tYxy[1],tYxy[2]);
+ for (ff = 0;; ff ^= 1) {
+ double Yxy[3]; /* Yxy of current reading */
+ double rgbdir[3]; /* Direction to adjust RGB */
+ double rgbxdir[3]; /* Biggest to move */
+ double bdir, terr;
+ int bx = 0;
+
+ if ((rv = dr->read(dr, tcols, 1, 0, 0, 1, ' ', instClamp)) != 0) {
+ if (rv == 4)
+ break; /* User is done with this adjustment */
+ dr->del(dr);
+ error("display read failed with '%s'\n",disprd_err(rv));
+ }
+
+
+ /* Compute numbers for black point error and direction */
+ icmYxy2XYZ(tLab, tYxy);
+ tLab[0] /= tLab[1];
+ tLab[2] /= tLab[1];
+ tLab[1] /= tLab[1];
+ icmAry2XYZ(tXYZ, tLab); /* Lab white reference */
+ icmXYZ2Lab(&tXYZ, tLab, tLab);
+
+ icmXYZ2Yxy(Yxy, tcols[1].XYZ);
+ icmAry2Ary(Lab, tcols[1].XYZ);
+ Lab[0] /= Lab[1];
+ Lab[2] /= Lab[1];
+ Lab[1] /= Lab[1];
+ icmXYZ2Lab(&tXYZ, Lab, Lab);
+
+ /* Compute dot products */
+ bdir = 0.0;
+ for (i = 0; i < 3; i++) {
+ double rgbLab[3];
+
+ icmXYZ2Lab(&tXYZ, rgbLab, rgbXYZ[i]);
+ rgbdir[i] = (tLab[1] - Lab[1]) * (rgbLab[1] - Lab[1])
+ + (tLab[2] - Lab[2]) * (rgbLab[2] - Lab[2]);
+ rgbxdir[i] = 0.0;
+ if (fabs(rgbdir[i]) > fabs(bdir)) {
+ bdir = rgbdir[i];
+ bx = i;
+ }
+ }
+
+ /* See how close to the target we are */
+ terr = sqrt((tLab[1] - Lab[1]) * (tLab[1] - Lab[1])
+ + (tLab[2] - Lab[2]) * (tLab[2] - Lab[2]));
+ if (terr < 0.1)
+ rgbdir[0] = rgbdir[1] = rgbdir[2] = 0.0;
+ rgbxdir[bx] = rgbdir[bx];
+
+ printf("%c%c Current x %.4f%c, y %.4f%c DE %4.1f R%c%c G%c%c B%c%c ",
+ cr_char,
+ ff == 0 ? '/' : '\\',
+ Yxy[1],
+ Yxy[1] > tYxy[1] ? '-': Yxy[1] < tYxy[1] ? '+' : '=',
+ Yxy[2],
+ Yxy[2] > tYxy[2] ? '-': Yxy[2] < tYxy[2] ? '+' : '=',
+ icmCIE2K(tLab, Lab),
+ rgbdir[0] < 0.0 ? '-' : rgbdir[0] > 0.0 ? '+' : '=',
+ rgbxdir[0] < 0.0 ? '-' : rgbxdir[0] > 0.0 ? '+' : ' ',
+ rgbdir[1] < 0.0 ? '-' : rgbdir[1] > 0.0 ? '+' : '=',
+ rgbxdir[1] < 0.0 ? '-' : rgbxdir[1] > 0.0 ? '+' : ' ',
+ rgbdir[2] < 0.0 ? '-' : rgbdir[2] > 0.0 ? '+' : '=',
+ rgbxdir[2] < 0.0 ? '-' : rgbxdir[2] > 0.0 ? '+' : ' ');
+ fflush(stdout);
+ }
+ printf("\n");
+ }
}
/* Make sure drift comp. is set to the command line options */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment