/* n = argc m = argv y = dfa p = infile q = outfile d = header b = buffer A = width k = x = type a = size r = c = range i = i = height = height1 u = ptr = width1 */ #include int main(int argc, char **argv) { char dfa[] = "vZwZcZcZeZaZpZvZgZeZXZ`ZiZhZkZkZjZwZfZfZcZmZeZaZhZhZmZnZdZdZvZfZ " "fZeZ`Z`ZgZqZnZgZ`ZXZ`ZaZoZoZXZXZhZhZqZtZhZhZ`ZpZsZjZXZXZhZ`ZkZuZ " "jZXZhZiZbZbZlZlZhZhZbZbZxZlZfZgZdZcZ`ZaZfZfZfZdZ`Z`ZfZgZpZpZrZiZ " "`Z`ZgZqZXZXZfZ`ZhZrZaZXZpZfZiZsZXZiZfZaZtZgZaZXZaZfZuZhZXZfZaZfZ " "vZvZXZfZgZ`ZwZjZaZXZ`ZiZiZkZXZbZiZXZbZXZlZXZ"; FILE *infile = (argc > 1 && (argv[1][0] - '-' || argv[1][1])) ? fopen(argv[1], "rb") : stdin; FILE *outfile = (argc < 3 || !(argv[2][0] - '-' || argv[2][1])) ? stdout : fopen(argv[2], "wb+"); char *header = "P%d\n%d %d\n%d\n"; char buffer[1024]; int type, width, height, range, ptr, width1, height1; int size, i, c, x; /* Check file handles */ if( !infile || !outfile ) return printf("Can not open %s for %s\n", argv[!infile ? 1 : 2], !infile ? "reading" : "writing"); /* Initialize DFA */ for(x = ptr = 0; dfa[ptr]; ptr += 2) if( dfa[ptr] - ' ' ) dfa[x++] = dfa[ptr]; /* Read header */ if( (size = fread(buffer, 1, 1024, infile)) > 2 && buffer[0] == 'P' && sscanf(buffer, header, &type, &width, &height, &range) == 4 && !(type - 5 && type - 6) && range == 255 ) { width1 = width; height1 = height; if( argc > 3 ) { /* Dropping odd pixels instead of even pixels, so dimensions round up instead of down. */ width1++; height1++; } fprintf(outfile, header, type, width1 / 2, height1 / 2, range); ptr = type != 5 ? 8 : 4; x = 3; } else { ptr = argc > 3 ? 2 : 10; } /* Run DFA */ for(i = c = 0;;) { ptr *= 6; ptr += (argc > 3 ? 1 : 0); /* Execute commands at current state */ if( dfa[ptr] & 1 ) fputc(c, outfile); if( dfa[ptr] & 16 ) x = width; if( dfa[ptr] & 2 ) x--; /* Read input */ if( i == size ) { if( !(size = fread(buffer, 1, 1024, infile)) ) break; i = 0; } c = buffer[i++]; /* Transition to next state */ ptr += (dfa[ptr] & 8) ? (c - 10 ? 4 : 2) : (dfa[ptr] & 4) ? (x ? 2 : 4) : 2; ptr = dfa[ptr] - 96; } /* Cleanup */ fclose(infile); fclose(outfile); return 0; }