home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 2
/
FFMCD02.bin
/
new
/
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);