107 lines
3.7 KiB
C
107 lines
3.7 KiB
C
// 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 <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
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;
|
|
}
|