home *** CD-ROM | disk | FTP | other *** search
- /* libpbm5.c - pbm utility library part 5
- **
- ** Copyright (C) 1988 by Jef Poskanzer.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
- #include <stdio.h>
- #include "pbm.h"
- #include "libpbm.h"
-
-
- static int item, bitsinitem, bitshift;
- static int bitspercount, count, maxcount, repeatbits, repeatcount, repeatindex;
- static bit repeat, bitbuf[MAX_MAXCOUNT], repeatbuf[MAX_REPEATBITS];
- static FILE *cbm_file;
-
-
- static
- cbm_putinit( cols, rows, file )
- int cols, rows;
- FILE *file;
- {
- putc( (char) CBM_MAGIC1, file );
- putc( (char) NCBM_MAGIC2, file );
-
- putc( (char) VERSION_RUNLEN, file );
-
- bitspercount = DEFAULT_BITSPERCOUNT;
- maxcount = ( 1 << bitspercount ) - 1;
- putc( (char) bitspercount, file );
-
- repeatbits = DEFAULT_REPEATBITS;
- putc( (char) repeatbits, file );
-
- putc( (char) ( ( cols >> 8 ) & 0xff ), file );
- putc( (char) ( cols & 0xff ), file );
- putc( (char) ( ( rows >> 8 ) & 0xff ), file );
- putc( (char) ( rows & 0xff ), file );
-
- /* Initialize statics for run-length encoding. */
- repeat = 1;
- count = 0;
- repeatindex = 0;
-
- /* Initialize statics for bit-to-byte encoding. */
- bitsinitem = 0;
- item = 0;
- bitshift = 7;
- cbm_file = file;
- }
-
- static
- cbm_putitem( )
- {
- putc( (char) item, cbm_file );
- bitsinitem = 0;
- item = 0;
- bitshift = 7;
- }
-
- static
- cbm_putbit( b )
- bit b;
- {
- if ( bitsinitem == 8 )
- cbm_putitem( );
- bitsinitem++;
- if ( b )
- item += 1 << bitshift;
- bitshift--;
- }
-
- static
- cbm_putrest( )
- {
- if ( bitsinitem > 0 )
- cbm_putitem( );
- }
-
- static
- cbm_putrlbuffer( )
- {
- int i;
-
- cbm_putbit( repeat );
-
- for ( i = bitspercount - 1; i >= 0; i-- )
- if ( count & ( 1 << i ) )
- cbm_putbit( 1 );
- else
- cbm_putbit( 0 );
-
- if ( repeat )
- for ( i = 0; i < repeatbits; i++ )
- cbm_putbit( repeatbuf[i] );
- else
- for ( i = 0; i < count; i++ )
- cbm_putbit( bitbuf[i] );
-
- repeat = 1;
- count = 0;
- }
-
- static
- cbm_putrlbit( b )
- bit b;
- {
- int i;
-
- if ( count == maxcount )
- {
- cbm_putrlbuffer( );
- repeatindex = 0;
- }
-
- if ( repeat && count < repeatbits )
- { /* Still initializing a repeat buf. */
- bitbuf[count] = repeatbuf[repeatindex] = b;
- count++;
- repeatindex = ( repeatindex + 1 ) % repeatbits;
- }
- else if ( repeat )
- { /* Repeating - watch for end of run. */
- if ( b == repeatbuf[repeatindex] )
- { /* Run continues. */
- bitbuf[count] = b;
- count++;
- repeatindex = ( repeatindex + 1 ) % repeatbits;
- }
- else
- { /* Run ended - is it long enough to dump? */
- if ( count > bitspercount + 1 )
- { /* Yes, dump a repeat-mode buffer and start a new one. */
- cbm_putrlbuffer( );
- repeatindex = 0;
- bitbuf[count] = repeatbuf[repeatindex] = b;
- count++;
- repeatindex++;
- }
- else
- { /* Not long enough - convert to non-repeat mode. */
- repeat = 0;
- bitbuf[count] = b;
- count++;
- for ( i = 0; i < repeatbits; i++ )
- repeatbuf[i] = bitbuf[count - repeatbits + i];
- repeatcount = repeatbits;
- repeatindex = 0;
- }
- }
- }
- else
- { /* Not repeating - watch for a run worth repeating. */
- if ( b == repeatbuf[repeatindex] )
- { /* Possible run continues. */
- repeatcount++;
- repeatindex = ( repeatindex + 1 ) % repeatbits;
- if ( repeatcount > 2 + 2 * bitspercount + repeatbits )
- { /* Long enough - dump non-repeat part and start repeat. */
- count = count - ( repeatcount - 1 );
- cbm_putrlbuffer( );
- count = repeatcount;
- /* ??? */
- }
- else
- { /* Not long enough yet - continue as non-repeat buf. */
- bitbuf[count] = b;
- count++;
- }
- }
- else
- { /* Broken run. */
- bitbuf[count] = b;
- count++;
- for ( i = 0; i < repeatbits; i++ )
- repeatbuf[i] = bitbuf[count - repeatbits + i];
- repeatcount = repeatbits;
- repeatindex = 0;
- }
- }
- }
-
- static
- cbm_putrlrest( )
- {
- if ( count > 0 )
- cbm_putrlbuffer( );
- cbm_putrest( );
- }
-
-
- pbm_writecbm( file, bits, cols, rows )
- FILE *file;
- bit **bits;
- int cols, rows;
- {
- int row, col, linecount;
-
- cbm_putinit( cols, rows, file );
-
- for ( row = 0; row < rows; row++ )
- for ( col = 0; col < cols; col++ )
- cbm_putrlbit( bits[row][col] );
-
- cbm_putrlrest( );
- }
-