static void plotWhitePoint(pixel ** const pixels, int const pixcols, int const pixrows, pixval const maxval, const struct colorSystem * const cs, bool const upvp, int const xBias, int const yBias) { int const pxcols = pixcols - xBias; int const pxrows = pixrows - yBias; int wx, wy; pixel rgbcolor; /* Color of the white point mark */ PPM_ASSIGN(rgbcolor, 0, 0, 0); if (upvp) { double wup, wvp; xy_to_upvp(cs->xWhite, cs->yWhite, &wup, &wvp); wx = wup; wy = wvp; wx = (pxcols - 1) * wup; wy = (pxrows - 1) - ((int) ((pxrows - 1) * wvp)); } else { wx = (pxcols - 1) * cs->xWhite; wy = (pxrows - 1) - ((int) ((pxrows - 1) * cs->yWhite)); } PPM_ASSIGN(rgbcolor, 0, 0, 0); /* We draw the four arms of the cross separately so as to leave the pixel representing the precise white point undisturbed. */ ppmd_line(pixels, pixcols, pixrows, maxval, B(wx + Sz(3), wy), B(wx + Sz(10), wy), PPMD_NULLDRAWPROC, (char *) &rgbcolor); ppmd_line(pixels, pixcols, pixrows, maxval, B(wx - Sz(3), wy), B(wx - Sz(10), wy), PPMD_NULLDRAWPROC, (char *) &rgbcolor); ppmd_line(pixels, pixcols, pixrows, maxval, B(wx, wy + Sz(3)), B(wx, wy + Sz(10)), PPMD_NULLDRAWPROC, (char *) &rgbcolor); ppmd_line(pixels, pixcols, pixrows, maxval, B(wx, wy - Sz(3)), B(wx, wy - Sz(10)), PPMD_NULLDRAWPROC, (char *) &rgbcolor); }
static void moveBlackToIndex0(colorhist_vector const chv, int const colors) { /*---------------------------------------------------------------------------- If black is in the palette, make it at Index 0. -----------------------------------------------------------------------------*/ pixel blackPixel; unsigned int i; bool blackPresent; PPM_ASSIGN(blackPixel, 0, 0, 0); blackPresent = FALSE; /* initial assumption */ for (i = 0; i < colors; ++i) if (PPM_EQUAL(chv[i].color, blackPixel)) blackPresent = TRUE; if (blackPresent) { /* We use a trick here. ppm_addtocolorhist() always adds to the beginning of the table and if the color is already elsewhere in the table, removes it. */ int colors2; colors2 = colors; ppm_addtocolorhist(chv, &colors2, MAXCOLORS, &blackPixel, 0, 0); assert(colors2 == colors); } }
static void generateStandardPalette(struct pcxCmapEntry ** const pcxcmapP, pixval const maxval, colorhash_table * const chtP, int * const colorsP) { unsigned int const stdPaletteSize = 16; unsigned int colorIndex; struct pcxCmapEntry * pcxcmap; colorhash_table cht; MALLOCARRAY_NOFAIL(pcxcmap, MAXCOLORS); *pcxcmapP = pcxcmap; cht = ppm_alloccolorhash(); for (colorIndex = 0; colorIndex < stdPaletteSize; ++colorIndex) { pixel pcxColor; /* The color of this colormap entry, in PCX resolution */ pcxcmap[colorIndex] = stdPalette[colorIndex]; PPM_ASSIGN(pcxColor, stdPalette[colorIndex].r, stdPalette[colorIndex].g, stdPalette[colorIndex].b); putPcxColorInHash(cht, pcxColor, colorIndex, maxval); } *chtP = cht; *colorsP = stdPaletteSize; }
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); }
static void processColorfileEntry(struct colorfile_entry const ce, colorhash_table const cht, const char ** const colornames, pixel * const colors, unsigned int * const colornameIndexP) { if (*colornameIndexP >= MAXCOLORNAMES) pm_error("Too many colors in colorname dictionary. " "Max allowed is %u", MAXCOLORNAMES); else { pixel color; PPM_ASSIGN(color, ce.r, ce.g, ce.b); if (ppm_lookupcolor(cht, &color) >= 0) { /* The color is already in the hash, which means we saw it earlier in the file. We prefer the first name that the file gives for each color, so we just ignore the current entry. */ } else { ppm_addtocolorhash(cht, &color, *colornameIndexP); colornames[*colornameIndexP] = strdup(ce.colorname); colors[*colornameIndexP] = color; if (colornames[*colornameIndexP] == NULL) pm_error("Unable to allocate space for color name"); ++(*colornameIndexP); } } }
static void copy_pixel_row(const JSAMPROW jpegbuffer, const int width, const unsigned int samples_per_pixel, const enum colorspace color_space, const unsigned int maxval, FILE * const output_file, const int output_type) { JSAMPLE *ptr; unsigned int output_cursor; /* Cursor into output buffer 'pnmbuffer' */ ptr = jpegbuffer; /* Start at beginning of input row */ for (output_cursor = 0; output_cursor < width; output_cursor++) { xel current_pixel; if (samples_per_pixel >= 3) { const rgb_type * const rgb_p = read_rgb(ptr, color_space, maxval); PPM_ASSIGN(current_pixel, rgb_p->r, rgb_p->g, rgb_p->b); } else { PNM_ASSIGN1(current_pixel, GETJSAMPLE(*ptr)); } ptr += samples_per_pixel; /* move to next pixel of input */ pnmbuffer[output_cursor] = current_pixel; } pnm_writepnmrow(output_file, pnmbuffer, width, maxval, output_type, FALSE); }
static void readPalettes(FILE * const ifP, Pal * const palP) { unsigned int row; /* Clear the first palette line. */ { unsigned int j; for (j = 0; j < 48; ++j) PPM_ASSIGN(palP->pal[0][j], 0, 0, 0); } /* Read the palettes. */ for (row = 1; row < ROWS; ++row) { unsigned int j; for (j = 0; j < 48; ++j) { short k; pm_readbigshort(ifP, &k); PPM_ASSIGN(palP->pal[row][j], (k & 0x700) >> 8, (k & 0x070) >> 4, (k & 0x007) >> 0); } } }
static void makeNewXel(xel * const outputXelP, xel const curXel, xel const prevXel, double const fracnew0, double const omfracnew0, int const format) { /*---------------------------------------------------------------------------- Create an output xel as *outputXel, which is part curXel and part prevXel, the part given by the fractions omfracnew0 and fracnew0, respectively. These fraction values are the numerator of a fraction whose denominator is SCALE. The format of the pixel is 'format'. -----------------------------------------------------------------------------*/ switch ( PNM_FORMAT_TYPE(format) ) { case PPM_TYPE: PPM_ASSIGN( *outputXelP, ( fracnew0 * PPM_GETR(prevXel) + omfracnew0 * PPM_GETR(curXel) + HALFSCALE ) / SCALE, ( fracnew0 * PPM_GETG(prevXel) + omfracnew0 * PPM_GETG(curXel) + HALFSCALE ) / SCALE, ( fracnew0 * PPM_GETB(prevXel) + omfracnew0 * PPM_GETB(curXel) + HALFSCALE ) / SCALE ); break; default: PNM_ASSIGN1( *outputXelP, ( fracnew0 * PNM_GET1(prevXel) + omfracnew0 * PNM_GET1(curXel) + HALFSCALE ) / SCALE ); break; } }
static void copyPixelRow(JSAMPROW const jpegbuffer, unsigned int const width, unsigned int const samplesPerPixel, enum colorspace const colorSpace, FILE * const ofP, int const format, xelval const maxval) { JSAMPLE * ptr; unsigned int outputCursor; /* Cursor into output buffer 'pnmbuffer' */ ptr = &jpegbuffer[0]; /* Start at beginning of input row */ for (outputCursor = 0; outputCursor < width; ++outputCursor) { xel currentPixel; if (samplesPerPixel >= 3) { const rgb_type * const rgb_p = read_rgb(ptr, colorSpace, maxval); PPM_ASSIGN(currentPixel, rgb_p->r, rgb_p->g, rgb_p->b); } else { PNM_ASSIGN1(currentPixel, GETJSAMPLE(*ptr)); } ptr += samplesPerPixel; /* move to next pixel of input */ pnmbuffer[outputCursor] = currentPixel; } pnm_writepnmrow(ofP, pnmbuffer, width, maxval, format, FALSE); }
static void ppm_writefile(uint8_t *prgb, int width, int height, int num) { pixel *pixelrow; int i, x, y; pixelrow = ppm_allocrow(width); for (i = 0; i < num; i++) { char filename[16]; FILE *fp; sprintf(filename, PPM_FILENAME, i); fp = fopen(filename, "w"); ppm_writeppminit(fp, width, height, (pixval)255, 0); for (y = 0; y < height; y++) { for (x = 0; x < width; x++, prgb += 3) PPM_ASSIGN(pixelrow[x], prgb[0], prgb[1], prgb[2]); ppm_writeppmrow(fp, pixelrow, width, (pixval)255, 0); } fclose(fp); } ppm_freerow(pixelrow); }
static void parseOldX11Dec(const char colorname[], pixval const maxval, bool const closeOk, pixel * const colorP) { float const epsilon = 1.0/65536.0; float fr, fg, fb; pixval rNorm, gNorm, bNorm; if (sscanf(colorname, "%f,%f,%f", &fr, &fg, &fb) != 3) pm_error("invalid color specifier '%s'", colorname); if (fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0) pm_error("invalid color specifier '%s' - " "values must be between 0.0 and 1.0", colorname ); rNorm = fr * maxval + 0.5; gNorm = fg * maxval + 0.5; bNorm = fb * maxval + 0.5; if (!closeOk) { if (fabs((float)rNorm/maxval - fr) > epsilon || fabs((float)gNorm/maxval - fg) > epsilon || fabs((float)bNorm/maxval - fb) > epsilon) pm_message("WARNING: Color '%s' cannot be represented " "precisely with maxval %u. " "Approximating as (%u,%u,%u).", colorname, maxval, rNorm, gNorm, bNorm); } PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm); }
static void writeLabel(pixel ** const pixels, int const pixcols, int const pixrows, pixval const maxval, const struct colorSystem * const cs) { pixel rgbcolor; /* color of text */ char sysdesc[256]; 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); sysdesc[sizeof(sysdesc)-1] = '\0'; /* for robustness */ ppmd_text(pixels, pixcols, pixrows, Maxval, pixcols / 3, Sz(24), Sz(12), 0, sysdesc, PPMD_NULLDRAWPROC, (char *) &rgbcolor); }
static void initDrawState(struct drawState * const drawStateP, pixval const maxval) { drawStateP->currentPos.x = 0; drawStateP->currentPos.y = 0; PPM_ASSIGN(drawStateP->color, maxval, maxval, maxval); }
void region_contour2ppm(pixel **pixels, int cols, int n_contour, contour_point_t *contour, int value) { int i; if (!pixels || !contour) return; for (i=0; i < n_contour; i++) { int index = cols * contour[i].y + contour[i].x; PPM_ASSIGN(pixels[contour[i].y][contour[i].x],value,value,value); } }
static void makeAllBlack(pixel ** const pixels, unsigned int const cols, unsigned int const rows) { unsigned int row; for (row = 0; row < rows; ++row) { unsigned int col; for (col = 0; col < cols; ++col) PPM_ASSIGN(pixels[row][col], 0, 0, 0); } }
static pixel random_camo_color(pixval const maxval) { int v1, v2, v3; pixel p; v1 = (maxval + 1 ) / 8; v2 = (maxval + 1 ) / 4; v3 = (maxval + 1 ) / 2; switch (rand() % 10) { case 0: case 1: case 2: /* light brown */ PPM_ASSIGN(p, rand() % v3 + v3, rand() % v3 + v2, rand() % v3 + v2); break; case 3: case 4: case 5: /* dark green */ PPM_ASSIGN(p, rand() % v2, rand() % v2 + 3 * v1, rand() % v2); break; case 6: case 7: /* brown */ PPM_ASSIGN(p, rand() % v2 + v2, rand() % v2, rand() % v2); break; case 8: case 9: /* dark brown */ PPM_ASSIGN(p, rand() % v1 + v1, rand() % v1, rand() % v1); break; } return p; }
static void putPcxColorInHash(colorhash_table const cht, pixel const newPcxColor, unsigned int const newColorIndex, pixval const maxval) { pixel ppmColor; /* Same color as 'newPcxColor', but at the PPM image's color resolution: 'maxval' */ int rc; PPM_DEPTH(ppmColor, newPcxColor, PCX_MAXVAL, maxval); rc = ppm_lookupcolor(cht, &ppmColor); if (rc == -1) /* This color is not in the hash yet, so we just add it */ ppm_addtocolorhash(cht, &ppmColor, newColorIndex); else { /* This color is already in the hash. That's because the subject image has less color resolution than PCX (i.e. 'maxval' is less than PCX_MAXVAL), and two distinct colors in the standard palette are indistinguishable at subject image color resolution. So we have to figure out wether color 'newPcxColor' or 'existingPcxColor' is a better match for 'ppmColor'. */ unsigned int const existingColorIndex = rc; pixel idealPcxColor; pixel existingPcxColor; PPM_DEPTH(idealPcxColor, ppmColor, maxval, PCX_MAXVAL); PPM_ASSIGN(existingPcxColor, stdPalette[existingColorIndex].r, stdPalette[existingColorIndex].g, stdPalette[existingColorIndex].b); if (PPM_DISTANCE(newPcxColor, idealPcxColor) < PPM_DISTANCE(existingPcxColor, idealPcxColor)) { /* The new PCX color is a better match. Make it the new translation of image color 'ppmColor'. */ ppm_delfromcolorhash(cht, &ppmColor); ppm_addtocolorhash(cht, &ppmColor, newColorIndex); } } }
static void out_splines(FILE * const fileP, spline_list_array_type const shape, unsigned int const height) { unsigned listSeq; pixel lastColor; PPM_ASSIGN(lastColor, 0, 0, 0); for (listSeq = 0; listSeq < SPLINE_LIST_ARRAY_LENGTH(shape); ++listSeq) { spline_list_type const splineList = SPLINE_LIST_ARRAY_ELT(shape, listSeq); spline_type const first = SPLINE_LIST_ELT(splineList, 0); if (listSeq == 0 || !PPM_EQUAL(splineList.color, lastColor)) { if (listSeq > 0) { /* Close previous <path> element */ if (!(shape.centerline || splineList.open)) fputs("z", fileP); fputs("\"/>\n", fileP); } /* Open new <path> element */ fprintf(fileP, "<path style=\"%s:#%02x%02x%02x; %s:none;\" d=\"", (shape.centerline || splineList.open) ? "stroke" : "fill", PPM_GETR(splineList.color), PPM_GETG(splineList.color), PPM_GETB(splineList.color), (shape.centerline || splineList.open) ? "fill" : "stroke"); } fprintf(fileP, "M%g %g", START_POINT(first).x, height - START_POINT(first).y); outSplineList(fileP, splineList, height); lastColor = splineList.color; } if (SPLINE_LIST_ARRAY_LENGTH(shape) > 0) { spline_list_type const lastSplineList = SPLINE_LIST_ARRAY_ELT(shape, SPLINE_LIST_ARRAY_LENGTH(shape)-1); if (!(shape.centerline || lastSplineList.open)) fputs("z", fileP); /* Close last <path> element */ fputs("\"/>\n", fileP); } }
static pixel random_color(pixval const maxval) { pixel p; PPM_ASSIGN(p, rand() % (maxval + 1), rand() % (maxval + 1), rand() % (maxval + 1) ); return p; }
void save_depth_ppm(char *file_name, struct depth_image_t *image, int max) { pixel **data = ppm_allocarray(IMG_WIDTH, IMG_HEIGHT); // Copy data back into PPM structure for(int x = 0; x < IMG_WIDTH; x++) { for(int y = 0; y < IMG_HEIGHT; y++) { struct depth8_t p = image->pixels[x][y]; // PPM data is indexed by y, then x PPM_ASSIGN(data[y][x], p.d, p.d, p.d); } } FILE *outfp = fopen(file_name, "w"); ppm_writeppm(outfp, data, IMG_WIDTH, IMG_HEIGHT, max, 0); }
void read_cmp(const char *fname) { unsigned char col[3]; FILE *cmp; int i; cmp = fopen(fname, "r"); if (cmp == NULL) { perror(fname); exit(1); } fseek(cmp, 48, SEEK_SET); for (i = 0; i < 256; i++) { col[0] = getc(cmp); col[1] = getc(cmp); col[2] = getc(cmp); PPM_ASSIGN(cmap[i], col[0], col[1], col[2]); } fclose(cmp); }
int main(int argc, char **argv) { int i; ppm_init(&argc, argv); for (i = 0; i < 256; i++) PPM_ASSIGN(cmap[i], i, i, i); i = 1; if (argc >= 3 && strncmp(argv[1], "-c", 2) == 0) { read_cmp(argv[2]); i = 3; } for (; i < argc; i++) process_file(argv[i]); return 0; }
static void parseNewHexX11(char const colorname[], pixval const maxval, bool const closeOk, pixel * const colorP) { /*---------------------------------------------------------------------------- Determine what color colorname[] specifies in the new style hex color specification format (e.g. rgb:55/40/55). Return that color as *colorP. Assume colorname[] starts with "rgb:", but otherwise it might be gibberish. -----------------------------------------------------------------------------*/ int hexit[256]; const char * cp; pixval n; unsigned int digitCount; pixval rNorm, gNorm, bNorm; computeHexTable(hexit); cp = &colorname[4]; parseHexDigits(cp, '/', hexit, &n, &digitCount); rNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname); cp += digitCount; ++cp; /* Skip the slash */ parseHexDigits(cp, '/', hexit, &n, &digitCount); gNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname); cp += digitCount; ++cp; /* Skip the slash */ parseHexDigits(cp, '\0', hexit, &n, &digitCount); bNorm = rgbnorm(n, maxval, digitCount, closeOk, colorname); PPM_ASSIGN(*colorP, rNorm, gNorm, bNorm); }
static void convertLinear(FILE * const ifP, unsigned int const cols, unsigned int const rows, gray const maxval, int const format, const char * const colorNameBlack, const char * const colorNameWhite, FILE * const ofP, gray * const grayrow, pixel * const pixelrow) { pixel colorBlack, colorWhite; pixval red0, grn0, blu0, red1, grn1, blu1; unsigned int row; ppm_writeppminit(ofP, cols, rows, maxval, 0); colorBlack = ppm_parsecolor(colorNameBlack, maxval); colorWhite = ppm_parsecolor(colorNameWhite, maxval); red0 = PPM_GETR(colorBlack); grn0 = PPM_GETG(colorBlack); blu0 = PPM_GETB(colorBlack); red1 = PPM_GETR(colorWhite); grn1 = PPM_GETG(colorWhite); blu1 = PPM_GETB(colorWhite); for (row = 0; row < rows; ++row) { unsigned int col; pgm_readpgmrow(ifP, grayrow, cols, maxval, format); for (col = 0; col < cols; ++col) { gray const input = grayrow[col]; PPM_ASSIGN( pixelrow[col], (red0 * (maxval - input) + red1 * input) / maxval, (grn0 * (maxval - input) + grn1 * input) / maxval, (blu0 * (maxval - input) + blu1 * input) / maxval); } ppm_writeppmrow(ofP, pixelrow, cols, maxval, 0); } }
ppm_t *pnm_image2ppm(ppm_t *ppm, pnm_image_t *image) { int i,j,k; if (!image) return (ppm); if (!ppm) { ppm = malloc(sizeof(ppm_t)); ppm_allocarray(ppm->cols=image->cols, ppm->rows=image->rows); } for (j=0; j < ppm->rows; j++) for (k=0; k < ppm->cols; k++) PPM_ASSIGN(ppm->pixels[j][k], (gray) image->pixels[0][j][k], (gray) image->pixels[1][j][k], (gray) image->pixels[2][j][k]); ppm->maxval = (gray) image->maxval; return (ppm); }
void savebmp(const char *filename, float wf, float hf, int dpi, std::vector< std::vector <Pixel> >* data) { /* Example program fragment to read a PAM or PNM image from stdin, add up the values of every sample in it (I don't know why), and write the image unchanged to stdout. */ FILE* f = fopen(filename,"wb"); pm_init(filename, 0); pixel** truePix = ppm_allocarray(wf,hf); for (int i = 0; i < wf; i++) { for (int j = 0; j < hf; j++) { PPM_ASSIGN(truePix[i][j],data->at(i).at(j).getColor()->getRed(), data->at(i).at(j).getColor()->getGreen(), data->at(i).at(j).getColor()->getBlue()); } } ppm_writeppm(f, truePix, (int)wf, (int)hf, 256, 0); ppm_freearray(truePix, (int)hf); }
static void writePpm(FILE * const ifP, const xvPalette * const xvPaletteP, unsigned int const cols, unsigned int const rows, pixval const maxval, FILE * const ofP) { /*---------------------------------------------------------------------------- Write out the PPM image, from the XV-mini input file ifP, which is positioned to the raster. The raster contains indices into the palette *xvPaletteP. -----------------------------------------------------------------------------*/ pixel * pixrow; unsigned int row; pixrow = ppm_allocrow(cols); ppm_writeppminit(ofP, cols, rows, maxval, 0); for (row = 0; row < rows; ++row) { unsigned int col; for (col = 0; col < cols; ++col) { int byte; byte = fgetc(ifP); if (byte == EOF) pm_error("unexpected EOF"); else { unsigned int const paletteIndex = byte; assert(byte >= 0); PPM_ASSIGN(pixrow[col], xvPaletteP->red[paletteIndex], xvPaletteP->grn[paletteIndex], xvPaletteP->blu[paletteIndex]); } } ppm_writeppmrow(ofP, pixrow, cols, maxval, 0); } ppm_freerow(pixrow); }
static int fill_clut(xel **pnm, int cols, int rows) { int clut_len = 0; int i, j, k; for (i = 0 ; i < rows; i++) for (j = 0; j < cols; j++) { for (k = 0; k < clut_len; k++) if (PPM_EQUAL(pnm[i][j], clut[k])) break; if (k == clut_len) { if (clut_len == 256) return 257; PPM_ASSIGN(clut[clut_len], PPM_GETR(pnm[i][j]), PPM_GETG(pnm[i][j]), PPM_GETB(pnm[i][j])); clut_len++; } } return clut_len; }
static void blackenTransparentAreas(pixel ** const xorPPMarray, int const cols, int const rows, gray ** const andPGMarray, pixval const andMaxval) { unsigned int row; if (verbose) pm_message("Setting transparent pixels to black"); for (row = 0; row < rows; ++row) { unsigned int col; for (col = 0; col < cols; ++col) { if (andPGMarray[row][col] < andMaxval) /* It's not opaque here; make it black */ PPM_ASSIGN(xorPPMarray[row][col], 0, 0, 0); } } }
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 pxcols = pixcols - xBias; int const pxrows = pixrows - yBias; pixel rgbcolor; int wavelength; int lx, ly; int fx, fy; PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); for (wavelength = 380; wavelength <= 700; wavelength += 5) { int icx, icy; computeMonochromeColorLocation(wavelength, pxcols, pxrows, upvp, &icx, &icy); if (wavelength > 380) ppmd_line(pixels, pixcols, pixrows, Maxval, B(lx, ly), B(icx, icy), PPMD_NULLDRAWPROC, (char *) &rgbcolor); else { fx = icx; fy = icy; } lx = icx; ly = icy; } ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly), B(fx, fy), PPMD_NULLDRAWPROC, (char *) &rgbcolor); }