/* gftopbm.c -- gf -> pbm conversion */ #include "defs.h" #define DEBUG 0 #if DEBUG #define D(x) x #else #define D(x) #endif #define IMGSIZE 32767 #define MAXL_NAME 64 #define ERRGLYPH -2 int main(int argc, char **argv); void usage(void); int preamble(void); int glyph(void); long geti4(unsigned char *); void paint(unsigned *, unsigned *, unsigned *, unsigned); int skipfile(long); int outpbm(char *); char *inname; unsigned char image[IMGSIZE]; char bname[MAXL_NAME]; FILE *infile; unsigned int code, width, height, hbytes; int main(int argc, char **argv) { int code; char *p, *q; int mincode = 0, maxcode = 255; for (argc--, argv++; argc; argc--, argv++) { p = *argv; if (*p == '-') { p = *argv + 1; mincode = (int)strtol(p, &p, 0); if (*p == '-') { p++; maxcode = (int)strtol(p, &p, 0); } else maxcode = mincode; } else inname = p; } if (*inname == 0) usage(); strcpy(bname, inname); p = strrchr(bname, '\\'); /* skip directory name */ if (p) p++; else p = bname; q = strchr(p, '.'); /* remove extension */ if (q) { if (q - p > 6) q = p + 6; /* short name */ *q = 0; } else q = strchr(p, 0); /* tail */ if (0 == (infile = fopen(inname, "rb"))) { fprintf(stderr, "Can't open %s\n", inname); exit(1); } if (preamble() == ERROR) { errmsg("Not a gf file\n"); exit(1); } while (0 <= (code = glyph())) { if (code == ERRGLYPH) { errmsg("Error in glyph section\n"); exit(1); } if (code >= mincode && code <= maxcode) { sprintf(q, "%02X.pbm", code); if (ERROR == outpbm(p)) { fprintf(stderr, "Can' to write to %s\n", bname); exit(1); } } } /* while */ return 0; } /* main */ void usage() { errmsg("Usage: gftopbm [-mincode[-maxcode]] infile\n"); exit(1); } int preamble() { unsigned char buf[3]; int n; if (3 > fread(buf, 1, 3, infile)) return ERROR; if (buf[0] != 247 || buf[1] != 131) return ERROR; n = buf[2]; if (n > fread(image, 1, n, infile)) return ERROR; fprintf(stderr, "comment='%s'\n", image); return OK; } int glyph() { int i; unsigned char buf[24]; long min_m, max_m, min_n, max_n; long count; unsigned sw, m, n; if (EOF == (i = fgetc(infile))) return ERRGLYPH; if (i == 67) { /* boc */ if (24 > fread(buf, 1, 24, infile)) return ERRGLYPH; code = (unsigned)geti4(buf); min_m = geti4(buf + 8); max_m = geti4(buf + 12); min_n = geti4(buf + 16); max_n = geti4(buf + 20); width = max_m - min_m; height = max_n - min_n + 1; } else if (i == 68) { /* boc1 */ if (5 > fread(buf, 1, 5, infile)) return ERRGLYPH; code = buf[0]; width = buf[1]; height = buf[3] + 1; } else if (i == 248) { /* post */ return EOF; } else return ERRGLYPH; fprintf(stderr, "code=%u, width=%u, height=%u\n", code, width, height); hbytes = (width + 7) / 8; memset(image, 0, IMGSIZE); sw = m = n = 0; while (0 <= (i = fgetc(infile))) { D(fprintf(stderr, "inst=%d ", i);) if (i >= 0 && i <= 63) { /* paint_0 - 63 */ paint(&m, &n, &sw, i); } else if (i >= 74 && i <= 238) { /* new_row */ m = i - 74; n++; sw = 1; D(fprintf(stderr, "(%u,%u)\n", m, n);) } else switch (i) { case 64: /* paint1 */ if (EOF == (i = fgetc(infile))) return ERRGLYPH; paint(&m, &n, &sw, (unsigned)i); break; case 65: /* paint2 */ if (2 > fread(buf, 1, 2, infile)) return ERRGLYPH; count = buf[0] * 0x100L + buf[1]; paint(&m, &n, &sw, (unsigned)count); break; case 66: /* paint3 */ if (3 > fread(buf, 1, 3, infile)) return ERRGLYPH; count = buf[0] * 0x10000L + buf[1] * 0x100L + buf[2]; paint(&m, &n, &sw, (unsigned)count); break; case 69: /* eoc */ return code; break; case 70: /* skip0 */ m = 0; n++; sw = 0; break; case 71: /* skip1 */ if (EOF == (i = fgetc(infile))) return ERRGLYPH; m = 0; n += i + 1; sw = 0; break; case 72: /* skip2 */ if (2 > fread(buf, 1, 2, infile)) return ERRGLYPH; count = buf[0] * 0x100L + buf[1]; m = 0; n += count + 1; sw = 0; break; case 73: /* skip3 */ if (3 > fread(buf, 1, 3, infile)) return ERRGLYPH; count = buf[0] * 0x10000L + buf[1] * 0x100L + buf[2]; m = 0; n += count + 1; sw = 0; break; case 239: /* xxx1 */ if (EOF == (i = fgetc(infile))) return ERRGLYPH; if (ERROR == skipfile(i)) return ERRGLYPH; break; case 240: /* xxx2 */ if (2 > fread(buf, 1, 2, infile)) return ERRGLYPH; count = buf[0] * 0x100 + buf[1]; if (ERROR == skipfile(count)) return ERRGLYPH; break; case 241: /* xxx3 */ if (3 > fread(buf, 1, 3, infile)) return ERRGLYPH; count = buf[0] * 0x10000L + buf[1] * 0x100L + buf[2]; if (ERROR == skipfile(count)) return ERRGLYPH; break; case 242: /* xxx4 */ if (4 > fread(buf, 1, 4, infile)) return ERRGLYPH; count = geti4(buf); if (ERROR == skipfile(count)) return ERRGLYPH; break; case 244: /* no_op */ break; default: return ERRGLYPH; } } /* while */ return ERRGLYPH; } long geti4(unsigned char *ptr) { long n; #if LITTLE_ENDIAN unsigned char *np = (unsigned char *)&n; np[0] = ptr[3]; np[1] = ptr[2]; np[2] = ptr[1]; np[3] = ptr[0]; #else n = *(long *)ptr; #endif return n; } void paint(unsigned *m, unsigned *n, unsigned *sw, unsigned i) { unsigned char *ptr; int bit; static unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; D(fprintf(stderr, "(%u,%u)+%u(%s)\n", *m, *n, i, (*sw ? "on" : "off"));) ptr = image + *n * hbytes + *m / 8; bit = *m % 8; *m += i; if (*sw) { while (i--) { *ptr |= mask[bit]; if (++bit > 7) { bit = 0; ptr++; } } } *sw = !*sw; } int skipfile(long i) { while (i-- > 0) { if (EOF == fgetc(infile)) return EOF; } return OK; } int outpbm(char *outname) { FILE *outfile; long nbyte; fprintf(stderr, "Writing into %s\n", outname); if (NULL == (outfile = fopen(outname, "wb"))) return ERROR; fprintf(outfile, "P4\n%u %u\n", width, height); nbyte = (((long)width + 7) / 8) * (long)height; if (nbyte > fwrite(image, 1, (size_t)nbyte, outfile)) return ERROR; fclose(outfile); return OK; }