home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
comm
/
misc
/
elcheapofax
/
rcs
/
fromfax.c,v
< prev
next >
Wrap
Text File
|
1993-12-21
|
15KB
|
762 lines
head 1.5;
access;
symbols
OCT93:1.5;
locks;
comment @ * @;
1.5
date 93.10.25.02.14.27; author Rhialto; state Exp;
branches;
next 1.4;
1.4
date 93.09.18.22.41.27; author Rhialto; state Exp;
branches;
next 1.3;
1.3
date 93.08.20.03.45.27; author Rhialto; state Exp;
branches;
next 1.2;
1.2
date 93.06.11.16.33.37; author Rhialto; state Exp;
branches;
next 1.1;
1.1
date 93.06.11.14.53.53; author Rhialto; state Exp;
branches;
next ;
desc
@Convert g3 data to bitmaps
@
1.5
log
@Make +FBOR flexible; fix RTC detection bug.
@
text
@/* Derived from: */
/* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap
**
** Copyright (C) 1989 by Paul Haeberli <paul@@manray.sgi.com>.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
/* $Id: fromfax.c,v 1.4 1993/09/18 22:41:27 Rhialto Exp $
* $Log: fromfax.c,v $
* Revision 1.4 1993/09/18 22:41:27 Rhialto
* Improve on bit order terminology: use msb/lsb first.
*
* Revision 1.3 1993/08/20 03:45:27 Rhialto
* Add hack for auto-detecting fax bit order.
*
* Revision 1.2 1993/06/11 16:33:37 Rhialto
* First real RCS checkin
*
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "g3.h"
#include "faxfile.h"
#ifdef DEBUG
#define debug(x) printf x
#else
#define debug(x)
#endif
#define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
#define MAXCOLS LINE_BITS
#define MAXROWS 4300 /* up to two pages long */
typedef struct faxin {
int raw;
FAXHDR faxhdr;
FAXHDR pagehdr;
int row;
int endoffile;
int eols;
int rawzeros;
int shdata;
int shbit;
int kludge;
int reversebits;
int stretch;
unsigned char *bitp;
unsigned char bitval;
} FAXIN;
static FAXIN faxin;
#define WHASHA 3510
#define WHASHB 1178
#define BHASHA 293
#define BHASHB 2695
#define HASHSIZE 1021
static tableentry *whash[HASHSIZE];
static tableentry *bhash[HASHSIZE];
static void addtohash(tableentry *hash[], tableentry* te, int n, int a, int b);
static tableentry *hashfind(tableentry *hash[], int length, int code, int a, int b);
static int getfaxrow(FILE *inf, int row, unsigned char *bitrow);
static void skiptoeol(FILE *file);
static int rawgetbit(FILE *file);
extern int verbose;
int
memisprint(unsigned char *s, int len)
{
while (len > 0) {
if (s[0] && !isprint((s[0])))
return 0;
s++;
len--;
}
return 1;
}
int
try_line(FILE *ifp)
{
int col;
int curlen,
curcode,
nextbit;
int count,
color;
tableentry *te;
col = 0;
curlen = 0;
curcode = 0;
color = 1; /* 1=white, 0=black */
count = 0;
while (!faxin.endoffile) {
if (col >= MAXCOLS) {
skiptoeol(ifp);
return col;
}
do {
if (faxin.rawzeros >= 11) {
nextbit = rawgetbit(ifp);
if (nextbit) {
if (col && col < LINE_BITS)
return -1;
return (col);
}
if (feof(ifp)) {
return -1;
}
} else
nextbit = rawgetbit(ifp);
curcode = (curcode << 1) + nextbit;
curlen++;
} while (curcode <= 0);
if (curlen > 13) {
skiptoeol(ifp);
return -1;
}
if (color) {
if (curlen < 4)
continue;
te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
} else {
if (curlen < 2)
continue;
te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
}
if (!te)
continue;
switch (te->tabid) {
case TWTABLE:
case TBTABLE:
count += te->count;
if (col + count > MAXCOLS)
count = MAXCOLS - col;
if (count > 0) {
col += count;
count = 0;
}
curcode = 0;
curlen = 0;
color = !color;
break;
case MWTABLE:
case MBTABLE:
count += te->count;
curcode = 0;
curlen = 0;
break;
case EXTABLE:
count += te->count;
curcode = 0;
curlen = 0;
break;
default:
fprintf(stderr, "internal bad poop\n");
}
}
}
int
infer_bitorder(FILE *f)
{
int normerrors = 0;
int reverrors = 0;
int i;
long pos;
pos = ftell(f);
if (verbose)
printf("try MSB first...");
faxin.reversebits = 0;
faxin.shbit = 0;
skiptoeol(f);
for (i = 0; i < 10; i++)
if (try_line(f) == -1)
normerrors++;
fseek(f, pos, SEEK_SET);
if (verbose)
printf(" %d errors\n", normerrors);
if (verbose)
printf("try LSB first...");
faxin.reversebits = 1;
faxin.shbit = 0;
skiptoeol(f);
for (i = 0; i < 10; i++)
if (try_line(f) == -1)
reverrors++;
fseek(f, pos, SEEK_SET);
if (verbose)
printf(" %d errors\n", reverrors);
if (normerrors < reverrors) {
return faxin.reversebits = 0;
} else {
fprintf(stderr, "Warning: this file has its bits the wrong way!\n");
return faxin.reversebits = 1;
}
}
/*
* Prepare for reading a faxfile.
* dostretch (ignored) indicates we must repeat each scan line.
* bitorder indicates bit order: 0=normal: lsb first, 1=reversed: msb first.
* -1: auto-detect.
* For understandable reasons, the designer of this decoder had
* the opposite idea of what was normal and reversed, hence
* some confusion.
*/
long /* error code */
faxin_open_fp(FILE *ifp, int dostretch, int bitorder)
{
int i;
faxin.stretch = dostretch;
for (i = 0; i < HASHSIZE; ++i)
whash[i] = bhash[i] = (tableentry *) 0;
addtohash(whash, twtable, TABSIZE(twtable), WHASHA, WHASHB);
addtohash(whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB);
addtohash(whash, extable, TABSIZE(extable), WHASHA, WHASHB);
addtohash(bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB);
addtohash(bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB);
addtohash(bhash, extable, TABSIZE(extable), BHASHA, BHASHB);
#ifdef _DCC
setvbuf(ifp, NULL, _IOFBF, 16384);
#endif
/* Attempt to read file/page header */
if (fread(&faxin.faxhdr, sizeof(faxin.faxhdr), 1, ifp) == 1) {
fseek(ifp, -sizeof(faxin.faxhdr), SEEK_CUR);
#if 1
faxin.raw = 1;
#else
faxin.raw = !memisprint(&faxin.faxhdr.id.magic[0], sizeof(faxin.faxhdr.id.magic));
debug(("assume faxin.raw = %d\n", faxin.raw));
#endif
/* If fax is raw, try to infer bit order */
if (faxin.raw) {
faxin.reversebits = !bitorder; /* swap 0 and 1 */
if (bitorder < 0)
bitorder = infer_bitorder(ifp);
if (bitorder < 0) {
debug(("fail on bit order\n"));
return 1;
}
}
return 0;
}
fprintf(stderr, "file too short\n");
return 1;
}
int
faxin_begin_page(FILE *ifp)
{
if (faxin.raw && ftell(ifp) != 0) {
/* Raw files contain only one page and no header */
return 1;
}
if (faxin.raw == 0) {
int bytes;
int byte;
/* Skip past page header by finding magic id */
retry:
bytes = 0;
/* Shortcut for first byte */
while ((byte = getc(ifp)) != faxin.faxhdr.id.magic[0]) {
if (feof(ifp)) {
return 1;
}
}
faxin.pagehdr.id.magic[0] = byte;
bytes = 1;
while (bytes < sizeof(faxin.faxhdr.id)) {
/* Do we have a matching prefix? */
if (memcmp(faxin.pagehdr.id.magic, faxin.faxhdr.id.magic, bytes) == 0) {
/* Yes, read one more byte and continue */
byte = getc(ifp);
if (feof(ifp))
return 1;
faxin.pagehdr.id.magic[bytes] = byte;
bytes++;
} else {
/* Shift everything down and reduce match length */
bytes--;
if (bytes == 0)
goto retry;
memmove(faxin.pagehdr.id.magic, faxin.pagehdr.id.magic + 1, bytes);
}
}
fread(&faxin.pagehdr.info, sizeof(faxin.pagehdr) - sizeof(faxin.pagehdr.id), 1, ifp);
if (feof(ifp)) {
fprintf(stderr, "Premature EOF after header\n");
return 1;
}
/* "Normal" bit ordering is MSB first */
faxin.reversebits = !faxin.pagehdr.info.msbfirst;
}
faxin.eols = 0;
faxin.rawzeros = 0;
faxin.endoffile = 0;
faxin.row = 0;
faxin.shbit = 0;
if (faxin.raw && feof(ifp)) {
return 1;
}
#ifdef KLUDGE
if (faxin.kludge) {
/* Skip extra lines to get in sync. */
skiptoeol(ifp);
skiptoeol(ifp);
skiptoeol(ifp);
}
#endif
skiptoeol(ifp);
if (feof(ifp)) {
return 1;
}
return 0;
}
static void
addtohash(hash, te, n, a, b)
tableentry *hash[];
tableentry *te;
int n,
a,
b;
{
unsigned int pos;
while (n--) {
pos = ((te->length + a) * (te->code + b)) % HASHSIZE;
if (hash[pos] != 0)
fprintf(stderr, "internal error: addtohash fatal hash collision\n");
hash[pos] = te;
te++;
}
}
static tableentry *
hashfind(hash, length, code, a, b)
tableentry *hash[];
int length,
code;
int a,
b;
{
unsigned int pos;
tableentry *te;
pos = ((length + a) * (code + b)) % HASHSIZE;
if (pos >= HASHSIZE)
fprintf(stderr,
"internal error: bad hash position, length %d code %d pos %d\n",
length, code, pos);
te = hash[pos];
return ((te && te->length == length && te->code == code) ? te : 0);
}
/* Put some black (color 1) bits in IFF bitmap format */
void
putblackbits(int count)
{
while (count > 0) {
*faxin.bitp |= faxin.bitval; /* Set a single bit */
count--;
faxin.bitval >>= 1;
if (faxin.bitval == 0) {
faxin.bitval = 0x80;
faxin.bitp++;
/* While we're byte-aligned, do 8 bits at a time */
while (count >= 8) {
*faxin.bitp++ = 0xFF;
count -= 8;
}
}
}
}
/* Put some white (color 0) bits in IFF bitmap format */
void
putwhitebits(int count)
{
while (count > 0) {
/* don't set a bit */
count--;
faxin.bitval >>= 1;
if (faxin.bitval == 0) {
faxin.bitval = 0x80;
faxin.bitp++;
/* While we're byte-aligned, do 8 bits at a time */
while (count >= 8) {
faxin.bitp++;
count -= 8;
}
}
}
}
int
fromfax(ifp, bitrow)
FILE *ifp;
unsigned char *bitrow;
{
int col;
int curlen,
curcode,
nextbit;
int count,
color;
tableentry *te;
col = 0;
curlen = 0;
curcode = 0;
color = 1; /* 1=white, 0=black */
count = 0;
faxin.bitp = bitrow;
faxin.bitval = 0x80;
faxin.row++;
while (!faxin.endoffile) {
if (col >= MAXCOLS) {
skiptoeol(ifp);
return (col);
}
do {
if (faxin.rawzeros >= 11) {
nextbit = rawgetbit(ifp);
if (nextbit) {
if (col == 0) {
/* XXX should be 6 */
faxin.endoffile = (++faxin.eols == 3);
if (verbose) {
fprintf(stderr, "empty row %d: found %d so far, eof=%d\n",
faxin.row, faxin.eols, faxin.endoffile);
}
}
#ifndef notdef
if (col && col < LINE_BITS)
fprintf(stderr, "warning, row %d short (len %d)\n",
faxin.row, col);
#endif /* notdef */
return col;
}
if (feof(ifp)) {
faxin.endoffile = 1;
return col;
}
} else
nextbit = rawgetbit(ifp);
curcode = (curcode << 1) + nextbit;
curlen++;
} while (curcode <= 0);
if (col != 0)
faxin.eols = 0;
if (curlen > 13) {
fprintf(stderr, "bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL\n",
faxin.row, col, curlen, curcode);
skiptoeol(ifp);
return (col);
}
if (color) {
if (curlen < 4)
continue;
te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
} else {
if (curlen < 2)
continue;
te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
}
if (!te)
continue;
switch (te->tabid) {
case TWTABLE:
case TBTABLE:
count += te->count;
if (col + count > MAXCOLS)
count = MAXCOLS - col;
if (count > 0) {
if (color) {
putwhitebits(count);
} else {
putblackbits(count);
}
col += count;
count = 0;
}
curcode = 0;
curlen = 0;
color = !color;
break;
case MWTABLE:
case MBTABLE:
count += te->count;
curcode = 0;
curlen = 0;
break;
case EXTABLE:
count += te->count;
curcode = 0;
curlen = 0;
break;
default:
fprintf(stderr, "internal bad poop\n");
}
}
return -1; /* End of page */
}
static void
skiptoeol(ifp)
FILE *ifp;
{
while (faxin.rawzeros < 11)
(void) rawgetbit(ifp);
for (;;) {
if (feof(ifp) || rawgetbit(ifp))
break;
}
}
static int
rawgetbit(ifp)
FILE *ifp;
{
int b;
if ((faxin.shbit & 0xff) == 0) {
faxin.shdata = getc(ifp);
if (faxin.shdata == EOF) {
fprintf(stderr, "EOF / read error at line %d\n", faxin.eols);
faxin.shdata = 0;
}
faxin.shbit = faxin.reversebits ? 0x01 : 0x80;
}
if (faxin.shdata & faxin.shbit) {
faxin.rawzeros = 0;
b = 1;
} else {
faxin.rawzeros++;
b = 0;
}
if (faxin.reversebits)
faxin.shbit <<= 1;
else
faxin.shbit >>= 1;
return b;
}
@
1.4
log
@Improve on bit order terminology: use msb/lsb first.
@
text
@d13 1
a13 1
/* $Id: fromfax.c,v 1.3 1993/08/20 03:45:27 Rhialto Exp $
d15 3
d170 1
a170 1
printf("internal bad poop\n");
d178 3
a180 3
int normerrors = 0;
int reverrors = 0;
int i;
d209 1
a209 1
if (normerrors < reverrors)
d211 2
a212 1
else
d214 1
d217 10
d228 1
a228 1
faxin_open_fp(FILE *ifp, int dostretch, int doreverse)
d257 4
a260 4
faxin.reversebits = doreverse;
if (doreverse < 0)
doreverse = infer_bitorder(ifp);
if (doreverse < 0) {
d365 1
a365 1
printf("internal error: addtohash fatal hash collision\n");
d385 1
a385 1
printf(
d463 1
a463 1
if (col == 0)
d466 5
a470 2
else
faxin.eols = 0;
d473 1
a473 1
printf("warning, row %d short (len %d)\n",
d476 1
a476 1
return (col);
d487 2
d490 1
a490 1
printf("bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL\n",
d537 1
a537 1
printf("internal bad poop\n");
d565 1
a565 1
printf("EOF / read error at line %d\n", faxin.eols);
@
1.3
log
@Add hack for auto-detecting fax bit order.
@
text
@d13 1
a13 1
/* $Id: fromfax.c,v 1.3 1993/08/20 02:48:24 Rhialto Exp $
d15 3
d183 1
a183 1
printf("try normal bit order...");
d195 1
a195 1
printf("try reverse bit order...");
@
1.2
log
@First real RCS checkin
@
text
@d13 8
a20 2
/* $Id$
* $Log$
d29 6
d43 1
d74 1
d88 124
d213 1
a213 1
faxin_open_fp(FILE *ifp, int dostretch)
d234 3
d238 12
d275 1
a275 1
if (feof(ifp))
d277 1
d313 2
d316 1
a316 1
if (faxin.raw && feof(ifp))
d318 1
d329 1
a329 1
if (feof(ifp))
d331 1
d437 1
d456 1
a456 1
-1, col);
d471 1
a471 1
-1, col, curlen, curcode);
@
1.1
log
@Initial revision
@
text
@d13 3
@