[comp.sources.misc] v15i086: G3 and G4 utilities

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

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

  This is a package of Group 3 and Group 4 image utilities submitted to
cbip. Since they are all source I'm passing them on to sources.misc.

Submitter (add%sciences@ucselx.sdsu.edu) says:

	This is the first release of the g3g4 utilities. Work in progress
	to enhance the capabilities of the toolkit includes table encoding
	of group 3 and group 4 images, and some optimization.

#!/bin/sh
# shar:	Shell Archiver  (v1.27)
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  builddec.c
#	  cg317-0i.001
#	  g3g4.h
#	  g3sdecod.c
#	  g3sencod.c
#	  g3tdecod.c
#	  g4sdecod.c
#	  g4sencod.c
#	  g4tdecod.c
#	  gnencode.c
#	  read.me
#	  submit.dsk
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
sed 's/^X//' << 'SHAR_EOF' > builddec.c &&
X/*	$Id: builddec.c 1.2 90/06/09 18:25:13 marking Exp $
X *
X NAME
X *	builddec.c -- build decoding tables for group 3 and group 4 images
X *
X TYPE
X *	C source for main program and subroutines
X *
X SYNOPSIS
X *	builddec
X *
X DESCRIPTION
X *	This program builds tables for decoding group 3 and group 4 encoded
X *	images. The tables are built as the arrays null_mode [] [],
X *	null_mode_next_state [] [], horiz_mode [] [], and
X *	horiz_mode_next_state [] []. The output is C source code which must
X *	be compiled and linked into a decoding program.
X *
X RETURNS
X *	zero if no errors detected, nonzero otherwise
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: builddec.c 1.2 90/06/09 18:25:13 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:	builddec.c $
X * Revision 1.2  90/06/09  18:25:13  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.	Since it is expected that this program will be run
X *		infrequently, there is no attempt at optimization.
X *	2.	The tables horiz_mode [] [] and horiz_mode_next_state [] []
X *		are used in both group 3 and group 4 decoding. The tables
X *		null_mode [] [] and null_mode_next_state [] [] are used only
X *		in decoding group 4.
X *	3.	On an XT, this can take around 15 minutes. The progress
X *		messages it displays let you know it's still alive, but
X *		otherwise can be ignored.
X *	4.	Most of the documentation for the tables themselves is in
X *		the decode routines g3tdecod.c and g4tdecod.c.
X *
X FILES
X *	Creates the file "tables.c", which is to be compiled and linked into
X *	the table-driven decoding routine.
X *
X PORTABILITY
X *	Tested under Microsoft C 5.1. Should be fairly portable.
X *
X SEE ALSO
X *	g3tdecod.c -- decode group 3 image using tables
X *	g4tdecod.c -- decode group 4 image using tables
X *	"Decoding Group 3 Images", C Users Journal, June 1990
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/*
X *	standard headers
X */
X
X#include	<stddef.h>		/* common types and macros */
X#include	<stdio.h>		/* streams and files */
X#include	<stdlib.h>		/* assorted functions, macros, types */
X
X/*
X *	application
X */
X
X#include "g3g4.h"			/* some #defines */
X
X#define INVALID_CODE -1
X#define INCOMPLETE_CODE -2
X#define EOL_CODE -3
X
Xunsigned long append_0 (unsigned long);
Xunsigned long append_1 (unsigned long);
Xshort black_run_length (unsigned long);
Xshort search_run_length_table (unsigned long, long *);
Xshort white_run_length (unsigned long);
X
Xunsigned long append_0 (unsigned long prefix)
X{
X  return (prefix + 0x10000);
X}
X
Xunsigned long append_1 (unsigned long prefix)
X{
X  unsigned short prefix_length;
X  static unsigned short prefix_mask [16] = {0x8000, 0x4000, 0x2000, 0x1000,
X    0x0800, 0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008,
X    0x0004, 0x0002, 0x0001};
X  prefix_length = 0xFF & (unsigned short) (prefix >> 16);
X  return (prefix + 0x10000 + prefix_mask [prefix_length]);
X}
X
Xshort search_run_length_table (unsigned long prefix, long *p_table)
X{
X  short table_offset = 0;
X  long prefix_length, prefix_value;
X  prefix_length = 0xFF & (prefix >> 16);
X  prefix_value = 0xFFFF & prefix;
X  while (p_table [table_offset])
X  {
X    if (p_table [table_offset] == prefix_length
X      && p_table [table_offset + 1] == prefix_value)
X	return ((short) p_table [table_offset + 2]);
X    table_offset += 3; /* move on to next entry */
X  }
X  return (INCOMPLETE_CODE); /* no entry found in table */
X}
X
Xshort white_run_length (unsigned long prefix)
X{
X  static long code_table [] =
X  {
X    8, 0x3500, 0, /* 0011 0101 */
X    6, 0x1C00, 1, /* 0001 11 */
X    4, 0x7000, 2, /* 0111 */
X    4, 0x8000, 3, /* 1000 */
X    4, 0xB000, 4, /* 1011 */
X    4, 0xC000, 5, /* 1100 */
X    4, 0xE000, 6, /* 1110 */
X    4, 0xF000, 7, /* 1111 */
X    5, 0x9800, 8, /* 1001 1 */
X    5, 0xA000, 9, /* 1010 0 */
X    5, 0x3800, 10, /* 0011 1 */
X    5, 0x4000, 11, /* 0100 0 */
X    6, 0x2000, 12, /* 0010 00 */
X    6, 0x0C00, 13, /* 0000 11 */
X    6, 0xD000, 14, /* 1101 00 */
X    6, 0xD400, 15, /* 1101 01 */
X    6, 0xA800, 16, /* 1010 10 */
X    6, 0xAC00, 17, /* 1010 11 */
X    7, 0x4E00, 18, /* 0100 111 */
X    7, 0x1800, 19, /* 0001 100 */
X    7, 0x1000, 20, /* 0001 000 */
X    7, 0x2E00, 21, /* 0010 111 */
X    7, 0x0600, 22, /* 0000 011 */
X    7, 0x0800, 23, /* 0000 100 */
X    7, 0x5000, 24, /* 0101 000 */
X    7, 0x5600, 25, /* 0101 011 */
X    7, 0x2600, 26, /* 0010 011 */
X    7, 0x4800, 27, /* 0100 100 */
X    7, 0x3000, 28, /* 0011 000 */
X    8, 0x0200, 29, /* 0000 0010 */
X    8, 0x0300, 30, /* 0000 0011 */
X    8, 0x1A00, 31, /* 0001 1010 */
X    8, 0x1B00, 32, /* 0001 1011 */
X    8, 0x1200, 33, /* 0001 0010 */
X    8, 0x1300, 34, /* 0001 0011 */
X    8, 0x1400, 35, /* 0001 0100 */
X    8, 0x1500, 36, /* 0001 0101 */
X    8, 0x1600, 37, /* 0001 0110 */
X    8, 0x1700, 38, /* 0001 0111 */
X    8, 0x2800, 39, /* 0010 1000 */
X    8, 0x2900, 40, /* 0010 1001 */
X    8, 0x2A00, 41, /* 0010 1010 */
X    8, 0x2B00, 42, /* 0010 1011 */
X    8, 0x2C00, 43, /* 0010 1100 */
X    8, 0x2D00, 44, /* 0010 1101 */
X    8, 0x0400, 45, /* 0000 0100 */
X    8, 0x0500, 46, /* 0000 0101 */
X    8, 0x0A00, 47, /* 0000 1010 */
X    8, 0x0B00, 48, /* 0000 1011 */
X    8, 0x5200, 49, /* 0101 0010 */
X    8, 0x5300, 50, /* 0101 0011 */
X    8, 0x5400, 51, /* 0101 0100 */
X    8, 0x5500, 52, /* 0101 0101 */
X    8, 0x2400, 53, /* 0010 0100 */
X    8, 0x2500, 54, /* 0010 0101 */
X    8, 0x5800, 55, /* 0101 1000 */
X    8, 0x5900, 56, /* 0101 1001 */
X    8, 0x5A00, 57, /* 0101 1010 */
X    8, 0x5B00, 58, /* 0101 1011 */
X    8, 0x4A00, 59, /* 0100 1010 */
X    8, 0x4B00, 60, /* 0100 1011 */
X    8, 0x3200, 61, /* 0011 0010 */
X    8, 0x3300, 62, /* 0011 0011 */
X    8, 0x3400, 63, /* 0011 0100 */
X    5, 0xD800, 64, /* 1101 1 */
X    5, 0x9000, 128, /* 1001 0 */
X    6, 0x5C00, 192, /* 0101 11 */
X    7, 0x6E00, 256, /* 0110 111 */
X    8, 0x3600, 320, /* 0011 0110 */
X    8, 0x3700, 384, /* 0011 0111 */
X    8, 0x6400, 448, /* 0110 0100 */
X    8, 0x6500, 512, /* 0110 0101 */
X    8, 0x6800, 576, /* 0110 1000 */
X    8, 0x6700, 640, /* 0110 0111 */
X    9, 0x6600, 704, /* 0110 0110 0 */
X    9, 0x6680, 768, /* 0110 0110 1 */
X    9, 0x6900, 832, /* 0110 1001 0 */
X    9, 0x6980, 896, /* 0110 1001 1 */
X    9, 0x6A00, 960, /* 0110 1010 0 */
X    9, 0x6A80, 1024, /* 0110 1010 1 */
X    9, 0x6B00, 1088, /* 0110 1011 0 */
X    9, 0x6B80, 1152, /* 0110 1011 1 */
X    9, 0x6C00, 1216, /* 0110 1100 0 */
X    9, 0x6C80, 1280, /* 0110 1100 1 */
X    9, 0x6D00, 1344, /* 0110 1101 0 */
X    9, 0x6D80, 1408, /* 0110 1101 1 */
X    9, 0x4C00, 1472, /* 0100 1100 0 */
X    9, 0x4C80, 1536, /* 0100 1100 1 */
X    9, 0x4D00, 1600, /* 0100 1101 0 */
X    6, 0x6000, 1664, /* 0110 00 */
X    9, 0x4D80, 1728, /* 0100 1101 1 */
X    11, 0x0100, 1792, /* 0000 0001 000 */
X    11, 0x0180, 1856, /* 0000 0001 100 */
X    11, 0x01A0, 1920, /* 0000 0001 101 */
X    12, 0x0120, 1984, /* 0000 0001 0010 */
X    12, 0x0130, 2048, /* 0000 0001 0011 */
X    12, 0x0140, 2112, /* 0000 0001 0100 */
X    12, 0x0150, 2176, /* 0000 0001 0101 */
X    12, 0x0160, 2240, /* 0000 0001 0110 */
X    12, 0x0170, 2304, /* 0000 0001 0111 */
X    12, 0x01C0, 2368, /* 0000 0001 1100 */
X    12, 0x01D0, 2432, /* 0000 0001 1101 */
X    12, 0x01E0, 2496, /* 0000 0001 1110 */
X    12, 0x01F0, 2560, /* 0000 0001 1111 */
X    12, 0x0010, EOL_CODE, /* 0000 0000 0001 */
X    9, 0x0080, INVALID_CODE, /* 0000 0000 1 */
X    10, 0x0040, INVALID_CODE, /* 0000 0000 01 */
X    11, 0x0020, INVALID_CODE, /* 0000 0000 001 */
X    12, 0x0000, INVALID_CODE, /* 0000 0000 0000 */
X    0 /* end-of-table */
X  };
X  return (search_run_length_table (prefix, code_table));
X}
X   
Xshort black_run_length (unsigned long prefix)
X{
X  static long code_table [] =
X  {
X    10, 0x0DC0, 0, /* 0000 1101 11 */
X    3, 0x4000, 1, /* 010 */
X    2, 0xC000, 2, /* 11 */
X    2, 0x8000, 3, /* 10 */
X    3, 0x6000, 4, /* 011 */
X    4, 0x3000, 5, /* 0011 */
X    4, 0x2000, 6, /* 0010 */
X    5, 0x1800, 7, /* 0001 1 */
X    6, 0x1400, 8, /* 0001 01 */
X    6, 0x1000, 9, /* 0001 00 */
X    7, 0x0800, 10, /* 0000 100 */
X    7, 0x0A00, 11, /* 0000 101 */
X    7, 0x0E00, 12, /* 0000 111 */
X    8, 0x0400, 13, /* 0000 0100 */
X    8, 0x0700, 14, /* 0000 0111 */
X    9, 0x0C00, 15, /* 0000 1100 0 */
X    10, 0x05C0, 16, /* 0000 0101 11 */
X    10, 0x0600, 17, /* 0000 0110 00 */
X    10, 0x0200, 18, /* 0000 0010 00 */
X    11, 0x0CE0, 19, /* 0000 1100 111 */
X    11, 0x0D00, 20, /* 0000 1101 000 */
X    11, 0x0D80, 21, /* 0000 1101 100 */
X    11, 0x06E0, 22, /* 0000 0110 111 */
X    11, 0x0500, 23, /* 0000 0101 000 */
X    11, 0x02E0, 24, /* 0000 0010 111 */
X    11, 0x0300, 25, /* 0000 0011 000 */
X    12, 0x0CA0, 26, /* 0000 1100 1010 */
X    12, 0x0CB0, 27, /* 0000 1100 1011 */
X    12, 0x0CC0, 28, /* 0000 1100 1100 */
X    12, 0x0CD0, 29, /* 0000 1100 1101 */
X    12, 0x0680, 30, /* 0000 0110 1000 */
X    12, 0x0690, 31, /* 0000 0110 1001 */
X    12, 0x06A0, 32, /* 0000 0110 1010 */
X    12, 0x06B0, 33, /* 0000 0110 1011 */
X    12, 0x0D20, 34, /* 0000 1101 0010 */
X    12, 0x0D30, 35, /* 0000 1101 0011 */
X    12, 0x0D40, 36, /* 0000 1101 0100 */
X    12, 0x0D50, 37, /* 0000 1101 0101 */
X    12, 0x0D60, 38, /* 0000 1101 0110 */
X    12, 0x0D70, 39, /* 0000 1101 0111 */
X    12, 0x06C0, 40, /* 0000 0110 1100 */
X    12, 0x06D0, 41, /* 0000 0110 1101 */
X    12, 0x0DA0, 42, /* 0000 1101 1010 */
X    12, 0x0DB0, 43, /* 0000 1101 1011 */
X    12, 0x0540, 44, /* 0000 0101 0100 */
X    12, 0x0550, 45, /* 0000 0101 0101 */
X    12, 0x0560, 46, /* 0000 0101 0110 */
X    12, 0x0570, 47, /* 0000 0101 0111 */
X    12, 0x0640, 48, /* 0000 0110 0100 */
X    12, 0x0650, 49, /* 0000 0110 0101 */
X    12, 0x0520, 50, /* 0000 0101 0010 */
X    12, 0x0530, 51, /* 0000 0101 0011 */
X    12, 0x0240, 52, /* 0000 0010 0100 */
X    12, 0x0370, 53, /* 0000 0011 0111 */
X    12, 0x0380, 54, /* 0000 0011 1000 */
X    12, 0x0270, 55, /* 0000 0010 0111 */
X    12, 0x0280, 56, /* 0000 0010 1000 */
X    12, 0x0580, 57, /* 0000 0101 1000 */
X    12, 0x0590, 58, /* 0000 0101 1001 */
X    12, 0x02B0, 59, /* 0000 0010 1011 */
X    12, 0x02C0, 60, /* 0000 0010 1100 */
X    12, 0x05A0, 61, /* 0000 0101 1010 */
X    12, 0x0660, 62, /* 0000 0110 0110 */
X    12, 0x0670, 63, /* 0000 0110 0111 */
X    10, 0x03C0, 64, /* 0000 0011 11 */
X    12, 0x0C80, 128, /* 0000 1100 1000 */
X    12, 0x0C90, 192, /* 0000 1100 1001 */
X    12, 0x05B0, 256, /* 0000 0101 1011 */
X    12, 0x0330, 320, /* 0000 0011 0011 */
X    12, 0x0340, 384, /* 0000 0011 0100 */
X    12, 0x0350, 448, /* 0000 0011 0101 */
X    13, 0x0360, 512, /* 0000 0011 0110 0 */
X    13, 0x0368, 576, /* 0000 0011 0110 1 */
X    13, 0x0250, 640, /* 0000 0010 0101 0 */
X    13, 0x0258, 704, /* 0000 0010 0101 1 */
X    13, 0x0260, 768, /* 0000 0010 0110 0 */
X    13, 0x0268, 832, /* 0000 0010 0110 1 */
X    13, 0x0390, 896, /* 0000 0011 1001 0 */
X    13, 0x0398, 960, /* 0000 0011 1001 1 */
X    13, 0x03A0, 1024, /* 0000 0011 1010 0 */
X    13, 0x03A8, 1088, /* 0000 0011 1010 1 */
X    13, 0x03B0, 1152, /* 0000 0011 1011 0 */
X    13, 0x03B8, 1216, /* 0000 0011 1011 1 */
X    13, 0x0290, 1280, /* 0000 0010 1001 0 */
X    13, 0x0298, 1344, /* 0000 0010 1001 1 */
X    13, 0x02A0, 1408, /* 0000 0010 1010 0 */
X    13, 0x02A8, 1472, /* 0000 0010 1010 1 */
X    13, 0x02D0, 1536, /* 0000 0010 1101 0 */
X    13, 0x02D8, 1600, /* 0000 0010 1101 1 */
X    13, 0x0320, 1664, /* 0000 0011 0010 0 */
X    13, 0x0328, 1728, /* 0000 0011 0010 1 */
X    11, 0x0100, 1792, /* 0000 0001 000 */
X    11, 0x0180, 1856, /* 0000 0001 100 */
X    11, 0x01A0, 1920, /* 0000 0001 101 */
X    12, 0x0120, 1984, /* 0000 0001 0010 */
X    12, 0x0130, 2048, /* 0000 0001 0011 */
X    12, 0x0140, 2112, /* 0000 0001 0100 */
X    12, 0x0150, 2176, /* 0000 0001 0101 */
X    12, 0x0160, 2240, /* 0000 0001 0110 */
X    12, 0x0170, 2304, /* 0000 0001 0111 */
X    12, 0x01C0, 2368, /* 0000 0001 1100 */
X    12, 0x01D0, 2432, /* 0000 0001 1101 */
X    12, 0x01E0, 2496, /* 0000 0001 1110 */
X    12, 0x01F0, 2560, /* 0000 0001 1111 */
X    12, 0x0010, EOL_CODE, /* 0000 0000 0001 */
X    9, 0x0080, INVALID_CODE, /* 0000 0000 1 */
X    10, 0x0040, INVALID_CODE, /* 0000 0000 01 */
X    11, 0x0020, INVALID_CODE, /* 0000 0000 001 */
X    12, 0x0000, INVALID_CODE, /* 0000 0000 0000 */
X    0 /* end-of-table */
X  };
X  return (search_run_length_table (prefix, code_table));
X}
X
X#define NULL_MODE_PREFIX_LIMIT 200 /* maximum number of null-mode prefixes */
X#define HORIZ_MODE_PREFIX_LIMIT 250 /* maximum number of indigestible
X  1-dimensional prefixes */
X
Xlong null_mode_prefix [NULL_MODE_PREFIX_LIMIT];
X  /* the bit string corresponding to this row of the decoding table */
Xunsigned char null_mode [NULL_MODE_PREFIX_LIMIT] [256];
X  /* one of the entries PASS_MODE, HORIZONTAL_MODE, etc, or zero */
Xunsigned char null_mode_next_state [NULL_MODE_PREFIX_LIMIT] [256];
X  /* next row of the decoding tables to be used */
Xshort null_mode_prefix_count = 0;
X  /* number of prefixes or rows in the G4 decoding tables */
X
X/* decoding script values for horiz_mode [] []:
X     0 - indigestible code
X     1 - invalid code or error
X     2..105 - white runs
X     106..209 - black runs
X     210 - EOL (valid only for Group 3)
X     211..255 - (undefined) */
Xunsigned char horiz_mode [HORIZ_MODE_PREFIX_LIMIT] [256];
Xunsigned char horiz_mode_next_state [HORIZ_MODE_PREFIX_LIMIT] [256];
X  /* if the corresponding horiz_mode [] [] entry is zero ("indigestible"),
X     this entry is a row number for decoding the next byte; otherwise, it
X     is the bit number to continue coding the next codeword */
Xlong horiz_mode_prefix [HORIZ_MODE_PREFIX_LIMIT];
X  /* the prefixes corresponding to the rows of the decoding table */
Xchar horiz_mode_color [HORIZ_MODE_PREFIX_LIMIT];
X  /* color of next run, BLACK or WHITE */
Xshort horiz_mode_prefix_count = 0;
X
Xstatic unsigned char bit_mask [8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04,
X  0x02, 0x01};
X
Xvoid build_null_mode_tables (void);
Xshort find_horiz_mode_prefix (long, char);
Xshort find_null_mode_prefix (long);
Xshort null_mode_type (long);
Xvoid process_horiz_mode_prefixes (void);
Xshort horiz_mode_code_black (short);
Xshort horiz_mode_code_invalid (void);
Xshort horiz_mode_code_indigestible (void);
Xshort horiz_mode_code_EOL (void);
Xshort horiz_mode_code_white (short);
Xvoid write_tables (void);
X
Xint main (int arg_count, char **p_args, char **p_env)
X{
X  printf ("g4build\n");
X  /* build the null mode decoding tables */
X    build_null_mode_tables ();
X    printf ("  %hd null mode prefixes defined\n", null_mode_prefix_count);
X  /* build the 1D decoding tables */
X    printf ("  building 1D scripts...\n");
X    process_horiz_mode_prefixes ();
X    printf ("  %hd indigestible prefixes defined\n", horiz_mode_prefix_count);
X  /* create tables.h */
X    write_tables ();
X  exit (0);
X}
X
Xvoid build_null_mode_tables ()
X{
X  short prefix_number;
X  /* note: the first eight entries correspond to a null prefix and starting
X    bit numbers 0, 1, ... 7 */
X  null_mode_prefix_count = 8;
X  for (prefix_number = 0; prefix_number < null_mode_prefix_count;
X   prefix_number++)
X  {
X    short byte_value;
X    for (byte_value = 0; byte_value < 256; byte_value++)
X    {
X      short beginning_bit_number, bit_number, mode;
X      long working_prefix;
X      char found_code = 0;
X      if (prefix_number < 8)
X      {
X        working_prefix = 0L;
X        beginning_bit_number = prefix_number;
X      }
X      else
X      {
X        working_prefix = null_mode_prefix [prefix_number];
X        beginning_bit_number = 0;
X      }
X      for (bit_number = beginning_bit_number; bit_number < 8 && !found_code;
X       bit_number++)
X      {
X        if (bit_mask [bit_number] & byte_value)
X	  working_prefix = append_1 (working_prefix);
X	else working_prefix = append_0 (working_prefix);
X        mode = null_mode_type (working_prefix);
X        switch (mode)
X        {
X	  case PASS_MODE:
X	  case HORIZONTAL_MODE:
X	  case VERTICAL_V0_MODE:
X	  case VERTICAL_VR1_MODE:
X	  case VERTICAL_VR2_MODE:
X	  case VERTICAL_VR3_MODE:
X	  case VERTICAL_VL1_MODE:
X	  case VERTICAL_VL2_MODE:
X	  case VERTICAL_VL3_MODE:
X	  case EXT_MODE_UNCOMPRESSED:
X	  case ERROR_MODE:
X	  case ERROR_MODE_1:
X	    found_code = 1;
X	    null_mode [prefix_number] [byte_value] = (unsigned char) mode;
X	    null_mode_next_state [prefix_number] [byte_value]
X	      = (unsigned char) ((bit_number + 1) & 0x7);
X	      /* note: if the bit number is 8, then
X	        the table entry will be zero, which indicates a new byte
X	        is to be fetched during the decoding process */
X	    break;
X	  default:
X	    break;
X        }
X      }
X      if (!found_code)
X      {
X	null_mode_next_state [prefix_number] [byte_value]
X	  = (unsigned char) find_null_mode_prefix (working_prefix);
X	null_mode [prefix_number] [byte_value] = 0; /* indicating to the
X	  decoder that no digestible state was found */
X      }
X    }
X  }
X}
X
Xshort find_null_mode_prefix (long prefix)
X{
X  short j1;
X  if (prefix == 0L) return (0);
X  for (j1 = 8; j1 < null_mode_prefix_count; j1++)
X    if (prefix == null_mode_prefix [j1]) return (j1);
X  if (null_mode_prefix_count == NULL_MODE_PREFIX_LIMIT)
X  {
X    printf ("ERROR: null mode prefix table overflow\n");
X    exit (1);
X  }
X  null_mode_prefix [null_mode_prefix_count] = prefix;
Xprintf ("adding null mode prefix [%hd] 0x%lx\n", null_mode_prefix_count,
Xprefix);
X  null_mode_prefix_count++;
X  return (null_mode_prefix_count - 1);
X}
X
Xshort find_horiz_mode_prefix (long prefix, char color)
X{
X  short j1;
X  for (j1 = 0; j1 < horiz_mode_prefix_count; j1++)
X    if (prefix == horiz_mode_prefix [j1] && horiz_mode_color [j1] == color)
X      return (j1);
X  /* it wasn't found, so add it to the tables */
X  /* but first, is there room? */
X    if (horiz_mode_prefix_count == HORIZ_MODE_PREFIX_LIMIT) /* we're full */
X    {
X      printf ("ERROR: 1D prefix table overflow\n");
X      exit (1);
X    }
X  /* OK, there's room... */
X  horiz_mode_prefix [horiz_mode_prefix_count] = prefix;
X  horiz_mode_color [horiz_mode_prefix_count] = color;
X  horiz_mode_prefix_count++;
Xprintf ("\n horiz mode prefix %hd, color %c = 0x%lx ",
X(short) (horiz_mode_prefix_count - 1), "WB" [color], prefix);
X  return (horiz_mode_prefix_count - 1);
X}
X
Xshort null_mode_type (long prefix)
X{
X  if (prefix == 0x18000L) return (VERTICAL_V0_MODE);      /* 1 */
X  if (prefix == 0x36000L) return (VERTICAL_VR1_MODE);     /* 011 */
X  if (prefix == 0x34000L) return (VERTICAL_VL1_MODE);     /* 010 */
X  if (prefix == 0x32000L) return (HORIZONTAL_MODE);       /* 001 */
X  if (prefix == 0x41000L) return (PASS_MODE);             /* 0001 */
X  if (prefix == 0x60C00L) return (VERTICAL_VR2_MODE);     /* 0000 11 */
X  if (prefix == 0x60800L) return (VERTICAL_VL2_MODE);     /* 0000 10 */
X  if (prefix == 0x70600L) return (VERTICAL_VR3_MODE);     /* 0000 011 */
X  if (prefix == 0x70400L) return (VERTICAL_VL3_MODE);     /* 0000 010 */
X  if (prefix == 0x80200L) return (ERROR_MODE);            /* 0000 0010 */
X  if (prefix == 0x90300L) return (ERROR_MODE);            /* 0000 0011 0 */
X  if (prefix == 0xA0380L) return (ERROR_MODE);            /* 0000 0011 10 */
X  if (prefix == 0xA03C0L) return (EXT_MODE_UNCOMPRESSED); /* 0000 0011 11 */
X  if (prefix == 0x70000L) return (ERROR_MODE_1);          /* 0000 000 */
X    /* under the assumption that there are no errors in the file, then this
X       bit string can only be the beginning of an EOFB (end-of-facsimile-block)
X       code */
X  return (-1);
X}
X
Xvoid process_horiz_mode_prefixes ()
X{
X  unsigned short code_byte_value;
X  short prefix_number;
X  horiz_mode_prefix_count = 16; /* the first 8 are for white, the second 8 are
X    for black, beginning with bits 0, 1, ... 7 */
X  for (prefix_number = 0; prefix_number < horiz_mode_prefix_count;
X    prefix_number++)
X    for (code_byte_value = 0; code_byte_value < 256; code_byte_value++)
X    {
X      short bits_digested = 0;
X      short bit_number, beginning_bit_number;
X      char working_color;
X      long working_prefix;
X      if (prefix_number < 8)
X      {
X	working_color = WHITE;
X	working_prefix = 0L;
X	beginning_bit_number = prefix_number;
X      }
X      else if (prefix_number < 16)
X      {
X	working_color = BLACK;
X	working_prefix = 0L;
X	beginning_bit_number = prefix_number - 8;
X      }
X      else
X      {
X        working_color = horiz_mode_color [prefix_number];
X        working_prefix = horiz_mode_prefix [prefix_number];
X	beginning_bit_number = 0;
X      }
X      for (bit_number = beginning_bit_number; bit_number < 8 && !bits_digested;
X	bit_number++)
X      {
X	if (bit_mask [bit_number] & code_byte_value)
X	  working_prefix = append_1 (working_prefix);
X	else working_prefix = append_0 (working_prefix);
X	if (working_prefix == 0xC0000L) working_prefix = 0xB0000L;
X	  /* This conversion allows for arbitrary strings of zeroes to precede
X	     the end-of-line code 0000 0000 0001.  It assumes no errors in the
X	     data, and is based on the assumption that the code replaced (12
X	     consecutive zeroes) can only be "legally" encountered before the
X	     end-of-line code.  This assumption is valid only for a Group 3
X	     image; the combination will never occur in horizontal mode in a
X	     proper Group 4 image. */
X	if (working_color == WHITE)
X	{
X	  short runlength;
X	  runlength = white_run_length (working_prefix);
X	  if (runlength == INVALID_CODE)
X	  {
X	    horiz_mode [prefix_number] [code_byte_value]
X	      = (unsigned char) horiz_mode_code_invalid ();
X	    horiz_mode_next_state [prefix_number] [code_byte_value]
X	      = (unsigned char) bit_number;
X	    bits_digested = bit_number + 1;
X	  }
X	  else if (runlength == EOL_CODE) /* Group 3 only */
X	  {
X	    horiz_mode [prefix_number] [code_byte_value]
X	      = (unsigned char) horiz_mode_code_EOL ();
X	    horiz_mode_next_state [prefix_number] [code_byte_value]
X	      = (unsigned char) ((bit_number + 1) & 0x7);
X	    bits_digested = bit_number + 1;
X	  }
X	  else if (runlength != INCOMPLETE_CODE)
X	  {
X	    horiz_mode [prefix_number] [code_byte_value]
X	      = (unsigned char) horiz_mode_code_white (runlength);
X	    horiz_mode_next_state [prefix_number] [code_byte_value]
X	      = (unsigned char) ((bit_number + 1) & 0x7);
X	    bits_digested = bit_number + 1;
X	  }
X	  /* else incomplete code */
X	}
X	else /* working_color == BLACK */
X	{
X	  short runlength;
X	  runlength = black_run_length (working_prefix);
X	  if (runlength == INVALID_CODE)
X	  {
X	    horiz_mode [prefix_number] [code_byte_value]
X	      = (unsigned char) horiz_mode_code_invalid ();
X	    horiz_mode_next_state [prefix_number] [code_byte_value]
X	      = (unsigned char) (bit_number + 8);
X	    bits_digested = bit_number + 1;
X	  }
X	  else if (runlength == EOL_CODE) /* Group 3 only */
X	  {
X	    horiz_mode [prefix_number] [code_byte_value]
X	      = (unsigned char) horiz_mode_code_EOL ();
X	    horiz_mode_next_state [prefix_number] [code_byte_value]
X	      = (unsigned char) ((bit_number + 1) & 0x7);
X	    bits_digested = bit_number + 1;
X	  }
X	  else if (runlength != INCOMPLETE_CODE)
X	  {
X	    horiz_mode [prefix_number] [code_byte_value]
X	      = (unsigned char) horiz_mode_code_black (runlength);
X	    horiz_mode_next_state [prefix_number] [code_byte_value]
X	      = (unsigned char) ((bit_number + 1) & 0x7);
X	    bits_digested = bit_number + 1;
X	  }
X	  /* else incomplete code */
X	}
X      }
X      if (!bits_digested) /* if no codewords after examining byte */
X      {
X	horiz_mode [prefix_number] [code_byte_value]
X	  = (unsigned char) horiz_mode_code_indigestible ();
X	horiz_mode_next_state [prefix_number] [code_byte_value]
X	  = (unsigned char) find_horiz_mode_prefix (working_prefix,
X	    working_color);
X      }
X    }
X}
X
Xshort horiz_mode_code_black (short runlength)
X{
X  /*
X	0	106
X	1	107
X	...	...
X	63	169
X	64	170
X	128	171
X	...	...
X	2560	209
X  */
X  if (runlength < 64) return (runlength + 106);
X  else return ((runlength / 64) + 169);
X}
X
Xshort horiz_mode_code_invalid ()
X{
X  return (1);
X}
X
Xshort horiz_mode_code_indigestible ()
X{
X  return (0);
X}
X
Xshort horiz_mode_code_EOL ()
X{
X  return (210);
X}
X
Xshort horiz_mode_code_white (short runlength)
X{
X  /*
X	0	2
X	1	3
X	...	...
X	63	65
X	64	66
X	128	67
X	...	...
X	2560	105
X  */
X  if (runlength < 64) return (runlength + 2);
X  else return ((runlength / 64) + 65);
X}
X
Xvoid write_tables ()
X{
X  FILE *p_table_file;
X  short j1, j2, j3;
X  p_table_file = fopen ("tables.c", "w+");
X  if (p_table_file == NULL)
X  {
X    printf ("can't open \"tables.c\"\n");
X    exit (1);
X  }
X  /* ---------------------------------------- null_mode [] [] */
X  fprintf (p_table_file,
X    "unsigned char null_mode [%hd] [256] = {\n",
X    null_mode_prefix_count);
X  for (j1 = 0; j1 < null_mode_prefix_count; j1++)
X  {
X    fprintf (p_table_file, "/* %hd */", j1);
X    j3 = 1;
X    fprintf (p_table_file, "  { ");
X    for (j2 = 0; j2 < 256; j2++)
X    {
X      fprintf (p_table_file, "%hd", (short) null_mode [j1] [j2]);
X      if (j3++ == 14)
X      {
X	j3 = 0; fprintf (p_table_file, ",\n    ");
X      }
X      else if (j2 != 255) fprintf (p_table_file, ", ");
X    }
X    if (j1 == horiz_mode_prefix_count - 1) fprintf (p_table_file, "  }\n");
X    else fprintf (p_table_file, "  },\n");
X  }
X  fprintf (p_table_file, "};\n");
X  /* ---------------------------------------- null_mode_next_state [] [] */
X  fprintf (p_table_file,
X    "unsigned char null_mode_next_state [%hd] [256] = {\n",
X    null_mode_prefix_count);
X  for (j1 = 0; j1 < null_mode_prefix_count; j1++)
X  {
X    fprintf (p_table_file, "/* %hd */", j1);
X    j3 = 1;
X    fprintf (p_table_file, "  { ");
X    for (j2 = 0; j2 < 256; j2++)
X    {
X      fprintf (p_table_file, "%hd", (short) null_mode_next_state [j1] [j2]);
X      if (j3++ == 14)
X      {
X	j3 = 0; fprintf (p_table_file, ",\n    ");
X      }
X      else if (j2 != 255) fprintf (p_table_file, ", ");
X    }
X    if (j1 == horiz_mode_prefix_count - 1) fprintf (p_table_file, "  }\n");
X    else fprintf (p_table_file, "  },\n");
X  }
X  fprintf (p_table_file, "};\n");
X  /* ---------------------------------------- horiz_mode [] [] */
X  fprintf (p_table_file,
X    "unsigned char horiz_mode [%hd] [256] = {\n",
X    horiz_mode_prefix_count);
X  for (j1 = 0; j1 < horiz_mode_prefix_count; j1++)
X  {
X    j3 = 1;
X    fprintf (p_table_file, "/* %hd */", j1);
X    fprintf (p_table_file, "  { ");
X    for (j2 = 0; j2 < 256; j2++)
X    {
X      fprintf (p_table_file, "%hd", (short) horiz_mode [j1] [j2]);
X      if (j3++ == 11)
X      {
X	j3 = 0; fprintf (p_table_file, ",\n    ");
X      }
X      else if (j2 != 255) fprintf (p_table_file, ", ");
X    }
X    if (j1 == horiz_mode_prefix_count - 1) fprintf (p_table_file, "  }\n");
X    else fprintf (p_table_file, "  },\n");
X  }
X  fprintf (p_table_file, "};\n");
X  /* ---------------------------------------- horiz_mode_next_state [] [] */
X  fprintf (p_table_file,
X    "unsigned char horiz_mode_next_state [%hd] [256] = {\n",
X    horiz_mode_prefix_count);
X  for (j1 = 0; j1 < horiz_mode_prefix_count; j1++)
X  {
X    fprintf (p_table_file, "/* %hd */", j1);
X    j3 = 1;
X    fprintf (p_table_file, "  { ");
X    for (j2 = 0; j2 < 256; j2++)
X    {
X      fprintf (p_table_file, "%hd", (short) horiz_mode_next_state [j1] [j2]);
X      if (j3++ == 14)
X      {
X	j3 = 0; fprintf (p_table_file, ",\n    ");
X      }
X      else if (j2 != 255) fprintf (p_table_file, ", ");
X    }
X    if (j1 == horiz_mode_prefix_count - 1) fprintf (p_table_file, "  }\n");
X    else fprintf (p_table_file, "  },\n");
X  }
X  fprintf (p_table_file, "};\n");
X  fclose (p_table_file);
X}
X
X/*	end $RCSfile: builddec.c $ */
SHAR_EOF
chmod 0644 builddec.c || echo "restore of builddec.c fails"
sed 's/^X//' << 'SHAR_EOF' > cg317-0i.001 &&
XSHAR_EOF
chmod 0644 cg317-0i.001 || echo "restore of cg317-0i.001 fails"
sed 's/^X//' << 'SHAR_EOF' > g3g4.h &&
X/*	$Id: g3g4.h 1.2 90/06/09 18:21:50 marking Exp $
X *
X NAME
X *	g3g4.h -- definitions for decoding group 3 and group 4 images
X *
X USED WITH
X *	builddec.c -- build decode tables
X *	group 3 and group 4 encoding and decoding routines
X *
X DESCRIPTION
X *	Common definitions for group 3 and group 4 utilities.
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: g3g4.h 1.2 90/06/09 18:21:50 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 PORTABILITY
X *
X *	There is a non-portable use of "global" variables in this file,
X *	about which a minority of compilers will justifiably complain. Certain
X *	variables are declared here without extern keywords. Strictly
X *	speaking, they should be declared extern in all but one module, but
X *	that would require complication of this file. If it gets past your
X *	compiler and linker, you can probably ignore it.
X * 
X HISTORY
X *	$Log:	g3g4.h $
X * Revision 1.2  90/06/09  18:21:50  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 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#define WHITE 0
X#define BLACK 1
X
X#define NULL_MODE 0
X#define PASS_MODE 1
X#define HORIZONTAL_MODE 2
X#define VERTICAL_V0_MODE 3
X#define VERTICAL_VR1_MODE 4
X#define VERTICAL_VR2_MODE 5
X#define VERTICAL_VR3_MODE 6
X#define VERTICAL_VL1_MODE 7
X#define VERTICAL_VL2_MODE 8
X#define VERTICAL_VL3_MODE 9
X#define EXT_MODE_UNCOMPRESSED 10
X#define ERROR_MODE 11
X#define ERROR_MODE_1 12
X
X#define PASS_CODEWORD		0x1000
X#define HORIZONTAL_CODEWORD	0x2000
X#define VERTICAL_V0_CODEWORD	0x8000
X#define VERTICAL_VR1_CODEWORD	0x6000
X#define VERTICAL_VR2_CODEWORD	0x0C00
X#define VERTICAL_VR3_CODEWORD	0x0600
X#define VERTICAL_VL1_CODEWORD	0x4000
X#define VERTICAL_VL2_CODEWORD	0x0800
X#define VERTICAL_VL3_CODEWORD	0x0400
X
X#define PASS_CODELEN		4
X#define HORIZONTAL_CODELEN	3
X#define VERTICAL_V0_CODELEN	1
X#define VERTICAL_VR1_CODELEN	3
X#define VERTICAL_VR2_CODELEN	6
X#define VERTICAL_VR3_CODELEN	7
X#define VERTICAL_VL1_CODELEN	3
X#define VERTICAL_VL2_CODELEN	6
X#define VERTICAL_VL3_CODELEN	7
X
X#define RETURN_OK 0
X#define ERROR_NEXT_BYTE 1 /* the routine next_byte () unexpectedly returned
X  an error or end-of-file before the end of the image (EOFB) was reached */
X#define ERROR_UNSUPPORTED_EXTENSION 2
X#define ERROR_INVALID_CODEWORD 3
X#define ERROR_PROGRAM_LOGIC 4
X
X#define EOL_CODE -1
X#define INVALID_CODE -2
X
X#define MSB_FIRST 1
X#define LSB_FIRST 2
X
X#define PAD_NONE 1
X#define PAD_BYTE 2
X#define PAD_NIBBLE 3
X#define PAD_ODD_NIBBLE 4
X
Xchar  (*p_decode_black) (short);
Xchar  (*p_decode_new_row) (void);
Xshort (*p_decode_next_byte) (void);
Xchar  (*p_decode_white) (short);
X
Xchar g3i_decode_T (void);
Xchar g3i_decode (void);
Xchar g3i_initialize (short, short);
Xchar g4i_decode (void);
Xchar g4i_initialize (short, short);
X
Xchar (*p_encode_next_byte) (unsigned char);
X
Xchar g3j_encode_black (short);
Xchar g3j_encode_white (short);
Xchar g3j_encode_new_row (void);
Xchar g3j_encode_pad (char);
Xchar g3j_initialize (short, short);
Xchar g4j_encode_black (short);
Xchar g4j_encode_white (short);
Xchar g4j_encode_EOFB (void);
Xchar g4j_encode_new_row (void);
Xchar g4j_initialize (short, short);
X
X/* internal stuff */
X
Xvoid encode_word (unsigned short, short);
Xvoid initialize_encode (void);
Xshort encode_position;
X
Xchar output_fill_order, input_fill_order;
Xunsigned char encode_buffer;
Xunsigned char *decode_mask, *encode_mask, *encode_head_mask, *encode_tail_mask;
Xshort pending_black, pending_white;
X
Xchar trace_flag;			/* for debug */
X
X/*	end $RCSfile: g3g4.h $ */
SHAR_EOF
chmod 0644 g3g4.h || echo "restore of g3g4.h fails"
sed 's/^X//' << 'SHAR_EOF' > g3sdecod.c &&
X/*	$Id: g3sdecod.c 1.2 90/06/09 18:22:19 marking Exp $
X *
X NAME
X *	g3sdecod.c -- decode group 3 data using nested if statements
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: g3sdecod.c 1.2 90/06/09 18:22:19 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:	g3sdecod.c $
X * Revision 1.2  90/06/09  18:22:19  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 *	g4sdecod.c -- decode 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
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 horiz_mode [] [256];
Xextern unsigned char horiz_mode_next_state [] [256];
X
Xstatic short 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);
X
Xstatic char decode_return;
X
X/* g3i_decode () successively invokes (*p_decode_next_byte) () for each byte
X   of the encoded image, and calls (*p_decode_white) () or (*p_decode_black) ()
X   as 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 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			  /* 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/*
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);
X		  else /* 011010010 */ return (832);
X		}
X		else /* 01101000 */ return (576);
X	      }
X	    }
X	  }
X	  else /* 01100... */
X	  {
X	    if (next_bit ()) /* 011001... */
X	    {
X	      if (next_bit ()) /* 0110011... */
X	      {
X		if (next_bit ()) /* 01100111 */ return (640);
X		else /* 01100110 */
X		{
X		  if (next_bit ()) /* 011001101 */ return (768);
X		  else /* 011001100 */ return (704);
X		}
X	      }
X	      else /* 0110010 */
X	      {
X		if (next_bit ()) /* 01100101 */ return (512);
X		else /* 01100100 */ return (448);
X	      }
X	    }
X	    else /* 011000 */ return (1664);
X	  }
X	}
X      }
X      else /* 010... */
X      {
X	if (next_bit ()) /* 0101... */
X	{
X	  if (next_bit ()) /* 01011... */
X	  {
X	    if (next_bit ()) /* 010111 */ return (192);
X	    else /* 010110... */
X	    {
X	      if (next_bit ()) /* 0101101... */
X	      {
X		if (next_bit ()) /* 01011011 */ return (58);
X		else /* 01011010 */ return (57);
X	      }
X	      else /* 0101100... */
X	      {
X		if (next_bit ()) /* 01011001 */ return (56);
X		else /* 01011000 */ return (55);
X	      }
SHAR_EOF
echo "End of part 1, continue with part 2"
echo "2" > s2_seq_.tmp
exit 0
--
bill davidsen (ibmbin-request@crdgw1.crd.ge.com, uunet!crdgw1!ibmbin-request)
  moderator c.b.i.p newsgroup and 386users mailing list.
  binary submissions to ibmbin@crdgw1.crd.ge.com (uunet!crdgw1!ibmbin)
            "Stupidity, like virtue, is its own reward" -me