diff options
Diffstat (limited to 'generator/ppmcie.c')
-rw-r--r-- | generator/ppmcie.c | 351 |
1 files changed, 234 insertions, 117 deletions
diff --git a/generator/ppmcie.c b/generator/ppmcie.c index fda0ab7c..717ed13b 100644 --- a/generator/ppmcie.c +++ b/generator/ppmcie.c @@ -26,6 +26,7 @@ Introduced option to plot 1976 u' v' chromaticities. */ +#include <assert.h> #include <math.h> #include "pm_c_util.h" @@ -34,10 +35,8 @@ #include "nstring.h" #define CLAMP(v, l, h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v)) -#define TRUE 1 -#define FALSE 0 -#define Maxval 255 /* Maxval to use in generated pixmaps */ +pixval const cieMaxval = 255; /* Maxval to use in generated pixmaps */ /* A color system is defined by the CIE x and y coordinates of its three primary illuminants and the x and y coordinates of the white @@ -462,8 +461,18 @@ gamma_correct_rgb(const struct colorSystem * const cs, -#define Sz(x) (((x) * MIN(pixcols, pixrows)) / 512) +/* Sz(X) is the displacement in pixels of a displacement of X normalized + distance units. (A normalized distance unit is 1/512 of the smaller + dimension of the canvas) +*/ +#define Sz(x) (((x) * (int)MIN(pixcols, pixrows)) / 512) + +/* B(X, Y) is a pair of function arguments (for a libppmd function) that + give a pixel position on the canvas. That position is (X, Y), biased + horizontally 'xBias' pixels. +*/ #define B(x, y) ((x) + xBias), (y) + #define Bixels(y, x) pixels[y][x + xBias] @@ -511,12 +520,12 @@ makeAllBlack(pixel ** const pixels, static void drawTongueOutline(pixel ** const pixels, - int const pixcols, - int const pixrows, - pixval const maxval, - bool const upvp, - int const xBias, - int const yBias) { + int const pixcols, + int const pixrows, + pixval const maxval, + bool const upvp, + int const xBias, + int const yBias) { int const pxcols = pixcols - xBias; int const pxrows = pixrows - yBias; @@ -535,7 +544,7 @@ drawTongueOutline(pixel ** const pixels, &icx, &icy); if (wavelength > 380) - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly), B(icx, icy), PPMD_NULLDRAWPROC, (char *) &rgbcolor); else { @@ -574,12 +583,12 @@ findTongue(pixel ** const pixels, ++i); if (i >= pxcols) - *presentP = FALSE; + *presentP = false; else { int j; int const leftEdge = i; - *presentP = TRUE; + *presentP = true; for (j = pxcols - 1; j >= leftEdge && PPM_GETR(Bixels(row, j)) == 0; @@ -641,16 +650,16 @@ fillInTongue(pixel ** const pixels, xyz_to_rgb(cs, cx, cy, cz, &jr, &jg, &jb); - mx = Maxval; + mx = maxval; /* Check whether the requested color is within the gamut achievable with the given color system. If not, draw it in a reduced intensity, interpolated by desaturation to the closest within-gamut color. */ - if (constrain_rgb(&jr, &jg, &jb)) { - mx = highlightGamut ? Maxval : ((Maxval + 1) * 3) / 4; - } + if (constrain_rgb(&jr, &jg, &jb)) + mx = highlightGamut ? maxval : ((maxval + 1) * 3) / 4; + /* Scale to max(rgb) = 1. */ jmax = MAX(jr, MAX(jg, jb)); if (jmax > 0) { @@ -672,67 +681,175 @@ fillInTongue(pixel ** const pixels, static void -drawAxes(pixel ** const pixels, - int const pixcols, - int const pixrows, - pixval const maxval, - bool const upvp, - int const xBias, - int const yBias) { +drawYAxis(pixel ** const pixels, + unsigned int const pixcols, + unsigned int const pixrows, + pixval const maxval, + unsigned int const xBias, + unsigned int const yBias, + pixel const axisColor) { + + unsigned int const pxrows = pixrows - yBias; - int const pxcols = pixcols - xBias; - int const pxrows = pixrows - yBias; - - pixel rgbcolor; /* Color of axes */ - int i; - - PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); ppmd_line(pixels, pixcols, pixrows, maxval, B(0, 0), B(0, pxrows - 1), PPMD_NULLDRAWPROC, - (char *) &rgbcolor); + (char *) &axisColor); +} + + + +static void +drawXAxis(pixel ** const pixels, + unsigned int const pixcols, + unsigned int const pixrows, + pixval const maxval, + unsigned int const xBias, + unsigned int const yBias, + pixel const axisColor) { + + unsigned int const pxcols = pixcols - xBias; + unsigned int const pxrows = pixrows - yBias; + ppmd_line(pixels, pixcols, pixrows, maxval, B(0, pxrows - 1), B(pxcols - 1, pxrows - 1), - PPMD_NULLDRAWPROC, (char *) &rgbcolor); - - /* Draw tick marks on X and Y axes every 0.1 units. Also - label axes. - */ + PPMD_NULLDRAWPROC, (char *) &axisColor); +} + + + +static void +tickX(pixel ** const pixels, + unsigned int const pixcols, + unsigned int const pixrows, + pixval const maxval, + unsigned int const xBias, + unsigned int const yBias, + pixel const axisColor, + unsigned int const tenth) { +/*---------------------------------------------------------------------------- + Put a tick mark 'tenth' tenths of the way along the X axis + and label it. + + 'pixels' is the canvas on which to draw it; its dimensions are + 'pixcols' by 'pixrows' and has maxval 'maxval'. +-----------------------------------------------------------------------------*/ + unsigned int const pxcols = pixcols - xBias; + unsigned int const pxrows = pixrows - yBias; + unsigned int const tickCol = (tenth * (pxcols - 1)) / 10; + /* Pixel column where the left edge of the tick goes */ + unsigned int const tickThickness = Sz(3); + /* Thickness of the tick in pixels */ + unsigned int const tickBottom = pxrows - Sz(1); + /* Pixel row of the bottom of the tick */ + + char s[20]; + + assert(tenth < 10); + + sprintf(s, "0.%u", tenth); + ppmd_line(pixels, pixcols, pixrows, maxval, + B(tickCol, tickBottom), + B(tickCol, tickBottom - tickThickness), + PPMD_NULLDRAWPROC, (char *) &axisColor); + ppmd_text(pixels, pixcols, pixrows, maxval, + B(tickCol - Sz(11), pxrows + Sz(12)), + Sz(10), 0, s, PPMD_NULLDRAWPROC, (char *) &axisColor); +} + + + +static void +tickY(pixel ** const pixels, + unsigned int const pixcols, + unsigned int const pixrows, + pixval const maxval, + unsigned int const xBias, + unsigned int const yBias, + pixel const axisColor, + unsigned int const tenth) { +/*---------------------------------------------------------------------------- + Put a tick mark 'tenth' tenths of the way along the Y axis and label it. + + 'pixels' is the canvas on which to draw it; its dimensions are + 'pixcols' by 'pixrows' and has maxval 'maxval'. +-----------------------------------------------------------------------------*/ + unsigned int const pxrows = pixrows - yBias; + unsigned int const tickRow = (tenth * (pxrows - 1)) / 10; + /* Pixel row where the top of the tick goes */ + unsigned int const tickThickness = Sz(3); + /* Thickness of the tick in pixels */ - for (i = 1; i <= 9; i += 1) { - char s[20]; - - /* X axis tick */ - - sprintf(s, "0.%d", i); - ppmd_line(pixels, pixcols, pixrows, maxval, - B((i * (pxcols - 1)) / 10, pxrows - Sz(1)), - B((i * (pxcols - 1)) / 10, pxrows - Sz(4)), - PPMD_NULLDRAWPROC, (char *) &rgbcolor); - ppmd_text(pixels, pixcols, pixrows, maxval, - B((i * (pxcols - 1)) / 10 - Sz(11), pxrows + Sz(12)), - Sz(10), 0, s, PPMD_NULLDRAWPROC, (char *) &rgbcolor); - - /* Y axis tick */ - - sprintf(s, "0.%d", 10 - i); - ppmd_line(pixels, pixcols, pixrows, maxval, - B(0, (i * (pxrows - 1)) / 10), - B(Sz(3), (i * (pxrows - 1)) / 10), - PPMD_NULLDRAWPROC, (char *) &rgbcolor); - - ppmd_text(pixels, pixcols, pixrows, maxval, - B(Sz(-30), (i * (pxrows - 1)) / 10 + Sz(5)), - Sz(10), 0, s, - PPMD_NULLDRAWPROC, (char *) &rgbcolor); - } + char s[20]; + + assert(tenth < 10); + + sprintf(s, "0.%d", 10 - tenth); + ppmd_line(pixels, pixcols, pixrows, maxval, + B(0, tickRow), B(tickThickness, tickRow), + PPMD_NULLDRAWPROC, (char *) &axisColor); + + ppmd_text(pixels, pixcols, pixrows, maxval, + B(Sz(-30), tickRow + Sz(5)), + Sz(10), 0, s, + PPMD_NULLDRAWPROC, (char *) &axisColor); +} + + + +static void +labelAxes(pixel ** const pixels, + unsigned int const pixcols, + unsigned int const pixrows, + pixval const maxval, + unsigned int const xBias, + unsigned int const yBias, + pixel const axisColor, + bool const upvp) { +/*---------------------------------------------------------------------------- + Label the axes "x" and "y" or "u" and "v". +-----------------------------------------------------------------------------*/ + unsigned int const pxcols = pixcols - xBias; + unsigned int const pxrows = pixrows - yBias; + ppmd_text(pixels, pixcols, pixrows, maxval, B((98 * (pxcols - 1)) / 100 - Sz(11), pxrows + Sz(12)), Sz(10), 0, (upvp ? "u'" : "x"), - PPMD_NULLDRAWPROC, (char *) &rgbcolor); + PPMD_NULLDRAWPROC, (char *) &axisColor); ppmd_text(pixels, pixcols, pixrows, maxval, B(Sz(-22), (2 * (pxrows - 1)) / 100 + Sz(5)), Sz(10), 0, (upvp ? "v'" : "y"), - PPMD_NULLDRAWPROC, (char *) &rgbcolor); + PPMD_NULLDRAWPROC, (char *) &axisColor); +} + + + +static void +drawAxes(pixel ** const pixels, + unsigned int const pixcols, + unsigned int const pixrows, + pixval const maxval, + bool const upvp, + unsigned int const xBias, + unsigned int const yBias) { +/*---------------------------------------------------------------------------- + Draw the axes, with tick marks every .1 units and labels. +-----------------------------------------------------------------------------*/ + pixel axisColor; /* Color of axes and labels */ + unsigned int i; + + PPM_ASSIGN(axisColor, maxval, maxval, maxval); + + drawYAxis(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor); + drawXAxis(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor); + + for (i = 1; i <= 9; i += 1) { + tickX(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor, i); + + tickY(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor, i); + } + + labelAxes(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor, + upvp); } @@ -840,14 +957,14 @@ plotBlackBodyCurve(pixel ** const pixels, } if (t > 1000) { - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly), B(xb, yb), PPMD_NULLDRAWPROC, (char *) &rgbcolor); /* Draw tick mark every 1000 kelvins */ if ((((int) t) % 1000) == 0) { - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly - Sz(2)), B(lx, ly + Sz(2)), PPMD_NULLDRAWPROC, (char *) &rgbcolor); @@ -859,7 +976,7 @@ plotBlackBodyCurve(pixel ** const pixels, char bb[20]; sprintf(bb, "%g", t); - ppmd_text(pixels, pixcols, pixrows, Maxval, + ppmd_text(pixels, pixcols, pixrows, maxval, B(lx - Sz(12), ly - Sz(4)), Sz(6), 0, bb, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } @@ -938,7 +1055,7 @@ plotMonochromeWavelengths( PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); tx = icx + ((x < 520) ? Sz(-2) : ((x >= 535) ? Sz(2) : 0)); ty = icy + ((x < 520) ? 0 : ((x >= 535) ? Sz(-1) : Sz(-2))); - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(icx, icy), B(tx, ty), PPMD_NULLDRAWPROC, (char *) &rgbcolor); @@ -970,13 +1087,13 @@ plotMonochromeWavelengths( } /* gamma correct from linear rgb to nonlinear rgb. */ gamma_correct_rgb(cs, &jr, &jg, &jb); - r = Maxval * jr; - g = Maxval * jg; - b = Maxval * jb; + r = maxval * jr; + g = maxval * jg; + b = maxval * jb; PPM_ASSIGN(rgbcolor, (pixval) r, (pixval) g, (pixval) b); sprintf(wl, "%d", x); - ppmd_text(pixels, pixcols, pixrows, Maxval, + ppmd_text(pixels, pixcols, pixrows, maxval, B(icx + bx, icy + by), Sz(6), 0, wl, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } @@ -997,18 +1114,18 @@ writeLabel(pixel ** const pixels, PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); - snprintfN(sysdesc, sizeof(sysdesc), - "System: %s\n" - "Primary illuminants (X, Y)\n" - " Red: %0.4f, %0.4f\n" - " Green: %0.4f, %0.4f\n" - " Blue: %0.4f, %0.4f\n" - "White point (X, Y): %0.4f, %0.4f", - cs->name, cs->xRed, cs->yRed, cs->xGreen, cs->yGreen, - cs->xBlue, cs->yBlue, cs->xWhite, cs->yWhite); + pm_snprintf(sysdesc, sizeof(sysdesc), + "System: %s\n" + "Primary illuminants (X, Y)\n" + " Red: %0.4f, %0.4f\n" + " Green: %0.4f, %0.4f\n" + " Blue: %0.4f, %0.4f\n" + "White point (X, Y): %0.4f, %0.4f", + cs->name, cs->xRed, cs->yRed, cs->xGreen, cs->yGreen, + cs->xBlue, cs->yBlue, cs->xWhite, cs->yWhite); sysdesc[sizeof(sysdesc)-1] = '\0'; /* for robustness */ - ppmd_text(pixels, pixcols, pixrows, Maxval, + ppmd_text(pixels, pixcols, pixrows, maxval, pixcols / 3, Sz(24), Sz(12), 0, sysdesc, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } @@ -1016,8 +1133,8 @@ writeLabel(pixel ** const pixels, int -main(int argc, - char * argv[]) { +main(int argc, + const char * argv[]) { int argn; const char * const usage = "[-[no]black] [-[no]wpoint] [-[no]label] [-no[axes]] [-full]\n\ @@ -1027,24 +1144,24 @@ main(int argc, [-size <s>] [-xsize|-width <x>] [-ysize|-height <y>]"; const struct colorSystem *cs; - int widspec = FALSE, hgtspec = FALSE; - int xBias, yBias; - int upvp = FALSE; /* xy or u'v' color coordinates? */ - int showWhite = TRUE; /* Show white point ? */ - int showBlack = TRUE; /* Show black body curve ? */ - int fullChart = FALSE; /* Fill entire tongue ? */ - int showLabel = TRUE; /* Show labels ? */ - int showAxes = TRUE; /* Plot axes ? */ + bool widspec = false, hgtspec = false; + unsigned int xBias, yBias; + bool upvp = false; /* xy or u'v' color coordinates? */ + bool showWhite = true; /* Show white point ? */ + bool showBlack = true; /* Show black body curve ? */ + bool fullChart = false; /* Fill entire tongue ? */ + bool showLabel = true; /* Show labels ? */ + bool showAxes = true; /* Plot axes ? */ - ppm_init(&argc, argv); + pm_proginit(&argc, argv); argn = 1; cs = &Rec709system; /* default */ while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { if (pm_keymatch(argv[argn], "-xy", 2)) { - upvp = FALSE; + upvp = false; } else if (pm_keymatch(argv[argn], "-upvp", 1)) { - upvp = TRUE; + upvp = true; } else if (pm_keymatch(argv[argn], "-xsize", 1) || pm_keymatch(argv[argn], "-width", 2)) { if (widspec) { @@ -1053,7 +1170,7 @@ main(int argc, argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1)) pm_usage(usage); - widspec = TRUE; + widspec = true; } else if (pm_keymatch(argv[argn], "-ysize", 1) || pm_keymatch(argv[argn], "-height", 2)) { if (hgtspec) { @@ -1062,7 +1179,7 @@ main(int argc, argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) pm_usage(usage); - hgtspec = TRUE; + hgtspec = true; } else if (pm_keymatch(argv[argn], "-size", 2)) { if (hgtspec || widspec) { pm_error("already specified a size/height/ysize"); @@ -1071,7 +1188,7 @@ main(int argc, if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) pm_usage(usage); sxsize = sysize; - hgtspec = widspec = TRUE; + hgtspec = widspec = true; } else if (pm_keymatch(argv[argn], "-rec709", 1)) { cs = &Rec709system; } else if (pm_keymatch(argv[argn], "-ntsc", 1)) { @@ -1085,23 +1202,23 @@ main(int argc, } else if (pm_keymatch(argv[argn], "-cie", 1)) { cs = &CIEsystem; } else if (pm_keymatch(argv[argn], "-black", 3)) { - showBlack = TRUE; /* Show black body curve */ + showBlack = true; /* Show black body curve */ } else if (pm_keymatch(argv[argn], "-wpoint", 2)) { - showWhite = TRUE; /* Show white point of color system */ + showWhite = true; /* Show white point of color system */ } else if (pm_keymatch(argv[argn], "-noblack", 3)) { - showBlack = FALSE; /* Don't show black body curve */ + showBlack = false; /* Don't show black body curve */ } else if (pm_keymatch(argv[argn], "-nowpoint", 3)) { - showWhite = FALSE; /* Don't show white point of system */ + showWhite = false; /* Don't show white point of system */ } else if (pm_keymatch(argv[argn], "-label", 1)) { - showLabel = TRUE; /* Show labels. */ + showLabel = true; /* Show labels. */ } else if (pm_keymatch(argv[argn], "-nolabel", 3)) { - showLabel = FALSE; /* Don't show labels */ + showLabel = false; /* Don't show labels */ } else if (pm_keymatch(argv[argn], "-axes", 1)) { - showAxes = TRUE; /* Show axes. */ + showAxes = true; /* Show axes. */ } else if (pm_keymatch(argv[argn], "-noaxes", 3)) { - showAxes = FALSE; /* Don't show axes */ + showAxes = false; /* Don't show axes */ } else if (pm_keymatch(argv[argn], "-full", 1)) { - fullChart = TRUE; /* Fill whole tongue full-intensity */ + fullChart = true; /* Fill whole tongue full-intensity */ } else if (pm_keymatch(argv[argn], "-gamma", 2)) { cs = &Customsystem; argn++; @@ -1170,32 +1287,32 @@ main(int argc, makeAllBlack(pixels, pixcols, pixrows); - drawTongueOutline(pixels, pixcols, pixrows, Maxval, upvp, xBias, yBias); + drawTongueOutline(pixels, pixcols, pixrows, cieMaxval, upvp, xBias, yBias); - fillInTongue(pixels, pixcols, pixrows, Maxval, cs, upvp, xBias, yBias, + fillInTongue(pixels, pixcols, pixrows, cieMaxval, cs, upvp, xBias, yBias, fullChart); if (showAxes) - drawAxes(pixels, pixcols, pixrows, Maxval, upvp, xBias, yBias); + drawAxes(pixels, pixcols, pixrows, cieMaxval, upvp, xBias, yBias); if (showWhite) - plotWhitePoint(pixels, pixcols, pixrows, Maxval, + plotWhitePoint(pixels, pixcols, pixrows, cieMaxval, cs, upvp, xBias, yBias); if (showBlack) - plotBlackBodyCurve(pixels, pixcols, pixrows, Maxval, + plotBlackBodyCurve(pixels, pixcols, pixrows, cieMaxval, upvp, xBias, yBias); /* Plot wavelengths around periphery of the tongue. */ if (showAxes) - plotMonochromeWavelengths(pixels, pixcols, pixrows, Maxval, + plotMonochromeWavelengths(pixels, pixcols, pixrows, cieMaxval, cs, upvp, xBias, yBias); if (showLabel) - writeLabel(pixels, pixcols, pixrows, Maxval, cs); + writeLabel(pixels, pixcols, pixrows, cieMaxval, cs); - ppm_writeppm(stdout, pixels, pixcols, pixrows, Maxval, FALSE); + ppm_writeppm(stdout, pixels, pixcols, pixrows, cieMaxval, 0); return 0; } |