home *** CD-ROM | disk | FTP | other *** search
- /*
- pktopbm, adapted from "pktopx in C by Tomas Rokicki" by AJCD 1/8/90
-
- compile with: cc -lpbm -o pktopbm pktopbm.c
- */
-
- #include <stdio.h>
- #include "pbm.h"
-
- #define NAMELENGTH 80
- #define MAXROWWIDTH 3200
- #define MAXPKCHAR 256
-
- typedef int integer ;
- typedef unsigned char quarterword ;
- typedef char boolean ;
- typedef quarterword eightbits ;
-
- static FILE *pkfile ;
- static char pkname[NAMELENGTH+1] ;
- static integer pktopbm_pkloc = 0;
- static char *filename[MAXPKCHAR] ;
- static bit **bitmap = NULL ;
- static integer dynf ;
- static eightbits inputbyte ;
- static eightbits bitweight ;
- static integer repeatcount ;
- static integer flagbyte ;
-
- /* add a suffix to a filename in an allocated space */
- void
- pktopbm_add_suffix(name, suffix)
- char *name, *suffix ;
- {
- char *slash = rindex(name, '/');
- char *dot = rindex(name, '.');
-
- if ((dot && slash ? dot < slash : !dot) && strcmp(name, "-"))
- strcat(name, suffix);
- }
-
- /* get a byte from the PK file */
- eightbits pktopbm_pkbyte()
- {
- pktopbm_pkloc++ ;
- return(getc(pkfile)) ;
- }
-
- /* get a 16-bit half word from the PK file */
- integer get16()
- {
- integer a = pktopbm_pkbyte() ;
- return((a<<8) + pktopbm_pkbyte()) ;
- }
-
- /* get a 32-bit word from the PK file */
- integer get32()
- {
- integer a = get16() ;
- if (a > 32767) a -= 65536 ;
- return((a<<16) + get16()) ;
- }
-
- /* get a nibble from current input byte, or new byte if no current byte */
- integer getnyb()
- {
- eightbits temp ;
- if (bitweight == 0) {
- inputbyte = pktopbm_pkbyte() ;
- bitweight = 16 ;
- }
- temp = inputbyte / bitweight ;
- inputbyte -= temp * bitweight ;
- bitweight >>= 4 ;
- return(temp) ;
- }
-
- /* get a bit from the current input byte, or a new byte if no current byte */
- boolean getbit()
- {
- boolean temp ;
- bitweight >>= 1 ;
- if (bitweight == 0) {
- inputbyte = pktopbm_pkbyte() ;
- bitweight = 128 ;
- }
- temp = (inputbyte >= bitweight) ;
- if (temp) inputbyte -= bitweight ;
- return(temp) ;
- }
-
- /* unpack a dynamically packed number. dynf is dynamic packing threshold */
- integer pkpackednum()
- {
- integer i, j ;
- i = getnyb() ;
- if (i == 0) { /* large run count, >= 3 nibbles */
- do {
- j = getnyb() ; /* count extra nibbles */
- i++ ;
- } while (j == 0) ;
- while (i > 0) {
- j = (j<<4) + getnyb() ; /* add extra nibbles */
- i-- ;
- }
- return (j - 15 +((13 - dynf)<<4) + dynf) ;
- } else if (i <= dynf) return (i) ; /* number > 0 and <= dynf */
- else if (i < 14) return (((i - dynf - 1)<<4) + getnyb() + dynf + 1) ;
- else {
- if (i == 14) repeatcount = pkpackednum() ; /* get repeat count */
- else repeatcount = 1 ; /* value 15 indicates repeat count 1 */
- return(pkpackednum()) ;
- }
- }
-
- /* skip specials in PK files, inserted by Metafont or some other program */
- void
- skipspecials()
- {
- integer i, j;
- do {
- flagbyte = pktopbm_pkbyte() ;
- if (flagbyte >= 240)
- switch(flagbyte) {
- case 240: /* specials of size 1-4 bytes */
- case 241:
- case 242:
- case 243:
- i = 0 ;
- for (j = 240 ; j <= flagbyte ; j ++) i = (i<<8) + pktopbm_pkbyte() ;
- for (j = 1 ; j <= i ; j ++) pktopbm_pkbyte() ; /* ignore special */
- break ;
- case 244: /* no-op, parameters to specials */
- get32() ;
- case 245: /* start of postamble */
- case 246: /* no-op */
- break ;
- case 247: /* pre-amble in wrong place */
- case 248:
- case 249:
- case 250:
- case 251:
- case 252:
- case 253:
- case 254:
- case 255:
- pm_error("unexpected flag byte %d", flagbyte) ;
- }
- } while (!(flagbyte < 240 || flagbyte == 245)) ;
- }
-
- /* ignore character packet */
- void
- ignorechar(car, endofpacket)
- integer car, endofpacket;
- {
- while (pktopbm_pkloc != endofpacket) pktopbm_pkbyte() ;
- if (car < 0 || car >= MAXPKCHAR)
- pm_message("Character %d out of range", car) ;
- skipspecials() ;
- }
-
- int
- main(argc, argv)
- int argc ;
- char *argv[] ;
- {
- integer endofpacket ;
- boolean turnon ;
- integer i, j;
- integer car ;
- bit row[MAXROWWIDTH+1] ;
- char *usage = "pkfile[.pk] [[-c num] pbmfile]...";
-
- pbm_init(&argc, argv);
- for (i = 0 ; i < MAXPKCHAR ; i ++) filename[i] = NULL ;
-
- pm_message("This is PKtoPBM, version 2.4") ;
-
- if (--argc < 1) pm_usage(usage) ;
-
- strcpy(pkname, *++argv) ;
- pktopbm_add_suffix(pkname, ".pk") ;
-
- car = 0 ;
- while (++argv, --argc) {
- if (argv[0][0] == '-' && argv[0][1])
- switch (argv[0][1]) {
- case 'C':
- case 'c':
- if (argv[0][2]) car = atoi(*argv+2) ;
- else if (++argv, --argc) car = atoi(*argv) ;
- else pm_usage(usage) ;
- break ;
- default:
- pm_usage(usage) ;
- } else if (car < 0 || car >= MAXPKCHAR) {
- pm_error("character must be in range 0 to %d (-c)", MAXPKCHAR-1) ;
- } else filename[car++] = *argv ;
- }
-
- pkfile = pm_openr(pkname);
- if (pktopbm_pkbyte() != 247)
- pm_error("bad PK file (pre command missing)") ;
- if (pktopbm_pkbyte() != 89)
- pm_error("wrong version of packed file") ;
- j = pktopbm_pkbyte() ; /* get header comment size */
- for (i = 1 ; i <= j ; i ++) pktopbm_pkbyte() ; /* ignore header comment */
- get32() ; /* ignore designsize */
- get32() ; /* ignore checksum */
- if (get32() != get32()) /* h & v pixels per point */
- pm_message("Warning: aspect ratio not 1:1") ;
- skipspecials() ;
- while (flagbyte != 245) { /* not at postamble */
- integer cheight, cwidth ;
- FILE *ofp;
-
- dynf = (flagbyte>>4) ; /* get dynamic packing value */
- flagbyte &= 15 ;
- turnon = (flagbyte >= 8) ; /* black or white initially? */
- if (turnon) flagbyte &= 7 ; /* long or short form */
- if (flagbyte == 7) { /* long form preamble */
- integer packetlength = get32() ; /* character packet length */
- car = get32() ; /* character number */
- endofpacket = packetlength + pktopbm_pkloc ; /* calculate end of packet */
- if (car >= MAXPKCHAR || car < 0) {
- ignorechar(car, endofpacket);
- continue;
- }
- get32() ; /* ignore tfmwidth */
- get32() ; /* ignore horiz escapement */
- get32() ; /* ignore vert escapement */
- cwidth = get32() ; /* bounding box width */
- cheight = get32() ; /* bounding box height */
- if (cwidth < 0 || cheight < 0 || cwidth > 65535 || cheight > 65535) {
- ignorechar(car, endofpacket);
- continue;
- }
- get32() ; /* ignore horiz offset */
- get32() ; /* ignore vert offset */
- } else if (flagbyte > 3) { /* extended short form */
- integer packetlength = ((flagbyte - 4)<<16) + get16() ;
- /* packet length */
- car = pktopbm_pkbyte() ; /* char number */
- endofpacket = packetlength + pktopbm_pkloc ; /* calculate end of packet */
- if (car >= MAXPKCHAR) {
- ignorechar(car, endofpacket);
- continue;
- }
- pktopbm_pkbyte() ; /* ignore tfmwidth (3 bytes) */
- get16() ; /* ignore tfmwidth (3 bytes) */
- get16() ; /* ignore horiz escapement */
- cwidth = get16() ; /* bounding box width */
- cheight = get16() ; /* bounding box height */
- get16() ; /* ignore horiz offset */
- get16() ; /* ignore vert offset */
- } else { /* short form preamble */
- integer packetlength = (flagbyte<<8) + pktopbm_pkbyte() ;
- /* packet length */
- car = pktopbm_pkbyte() ; /* char number */
- endofpacket = packetlength + pktopbm_pkloc ; /* calculate end of packet */
- if (car >= MAXPKCHAR) {
- ignorechar(car, endofpacket);
- continue;
- }
- pktopbm_pkbyte() ; /* ignore tfmwidth (3 bytes) */
- get16() ; /* ignore tfmwidth (3 bytes) */
- pktopbm_pkbyte() ; /* ignore horiz escapement */
- cwidth = pktopbm_pkbyte() ; /* bounding box width */
- cheight = pktopbm_pkbyte() ; /* bounding box height */
- pktopbm_pkbyte() ; /* ignore horiz offset */
- pktopbm_pkbyte() ; /* ignore vert offset */
- }
- if (filename[car]) {
- bitmap = pbm_allocarray(cwidth, cheight) ;
- if (bitmap == NULL)
- pm_error("out of memory allocating bitmap") ;
- } else {
- ignorechar(car, endofpacket);
- continue;
- }
- bitweight = 0 ;
- if (dynf == 14) { /* bitmapped character */
- for (i = 0 ; i < cheight ; i ++)
- for (j = 0 ; j < cwidth ; j ++) {
- if (getbit())
- bitmap[i][j] = PBM_BLACK ;
- else
- bitmap[i][j] = PBM_WHITE ;
- }
- } else { /* dynamically packed char */
- integer rowsleft = cheight ;
- integer hbit = cwidth ;
- integer rp = 0;
- repeatcount = 0 ;
- while (rowsleft > 0) {
- integer count = pkpackednum() ; /* get current colour count */
- while (count > 0) {
- if (count < hbit) { /* doesn't extend past row */
- hbit -= count ;
- while (count--)
- row[rp++] = turnon ? PBM_BLACK : PBM_WHITE;
- } else { /* reaches end of row */
- count -= hbit ;
- while (hbit--)
- row[rp++] = turnon ? PBM_BLACK : PBM_WHITE;
- for (i = 0; i <= repeatcount; i++) /* fill row */
- for (j = 0; j < cwidth; j++)
- bitmap[i + cheight-rowsleft][j] = row[j] ;
- rowsleft -= repeatcount + 1;
- repeatcount = rp = 0 ;
- hbit = cwidth ;
- }
- }
- turnon = !turnon ;
- }
- if (rowsleft != 0 || hbit != cwidth)
- pm_error("bad pk file (more bits than required)") ;
- }
- if (endofpacket != pktopbm_pkloc)
- pm_error("bad pk file (bad packet length)") ;
-
- ofp = pm_openw(filename[car]);
- filename[car] = NULL;
- pbm_writepbm(ofp, bitmap, cwidth, cheight, 0) ;
- pbm_freearray(bitmap, cheight) ;
- pm_close(ofp) ;
- skipspecials() ;
- }
- while (! feof(pkfile)) pktopbm_pkbyte() ; /* skip trailing junk */
- pm_close(pkfile);
- for (car = 0; car < MAXPKCHAR; car++)
- if (filename[car])
- pm_message("Warning: No character in position %d (file %s).",
- car, filename[car]) ;
- pm_message("%d bytes read from packed file.", pktopbm_pkloc-1) ;
- exit(0);
- }
-