// sampleRow: print color symbols at sampled X positions for a Y range. // Reads PPM (P6) images. Used to visually inspect specific rows of a // rendered scene without ever Read'ing the PNG file (which the user has // banned for context-corruption reasons). #include #include #include #include static int readToken(FILE *f, char *buf, size_t sz) { int c; while ((c = fgetc(f)) != EOF) { if (c == '#') { while ((c = fgetc(f)) != EOF && c != '\n') {} continue; } if (!isspace(c)) { break; } } if (c == EOF) { return -1; } size_t i = 0; do { if (i + 1 >= sz) { return -1; } buf[i++] = (char)c; c = fgetc(f); } while (c != EOF && !isspace(c)); buf[i] = '\0'; return (int)i; } int main(int argc, char **argv) { if (argc < 4) { fprintf(stderr, "usage: %s img.ppm yStart yEnd [scaleY]\n", argv[0]); return 2; } FILE *f = fopen(argv[1], "rb"); if (f == NULL) { fprintf(stderr, "cannot open %s\n", argv[1]); return 1; } char tok[32]; if (readToken(f, tok, sizeof(tok)) < 0 || strcmp(tok, "P6") != 0) { fprintf(stderr, "not P6\n"); fclose(f); return 1; } readToken(f, tok, sizeof(tok)); int w = atoi(tok); readToken(f, tok, sizeof(tok)); int h = atoi(tok); readToken(f, tok, sizeof(tok)); unsigned char *p = malloc((size_t)w * h * 3); if (p == NULL || fread(p, 1, (size_t)w * h * 3, f) != (size_t)w * h * 3) { fclose(f); free(p); return 1; } fclose(f); int yStart = atoi(argv[2]); int yEnd = atoi(argv[3]); int scaleY = (argc > 4) ? atoi(argv[4]) : (h / 192); int sampleW = (w >= 70) ? 70 : w; int xStep = w / sampleW; for (int hy = yStart; hy <= yEnd; hy++) { int sy = hy * scaleY + scaleY/2; if (sy >= h) { break; } printf("y=%3d: ", hy); for (int sx = 0; sx < w && sx < sampleW * xStep; sx += xStep) { unsigned char *px = &p[((size_t)sy * w + sx) * 3]; int r = px[0]; int g = px[1]; int b = px[2]; char c; if (r < 30 && g < 30 && b < 30) { c = '.'; } else if (b > r + 30 && b > g + 30) { c = 'B'; } else if (g > r + 30 && g > b + 30) { c = 'G'; } else if (r > 200 && g > 200 && b > 200) { c = 'W'; } else if (r > 100 && b > 100 && g < (r + b) / 4) { c = 'V'; } else if (r > 200 && g > 100 && b < 80) { c = 'O'; } else if (r > 100 && b > 100) { c = 'M'; } else if (g > 100 && b > 100) { c = 'C'; } else { c = '?'; } putchar(c); } putchar('\n'); } free(p); return 0; }