home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume5 / pbm3 / part4 / libpbm5.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-03  |  4.5 KB  |  213 lines

  1. /* libpbm5.c - pbm utility library part 5
  2. **
  3. ** Copyright (C) 1988 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include "pbm.h"
  15. #include "libpbm.h"
  16.  
  17.  
  18. static int item, bitsinitem, bitshift;
  19. static int bitspercount, count, maxcount, repeatbits, repeatcount, repeatindex;
  20. static bit repeat, bitbuf[MAX_MAXCOUNT], repeatbuf[MAX_REPEATBITS];
  21. static FILE *cbm_file;
  22.  
  23.  
  24. static
  25. cbm_putinit( cols, rows, file )
  26. int cols, rows;
  27. FILE *file;
  28.     {
  29.     putc( (char) CBM_MAGIC1, file );
  30.     putc( (char) NCBM_MAGIC2, file );
  31.  
  32.     putc( (char) VERSION_RUNLEN, file );
  33.  
  34.     bitspercount = DEFAULT_BITSPERCOUNT;
  35.     maxcount = ( 1 << bitspercount ) - 1;
  36.     putc( (char) bitspercount, file );
  37.  
  38.     repeatbits = DEFAULT_REPEATBITS;
  39.     putc( (char) repeatbits, file );
  40.  
  41.     putc( (char) ( ( cols >> 8 ) & 0xff ), file );
  42.     putc( (char) ( cols & 0xff ), file );
  43.     putc( (char) ( ( rows >> 8 ) & 0xff ), file );
  44.     putc( (char) ( rows & 0xff ), file );
  45.  
  46.     /* Initialize statics for run-length encoding. */
  47.     repeat = 1;
  48.     count = 0;
  49.     repeatindex = 0;
  50.  
  51.     /* Initialize statics for bit-to-byte encoding. */
  52.     bitsinitem = 0;
  53.     item = 0;
  54.     bitshift = 7;
  55.     cbm_file = file;
  56.     }
  57.  
  58. static
  59. cbm_putitem( )
  60.     {
  61.     putc( (char) item, cbm_file );
  62.     bitsinitem = 0;
  63.     item = 0;
  64.     bitshift = 7;
  65.     }
  66.  
  67. static
  68. cbm_putbit( b )
  69. bit b;
  70.     {
  71.     if ( bitsinitem == 8 )
  72.     cbm_putitem( );
  73.     bitsinitem++;
  74.     if ( b )
  75.     item += 1 << bitshift;
  76.     bitshift--;
  77.     }
  78.  
  79. static
  80. cbm_putrest( )
  81.     {
  82.     if ( bitsinitem > 0 )
  83.     cbm_putitem( );
  84.     }
  85.  
  86. static
  87. cbm_putrlbuffer( )
  88.     {
  89.     int i;
  90.  
  91.     cbm_putbit( repeat );
  92.  
  93.     for ( i = bitspercount - 1; i >= 0; i-- )
  94.     if ( count & ( 1 << i ) )
  95.         cbm_putbit( 1 );
  96.     else
  97.         cbm_putbit( 0 );
  98.  
  99.     if ( repeat )
  100.     for ( i = 0; i < repeatbits; i++ )
  101.         cbm_putbit( repeatbuf[i] );
  102.     else
  103.     for ( i = 0; i < count; i++ )
  104.         cbm_putbit( bitbuf[i] );
  105.  
  106.     repeat = 1;
  107.     count = 0;
  108.     }
  109.  
  110. static
  111. cbm_putrlbit( b )
  112. bit b;
  113.     {
  114.     int i;
  115.  
  116.     if ( count == maxcount )
  117.     {
  118.     cbm_putrlbuffer( );
  119.     repeatindex = 0;
  120.     }
  121.  
  122.     if ( repeat && count < repeatbits )
  123.     { /* Still initializing a repeat buf. */
  124.     bitbuf[count] = repeatbuf[repeatindex] = b;
  125.     count++;
  126.     repeatindex = ( repeatindex + 1 ) % repeatbits;
  127.     }
  128.     else if ( repeat )
  129.     { /* Repeating - watch for end of run. */
  130.     if ( b == repeatbuf[repeatindex] )
  131.         { /* Run continues. */
  132.         bitbuf[count] = b;
  133.         count++;
  134.         repeatindex = ( repeatindex + 1 ) % repeatbits;
  135.         }
  136.     else
  137.         { /* Run ended - is it long enough to dump? */
  138.         if ( count > bitspercount + 1 )
  139.         { /* Yes, dump a repeat-mode buffer and start a new one. */
  140.         cbm_putrlbuffer( );
  141.         repeatindex = 0;
  142.         bitbuf[count] = repeatbuf[repeatindex] = b;
  143.         count++;
  144.         repeatindex++;
  145.         }
  146.         else
  147.         { /* Not long enough - convert to non-repeat mode. */
  148.         repeat = 0;
  149.         bitbuf[count] = b;
  150.         count++;
  151.         for ( i = 0; i < repeatbits; i++ )
  152.             repeatbuf[i] = bitbuf[count - repeatbits + i];
  153.         repeatcount = repeatbits;
  154.         repeatindex = 0;
  155.         }
  156.         }
  157.     }
  158.     else
  159.     { /* Not repeating - watch for a run worth repeating. */
  160.     if ( b == repeatbuf[repeatindex] )
  161.         { /* Possible run continues. */
  162.         repeatcount++;
  163.         repeatindex = ( repeatindex + 1 ) % repeatbits;
  164.         if ( repeatcount > 2 + 2 * bitspercount + repeatbits )
  165.         { /* Long enough - dump non-repeat part and start repeat. */
  166.         count = count - ( repeatcount - 1 );
  167.         cbm_putrlbuffer( );
  168.         count = repeatcount;
  169.         /* ??? */
  170.         }
  171.         else
  172.         { /* Not long enough yet - continue as non-repeat buf. */
  173.         bitbuf[count] = b;
  174.         count++;
  175.         }
  176.         }
  177.     else
  178.         { /* Broken run. */
  179.         bitbuf[count] = b;
  180.         count++;
  181.         for ( i = 0; i < repeatbits; i++ )
  182.         repeatbuf[i] = bitbuf[count - repeatbits + i];
  183.         repeatcount = repeatbits;
  184.         repeatindex = 0;
  185.         }
  186.     }
  187.     }
  188.  
  189. static
  190. cbm_putrlrest( )
  191.     {
  192.     if ( count > 0 )
  193.     cbm_putrlbuffer( );
  194.     cbm_putrest( );
  195.     }
  196.  
  197.  
  198. pbm_writecbm( file, bits, cols, rows )
  199. FILE *file;
  200. bit **bits;
  201. int cols, rows;
  202.     {
  203.     int row, col, linecount;
  204.  
  205.     cbm_putinit( cols, rows, file );
  206.  
  207.     for ( row = 0; row < rows; row++ )
  208.         for ( col = 0; col < cols; col++ )
  209.         cbm_putrlbit( bits[row][col] );
  210.  
  211.     cbm_putrlrest( );
  212.     }
  213.