home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / netpbm_src.lzh / NETPBM / PBM / pktopbm.c < prev    next >
C/C++ Source or Header  |  1996-11-18  |  11KB  |  373 lines

  1. /*
  2.   pktopbm, adapted from "pktopx in C by Tomas Rokicki" by AJCD 1/8/90
  3.   
  4.   compile with: cc -lpbm -o pktopbm pktopbm.c
  5.   */
  6.  
  7. #include <stdio.h>
  8. #include "pbm.h"
  9.  
  10. #define NAMELENGTH 80
  11. #define MAXROWWIDTH 3200
  12. #define MAXPKCHAR 256
  13.  
  14. typedef int integer ;
  15. typedef unsigned char quarterword ;
  16. typedef char boolean ;
  17. typedef quarterword eightbits ;
  18.  
  19. static FILE *pkfile ;
  20. static char pkname[NAMELENGTH+1] ;
  21. static integer pktopbm_pkloc = 0;
  22. static char *filename[MAXPKCHAR] ;
  23. static bit **bitmap = NULL ;
  24. static integer dynf ;
  25. static eightbits inputbyte ;
  26. static eightbits bitweight ;
  27. static integer repeatcount ;
  28. static integer flagbyte ;
  29.  
  30. /* add a suffix to a filename in an allocated space */
  31. static void
  32. pktopbm_add_suffix(name, suffix)
  33.      char *name, *suffix ;
  34. {
  35.    char *slash = rindex(name, '/');
  36.    char *dot = rindex(name, '.');
  37.  
  38.    if ((dot && slash ? dot < slash : !dot) && strcmp(name, "-"))
  39.       strcat(name, suffix);
  40. }
  41.  
  42. /* get a byte from the PK file */
  43. static eightbits pktopbm_pkbyte()
  44. {
  45.    pktopbm_pkloc++ ;
  46.    return(getc(pkfile)) ;
  47. }
  48.  
  49. /* get a 16-bit half word from the PK file */
  50. static integer get16()
  51. {
  52.    integer a = pktopbm_pkbyte() ;
  53.    return((a<<8) + pktopbm_pkbyte()) ;
  54. }
  55.  
  56. /* get a 32-bit word from the PK file */
  57. static integer get32()
  58. {
  59.    integer a = get16() ;
  60.    if (a > 32767) a -= 65536 ;
  61.    return((a<<16) + get16()) ;
  62. }
  63.  
  64. /* get a nibble from current input byte, or new byte if no current byte */
  65. static integer getnyb()
  66. {
  67.    eightbits temp ;
  68.    if (bitweight == 0) {
  69.       inputbyte = pktopbm_pkbyte() ;
  70.       bitweight = 16 ;
  71.    }
  72.    temp = inputbyte / bitweight ;
  73.    inputbyte -= temp * bitweight ;
  74.    bitweight >>= 4 ;
  75.    return(temp) ;
  76. }
  77.  
  78. /* get a bit from the current input byte, or a new byte if no current byte */
  79. static boolean getbit()
  80. {
  81.    boolean temp ;
  82.    bitweight >>= 1 ;
  83.    if (bitweight == 0) {
  84.       inputbyte = pktopbm_pkbyte() ;
  85.       bitweight = 128 ;
  86.    }
  87.    temp = (inputbyte >= bitweight) ;
  88.    if (temp) inputbyte -= bitweight ;
  89.    return(temp) ;
  90. }
  91.  
  92. /* unpack a dynamically packed number. dynf is dynamic packing threshold  */
  93. static integer pkpackednum()
  94. {
  95.    integer i, j ;
  96.    i = getnyb() ;
  97.    if (i == 0) {            /* large run count, >= 3 nibbles */
  98.       do {
  99.      j = getnyb() ;            /* count extra nibbles */
  100.      i++ ;
  101.       } while (j == 0) ;
  102.       while (i > 0) {
  103.      j = (j<<4) + getnyb() ;    /* add extra nibbles */
  104.      i-- ;
  105.       }
  106.       return (j - 15 +((13 - dynf)<<4) + dynf) ;
  107.    } else if (i <= dynf) return (i) ;    /* number > 0 and <= dynf */
  108.    else if (i < 14) return (((i - dynf - 1)<<4) + getnyb() + dynf + 1) ;
  109.    else {
  110.       if (i == 14) repeatcount = pkpackednum() ;    /* get repeat count */
  111.       else repeatcount = 1 ;        /* value 15 indicates repeat count 1 */
  112.       return(pkpackednum()) ;
  113.    }
  114. }
  115.  
  116. /* skip specials in PK files, inserted by Metafont or some other program */
  117. static void
  118. skipspecials()
  119. {
  120.    integer i, j;
  121.    do {
  122.       flagbyte = pktopbm_pkbyte() ;
  123.       if (flagbyte >= 240)
  124.      switch(flagbyte) {
  125.      case 240:            /* specials of size 1-4 bytes */
  126.      case 241:
  127.      case 242:
  128.      case 243:
  129.         i = 0 ;
  130.         for (j = 240 ; j <= flagbyte ; j ++) i = (i<<8) + pktopbm_pkbyte() ;
  131.         for (j = 1 ; j <= i ; j ++) pktopbm_pkbyte() ;    /* ignore special */
  132.         break ;
  133.      case 244:            /* no-op, parameters to specials */
  134.         get32() ;
  135.      case 245:            /* start of postamble */
  136.      case 246:            /* no-op */
  137.         break ;
  138.      case 247:            /* pre-amble in wrong place */
  139.      case 248:
  140.      case 249:
  141.      case 250:
  142.      case 251:
  143.      case 252:
  144.      case 253:
  145.      case 254:
  146.      case 255:
  147.         pm_error("unexpected flag byte %d", flagbyte) ;
  148.      }
  149.    } while (!(flagbyte < 240 || flagbyte == 245)) ;
  150. }
  151.  
  152. /* ignore character packet */
  153. static void
  154. ignorechar(car, endofpacket)
  155.      integer car, endofpacket;
  156. {
  157.    while (pktopbm_pkloc != endofpacket) pktopbm_pkbyte() ;
  158.    if (car < 0 || car >= MAXPKCHAR)
  159.       pm_message("Character %d out of range", car) ;
  160.    skipspecials() ;
  161. }
  162.  
  163. int
  164. main(argc, argv)
  165.      int argc ;
  166.      char *argv[] ;
  167. {
  168.    integer endofpacket ;
  169.    boolean turnon ;
  170.    integer i, j;
  171.    integer car ;
  172.    integer bmx=0, bmy=0;
  173.    bit row[MAXROWWIDTH+1] ;
  174.    char *usage = "pkfile[.pk] [[-x width] [-y height] [-c num] pbmfile]...";
  175.    
  176.    pbm_init(&argc, argv);
  177.    for (i = 0 ; i < MAXPKCHAR ; i ++) filename[i] = NULL ;
  178.  
  179.    pm_message("This is PKtoPBM, version 2.4") ;
  180.  
  181.    if (--argc < 1) pm_usage(usage) ;
  182.  
  183.    strcpy(pkname, *++argv) ;
  184.    pktopbm_add_suffix(pkname, ".pk") ;
  185.  
  186.    car = 0 ;
  187.    while (++argv, --argc) {
  188.       if (argv[0][0] == '-' && argv[0][1])
  189.      switch (argv[0][1]) {
  190.        case 'X':
  191.        case 'x':
  192.       if (argv[0][2]) bmx = atoi(*argv+2) ;
  193.       else if (++argv, --argc) bmx = atoi(*argv) ;
  194.       else pm_usage(usage) ;
  195.       continue ;
  196.        case 'Y':
  197.        case 'y':
  198.       if (argv[0][2]) bmy = atoi(*argv+2) ;
  199.       else if (++argv, --argc) bmy = atoi(*argv) ;
  200.       else pm_usage(usage) ;
  201.       continue ;
  202.      case 'C':
  203.      case 'c':
  204.         if (argv[0][2]) car = atoi(*argv+2) ;
  205.         else if (++argv, --argc) car = atoi(*argv) ;
  206.         else pm_usage(usage) ;
  207.         break ;
  208.      default:
  209.         pm_usage(usage) ;
  210.      } else if (car < 0 || car >= MAXPKCHAR) {
  211.         pm_error("character must be in range 0 to %d (-c)", MAXPKCHAR-1) ;
  212.      } else filename[car++] = *argv ;
  213.    }
  214.  
  215.    pkfile = pm_openr(pkname);
  216.    if (pktopbm_pkbyte() != 247)
  217.       pm_error("bad PK file (pre command missing)") ;
  218.    if (pktopbm_pkbyte() != 89)
  219.       pm_error("wrong version of packed file") ;
  220.    j = pktopbm_pkbyte() ;                /* get header comment size */
  221.    for (i = 1 ; i <= j ; i ++) pktopbm_pkbyte() ;    /* ignore header comment */
  222.    get32() ;                    /* ignore designsize */
  223.    get32() ;                    /* ignore checksum */
  224.    if (get32() != get32())            /* h & v pixels per point */
  225.       pm_message("Warning: aspect ratio not 1:1") ;
  226.    skipspecials() ;
  227.    while (flagbyte != 245) {            /* not at postamble */
  228.       integer cheight, cwidth ;
  229.       integer xoffs=0, yoffs=0;
  230.       FILE *ofp;
  231.  
  232.       dynf = (flagbyte>>4) ;            /* get dynamic packing value */
  233.       flagbyte &= 15 ;
  234.       turnon = (flagbyte >= 8) ;        /* black or white initially? */
  235.       if (turnon) flagbyte &= 7 ;        /* long or short form */
  236.       if (flagbyte == 7) {            /* long form preamble */
  237.      integer packetlength = get32() ;    /* character packet length */
  238.      car = get32() ;            /* character number */
  239.      endofpacket = packetlength + pktopbm_pkloc ;    /* calculate end of packet */
  240.      if (car >= MAXPKCHAR || car < 0) {
  241.         ignorechar(car, endofpacket);
  242.         continue;
  243.      }
  244.      get32() ;                 /* ignore tfmwidth */
  245.      get32() ;                /* ignore horiz escapement */
  246.      get32() ;                /* ignore vert escapement */
  247.      cwidth = get32() ;            /* bounding box width */
  248.      cheight = get32() ;            /* bounding box height */
  249.      if (cwidth < 0 || cheight < 0 || cwidth > 65535 || cheight > 65535) {
  250.         ignorechar(car, endofpacket);
  251.         continue;
  252.      }
  253.      if (bmx) xoffs= get32() ;              /* horiz offset */
  254.      if (bmy) yoffs= get32() ;              /* vert offset */
  255.       } else if (flagbyte > 3) {        /* extended short form */
  256.      integer packetlength = ((flagbyte - 4)<<16) + get16() ;
  257.                         /* packet length */
  258.      car = pktopbm_pkbyte() ;            /* char number */
  259.      endofpacket = packetlength + pktopbm_pkloc ;    /* calculate end of packet */
  260.      if (car >= MAXPKCHAR) {
  261.         ignorechar(car, endofpacket);
  262.         continue;
  263.      }
  264.      pktopbm_pkbyte() ;                 /* ignore tfmwidth (3 bytes) */
  265.      get16() ;                /* ignore tfmwidth (3 bytes) */
  266.      get16() ;                /* ignore horiz escapement */
  267.      cwidth = get16() ;            /* bounding box width */
  268.      cheight = get16() ;            /* bounding box height */
  269.      if (bmx)                               /* horiz offset */
  270.         if ((xoffs=get16()) >= 32768)
  271.         xoffs-= 65536;
  272.      if (bmy)                               /* vert offset */
  273.         if ((yoffs=get16()) >= 32768)
  274.         yoffs-= 65536;
  275.       } else {                    /* short form preamble */
  276.      integer packetlength = (flagbyte<<8) + pktopbm_pkbyte() ;
  277.                         /* packet length */
  278.      car = pktopbm_pkbyte() ;            /* char number */
  279.      endofpacket = packetlength + pktopbm_pkloc ;    /* calculate end of packet */
  280.      if (car >= MAXPKCHAR) {
  281.         ignorechar(car, endofpacket);
  282.         continue;
  283.      }
  284.      pktopbm_pkbyte() ;             /* ignore tfmwidth (3 bytes) */
  285.      get16() ;                 /* ignore tfmwidth (3 bytes) */
  286.      pktopbm_pkbyte() ;                     /* ignore horiz escapement */
  287.      cwidth = pktopbm_pkbyte() ;            /* bounding box width */
  288.      cheight = pktopbm_pkbyte() ;           /* bounding box height */
  289.      if (bmx)                               /* horiz offset */
  290.         if ((xoffs=pktopbm_pkbyte()) >= 128)
  291.            xoffs-= 256;;
  292.      if (bmy)                               /* vert offset */
  293.         if ((yoffs=pktopbm_pkbyte()) >= 128)
  294.            yoffs-= 256;;
  295.       }
  296.       if (filename[car]) {
  297.      if (!bmx) bmx= cwidth;
  298.      if (!bmy) bmy= cheight;
  299.      bitmap = pbm_allocarray(bmx, bmy) ;
  300.      if (bitmap == NULL)
  301.         pm_error("out of memory allocating bitmap") ;
  302.       } else {
  303.      ignorechar(car, endofpacket);
  304.      continue;
  305.       }
  306.       bitweight = 0 ;
  307.       if (dynf == 14) {                /* bitmapped character */
  308.      for (i = 0 ; i < bmy ; i ++)           /* make it blank */
  309.         for (j = 0 ; j < bmx ; j ++)
  310.            bitmap[i][j]= PBM_WHITE;
  311.      for (i = 0 ; i < cheight ; i ++) {
  312.         int yi= i+(bmy-yoffs-1);
  313.         for (j = 0 ; j < cwidth ; j ++) {
  314.            int xj= j-xoffs;
  315.            if (getbit() && 0<=xj && xj<bmx && 0<=yi && yi<bmy)
  316.           bitmap[yi][xj] = PBM_BLACK ;
  317.         }
  318.     }
  319.       } else {                    /* dynamically packed char */
  320.      integer rowsleft = cheight ;
  321.      integer hbit = cwidth ;
  322.      integer rp = 0;
  323.      repeatcount = 0 ;
  324.      while (rowsleft > 0) {
  325.         integer count = pkpackednum() ;    /* get current colour count */
  326.         while (count > 0) {
  327.            if (count < hbit) {        /* doesn't extend past row */
  328.           hbit -= count ;
  329.           while (count--)
  330.              row[rp++] = turnon ? PBM_BLACK : PBM_WHITE;
  331.            } else {                /* reaches end of row */
  332.           count -= hbit ;
  333.           while (hbit--)
  334.              row[rp++] = turnon ? PBM_BLACK : PBM_WHITE;
  335.           for (i = 0; i <= repeatcount; i++) {  /* fill row */
  336.              int yi= i+cheight-rowsleft+(bmy-yoffs-1);
  337.              if (0<=yi && yi < bmy)
  338.             for (j = 0; j < cwidth; j++) {
  339.                int xj= j-xoffs;
  340.                if (0<=xj && xj<bmx)
  341.                   bitmap[yi][xj] = row[j] ;
  342.             }
  343.           }
  344.           rowsleft -= repeatcount + 1;
  345.           repeatcount = rp = 0 ;
  346.           hbit = cwidth ;
  347.            }
  348.         }
  349.         turnon = !turnon ;
  350.      }
  351.      if (rowsleft != 0 || hbit != cwidth)
  352.         pm_error("bad pk file (more bits than required)") ;
  353.       }
  354.       if (endofpacket != pktopbm_pkloc)
  355.      pm_error("bad pk file (bad packet length)") ;
  356.  
  357.       ofp = pm_openw(filename[car]);
  358.       filename[car] = NULL;
  359.       pbm_writepbm(ofp, bitmap, bmx, bmy, 0) ;
  360.       pbm_freearray(bitmap, bmy) ;
  361.       pm_close(ofp) ;
  362.       skipspecials() ;
  363.    }
  364.    while (! feof(pkfile)) pktopbm_pkbyte() ;        /* skip trailing junk */
  365.    pm_close(pkfile);
  366.    for (car = 0; car < MAXPKCHAR; car++)
  367.       if (filename[car])
  368.      pm_message("Warning: No character in position %d (file %s).",
  369.             car, filename[car]) ;
  370.    pm_message("%d bytes read from packed file.", pktopbm_pkloc-1) ;
  371.    exit(0);
  372. }
  373.