[comp.sources.misc] v15i087: G3 and G4 utilities - part 2/3

davidsen@crdos1.crd.ge.com (12/17/90)

Posting-number: Volume 15, Issue 87
Submitted-by: davidsen@crdos1.crd.ge.com
Archive-name: g3g4/part02

#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file g3sdecod.c continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> g3sdecod.c
X	    }
X	  }
X	  else /* 01010... */
X	  {
X	    if (next_bit ()) /* 010101... */
X	    {
X	      if (next_bit ()) /* 0101011 */ return (25);
X	      else /* 0101010... */
X	      {
X		if (next_bit ()) /* 01010101 */ return (52);
X		else /* 01010100 */ return (51);
X	      }
X	    }
X	    else /* 010100... */
X	    {
X	      if (next_bit ()) /* 0101001... */
X	      {
X		if (next_bit ()) /* 01010011 */ return (50);
X		else /* 01010010 */ return (49);
X	      }
X	      else /* 0101000 */ return (24);
X	    }
X	  }
X	}
X	else /* 0100... */
X	{
X	  if (next_bit ()) /* 01001... */
X	  {
X	    if (next_bit ()) /* 010011... */
X	    {
X	      if (next_bit ()) /* 0100111 */ return (18);
X	      else /* 0100110... */
X	      {
X		if (next_bit ()) /* 01001101... */
X		{
X		  if (next_bit ()) /* 010011011 */ return (1728);
X		  else /* 010011010 */ return (1600);
X		}
X		else /* 01001100... */
X		{
X		  if (next_bit ()) /* 010011001 */ return (1536);
X		  else /* 010011000 */ return (1472);
X		}
X	      }
X	    }
X	    else /* 010010... */
X	    {
X	      if (next_bit ()) /* 0100101... */
X	      {
X		if (next_bit ()) /* 01001011 */ return (60);
X		else /* 01001010 */ return (59);
X	      }
X	      else /* 0100100 */ return (27);
X	    }
X	  }
X	  else /* 01000 */ return (11);
X	}
X      }
X    }
X    else /* 00... */
X    {
X      if (next_bit ()) /* 001... */
X      {
X	if (next_bit ()) /* 0011... */
X	{
X	  if (next_bit ()) /* 00111 */ return (10);
X	  else /* 00110... */
X	  {
X	    if (next_bit ()) /* 001101... */
X	    {
X	      if (next_bit ()) /* 0011011... */
X	      {
X		if (next_bit ()) /* 00110111 */ return (384);
X		else /* 00110110 */ return (320);
X	      }
X	      else /* 0011010... */
X	      {
X		if (next_bit ()) /* 00110101 */ return (0);
X		else /* 00110100 */ return (63);
X	      }
X	    }
X	    else /* 001100... */
X	    {
X	      if (next_bit ()) /* 0011001... */
X	      {
X		if (next_bit ()) /* 00110011 */ return (62);
X		else /* 00110010 */ return (61);
X	      }
X	      else /* 0011000 */ return (28);
X	    }
X	  }
X	}
X	else /* 0010... */
X	{
X	  if (next_bit ()) /* 00101... */
X	  {
X	    if (next_bit ()) /* 001011... */
X	    {
X	      if (next_bit ()) /* 0010111 */ return (21);
X	      else /* 0010110... */
X	      {
X		if (next_bit ()) /* 00101101 */ return (44);
X		else /* 00101100 */ return (43);
X	      }
X	    }
X	    else /* 001010... */
X	    {
X	      if (next_bit ()) /* 0010101... */
X	      {
X		if (next_bit ()) /* 00101011 */ return (42);
X		else /* 00101010 */ return (41);
X	      }
X	      else /* 0010100... */
X	      {
X		if (next_bit ()) /* 00101001 */ return (40);
X		else /* 00101000 */ return (39);
X	      }
X	    }
X	  }
X	  else /* 00100... */
X	  {
X	    if (next_bit ()) /* 001001... */
X	    {
X	      if (next_bit ()) /* 0010011 */ return (26);
X	      else /* 0010010... */
X	      {
X		if (next_bit ()) /* 00100101 */ return (54);
X		else /* 00100100 */ return (53);
X	      }
X	    }
X	    else /* 001000 */ return (12);
X	  }
X	}
X      }
X      else /* 000... */
X      {
X	if (next_bit ()) /* 0001... */
X	{
X	  if (next_bit ()) /* 00011... */
X	  {
X	    if (next_bit ()) /* 000111 */ return (1);
X	    else /* 000110... */
X	    {
X	      if (next_bit ()) /* 0001101... */
X	      {
X		if (next_bit ()) /* 00011011 */ return (32);
X		else /* 00011010 */ return (31);
X	      }
X	      else /* 0001100 */ return (19);
X	    }
X	  }
X	  else /* 00010... */
X	  {
X	    if (next_bit ()) /* 000101... */
X	    {
X	      if (next_bit ()) /* 0001011... */
X	      {
X		if (next_bit ()) /* 00010111 */ return (38);
X		else /* 00010110 */ return (37);
X	      }
X	      else /* 0001010... */
X	      {
X		if (next_bit ()) /* 00010101 */ return (36);
X		else /* 00010100 */ return (35);
X	      }
X	    }
X	    else /* 000100... */
X	    {
X	      if (next_bit ()) /* 0001001... */
X	      {
X		if (next_bit ()) /* 00010011 */ return (34);
X		else /* 00010010 */ return (33);
X	      }
X	      else /* 0001000 */ return (20);
X	    }
X	  }
X	}
X	else /* 0000... */
X	{
X	  if (next_bit ()) /* 00001... */
X	  {
X	    if (next_bit ()) /* 000011 */ return (13);
X	    else /* 000010... */
X	    {
X	      if (next_bit ()) /* 0000101... */
X	      {
X		if (next_bit ()) /* 00001011 */ return (48);
X		else /* 00001010 */ return (47);
X	      }
X	      else /* 0000100 */ return (23);
X	    }
X	  }
X	  else /* 00000... */
X	  {
X	    if (next_bit ()) /* 000001... */
X	    {
X	      if (next_bit ()) /* 0000011 */ return (22);
X	      else /* 0000010... */
X	      {
X		if (next_bit ()) /* 00000101 */ return (46);
X		else /* 00000100 */ return (45);
X	      }
X	    }
X	    else /* 000000... */
X	    {
X	      if (next_bit ()) /* 0000001... */
X	      {
X		if (next_bit ()) /* 00000011 */ return (30);
X		else /* 00000010 */ return (29);
X	      }
X	      else /* 0000 000... */
X	      {
X		if (next_bit ()) /* 0000 0001... */
X		{
X		  if (next_bit ()) /* 0000 0001 1... */
X		  {
X		    if (next_bit ()) /* 0000 0001 11... */
X		    {
X		      if (next_bit ()) /* 0000 0001 111... */
X		      {
X			if (next_bit ()) /* 0000 0001 1111 */ return (2560);
X			else /* 0000 0001 1110 */ return (2496);
X		      }
X		      else /* 0000 0001 110... */
X		      {
X			if (next_bit ()) /* 0000 0001 1101 */ return (2432);
X			else /* 0000 0001 1100 */ return (2368);
X		      }
X		    }
X		    else /* 0000 0001 10... */
X		    {
X		      if (next_bit ()) /* 0000 0001 101 */ return (1920);
X		      else /* 0000 0001 100 */ return (1856);
X		    }
X		  }
X		  else /* 0000 0001 0... */
X		  {
X		    if (next_bit ()) /* 0000 0001 01... */
X		    {
X		      if (next_bit ()) /* 0000 0001 011... */
X		      {
X			if (next_bit ()) /* 0000 0001 0111 */ return (2304);
X			else /* 0000 0001 0110 */ return (2240);
X		      }
X		      else /* 0000 0001 010... */
X		      {
X			if (next_bit ()) /* 0000 0001 0101 */ return (2176);
X			else /* 0000 0001 0100 */ return (2112);
X		      }
X		    }
X		    else /* 0000 0001 00... */
X		    {
X		      if (next_bit ()) /* 0000 0001 001... */
X		      {
X			if (next_bit ()) /* 0000 0001 0011 */ return (2048);
X			else /* 0000 0001 0010 */ return (1984);
X		      }
X		      else /* 0000 0001 000 */ return (1792);
X		    }
X		  }
X		}
X		else /* 0000 0000... */
X		{
X		  if (next_bit ()) /* 0000 0000 1 */ return (INVALID_CODE);
X		  else /* 0000 0000 0... */
X		  {
X		    if (next_bit ()) /* 0000 0000 01 */ return (INVALID_CODE);
X		    else /* 0000 0000 00... */
X		    {
X		      if (next_bit ()) /* 0000 0000 001 */
X							return (INVALID_CODE);
X		      else /* 0000 0000 000... */
X		      {
X			if (next_bit ()) /* 0000 0000 0001 */ return (EOL_CODE);
X			else /* 0000 0000 0000 */ /* return (INVALID_CODE); */
X			  /* normally this is an invalid code, but *if* we
X				assume the file has no errors, then we can
X				greatly simplify pad stripping with the
X				following... */
X			  for (;;) if (next_bit ()) return (EOL_CODE);
X		      }
X		    }
X		  }
X		}
X	      }
X	    }
X	  }
X	}
X      }
X    }
X  }
X}
X
X/*	end $RCSfile: g3sdecod.c $ */
SHAR_EOF
chmod 0644 g3sdecod.c || echo "restore of g3sdecod.c fails"
sed 's/^X//' << 'SHAR_EOF' > g3sencod.c &&
X/*	$Id: g3sencod.c 1.2 90/06/09 18:22:52 marking Exp $
X *
X NAME
X *	g3sencod.c -- encode group 3 data using nested if statements
X *
X TYPE
X *	C procedures
X *
X SYNOPSIS
X *	char	g3j_initialize (short image_width, short image_length);
X *	char	g3j_encode_new_row (void);
X *	char	g3j_encode_pad (char pad_type);
X *	char	g3j_encode_black (short);
X *	char	g3j_encode_white (short);
X *
X DESCRIPTION
X *	These routines are used to encode group 3 and group 4 images. (The
X *	encoding of group 4 also requires other routines in a separate file.)
X *
X RETURNS
X *
X LEGAL
X *	Copyright 1989, 1990 Michael P. Marking, Post Office Box 8039,
X *	Scottsdale, Arizona 85252-8039. All rights reserved.
X *
X *	License is granted by the copyright holder to distribute and use this
X *	code without payment of royalties or the necessity of notification as
X *	long as this notice (all the text under "LEGAL") is included.
X *
X *	Reference: $Id: g3sencod.c 1.2 90/06/09 18:22:52 marking Exp $
X *
X *	This program is offered without any warranty of any kind. It includes
X *	no warranty of merchantability or fitness for any purpose. Testing and
X *	suitability for any use are the sole responsibility of the user.
X * 
X HISTORY
X *	$Log:	g3sencod.c $
X * Revision 1.2  90/06/09  18:22:52  marking
X * clean up comments for release
X * 
X * Revision 1.1  89/06/30  17:00:00  marking
X * Initial revision
X * 
X *
X NOTES
X *	1.	Encode a pad to the next byte to flush the output buffer.
X *
X PORTABILITY
X *	Tested using Microsoft C 5.1. Some memory models may not work due to
X *	the large encoding arrays.
X *
X *	There is a non-portable use of "global" variables in the file g3g4.h,
X *	about which a minority of compilers will justifiably complain. Certain
X *	variables are declared in g3g4.h without extern keywords. Strictly
X *	speaking, they should be declared extern in all but one module, but
X *	that would require complication of g3g4.h. If it gets past your
X *	compiler and linker, you can probably ignore it.
X *
X SEE ALSO
X *	g4sencod.c -- encode group 4 image using nested if statements
X *
X INFORMATION
X *	Although there is no support offered with this program, the author will
X *	endeavor to correct errors. Updates will also be made available from
X *	time to time.
X *
X *	Contact: Michael P. Marking, Post Office Box 8039, Scottsdale, Arizona
X *	85252-8039 USA. Replies are not guaranteed to be swift. Beginning
X *	July 1990, e-mail may be sent to uunet!ipel!marking.
X *
X *	Also beginning in July 1990, this code will be archived at the
X *	ipel!phoenix BBS in file g3g4.zoo. The 24-hour telephone number
X *	for 300/1200/2400 is (602)274-0462. When logging in, specify user
X *	"public", system "bbs", and password "public".
X *
X *	This code is also available from the C Users Group in volume 317.
X *
X */
X
X#include "g3g4.h"
X
Xstatic short EOL_code = 0x0010, EOL_length = 12;
X
Xstatic short encode_black_code (short);
Xstatic short encode_white_code (short);
X
Xchar g3j_initialize (short image_width, short image_length)
X{
X  initialize_encode ();
X  return (0);
X}
X
Xchar g3j_encode_new_row (void)
X{
X  encode_word (EOL_code, EOL_length);
X  return (0);
X}
X
Xchar g3j_encode_pad (char pad_type)
X{
X  short bits_to_pad;
X  switch (pad_type)
X  {
X    case PAD_NONE:
X      break;
X    case PAD_BYTE:
X      if (encode_position) /* if not already on a byte boundary */
X	encode_word (0, 8 - encode_position);
X      break;
X    case PAD_NIBBLE:
X      bits_to_pad = (8 - encode_position) & 3;
X      if (bits_to_pad) encode_word (0, bits_to_pad);
X      break;
X    case PAD_ODD_NIBBLE:
X      if (encode_position > 0 && encode_position < 4)
X      {
X	bits_to_pad = 4 - encode_position;
X	encode_word (0, bits_to_pad);
X      }
X      else if (encode_position > 4)
X      {
X	bits_to_pad = 12 - encode_position;
X	encode_word (0, bits_to_pad);
X      }
X      break;
X    default:
X      break;
X  }
X  return (0);
X}
X
Xchar g3j_encode_black (short runlength)
X{
X  runlength = encode_black_code (runlength);
X  while (runlength) runlength = encode_black_code (runlength);
X  return (0);
X}
X
Xstatic short encode_black_code (short runlength)
X{
X  static short term_codes [64] =
X  {
X    0x0DC0, 0x4000, 0xC000, 0x8000, 0x6000, 0x3000,
X    0x2000, 0x1800, 0x1400, 0x1000, 0x0800, 0x0A00,
X    0x0E00, 0x0400, 0x0700, 0x0C00, 0x05C0, 0x0600,
X    0x0200, 0x0CE0, 0x0D00, 0x0D80, 0x06E0, 0x0500,
X    0x02E0, 0x0300, 0x0CA0, 0x0CB0, 0x0CC0, 0x0CD0,
X    0x0680, 0x0690, 0x06A0, 0x06B0, 0x0D20, 0x0D30,
X    0x0D40, 0x0D50, 0x0D60, 0x0D70, 0x06C0, 0x06D0,
X    0x0DA0, 0x0DB0, 0x0540, 0x0550, 0x0560, 0x0570,
X    0x0640, 0x0650, 0x0520, 0x0530, 0x0240, 0x0370,
X    0x0380, 0x0270, 0x0280, 0x0580, 0x0590, 0x02B0,
X    0x02C0, 0x05A0, 0x0660, 0x0670
X  };
X  static short makeup_codes [40] =
X  {
X    0x03C0, 0x0C80, 0x0C90, 0x05B0, 0x0330, 0x0340,
X    0x0350, 0x0360, 0x0368, 0x0250, 0x0258, 0x0260,
X    0x0268, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0,
X    0x03B8, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02D0,
X    0x02D8, 0x0320, 0x0328, 0x0100, 0x0180, 0x01A0,
X    0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170,
X    0x01C0, 0x01D0, 0x01E0, 0x01F0
X  };
X  static short term_lengths [64] =
X  {
X    10, 3, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10,
X    10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
X    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
X    12, 12, 12, 12, 12, 12, 12, 12, 12, 12
X  };
X  static short makeup_lengths [40] =
X  {
X    10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
X    13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 12, 12, 12, 12, 12, 12,
X    12, 12, 12, 12
X  };
X  short remaining;
X  if (runlength < 64)
X  {
X    encode_word (term_codes [runlength], term_lengths [runlength]);
X    return (0);
X  }
X  else if (runlength < 2561)
X  {
X    short x;
X    x = (runlength - 64) / 64;
X    encode_word (makeup_codes [x], makeup_lengths [x]);
X    remaining = runlength - (64 * (1 + x));
X    if (!remaining) encode_word (term_codes [0], term_lengths [0]);
X    return (remaining);
X  }
X  else
X  {
X    encode_word (makeup_codes [39], makeup_lengths [39]);
X    return (runlength - 2560);
X  }
X}
X
Xchar g3j_encode_white (short runlength)
X{
X  runlength = encode_white_code (runlength);
X  while (runlength) runlength = encode_white_code (runlength);
X  return (0);
X}
X
Xstatic short encode_white_code (short runlength)
X{
X  static short term_codes [64] =
X  {
X    0x3500, 0x1c00, 0x7000, 0x8000, 0xb000, 0xc000,
X    0xe000, 0xf000, 0x9800, 0xa000, 0x3800, 0x4000,
X    0x2000, 0x0c00, 0xd000, 0xd400, 0xa800, 0xac00,
X    0x4e00, 0x1800, 0x1000, 0x2e00, 0x0600, 0x0800,
X    0x5000, 0x5600, 0x2600, 0x4800, 0x3000, 0x0200,
X    0x0300, 0x1a00, 0x1b00, 0x1200, 0x1300, 0x1400,
X    0x1500, 0x1600, 0x1700, 0x2800, 0x2900, 0x2a00,
X    0x2b00, 0x2c00, 0x2d00, 0x0400, 0x0500, 0x0a00,
X    0x0b00, 0x5200, 0x5300, 0x5400, 0x5500, 0x2400,
X    0x2500, 0x5800, 0x5900, 0x5a00, 0x5b00, 0x4a00,
X    0x4b00, 0x3200, 0x3300, 0x3400
X  };
X  static short makeup_codes [40] =
X  {
X    0xd800, 0x9000, 0x5c00, 0x6e00, 0x3600, 0x3700,
X    0x6400, 0x6500, 0x6800, 0x6700, 0x6600, 0x6680,
X    0x6900, 0x6980, 0x6a00, 0x6a80, 0x6b00, 0x6b80,
X    0x6c00, 0x6c80, 0x6d00, 0x6d80, 0x4c00, 0x4c80,
X    0x4d00, 0x6000, 0x4d80, 0x0100, 0x0180, 0x01a0,
X    0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170,
X    0x01c0, 0x01d0, 0x01e0, 0x01f0
X  };
X  static short term_lengths [64] =
X  {
X    8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
X    7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
X  };
X  static short makeup_lengths [40] =
X  {
X    5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
X    9, 6, 9, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
X  };
X  short remaining;
X  if (runlength < 64)
X  {
X    encode_word (term_codes [runlength], term_lengths [runlength]);
X    return (0);
X  }
X  else if (runlength < 2561)
X  {
X    short x;
X    x = (runlength - 64) / 64;
X    encode_word (makeup_codes [x], makeup_lengths [x]);
X    remaining = runlength - (64 * (1 + x));
X    if (!remaining) encode_word (term_codes [0], term_lengths [0]);
X    return (remaining);
X  }
X  else
X  {
X    encode_word (makeup_codes [39], makeup_lengths [39]);
X    return (runlength - 2560);
X  }
X}
X
X/*	end $RCSfile: g3sencod.c $ */
SHAR_EOF
chmod 0644 g3sencod.c || echo "restore of g3sencod.c fails"
sed 's/^X//' << 'SHAR_EOF' > g3tdecod.c &&
X/*	$Id: g3tdecod.c 1.2 90/06/09 18:23:04 marking Exp $
X *
X NAME
X *	g3tdecod.c -- decode group 3 data using tables
X *
X TYPE
X *	C procedures
X *
X SYNOPSIS
X *	char	g3i_initialize (short image_width, short image_length);
X *	char	g3i_decode (void);	-- for standard group 3
X *	char	g3i_decode_T (void);	-- for TIFF g3 with no EOL chars
X *
X DESCRIPTION
X *	In order to acquire data from the image and to return run lengths and
X *	new line information, these routines invoke procedures provided by the
X *	caller. These caller-provided procedures are invoked throught pointers
X *	which have been stuffed by the caller with the procedure addresses.
X *	To acquire a new data byte, g3i_decode () and g3i_decode_T () call
X *	(*p_decode_next_byte) (). To report the decoding of a black or white
X *	run, the routines (*p_decode_black) () or (*p_decode_white) () are
X *	called.
X *
X RETURNS
X *	Initialization always returns zero.
X *
X *	For decoding,
X *		0	end of image reached
X *		-1	on error (bad data)
X *	The decode loop will be prematurely terminated if decode_return is
X *	set to not zero, and the value of decode_return will be returned.
X *	No code here does this, but it might be useful under certain
X *	circumstances.
X *
X LEGAL
X *	Copyright 1989, 1990 Michael P. Marking, Post Office Box 8039,
X *	Scottsdale, Arizona 85252-8039. All rights reserved.
X *
X *	License is granted by the copyright holder to distribute and use this
X *	code without payment of royalties or the necessity of notification as
X *	long as this notice (all the text under "LEGAL") is included.
X *
X *	Reference: $Id: g3tdecod.c 1.2 90/06/09 18:23:04 marking Exp $
X *
X *	This program is offered without any warranty of any kind. It includes
X *	no warranty of merchantability or fitness for any purpose. Testing and
X *	suitability for any use are the sole responsibility of the user.
X * 
X HISTORY
X *	$Log:	g3tdecod.c $
X * Revision 1.2  90/06/09  18:23:04  marking
X * clean up comments for release
X * 
X * Revision 1.1  89/06/30  17:00:00  marking
X * Initial revision
X * 
X *
X NOTES
X *
X PORTABILITY
X *	Tested using Microsoft C 5.1. Some memory models may not work due to
X *	the large decoding arrays.
X *
X *	There is a non-portable use of "global" variables in the file g3g4.h,
X *	about which a minority of compilers will justifiably complain. Certain
X *	variables are declared in g3g4.h without extern keywords. Strictly
X *	speaking, they should be declared extern in all but one module, but
X *	that would require complication of g3g4.h. If it gets past your
X *	compiler and linker, you can probably ignore it.
X *
X SEE ALSO
X *	g4tdecod.c -- decode group 4 image using tables
X *	builddec.c -- build image decoding tables
X *
X INFORMATION
X *	Although there is no support offered with this program, the author will
X *	endeavor to correct errors. Updates will also be made available from
X *	time to time.
X *
X *	Contact: Michael P. Marking, Post Office Box 8039, Scottsdale, Arizona
X *	85252-8039 USA. Replies are not guaranteed to be swift. Beginning
X *	July 1990, e-mail may be sent to uunet!ipel!marking.
X *
X *	Also beginning in July 1990, this code will be archived at the
X *	ipel!phoenix BBS in file g3g4.zoo. The 24-hour telephone number
X *	for 300/1200/2400 is (602)274-0462. When logging in, specify user
X *	"public", system "bbs", and password "public".
X *
X *	This code is also available from the C Users Group in volume 317.
X */
X
X#include "g3g4.h"
X
X/* #define TRACE 1 */
X#define TRACE_BEGIN 0
X#define TRACE_END 30000
X
Xstatic short bit_number, code_byte;
Xstatic unsigned char color, current_row, mode, next_state;
Xstatic short column_limit, row_limit;
Xstatic short row_number = 0, column_number;
X
Xextern unsigned char huge horiz_mode [] [256];
Xextern unsigned char huge horiz_mode_next_state [] [256];
X
Xstatic short new_row (void);
Xstatic short decode_white_run (void);
Xstatic short decode_black_run (void);
X
Xstatic char decode_return;
X
X/* g3i_decode () successively invokes (*p_decode_next_byte) () for each byte of the
X   encoded image, and calls (*p_decode_white) () or (*p_decode_black) () as
X   required to return the image contents on a run-by-run basis. */
X
Xchar g3i_decode ()
X{
X  short runlength;
X  while (!decode_return)
X  {
X    if (color == WHITE)
X    {
X      runlength = decode_white_run ();
X      if (runlength == -2) return (-1);
X      else if (runlength == -1)
X      {
X	if (new_row ()) return (0);
X      }
X      else
X      {
X	column_number += runlength;
X	(*p_decode_white) ((short) runlength);
X	color = BLACK;
X      }
X    }
X    else
X    {
X      runlength = decode_black_run ();
X      if (runlength == -2) return (-1);
X      else if (runlength == -1)
X      {
X	if (new_row ()) return (0);
X      }
X      else
X      {
X	column_number += runlength;
X	(*p_decode_black) ((short) runlength);
X	color = WHITE;
X      }
X    }
X  }
X  return (decode_return);
X}
X
X/* special version for TIFF files with no EOL characters */
Xchar g3i_decode_T ()
X{
X  short runlength;
X  while (!decode_return)
X  {
X    if (color == WHITE)
X    {
X      runlength = decode_white_run ();
X      if (runlength == -2) return (-1);
X      else if (runlength == -1)
X      {
X	if (new_row ()) return (0);
X      }
X      else
X      {
X	column_number += runlength;
X	(*p_decode_white) ((short) runlength);
X	color = BLACK;
X	if (column_number >= column_limit)
X	{
X	  if (new_row ()) return (0);
X	  bit_number = 0;
X	}
X      }
X    }
X    else
X    {
X      runlength = decode_black_run ();
X      if (runlength == -2) return (-1);
X      else if (runlength == -1)
X      {
X	if (new_row ()) return (0);
X      }
X      else
X      {
X	column_number += runlength;
X	(*p_decode_black) ((short) runlength);
X	color = WHITE;
X	if (column_number >= column_limit)
X	{
X	  if (new_row ()) return (0);
X	  bit_number = 0;
X	}
X      }
X    }
X  }
X  return (decode_return);
X}
X
X/* g3i_initialize () is called to set up to decode a new image.  All of the
X   static data (flags, etc) for g3i_decode () are initialized, allowing the
X   decoding of multiple images as long as g3i_initialize () is
X   called before each. */
Xchar g3i_initialize (short image_width, short image_length)
X{
X  color = WHITE;
X  bit_number= 0;
X  column_limit = image_width;
X  row_limit = image_length;
X  row_number = 0;
X  column_number = 0;
X  decode_return = 0;
X  return (0);
X}
X
Xstatic short new_row ()
X{
X  if (column_number)
X  {
X    (*p_decode_new_row) ();
X    color = WHITE;
X    if (++row_number >= row_limit) return (-1);
X    column_number = 0;
X    return (0);
X  }
X  else return (0);
X}
X
Xstatic short run_length_table [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
X  13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
X  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
X  51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 128, 192, 256, 320,
X  384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216,
X  1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984,
X  2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560};
X
Xstatic short decode_black_run ()
X{
X  short runlength, accum_runlength = 0;
X  next_state = (unsigned char) (bit_number + 8);
X  for (;;) /* exit with "return" */
X  {
X    if (!bit_number) code_byte = (*p_decode_next_byte) ();
X      /* this will fetch a new byte
X        if the previous codeword ended on a byte boundary */
X    mode = horiz_mode [next_state] [code_byte];
X    next_state = horiz_mode_next_state [next_state] [code_byte];
X    if (mode == 1) return (-2); /* invalid code */
X    else if (mode == 210)
X    {
X      bit_number = next_state;
X      return (-1);
X    }
X    else if (mode) /* if digestible */
X    {
X      bit_number = next_state;
X      runlength = run_length_table [mode - 106];
X      accum_runlength += runlength;
X      if (runlength < 64) return (accum_runlength);
X      next_state += 8;
X    }
X    else bit_number = 0;
X  }
X}
X
Xstatic short decode_white_run ()
X{
X  short runlength, accum_runlength = 0;
X  next_state = (unsigned char) bit_number;
X  for (;;) /* exit with "return" */
X  {
X    if (!bit_number) code_byte = (*p_decode_next_byte) ();
X      /* this will fetch a new byte
X        if the previous codeword ended on a byte boundary */
X    mode = horiz_mode [next_state] [code_byte];
X    next_state = horiz_mode_next_state [next_state] [code_byte];
X    if (mode == 1) return (-2); /* invalid code */
X    else if (mode == 210)
X    {
X      bit_number = next_state;
X      return (-1);
X    }
X    else if (mode) /* if digestible */
X    {
X      bit_number = next_state;
X      runlength = run_length_table [mode - 2];
X      accum_runlength += runlength;
X      if (runlength < 64) return (accum_runlength);
X    }
X    else bit_number = 0;
X  }
X}
X
X/*	end $RCSfile: g3tdecod.c $ */
SHAR_EOF
chmod 0644 g3tdecod.c || echo "restore of g3tdecod.c fails"
sed 's/^X//' << 'SHAR_EOF' > g4sdecod.c &&
X/*	$Id: g4sdecod.c 1.2 90/06/09 18:23:27 marking Exp $
X *
X NAME
X *	g4sdecod.c -- decode group 4 data using nested if statements
X *
X TYPE
X *	C procedures
X *
X SYNOPSIS
X *	char	g4i_initialize (short image_width, short image_length);
X *	char	g4i_decode (void);
X *
X DESCRIPTION
X *	In order to acquire data from the image and to return run lengths and
X *	new line information, these routines invoke procedures provided by the
X *	caller. These caller-provided procedures are invoked throught pointers
X *	which have been stuffed by the caller with the procedure addresses.
X *	To acquire a new data byte, g4i_decode () calls (*p_g4i_next_byte) ().
X *	To report the decoding of a black or white run, the routines
X *	(*p_decode_black) () or (*p_decode_white) () are called.
X *
X RETURNS
X *	Initialization always returns zero.
X *
X *	For decoding,
X *		0	end of image reached
X *		-1	on error (bad data)
X *	The decode loop will be prematurely terminated if decode_return is
X *	set to not zero, and the value of decode_return will be returned.
X *	No code here does this, but it might be useful under certain
X *	circumstances.
X *
X LEGAL
X *	Copyright 1989, 1990 Michael P. Marking, Post Office Box 8039,
X *	Scottsdale, Arizona 85252-8039. All rights reserved.
X *
X *	License is granted by the copyright holder to distribute and use this
X *	code without payment of royalties or the necessity of notification as
X *	long as this notice (all the text under "LEGAL") is included.
X *
X *	Reference: $Id: g4sdecod.c 1.2 90/06/09 18:23:27 marking Exp $
X *
X *	This program is offered without any warranty of any kind. It includes
X *	no warranty of merchantability or fitness for any purpose. Testing and
X *	suitability for any use are the sole responsibility of the user.
X * 
X HISTORY
X *	$Log:	g4sdecod.c $
X * Revision 1.2  90/06/09  18:23:27  marking
X * clean up comments for release
X * 
X * Revision 1.1  90/05/01  02:00:00  marking
X * Initial revision
X * 
X *
X NOTES
X *
X PORTABILITY
X *	Tested using Microsoft C 5.1. Some memory models may not work due to
X *	the large decoding arrays.
X *
X *	There is a non-portable use of "global" variables in the file g3g4.h,
X *	about which a minority of compilers will justifiably complain. Certain
X *	variables are declared in g3g4.h without extern keywords. Strictly
X *	speaking, they should be declared extern in all but one module, but
X *	that would require complication of g3g4.h. If it gets past your
X *	compiler and linker, you can probably ignore it.
X *
X SEE ALSO
X *	g3tdecod.c -- decode group 3 image using tables
X *	builddec.c -- build image decoding tables
X *
X INFORMATION
X *	Although there is no support offered with this program, the author will
X *	endeavor to correct errors. Updates will also be made available from
X *	time to time.
X *
X *	Contact: Michael P. Marking, Post Office Box 8039, Scottsdale, Arizona
X *	85252-8039 USA. Replies are not guaranteed to be swift. Beginning
X *	July 1990, e-mail may be sent to uunet!ipel!marking.
X *
X *	Also beginning in July 1990, this code will be archived at the
X *	ipel!phoenix BBS in file g3g4.zoo. The 24-hour telephone number
X *	for 300/1200/2400 is (602)274-0462. When logging in, specify user
X *	"public", system "bbs", and password "public".
X *
X *	This code is also available from the C Users Group in volume 317.
X */
X
X#include "g3g4.h"
X
X/* #define TRACE 1 */
X
X/* implementation limits: Due to the sizes of arrays and variables, and not
X   due to any restrictions in the algorithm, the following limits exist:
X     maximum number of pixels per row: 65533
X     maximum number of rows per image: none
X     maximum or minimum k-factor: none
X     maximum number of runs per row: 16382 white, 16382 black
X   To increase (or decrease) these limits, it will be necessary to play with
X   array and variable sizes.  On segmented machines (such as the 8086), a
X   different memory model may be necessary.  The algorithm itself has no
X   limits on image size or complexity, and the stack requirements are in-
X   sensitive to changes in these limits or to image complexity. */
X
X#define EVEN 0
X#define ODD 1
X
Xstatic short a0, a1, a2, b0, b1, b2, bit_number, code_byte;
Xstatic unsigned char color, current_row, mode;
Xstatic unsigned short even_runs [32768], odd_runs [32768];
Xstatic unsigned short even_index, odd_index;
Xstatic short column_limit;
Xstatic short row_number = 0;
X  /* Depending as current_row == EVEN or current_row == ODD, the runs of the
X     current row are represented in even_runs [] or odd_runs [].  The white
X     runs have even subscripts and the black runs have odd subscripts.  The
X     values of the array elements are the offsets of the beginnings of the
X     corresponding runs from the beginning of the row.  As defined by the
X     specification,
X	a0 is the reference or starting changing element on the coding line.
X		It may be considered the "current position".
X	a1 is the next changing element to the right of a0 on the coding line.
X	a2 is the next changing element to the right of a1 on the coding line.
X	b1 is the first changing element on the reference line to the right of
X		a0 and of opposite color to a0.
X	b2 is the next changing element to the right of b1 on the reference
X		line.
X     Furthermore,
X	b0 is the "previous" value of b1. 
X     Depending as current_row == EVEN or == ODD, even_index or odd_index is
X     the subscript of the entry in even_runs [] or odd_runs [] corresponding
X     to the run containing the current value of a0, and its counterpart cor-
X     responds to the run containing b1. */
X
Xstatic void new_row (void);
Xstatic short decode_white_run (void);
Xstatic short decode_black_run (void);
Xstatic short decode_white_word (void);
Xstatic short decode_black_word (void);
Xstatic char next_bit (void);
Xstatic short null_mode (void);
X
Xstatic char decode_return;
X
X/* g4i_decode () successively invokes (*p_decode_next_byte) () for each byte of the
X   encoded image, and calls (*p_decode_white) () or (*p_decode_black) () as
X   required to return the image contents on a run-by-run basis. */
Xchar g4i_decode ()
X{
X  /* At the beginning of this routine, we are in the NULL mode, which is to
X     to say that no codewords are currently understood or digested.  The
X     variable bit_number has been initialized to zero, to indicate that the
X     next (first) codeword is to begin with bit zero of the next code byte.
X     This betrays an assumption that all images begin on byte boundaries, a
X     condition that can be changed by arranging for bit_number to be set
X     otherwise by g4i_initialize () or elsewhere. */
X  while (!decode_return)
X  {
X    mode = (unsigned char) null_mode ();
X    if (current_row == EVEN)
X    {
X      b0 = b1;
X      b1 = odd_runs [odd_index];
X      if ((b1 <= a0) && a0)
X      {
X	odd_index += 2;
X	b0 = odd_runs [odd_index - 1];
X	b1 = odd_runs [odd_index];
X      }
X      b2 = odd_runs [odd_index + 1];
X    }
X    else /* current_row == ODD */
X    {
X      b0 = b1;
X      b1 = even_runs [even_index];
X      if ((b1 <= a0) && a0)
X      {
X	even_index += 2;
X	b0 = even_runs [even_index - 1];
X	b1 = even_runs [even_index];
X      }
X      b2 = even_runs [even_index + 1];
X    }
X    #if defined (TRACE)
X      if (trace_flag)
X      {
X	if (current_row == EVEN)
X	{
X	  printf ("\n ref_index=%hd b1=%hd b2=%hd a0=%hd curr[%hd]=%hd "
X	    "color=%hd ",
X	    odd_index, b1, b2, a0, even_index, even_runs [even_index],
X	    (short) color);
X	}
X	else /* current_row == ODD */
X	{
X	  printf ("\n ref_index=%hd b1=%hd b2=%hd a0=%hd curr[%hd]=%hd "
X	    "color=%hd ",
X	    even_index, b1, b2, a0, odd_index, odd_runs [odd_index],
X	    (short) color);
X	}
X      }
X    #endif
X    switch (mode)
X    {
X      case PASS_MODE: /* skip (pass) two color changes on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" P ");
X	#endif
X	if (color == WHITE) (*p_decode_white) ((short) (b2 - a0));
X	else /* color == BLACK */ (*p_decode_black) ((short) (b2 - a0));
X	a0 = b2;
X	if (current_row == EVEN)
X	{
X	  odd_index += 2;
X	  b1 = odd_runs [odd_index];
X	}
X	else /* current_row == ODD */
X	{
X	  even_index += 2;
X	  b1 = even_runs [even_index];
X	}
X	break;
X      case HORIZONTAL_MODE: /* revert to 1-dimensional modified Huffman
X	encoding for a pair of runs */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" H ");
X	#endif
X	if (color == WHITE)
X	{
X	  short black_runlength, white_runlength;
X	  white_runlength = decode_white_run ();
X	  (*p_decode_white) ((short) white_runlength);
X	  a1 = (a0 += white_runlength);
X	  black_runlength = decode_black_run ();
X	  (*p_decode_black) ((short) black_runlength);
X	  a2 = (a0 += black_runlength);
X	}
X	else /* color == BLACK */
X	{
X	  short black_runlength, white_runlength;
X	  black_runlength = decode_black_run ();
X	  (*p_decode_black) ((short) black_runlength);
X	  a1 = (a0 += black_runlength);
X	  white_runlength = decode_white_run ();
X	  (*p_decode_white) ((short) white_runlength);
X	  a2 = (a0 += white_runlength);
X	}
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a1;
X	  even_runs [++even_index] = a2;
X	  while (a0 > odd_runs [odd_index]) odd_index += 2;
X	  b1 = odd_runs [odd_index];
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a1;
X	  odd_runs [++odd_index] = a2;
X	  while (a0 > even_runs [even_index]) even_index += 2;
X	  b1 = even_runs [even_index];
X	}
X	break;
X      case VERTICAL_V0_MODE: /* the next color change begins at the same
X	location as in the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" V0 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0));
X	  color = WHITE;
X	}
X	a0 = b1; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  even_index++;
X	}
X	break;
X      case VERTICAL_VR1_MODE: /* the next color change begins one pixel to the
X	right of its location on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" VR1 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0 + 1));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0 + 1));
X	  color = WHITE;
X	}
X	a0 = b1 + 1; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  even_index++;
X	}
X	break;
X      case VERTICAL_VR2_MODE: /* the next color change begins two pixels to
X	the right of its location on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" VR2 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0 + 2));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0 + 2));
X	  color = WHITE;
X	}
X	a0 = b1 + 2; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  even_index++;
X	}
X	break;
X      case VERTICAL_VR3_MODE: /* the next color change begins three pixels to
X	the right of its location on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" VR3 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0 + 3));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0 + 3));
X	  color = WHITE;
X	}
X	a0 = b1 + 3; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  even_index++;
X	}
X	break;
X      case VERTICAL_VL1_MODE: /* the next color change begins one pixel to the
X	left of its location on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" VL1 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0 - 1));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0 - 1));
X	  color = WHITE;
X	}
X	a0 = b1 - 1; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  even_index++;
X	}
X	break;
X      case VERTICAL_VL2_MODE: /* the next color change begins two pixels to
X	the left of its location on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" VL2 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0 - 2));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0 - 2));
X	  color = WHITE;
X	}
X	a0 = b1 - 2; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  if (a0 < b0) odd_index--;
X	  else odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  if (a0 < b0) even_index--;
X	  else even_index++;
X	}
X	break;
X      case VERTICAL_VL3_MODE: /* the next color change begins three pixels to
X	the left of its location on the previous row */
X	#if defined (TRACE)
X	  if (trace_flag) printf (" VL3 ");
X	#endif
X	if (color == WHITE)
X	{
X	  (*p_decode_white) ((short) (b1 - a0 - 3));
X	  color = BLACK;
X	}
X	else /* color == BLACK */
X	{
X	  (*p_decode_black) ((short) (b1 - a0 - 3));
X	  color = WHITE;
X	}
X	a0 = b1 - 3; 
X	if (current_row == EVEN)
X	{
X	  even_runs [++even_index] = a0;
X	  if (a0 < b0) odd_index--;
X	  else odd_index++;
X	}
X	else /* current_row == ODD */
X	{
X	  odd_runs [++odd_index] = a0;
X	  if (a0 < b0) even_index--;
X	  else even_index++;
X	}
X	break;
X      case EXT_MODE_UNCOMPRESSED: /* enter extension type 7 ("111"), an
X	uncompressed encoding scheme */
X	return (ERROR_UNSUPPORTED_EXTENSION);
X	break;
X      case ERROR_MODE: /* The bit pattern found corresponds to an unknown or
X	invalid codeword.  This MAY be one of the seven possible extensions
X	not defined by the specification. */
X	return (ERROR_INVALID_CODEWORD);
X	break;
X      case ERROR_MODE_1: /* assumed in this implementation to be equivalent
X	to EOFB (end-of-facsimile-block) */
X	return (RETURN_OK);
X	break;
X      default: /* we should never get here; if we do, the tables are bad */
X	return (ERROR_PROGRAM_LOGIC);
X	break;
X    }
X    if (a0 >= column_limit) new_row ();
X  }
X  return (decode_return);
X}
X
X/* g4i_initialize () is called to set up to decode a new image.  All of the
X   static data (flags, etc) for g4i_decode () are initialized, allowing the
X   decoding of multiple images in a run as long as g4i_initialize () is
X   called before each one. */
Xchar g4i_initialize (short image_width, short image_length)
X{
X  color = WHITE;
X  bit_number= 0;
X  current_row = ODD;
X  even_runs [0] = 0;
X  even_runs [1] = image_width; /* initial b1 */
X  even_runs [2] = image_width; /* initial b2 */
X  odd_runs [0] = 0;
X  a0 = 0;
X  even_index = 1; odd_index = 0;
X  column_limit = image_width;
X  row_number = 0;
X  b1 = -1;
X  decode_return = 0;
X  return (0);
X}
X
Xstatic short null_mode ()
X{
X  if (next_bit ()) /* 1 */ return (VERTICAL_V0_MODE);
X  else /* 0... */
X  {
X    if (next_bit ()) /* 01... */
X    {
X      if (next_bit ()) /* 011 */ return (VERTICAL_VR1_MODE);
X      else /* 010 */ return (VERTICAL_VL1_MODE);
X    }
X    else /* 00... */
X    {
X      if (next_bit ()) /* 001 */ return (HORIZONTAL_MODE);
X      else /* 000... */
X      {
X	if (next_bit ()) /* 0001 */ return (PASS_MODE);
X	else /* 0000... */
X	{
X	  if (next_bit ()) /* 0000 1... */
X	  {
X	    if (next_bit ()) /* 0000 11 */ return (VERTICAL_VR2_MODE);
X	    else /* 0000 10 */ return (VERTICAL_VL2_MODE);
X	  }
X	  else /* 0000 0... */
X	  {
X	    if (next_bit ()) /* 0000 01... */
X	    {
X	      if (next_bit ()) /* 0000 011 */ return (VERTICAL_VR3_MODE);
X	      else /* 0000 010 */ return (VERTICAL_VL3_MODE);
X	    }
X	    else /* 0000 00... */
X	    {
X	      if (next_bit ()) /* 0000 001... */
X	      {
X		if (next_bit ()) /* 0000 0011... */
X		{
X		  if (next_bit ()) /* 0000 0011 1... */
X		  {
X		    if (next_bit ()) /* 0000 0011 11 */
X					return (EXT_MODE_UNCOMPRESSED);
X		    else /* 0000 0011 10 */ return (ERROR_MODE);
X		  }
X		  else /* 0000 0011 0 */ return (ERROR_MODE);
X		}
X		else /* 0000 0010 */ return (ERROR_MODE);
X	      }
X	      else /* 0000 000 */ return (ERROR_MODE_1);
X		/* under the assumption that there are no errors in the file,
X			then this bit string can only be the beginning of an
X			EOFB (end-of-facsimile-block) code */
X	    }
X	  }
X	}
X      }
X    }
X  }
X  return (-1);
X}
X
Xstatic void new_row ()
X{
X  (*p_decode_new_row) ();
X  color = WHITE;
X  if (current_row == ODD)
X  {
X    current_row = EVEN;
X    odd_runs [++odd_index] = a0;
X    odd_runs [++odd_index] = a0;
X    odd_index = 1;
X    even_index = 0;
X  }
X  else /* current_row == EVEN */
X  {
X    current_row = ODD;
X    even_runs [++even_index] = a0;
X    even_runs [++even_index] = a0;
X    even_index = 1;
X    odd_index = 0;
X  }
X  a0 = 0;
X  b1 = -1;
X  #if defined (TRACE)
X    row_number++;
X  #endif
X}
X
Xstatic char next_bit (void)
X{
X  char value;
X  static unsigned char decode_mask [8] =
X    { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
X  if (!bit_number) code_byte = (*p_decode_next_byte) ();
X  if ((unsigned char) code_byte & decode_mask [bit_number]) value = 1;
X  else value = 0;
X  if (++bit_number > 7) bit_number = 0;
X  return (value);
X}
X
X/*
X *	return the length of the next run, assumed to be black
X */
X
Xstatic short decode_black_run ()
X{
X  short cumulative = 0, code_value;
X  for (;;)
X  {
X    code_value = decode_black_word ();
X    cumulative += code_value;
X    if (code_value < 0) return (code_value);
X    if (code_value < 64) return (cumulative);
X  }
X}
X
Xstatic short decode_black_word ()
X{
X  if (next_bit ()) /* 1... */
X  {
X    if (next_bit ()) /* 11 */ return (2);
X    else /* 10 */ return (3);
X  }
X  else /* 0... */
X  {
X    if (next_bit ()) /* 01... */
X    {
X      if (next_bit ()) /* 011 */ return (4);
X      else /* 010 */ return (1);
X    }
X    else /* 00... */
X    {
X      if (next_bit ()) /* 001... */
X      {
X	if (next_bit ()) /* 0011 */ return (5);
X	else /* 0010 */ return (6);
X      }
X      else /* 000... */
X      {
X	if (next_bit ()) /* 0001... */
X	{
X	  if (next_bit ()) /* 0001 1 */ return (7);
X	  else /* 0001 0... */
X	  {
X	    if (next_bit ()) /* 0001 01 */ return (8);
X	    else /* 0001 00 */ return (9);
X	  }
X	}
X	else /* 0000... */
X	{
X	  if (next_bit ()) /* 0000 1... */
X	  {
X	    if (next_bit ()) /* 0000 11... */
X	    {
X	      if (next_bit ()) /* 0000 111 */ return (12);
X	      else /* 0000 110... */
X	      {
X		if (next_bit ()) /* 0000 1101... */
X		{
X		  if (next_bit ()) /* 0000 1101 1... */
X		  {
X		    if (next_bit ()) /* 0000 1101 11 */ return (0);
X		    else /* 0000 1101 10... */
X		    {
X		      if (next_bit ()) /* 0000 1101 101... */
X		      {
X			if (next_bit ()) /* 0000 1101 1011 */ return (43);
X			else /* 0000 1101 1010 */ return (42);
X		      }
X		      else /* 0000 1101 100 */ return (21);
X		    }
X		  }
X		  else /* 0000 1101 0... */
X		  {
X		    if (next_bit ()) /* 0000 1101 01... */
X		    {
X		      if (next_bit ()) /* 0000 1101 011... */
X		      {
X			if (next_bit ()) /* 0000 1101 0111 */ return (39);
X			else /* 0000 1101 0110 */ return (38);
X		      }
X		      else /* 0000 1101 010... */
X		      {
X			if (next_bit ()) /* 0000 1101 0101 */ return (37);
X			else /* 0000 1101 0100 */ return (36);
X		      }
X		    }
X		    else /* 0000 1101 00... */
X		    {
X		      if (next_bit ()) /* 0000 1101 001... */
X		      {
X			if (next_bit ()) /* 0000 1101 0011 */ return (35);
X			else /* 0000 1101 0010 */ return (34);
X		      }
X		      else /* 0000 1101 000 */ return (20);
X		    }
X		  }
X		}
X		else /* 0000 1100... */
X		{
X		  if (next_bit ()) /* 0000 1100 1... */
X		  {
X		    if (next_bit ()) /* 0000 1100 11... */
X		    {
X		      if (next_bit ()) /* 0000 1100 111 */ return (19);
X		      else /* 0000 1100 110... */
X		      {
X			if (next_bit ()) /* 0000 1100 1101 */ return (29);
X			else /* 0000 1100 1100 */ return (28);
X		      }
X		    }
X		    else /* 0000 1100 10... */
X		    {
X		      if (next_bit ()) /* 0000 1100 101.. */
X		      {
X			if (next_bit ()) /* 0000 1100 1011 */ return (27);
X			else /* 0000 1100 1010 */ return (26);
X		      }
X		      else /* 0000 1100 100... */
X		      {
X			if (next_bit ()) /* 0000 1100 1001 */ return (192);
X			else /* 0000 1100 1000 */ return (128);
X		      }
X		    }
X		  }
X		  else /* 0000 1100 0 */ return (15);
X		}
X	      }
X	    }
X	    else /* 0000 10... */
X	    {
X	      if (next_bit ()) /* 0000 101 */ return (11);
X	      else /* 0000 100 */ return (10);
X	    }
X	  }
X	  else /* 0000 0... */
X	  {
X	    if (next_bit ()) /* 0000 01... */
X	    {
X	      if (next_bit ()) /* 0000 011... */
X	      {
X		if (next_bit ()) /* 0000 0111 */ return (14);
X		else /* 0000 0110... */
X		{
X		  if (next_bit ()) /* 0000 0110 1... */
X		  {
X		    if (next_bit ()) /* 0000 0110 11... */
X		    {
X		      if (next_bit ()) /* 0000 0110 111 */ return (22);
X		      else /* 0000 0110 110... */
X		      {
X			if (next_bit ()) /* 0000 0110 1101 */ return (41);
X			else /* 0000 0110 1100 */ return (40);
X		      }
X		    }
X		    else /* 0000 0110 10... */
X		    {
X		      if (next_bit ()) /* 0000 0110 101... */
X		      {
X			if (next_bit ()) /* 0000 0110 1011 */ return (33);
X			else /* 0000 0110 1010 */ return (32);
X		      }
X		      else /* 0000 0110 100... */
X		      {
X			if (next_bit ()) /* 0000 0110 1001 */ return (31);
X			else /* 0000 0110 1000 */ return (30);
X		      }
X		    }
X		  }
X		  else /* 0000 0110 0... */
X		  {
X		    if (next_bit ()) /* 0000 0110 01... */
X		    {
X		      if (next_bit ()) /* 0000 0110 011... */
X		      {
X			if (next_bit ()) /* 0000 0110 0111 */ return (63);
X			else /* 0000 0110 0110 */ return (62);
X		      }
X		      else /* 0000 0110 010... */
X		      {
X			if (next_bit ()) /* 0000 0110 0101 */ return (49);
X			else /* 0000 0110 0100 */ return (48);
X		      }
X		    }
X		    else /* 0000 0110 00 */ return (17);
X		  }
X		}
X	      }
X	      else /* 0000 010... */
X	      {
X		if (next_bit ()) /* 0000 0101... */
X		{
X		  if (next_bit ()) /* 0000 0101 1... */
X		  {
X		    if (next_bit ()) /* 0000 0101 11 */ return (16);
X		    else /* 0000 0101 10... */
X		    {
X		      if (next_bit ()) /* 0000 0101 101... */
X		      {
X			if (next_bit ()) /* 0000 0101 1011 */ return (256);
X			else /* 0000 0101 1010 */ return (61);
X		      }
X		      else /* 0000 0101 100... */
X		      {
X			if (next_bit ()) /* 0000 0101 1001 */ return (58);
X			else /* 0000 0101 1000 */ return (57);
X		      }
X		    }
X		  }
X		  else /* 0000 0101 0... */
X		  {
X		    if (next_bit ()) /* 0000 0101 01... */
X		    {
X		      if (next_bit ()) /* 0000 0101 011... */
X		      {
X			if (next_bit ()) /* 0000 0101 0111 */ return (47);
X			else /* 0000 0101 0110 */ return (46);
X		      }
X		      else /* 0000 0101 010... */
X		      {
X			if (next_bit ()) /* 0000 0101 0101 */ return (45);
X			else /* 0000 0101 0100 */ return (44);
X		      }
X		    }
X		    else /* 0000 0101 00... */
X		    {
X		      if (next_bit ()) /* 0000 0101 001... */
X		      {
X			if (next_bit ()) /* 0000 0101 0011 */ return (51);
X			else /* 0000 0101 0010 */ return (50);
X		      }
X		      else /* 0000 0101 000 */ return (23);
X		    }
X		  }
X		}
X		else /* 0000 0100 */ return (13);
X	      }
X	    }
X	    else /* 0000 00... */
X	    {
X	      if (next_bit ()) /* 0000 001... */
X	      {
X		if (next_bit ()) /* 0000 0011... */
X		{
X		  if (next_bit ()) /* 0000 0011 1... */
X		  {
X		    if (next_bit ()) /* 0000 0011 11 */ return (64);
X		    else /* 0000 0011 10... */
X		    {
X		      if (next_bit ()) /* 0000 0011 101... */
X		      {
X			if (next_bit ()) /* 0000 0011 1011... */
X			{
X			  if (next_bit ()) /* 0000 0011 1011 1 */ return (1216);
X			  else /* 0000 0011 1011 0 */ return (1152);
X			}
X			else /* 0000 0011 1010... */
X			{
X			  if (next_bit ()) /* 0000 0011 1010 1 */ return (1088);
X			  else /* 0000 0011 1010 0 */ return (1024);
X			}
X		      }
X		      else /* 0000 0011 100... */
X		      {
X			if (next_bit ()) /* 0000 0011 1001... */
X			{
X			  if (next_bit ()) /* 0000 0011 1001 1 */ return (960);
X			  else /* 0000 0011 1001 0 */ return (896);
X			}
X			else /* 0000 0011 1000 */ return (54);
X		      }
X		    }
X		  }
X		  else /* 0000 0011 0... */
X		  {
X		    if (next_bit ()) /* 0000 0011 01... */
X		    {
X		      if (next_bit ()) /* 0000 0011 011... */
X		      {
X			if (next_bit ()) /* 0000 0011 0111 */ return (53);
X			else /* 0000 0011 0110... */
X			{
X			  if (next_bit ()) /* 0000 0011 0110 1 */ return (576);
X			  else /* 0000 0011 0110 0 */ return (512);
X			}
X		      }
X		      else /* 0000 0011 010... */
X		      {
X			if (next_bit ()) /* 0000 0011 0101 */ return (448);
X			else /* 0000 0011 0100 */ return (384);
X		      }
X		    }
X		    else /* 0000 0011 00... */
X		    {
X		      if (next_bit ()) /* 0000 0011 001... */
X		      {
X			if (next_bit ()) /* 0000 0011 0011 */ return (320);
X			else /* 0000 0011 0010... */
X			{
X			  if (next_bit ()) /* 0000 0011 0010 1 */ return (1728);
X			  else /* 0000 0011 0010 0 */ return (1664);
X			}
X		      }
X		      else /* 0000 0011 000 */ return (25);
X		    }
X		  }
X		}
X		else /* 0000 0010... */
X		{
X		  if (next_bit ()) /* 0000 0010 1... */
X		  {
X		    if (next_bit ()) /* 0000 0010 11... */
X		    {
X		      if (next_bit ()) /* 0000 0010 111 */ return (24);
X		      else /* 0000 0010 110... */
X		      {
X			if (next_bit ()) /* 0000 0010 1101... */
X			{
X			  if (next_bit ()) /* 0000 0010 1101 1 */ return (1600);
X			  else /* 0000 0010 1101 0 */ return (1536);
X			}
X			else /* 0000 0010 1100 */ return (60);
X		      }
X		    }
X		    else /* 0000 0010 10... */
X		    {
X		      if (next_bit ()) /* 0000 0010 101... */
X		      {
X			if (next_bit ()) /* 0000 0010 1011 */ return (59);
X			else /* 0000 0010 1010... */
X			{
X			  if (next_bit ()) /* 0000 0010 1010 1 */ return (1472);
X			  else /* 0000 0010 1010 0 */ return (1408);
X			}
X		      }
X		      else /* 0000 0010 100... */
X		      {
X			if (next_bit ()) /* 0000 0010 1001... */
X			{
X			  if (next_bit ()) /* 0000 0010 1001 1 */ return (1344);
X			  else /* 0000 0010 1001 0 */ return (1280);
X			}
X			else /* 0000 0010 1000 */ return (56);
X		      }
X		    }
X		  }
X		  else /* 0000 0010 0... */
X		  {
X		    if (next_bit ()) /* 0000 0010 01... */
X		    {
X		      if (next_bit ()) /* 0000 0010 011... */
X		      {
X			if (next_bit ()) /* 0000 0010 0111 */ return (55);
X			else /* 0000 0010 0110... */
X			{
X			  if (next_bit ()) /* 0000 0010 0110 1 */ return (832);
X			  else /* 0000 0010 0110 0 */ return (768);
X			}
X		      }
X		      else /* 0000 0010 010... */
X		      {
X			if (next_bit ()) /* 0000 0010 0101... */
X			{
X			  if (next_bit ()) /* 0000 0010 0101 1 */ return (704);
X			  else /* 0000 0010 0101 0 */ return (640);
X			}
X			else /* 0000 0010 0100 */ return (52);
X		      }
X		    }
X		    else /* 0000 0010 00 */ return (18);
X		  }
X		}
X	      }
X	      else /* 0000 000... */
X	      {
X		if (next_bit ()) /* 0000 0001... */
X		{
X		  if (next_bit ()) /* 0000 0001 1... */
X		  {
X		    if (next_bit ()) /* 0000 0001 11... */
X		    {
X		      if (next_bit ()) /* 0000 0001 111... */
X		      {
X			if (next_bit ()) /* 0000 0001 1111 */ return (2560);
X			else /* 0000 0001 1110 */ return (2496);
X		      }
X		      else /* 0000 0001 110... */
X		      {
X			if (next_bit ()) /* 0000 0001 1101 */ return (2432);
X			else /* 0000 0001 1100 */ return (2368);
X		      }
X		    }
X		    else /* 0000 0001 10... */
X		    {
X		      if (next_bit ()) /* 0000 0001 101 */ return (1920);
X		      else /* 0000 0001 100 */ return (1856);
X		    }
X		  }
X		  else /* 0000 0001 0... */
X		  {
X		    if (next_bit ()) /* 0000 0001 01... */
X		    {
X		      if (next_bit ()) /* 0000 0001 011... */
X		      {
X			if (next_bit ()) /* 0000 0001 0111 */ return (2304);
X			else /* 0000 0001 0110 */ return (2240);
X		      }
X		      else /* 0000 0001 010... */
X		      {
X			if (next_bit ()) /* 0000 0001 0101 */ return (2176);
X			else /* 0000 0001 0100 */ return (2112);
X		      }
X		    }
X		    else /* 0000 0001 00... */
X		    {
X		      if (next_bit ()) /* 0000 0001 001... */
X		      {
X			if (next_bit ()) /* 0000 0001 0011 */ return (2048);
X			else /* 0000 0001 0010 */ return (1984);
X		      }
X		      else /* 0000 0001 000 */ return (1792);
X		    }
X		  }
X		}
X		else /* 0000 0000... */
X		{
X		  if (next_bit ()) /* 0000 0000 1 */ return (INVALID_CODE);
X		  else /* 0000 0000 0... */
X		  {
X		    if (next_bit ()) /* 0000 0000 01 */ return (INVALID_CODE);
X		    else /* 0000 0000 00... */
X		    {
X		      if (next_bit ()) /* 0000 0000 001 */
X							return (INVALID_CODE);
X		      else /* 0000 0000 000... */
X		      {
X			if (next_bit ()) /* 0000 0000 0001 */ return (EOL_CODE);
X			else /* 0000 0000 0000 */ return (INVALID_CODE);
X		      }
X		    }
X		  }
X		}
X	      }
X	    }
X	  }
X	}
X      }
X    }
X  }
X}
X
X/*
X *	return the length of the next run, assumed to be white 
X */
X
Xstatic short decode_white_run ()
X{
X  short cumulative = 0, code_value;
X  for (;;)
X  {
X    code_value = decode_white_word ();
X    cumulative += code_value;
X    if (code_value < 0) return (code_value);
X    if (code_value < 64) return (cumulative);
X  }
X}
X
Xstatic short decode_white_word ()
X{
X  if (next_bit ()) /* 1... */
X  {
X    if (next_bit ()) /* 11... */
X    {
X      if (next_bit ()) /* 111... */
X      {
X	if (next_bit ()) /* 1111 */ return (7);
X	else /* 1110 */ return (6);
X      }
X      else /* 110... */
X      {
X	if (next_bit ()) /* 1101... */
X	{
X	  if (next_bit ()) /* 1101 1 */ return (64);
X	  else /* 1101 0... */
X	  {
X	    if (next_bit ()) /* 1101 01 */ return (15);
X	    else /* 1101 00 */ return (14);
X	  }
X	}
X	else /* 1100 */ return (5);
X      }
X    }
X    else /* 10... */
X    {
X      if (next_bit ()) /* 101... */
X      {
X	if (next_bit ()) /* 1011 */ return (4);
X	else /* 1010... */
X	{
X	  if (next_bit ()) /* 10101... */
X	  {
X	    if (next_bit ()) /* 101011 */ return (17);
X	    else /* 101010 */ return (16);
X	  }
X	  else /* 10100 */ return (9);
X	}
X      }
X      else /* 100... */
X      {
X	if (next_bit ()) /* 1001... */
X	{
X	  if (next_bit ()) /* 10011 */ return (8);
X	  else /* 10010 */ return (128);
X	}
X	else /* 1000 */ return (3);
X      }
X    }
X  }
X  else /* 0... */
X  {
X    if (next_bit ()) /* 01... */
X    {
X      if (next_bit ()) /* 011... */
X      {
X	if (next_bit ()) /* 0111 */ return (2);
X	else /* 0110... */
X	{
X	  if (next_bit ()) /* 01101... */
X	  {
X	    if (next_bit ()) /* 011011... */
X	    {
X	      if (next_bit ()) /* 0110111 */ return (256);
X	      else /* 0110110... */
X	      {
X		if (next_bit ()) /* 01101101... */
X		{
X		  if (next_bit ()) /* 011011011 */ return (1408);
X		  else /* 011011010 */ return (1344);
X		}
X	        else /* 01101100... */
X		{
X		  if (next_bit ()) /* 011011001 */ return (1280);
X		  else /* 011011000 */ return (1216);
X		}
X	      }
X	    }
X	    else /* 011010... */
X	    {
X	      if (next_bit ()) /* 0110101... */
X	      {
X		if (next_bit ()) /* 01101011... */
X		{
X		  if (next_bit ()) /* 011010111 */ return (1152);
X		  else /* 011010110 */ return (1088);
X		}
X		else /* 01101010... */
X		{
X		  if (next_bit ()) /* 011010101 */ return (1024);
X		  else /* 011010100 */ return (960);
X		}
X	      }
X	      else /* 0110100... */
X	      {
X		if (next_bit ()) /* 01101001... */
X		{
X		  if (next_bit ()) /* 011010011 */ return (896);
SHAR_EOF
echo "End of part 2, continue with part 3"
echo "3" > s2_seq_.tmp
exit 0