#include #define TXT_INIT_ODD 10 #define TXT_INIT_EVEN 2 #define PGM_INIT 4 #define PPM_INIT 8 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 = stdin; FILE *outfile = stdout; char buffer[1024]; int type, width, height, range, ptr, width1, height1; int size, i, c, x; /* Open files */ if( argc > 1 && (argv[1][0] != '-' || argv[1][1] != '\0') ) { if( (infile = fopen(argv[1], "rb")) == NULL ) return printf("Can not open %s for reading\n", argv[1]); } if( argc > 2 && (argv[2][0] != '-' || argv[2][1] != '\0') ) { if( (outfile = fopen(argv[2], "wb+")) == NULL ) return printf("Can not open %s for writing\n", argv[2]); } /* Initialize DFA */ for(x = ptr = 0; dfa[ptr] != '\0'; ptr += 2) { if( dfa[ptr] != ' ' ) dfa[x++] = dfa[ptr]; } /* Read header */ size = fread(buffer, 1, 1024, infile); if( size > 2 && buffer[0] == 'P' && sscanf(buffer, "P%d %d %d %d", &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, "P%d\n%d %d\n%d\n", type, width1 / 2, height1 / 2, range); ptr = type != 5 ? PPM_INIT : PGM_INIT; x = 3; } else { ptr = argc > 3 ? TXT_INIT_EVEN : TXT_INIT_ODD; } /* 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)) == 0 ) break; i = 0; } c = buffer[i++]; /* Transition to next state */ ptr += (dfa[ptr] & 8) ? (c == '\n' ? 2 : 4) : (dfa[ptr] & 4) ? (x != 0 ? 2 : 4) : 2; ptr = dfa[ptr] - 96; } /* Cleanup */ fclose(infile); fclose(outfile); return 0; }