/*----------------------------------------------------------------------*/
/* Copyright (c) 1988-1989						*/
/* by CompuServe Inc., Tucson, AZ.  All Rights Reserved			*/
/* RLETIF.C can be copied and distributed freely for any		*/
/* non-commercial purposes. RLETIF.C can only be incorporated		*/
/* into commercial software with the permission of CompuServe Inc.	*/
/*----------------------------------------------------------------------*/

/* RLETIF.C */

/*
 * ABSTRACT:
 *	This file contains routines to convert Run Length Encoded lines
 *	 into one-dimensional group-3 FAX compressed lines.
 *
 *	See RLETIF.H for a summary of functions.
 *
 * AUTHOR: Doug Chinnock
 *
 * REVISION HISTORY:
 *
 */



#include	"cnvhuf.h"
#include	"rletif.h"
#include	"writetif.h"


/* The five constant tables have the form:
|
|	huffman_code
|	    array_xxx_yyy[ n ];
|
|	where n is the length of the run or 1/64th of it.
*/

#include	"dehuftab.h"

/* Variables used among functions: */

static union
    {
    unsigned char
	TIF_ch[4];		/* Assembly buffer for packed bits */
    short int
	TIF_sh[2];
    long int
	TIF_lg;			/* Residue always left justified here */
    } TIF_pack;

short int
    TIF_bit_count,
    TIF_pack_filled;		/* Bits filled in TIF_pack */

extern void	compress_huffman_line( rle_line	*emit_line )
{
(*emit_line).rle_color = WHITE;
TIF_bit_count = 0,
TIF_pack_filled = 0;

TIF_write_bits( 12, 0x1 );			/* Output EOL (sync?) */

for ( (*emit_line).rle_pointer = 0;
      (*emit_line).rle_pointer < (*emit_line).rle_count;
      (*emit_line).rle_pointer ++ )
    {
    compress_huffman_code( (*emit_line).rle_color,
			   (*emit_line).rle_list[(*emit_line).rle_pointer] );
    (*emit_line).rle_color = ! (*emit_line).rle_color;
    };

TIF_write_bits( 16 - TIF_pack_filled, 0 );	/* Even out bits to even byte */

while ( TIF_bit_count < FAX_min_line )		/* Now pad line as needed */
    TIF_write_bits( 8, 0 );

} /* compress_huffman_line */


extern void 	compress_huffman_code( colors	color_of_run,
				       int	length_of_color )
{

/* First put out makeup codes */

while ( length_of_color > 63 )
    {
    if ( length_of_color <= (1728+63) )
	{
	if ( color_of_run == WHITE )
	    TIF_write_bits( huf_wht_makeup[length_of_color/64-1].code_bits,
			    huf_wht_makeup[length_of_color/64-1].code_value );
	else
	    TIF_write_bits( huf_blk_makeup[length_of_color/64-1].code_bits,
			    huf_blk_makeup[length_of_color/64-1].code_value );
	length_of_color %= 64;
	}
    else if ( length_of_color <= (2560+63) )
	{
	TIF_write_bits( huf_big_makeup[(length_of_color-1792)/64].code_bits,
			huf_wht_makeup[(length_of_color-1792)/64].code_value );
	length_of_color %= 64;
	}
    else
	{
	TIF_write_bits( huf_big_makeup[(2560-1792)/64].code_bits,
			huf_wht_makeup[(2560-1792)/64].code_value );
	length_of_color -= 2560;
	};
    };

/* Finally put out termination code */

if ( color_of_run == WHITE )
    TIF_write_bits( huf_wht_final[length_of_color].code_bits,
		    huf_wht_final[length_of_color].code_value );
else
    TIF_write_bits( huf_blk_final[length_of_color].code_bits,
		    huf_blk_final[length_of_color].code_value );

} /* compress_huffman_code */

void	TIF_write_bits( short int	size_to_write,
			unsigned int	bit_value )
{
short int
    i;

bit_value <<= 16 - size_to_write;		/* Left justify new data */

for ( i = 0; i < size_to_write; i ++ )
    {
    TIF_pack.TIF_lg >>= 1;

    if ( (bit_value & 0x8000) != 0 )
	TIF_pack.TIF_ch[3] |= 0x80;
    else
	TIF_pack.TIF_ch[3] &= 0x7F;

    bit_value <<= 1;
    };

TIF_pack_filled += size_to_write;
TIF_pack.TIF_lg >>= 32 - TIF_pack_filled;	/* Right justify result */

while ( TIF_pack_filled >= 8 )			/* Output any full bytes */
    {
    put_TIF_byte( TIF_pack.TIF_ch[0] );
    TIF_pack.TIF_lg >>= 8;
    TIF_pack_filled -= 8;
    TIF_bit_count += 8;
    };

TIF_pack.TIF_lg <<= 32 - TIF_pack_filled;	/* Left justify remainder */

} /* TIF_write_bits */
