home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
grfx_snd
/
tifflib
/
source
/
tif_fax3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-17
|
37KB
|
1,025 lines
#pragma warn -use
static char *sccsid = "@(#)TIFF/tif_fax3.c 1.34, Copyright (c) Sam Leffler, Dieter Linde, "__DATE__;
#pragma warn .use
/*
* Copyright (c) 1988, 1990 by Sam Leffler, Nov 24 1990
* All rights reserved.
*
* This file is provided for unrestricted use provided that this legend is included on all tape media and as a part of the
* software program in whole or part. Users may copy, modify or distribute this file at will.
*
* TIFF Library.
*
* CCITT Group 3 Facsimile-compatible Compression Scheme Support.
*
* This stuff was derived from code by Jef Pozkanzer.
*/
#include <stdlib.h>
#include "tiffio.h"
#include "tif_fax3.h"
#include "t4.h"
#include "g3codes.h"
typedef struct {
Fax3BaseState b;
} Fax3DecodeState;
typedef struct {
Fax3BaseState b;
u_char *wruns;
u_char *bruns;
short k; /* #rows left that can be 2d encoded */
short maxk; /* max #rows that can be 2d encoded */
} Fax3EncodeState;
/****************************************************************************
*
*/
void
TIFFModeCCITTFax3(
TIFF *tif,
int isClassF
)
{
if (isClassF)
tif->tif_options |= FAX3_CLASSF;
else
tif->tif_options &= ~FAX3_CLASSF;
}
#define is2DEncoding(tif) (tif->tif_dir.td_group3options & GROUP3OPT_2DENCODING)
#define fetchByte(tif, sp) (sp)->b.bitmap[*(u_char *)(tif)->tif_rawcp++]
#define BITCASE(b) case b: \
code <<= 1; \
if (data & b) \
code |= 1; \
len++; \
if (code > 0) { \
bit = (b >> 1); \
break; \
}
/****************************************************************************
* Skip over input until an EOL code is found.
*/
static void
skiptoeol(
TIFF *tif
)
{
Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data;
register int bit = sp->b.bit;
register int data = sp->b.data;
int code, len;
do {
code = len = 0;
switch (bit) {
again:
BITCASE(0x80);
BITCASE(0x40);
BITCASE(0x20);
BITCASE(0x10);
BITCASE(0x08);
BITCASE(0x04);
BITCASE(0x02);
BITCASE(0x01);
default:
if (tif->tif_rawcc <= 0) {
TIFFError("skiptoeol", "%s: premature EOF at scanline %d", tif->tif_name, tif->tif_row);
return;
}
data = fetchByte(tif, sp);
goto again;
}
} while (len < 12 || code != EOL);
sp->b.bit = bit;
sp->b.data = data;
}
/****************************************************************************
* Setup G3-related compression/decompression state before data is processed. This routine
* is called once per image -- it sets up different state based on whether or not 2D encoding is used.
*/
static void *
Fax3SetupState(
TIFF *tif,
int space
)
{
TIFFDirectory *td = &tif->tif_dir;
Fax3BaseState *sp;
int cc = space;
if (td->td_bitspersample != 1) {
TIFFError(tif->tif_name, "Bits/sample must be 1 for Group 3/4 encoding/decoding");
return(0);
}
if (is2DEncoding(tif) || td->td_compression == COMPRESSION_CCITTFAX4)
cc += tif->tif_scanlinesize;
tif->tif_data = malloc(cc);
if (tif->tif_data == NULL) {
TIFFError(tif->tif_name, "No space for Fax3 state block");
return(0);
}
sp = (Fax3BaseState *)tif->tif_data;
sp->bitmap = (tif->tif_fillorder != td->td_fillorder ? TIFFBitRevTable : TIFFNoBitRevTable);
sp->white = (td->td_photometric == PHOTOMETRIC_MINISBLACK);
if (is2DEncoding(tif) || td->td_compression == COMPRESSION_CCITTFAX4) {
/*
* 2d encoding/decoding requires a scanline buffer for the ``reference line''; the
* scanline against which delta encoding is referenced. The referennce line must
* be initialized to be ``white.''
*/
sp->refline = tif->tif_data + space;
bzero(sp->refline, tif->tif_scanlinesize);
if (sp->white == 1)
TIFFReverseBits(sp->refline, tif->tif_scanlinesize);
}
else
sp->refline = 0;
return(sp);
}
/****************************************************************************
* Setup state for decoding a strip.
*/
static int
Fax3PreDecode(
TIFF *tif
)
{
Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data;
if (sp == NULL) {
sp = (Fax3DecodeState *)Fax3SetupState(tif, (int)sizeof(*sp));
if (!sp)
return(0);
}
sp->b.bit = 0; /* force initial read */
sp->b.data = 0;
sp->b.tag = G3_1D;
/*
* Non-TIFF/F images have an initial blank line that we need to skip over. Note that this
* is only done at the beginning of the image, not at the start of each strip.
*/
if (tif->tif_curstrip == 0 && (tif->tif_options & FAX3_CLASSF) == 0)
skiptoeol(tif);
return(1);
}
/****************************************************************************
* Fill a span with ones.
*/
static void
fillspan(
register char *cp,
register int x,
register int count
)
{
static u_char masks[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
cp += (x >> 3);
if (x &= 7) { /* align to byte boundary */
if (count < 8 - x) {
*cp++ |= (masks[count] >> x);
return;
}
*cp++ |= (0xff >> x);
count -= 8 - x;
}
while (count >= 8) {
*cp++ = 0xff;
count -= 8;
}
*cp |= masks[count];
}
/****************************************************************************
* Process one row of 1d Huffman-encoded data.
*/
static int
Fax3Decode1DRow(
TIFF *tif,
u_char *buf,
int npels
)
{
Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data;
short bit = sp->b.bit;
short data = sp->b.data;
int x = 0;
int count = 0;
short len = 0;
short code = 0;
short color = sp->b.white;
tableentry *te;
static char module[] = "Fax3Decode1D";
for (;;) {
switch (bit) {
again:
BITCASE(0x80);
BITCASE(0x40);
BITCASE(0x20);
BITCASE(0x10);
BITCASE(0x08);
BITCASE(0x04);
BITCASE(0x02);
BITCASE(0x01);
default:
if (tif->tif_rawcc <= 0) {
TIFFError(module, "%s: Premature EOF at scanline %d (x %d)", tif->tif_name, tif->tif_row, x);
return(0);
}
data = fetchByte(tif, sp);
goto again;
}
if (len >= 12) {
if (code == EOL) {
if (x == 0) {
TIFFWarning(tif->tif_name, "%s: Ignoring null row at scanline %d", module, tif->tif_row);
code = len = 0;
continue;
}
sp->b.bit = bit;
sp->b.data = data;
TIFFWarning(tif->tif_name, "%s: Premature EOL at scanline %d (x %d)", module, tif->tif_row, x);
return(1); /* try to resynchronize... */
}
if (len > 13) {
TIFFError(tif->tif_name, "%s: Bad code word (len %d code 0x%x) at scanline %d (x %d)", module, len, code, tif->tif_row, x);
break;
}
}
if (color == sp->b.white) {
u_char ix = TIFFFax3wtab[code << (13 - len)];
if (ix == 0xff)
continue;
te = &TIFFFax3wcodes[ix];
}
else {
u_char ix = TIFFFax3btab[code << (13 - len)];
if (ix == 0xff)
continue;
te = &TIFFFax3bcodes[ix];
}
if (te->length != len)
continue;
count += te->count;
if (te->tabid < 0) { /* terminating code */
if (x + count > npels)
count = npels - x;
if (count > 0) {
if (color)
fillspan((char *)buf, x, count);
x += count;
if (x >= npels)
break;
}
count = 0;
color = !color;
}
code = len = 0;
}
sp->b.data = data;
sp->b.bit = bit;
/*
* Cleanup at the end of the row. This convoluted logic is merely so that we can reuse the code with
* two other related compression algorithms (2 & 32771).
*
* Note also that our handling of word alignment assumes that the buffer is at least word aligned. This is
* the case for most all versions of malloc (typically the buffer is returned longword aligned).
*/
if ((tif->tif_options & FAX3_NOEOL) == 0)
skiptoeol(tif);
if (tif->tif_options & FAX3_BYTEALIGN)
sp->b.bit = 0;
if ((tif->tif_options & FAX3_WORDALIGN) && ((long)tif->tif_rawcp & 1)) {
tif->tif_rawcp++;
tif->tif_rawcc--;
}
return(x == npels);
}
/****************************************************************************
* Decode the requested amount of data.
*/
static int
Fax3Decode(
TIFF *tif,
u_char *buf,
int occ
)
{
Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data;
int scanline = tif->tif_scanlinesize;
int imagewidth = tif->tif_dir.td_imagewidth;
bzero(buf, occ); /* decoding only sets non-zero bits */
while (occ > 0) {
if (sp->b.tag == G3_1D) {
if (!Fax3Decode1DRow(tif, buf, imagewidth))
return(0);
}
else {
if (!Fax3Decode2DRow(tif, buf, imagewidth))
return(0);
}
if (is2DEncoding(tif)) {
/*
* Fetch the tag bit that indicates whether the next row is 1d or 2d
* encoded. If 2d-encoded, then setup the reference line from the decoded
* scanline just completed.
*/
if (sp->b.bit == 0) {
if (tif->tif_rawcc <= 0) {
TIFFError("Fax3Decode", "%s: Premature EOF at scanline %d", tif->tif_name, tif->tif_row);
return(0);
}
sp->b.data = fetchByte(tif, sp);
sp->b.bit = 0x80;
}
sp->b.tag = (sp->b.data & sp->b.bit) ? G3_1D : G3_2D;
sp->b.bit >>= 1;
if (sp->b.tag == G3_2D)
bcopy(buf, sp->b.refline, scanline);
}
buf += scanline;
occ -= scanline;
}
return(1);
}
/*
* Group 3 2d Decoding support.
*
* NB: the order of the decoding modes is used below
*/
#define MODE_HORIZ 0 /* horizontal mode, handling 1st runlen */
#define MODE_HORIZ1 1 /* horizontal mode, handling 2d runlen */
#define MODE_OTHER 2 /* !horizontal mode */
#define PACK(code, len) (((len) << 2) + (code))
/*
* Group 3 2d decoding modes
*/
#define PASS 1
#define HORIZONTAL 2
#define VERTICAL 3
#define EXTENSION 4
#define UNCOMPRESSED 1
#define PACKINFO(mode, v) (((v) << 4) + mode)
#define UNPACKMODE(v) ((v) & 0xf)
#define UNPACKINFO(v) ((v) >> 4)
static short g32dtab[56] = {
0, 0, 0, 0, 0, 3, 0, 0, /* 0x00 - 0x07 */
0, 0, 0, 0, 0, 2, -13, 19, /* 0x08 - 0x0f */
0, 1, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x17 */
0, 0, -29, 35, 0, 0, -45, 51, /* 0x18 - 0x1f */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x27 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x28 - 0x2f */
0, 0, 0, 0, 0, 0, 0, 20, /* 0x30 - 0x37 */
};
#define NG32D (sizeof(g32dtab) / sizeof(g32dtab[0]))
/*
* Bit handling utilities.
*/
static u_char zeroruns[256] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
};
static u_char oneruns[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
};
/****************************************************************************
* Find a span of ones or zeros using the supplied table. The byte-aligned start of the bit string
* is supplied along with the start+end bit indices. The table gives the number of consecutive ones or
* zeros starting from the msb and is indexed by byte value.
*/
static int
findspan(
u_char **bpp,
int bs,
int be,
register u_char *tab
)
{
register u_char *bp = *bpp;
register int bits = be - bs;
register int n, span;
/*
* Check partial byte on lhs.
*/
if (bits > 0 && ((n = (bs & 7)) != 0)) {
span = tab[(*bp << n) & 0xff];
if (span > 8 - n) /* table value too generous */
span = 8 - n;
if (n + span < 8) /* doesn't extend to edge of byte */
goto done;
bits -= span;
bp++;
}
else
span = 0;
/*
* Scan full bytes for all 1's or all 0's.
*/
while (bits >= 8) {
n = tab[*bp];
span += n;
bits -= n;
if (n < 8) /* end of run */
goto done;
bp++;
}
/*
* Check partial byte on rhs.
*/
if (bits > 0) {
n = tab[*bp];
span += (n > bits ? bits : n);
}
done:
*bpp = bp;
return(span);
}
/****************************************************************************
* Return the offset of the next bit in the range [bs..be] that is different from bs. The end,
* be, is returned if no such bit exists.
*/
static int
finddiff(
u_char *cp,
int bs,
int be
)
{
cp += (bs >> 3); /* adjust byte offset */
return(bs + findspan(&cp, bs, be, (*cp & (0x80 >> (bs & 7))) ? oneruns : zeroruns));
}
/****************************************************************************
* Process one row of 2d encoded data.
*/
int
Fax3Decode2DRow(
TIFF *tif,
u_char *buf,
int npels
)
{
#define PIXEL(buf, ix) ((((buf)[(ix) >> 3]) >> (7 - ((ix) & 7))) & 1)
Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data;
short bit = sp->b.bit;
short data = sp->b.data;
short len = 0;
short code = 0;
int a0 = 0;
int b1 = 0;
int b2 = 0;
int count = 0;
short mode = MODE_OTHER;
short color = sp->b.white;
static char module[] = "Fax3Decode2D";
do {
switch (bit) {
again:
BITCASE(0x80);
BITCASE(0x40);
BITCASE(0x20);
BITCASE(0x10);
BITCASE(0x08);
BITCASE(0x04);
BITCASE(0x02);
BITCASE(0x01);
default:
if (tif->tif_rawcc <= 0) {
TIFFError(module, "%s: Premature EOF at scanline %d", tif->tif_name, tif->tif_row);
return(0);
}
data = fetchByte(tif, sp);
goto again;
}
if (len >= 12) {
if (code == EOL) {
if (a0 == 0) {
TIFFWarning(tif->tif_name, "%s: Ignoring null row at scanline %d", module, tif->tif_row);
code = len = 0;
continue;
}
sp->b.bit = bit;
sp->b.data = data;
TIFFWarning(tif->tif_name, "%s: Premature EOL at scanline %d (x %d)", module, tif->tif_row, a0);
return(1); /* try to resynchronize... */
}
if (len > 13) {
TIFFError(tif->tif_name, "%s: Bad code word (len %d code 0x%x) at scanline %d", module, len, code, tif->tif_row);
break;
}
}
if (mode != MODE_OTHER) {
tableentry *te;
/*
* In horizontal mode, collect 1d code words that represent a0.a1 and a1.a2.
*/
if (color == sp->b.white) {
u_char ix = TIFFFax3wtab[code << (13 - len)];
if (ix == 0xff)
continue;
te = &TIFFFax3wcodes[ix];
}
else {
u_char ix = TIFFFax3btab[code << (13 - len)];
if (ix == 0xff)
continue;
te = &TIFFFax3bcodes[ix];
}
if (te->length != len)
continue;
count += te->count;
if (te->tabid < 0) { /* terminating code */
if (a0 + count > npels)
count = npels - a0;
if (count > 0) {
if (color)
fillspan((char *)buf, a0, count);
a0 += count;
}
mode++; /* NB: assumes state ordering */
count = 0;
color = !color;
}
}
else {
int v = PACK(code, len);
if (v >= NG32D || ((v = g32dtab[v]) == 0)) {
continue;
}
switch (UNPACKMODE(v)) {
case PASS:
b1 = (a0 || PIXEL(sp->b.refline, 0)) ? finddiff(sp->b.refline, a0, npels) : 0;
if (color == PIXEL(sp->b.refline, b1))
b1 = finddiff(sp->b.refline, b1, npels);
b2 = finddiff(sp->b.refline, b1, npels);
if (color)
fillspan((char *)buf, a0, b2 - a0);
a0 += b2 - a0;
break;
case HORIZONTAL:
mode = MODE_HORIZ;
count = 0;
break;
case VERTICAL:
b1 = (a0 || PIXEL(sp->b.refline, 0)) ? finddiff(sp->b.refline, a0, npels) : 0;
if (color == PIXEL(sp->b.refline, b1))
b1 = finddiff(sp->b.refline, b1, npels);
b1 += UNPACKINFO(v);
if (color)
fillspan((char *)buf, a0, b1 - a0);
a0 += b1 - a0;
color = !color;
break;
case EXTENSION:
/*** XXX fill in... ***/
break;
}
}
code = len = 0;
} while (a0 < npels);
sp->b.data = data;
sp->b.bit = bit;
/*
* Cleanup at the end of row. We check for EOL separately so that this code can be
* reused by the Group 4 decoding routine.
*/
if ((tif->tif_options & FAX3_NOEOL) == 0)
skiptoeol(tif);
return(a0 >= npels);
#undef PIXEL
}
/*
* CCITT Group 3 FAX Encoding.
*/
/****************************************************************************
* Write a variable-length bit-value to the output stream. Values are
* assumed to be at most 16 bits.
*/
static void
putbits(
TIFF *tif,
u_int bits,
u_int length
)
{
Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data;
static int mask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
while (length > sp->bit) {
sp->data |= (bits >> (length - sp->bit));
if (tif->tif_rawcc >= tif->tif_rawdatasize)
TIFFFlushData1(tif);
*tif->tif_rawcp++ = sp->bitmap[sp->data];
tif->tif_rawcc++;
length -= sp->bit;
sp->data = 0;
sp->bit = 8;
}
sp->data |= ((bits & mask[length]) << (sp->bit - length));
sp->bit -= length;
if (sp->bit == 0) {
if (tif->tif_rawcc >= tif->tif_rawdatasize)
TIFFFlushData1(tif);
*tif->tif_rawcp++ = sp->bitmap[sp->data];
tif->tif_rawcc++;
sp->data = 0;
sp->bit = 8;
}
}
/****************************************************************************
* Write a code to the output stream.
*/
static void
putcode(
TIFF *tif,
tableentry *te
)
{
putbits(tif, te->code, te->length);
}
/****************************************************************************
* Write the sequence of codes that describes the specified span of zero's or one's. The
* appropriate tables that hold the make-up and terminating codes are supplied.
*/
static void
putspan(
TIFF *tif,
int span,
tableentry *mtab,
tableentry *ttab
)
{
if (span >= 64) {
tableentry *te = &mtab[(span / 64) - 1];
putcode(tif, te);
span -= te->count;
}
putcode(tif, &ttab[span]);
}
/****************************************************************************
* Write an EOL code to the output stream. The zero-fill logic for byte-aligning encoded scanlines is handled
* here. We also handle writing the tag bit for the next scanline when doing 2d encoding.
*
* Note that when doing 2d encoding, we byte-align the combination of the EOL + tag bits. It is unclear
* (to me) from the documentation whether this is the correct behaviour, or whether the EOL should be
* aligned and the tag bit should be the first bit in the next byte. I've implemented what seems to make
* the most sense.
*/
void
Fax3PutEOL(
TIFF *tif
)
{
Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data;
if (tif->tif_dir.td_group3options & GROUP3OPT_FILLBITS) {
/*
* Force bit alignment so EOL (+tag bit) will terminate on a byte boundary. That is, force
* the bit alignment to 16-12 = 4 (or 16-13 = 3 for 2d encoding) before putting out the EOL code.
*/
int align = 8 - (is2DEncoding(tif) ? 3 : 4);
if (align != sp->bit) {
if (align > sp->bit)
align = sp->bit + (8 - align);
else
align = sp->bit - align;
putbits(tif, 0, align);
}
}
putbits(tif, EOL, 12);
if (is2DEncoding(tif))
putbits(tif, sp->tag == G3_1D, 1);
}
/****************************************************************************
* Reset encoding state at the start of a strip.
*/
static int
Fax3PreEncode(
TIFF *tif
)
{
Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data;
if (sp == NULL) {
sp = (Fax3EncodeState *)Fax3SetupState(tif, (int)sizeof(*sp));
if (!sp)
return(0);
if (sp->b.white == 0) {
sp->wruns = zeroruns;
sp->bruns = oneruns;
}
else {
sp->wruns = oneruns;
sp->bruns = zeroruns;
}
}
sp->b.bit = 8;
sp->b.data = 0;
sp->b.tag = G3_1D;
if (is2DEncoding(tif)) {
float res = tif->tif_dir.td_yresolution;
/*
* The CCITT spec says that when doing 2d encoding, you should only do it on K consecutive scanlines, where K
* depends on the resolution of the image being encoded (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory
* code initializes td_yresolution to 0, this code will select a K of 2 unless the YResolution tag is set
* appropriately. (Note also that we fudge a little here and use 150 lpi to avoid problems with units conversion.)
*/
if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER)
res = (res * .3937) / 2.54; /* convert to inches */
sp->maxk = (res > 150 ? 4 : 2);
sp->k = sp->maxk-1;
}
else
sp->k = sp->maxk = 0;
if ((tif->tif_options & FAX3_CLASSF) == 0 && tif->tif_curstrip == 0)
Fax3PutEOL(tif);
return(1);
}
/****************************************************************************
* 1d-encode a row of pixels. The encoding is a sequence of all-white or all-black spans
* of pixels encoded with Huffman codes.
*/
static void
Fax3Encode1DRow(
TIFF *tif,
u_char *bp,
int bits
)
{
Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data;
int bs = 0;
int span;
for (;;) {
span = findspan(&bp, bs, bits, sp->wruns); /* white span */
putspan(tif, span, g3mwtab, g3twtab);
bs += span;
if (bs >= bits)
break;
span = findspan(&bp, bs, bits, sp->bruns); /* black span */
putspan(tif, span, g3mbtab, g3tbtab);
bs += span;
if (bs >= bits)
break;
}
}
static tableentry horizcode = { 0x1, 3 };
static tableentry passcode = { 0x1, 4 };
static tableentry vcodes[7] = {
{ 0x3, 7 },
{ 0x3, 6 },
{ 0x3, 3 },
{ 0x1, 1 },
{ 0x2, 3 },
{ 0x2, 6 },
{ 0x2, 7 },
};
/****************************************************************************
* 2d-encode a row of pixels. Consult the CCITT documentation for the algorithm.
*/
int
Fax3Encode2DRow(
TIFF *tif,
u_char *bp,
u_char *rp,
int bits
)
{
#define PIXEL(buf, ix) ((((buf)[(ix) >> 3]) >> (7 - ((ix) & 7))) & 1)
short white = ((Fax3BaseState *)tif->tif_data)->white;
int a0 = 0;
int a1 = (PIXEL(bp, 0) != white ? 0 : finddiff(bp, 0, bits));
int a2 = 0;
int b1 = (PIXEL(rp, 0) != white ? 0 : finddiff(rp, 0, bits));
int b2 = 0;
for (;;) {
b2 = finddiff(rp, b1, bits);
if (b2 >= a1) {
int d = b1 - a1;
if (!(-3 <= d && d <= 3)) { /* horizontal mode */
a2 = finddiff(bp, a1, bits);
putcode(tif, &horizcode);
if (a0 + a1 == 0 || PIXEL(bp, a0) == white) {
putspan(tif, a1 - a0, g3mwtab, g3twtab);
putspan(tif, a2 - a1, g3mbtab, g3tbtab);
}
else {
putspan(tif, a1 - a0, g3mbtab, g3tbtab);
putspan(tif, a2 - a1, g3mwtab, g3twtab);
}
a0 = a2;
}
else { /* vertical mode */
putcode(tif, &vcodes[d + 3]);
a0 = a1;
}
}
else { /* pass mode */
putcode(tif, &passcode);
a0 = b2;
}
if (a0 >= bits)
break;
a1 = finddiff(bp, a0, bits);
b1 = finddiff(rp, a0, bits);
if (PIXEL(rp, b1) == PIXEL(bp, a0))
b1 = finddiff(rp, b1, bits);
}
return(1);
#undef PIXEL
}
/****************************************************************************
* Encode a buffer of pixels.
*/
static int
Fax3Encode(
TIFF *tif,
u_char *bp,
int cc
)
{
Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data;
int scanline = tif->tif_scanlinesize;
int imagewidth = tif->tif_dir.td_imagewidth;
while (cc > 0) {
if (is2DEncoding(tif)) {
if (sp->b.tag == G3_1D) {
Fax3Encode1DRow(tif, bp, imagewidth);
/* if (!Fax3Encode1DRow(tif, bp, imagewidth))
return(0);*/
sp->b.tag = G3_2D;
}
else {
if (!Fax3Encode2DRow(tif, bp, sp->b.refline, imagewidth))
return(0);
sp->k--;
}
if (sp->k == 0) {
sp->b.tag = G3_1D;
sp->k = sp->maxk - 1;
}
else
bcopy(bp, sp->b.refline, scanline);
}
else {
Fax3Encode1DRow(tif, bp, imagewidth);
/* if (!Fax3Encode1DRow(tif, bp, imagewidth))
return(0);*/
}
Fax3PutEOL(tif);
bp += scanline;
cc -= scanline;
}
return(1);
}
/****************************************************************************
*
*/
static int
Fax3PostEncode(
TIFF *tif
)
{
Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data;
if (sp->b.bit != 8) {
if (tif->tif_rawcc >= tif->tif_rawdatasize && !TIFFFlushData1(tif))
return(0);
*tif->tif_rawcp++ = sp->b.bitmap[sp->b.data];
tif->tif_rawcc++;
}
return(1);
}
/****************************************************************************
*
*/
static void
Fax3Close(
TIFF *tif
)
{
if ((tif->tif_options & FAX3_CLASSF) == 0) { /* append RTC */
int i;
for (i = 0; i < 6; i++)
Fax3PutEOL(tif);
Fax3PostEncode(tif);
}
}
/****************************************************************************
*
*/
static void
Fax3Cleanup(
TIFF *tif
)
{
if (tif->tif_data) {
free(tif->tif_data);
tif->tif_data = NULL;
}
}
/****************************************************************************
*
*/
int
TIFFInitCCITTFax3(
TIFF *tif
)
{
tif->tif_stripdecode = Fax3PreDecode;
tif->tif_decoderow = Fax3Decode;
tif->tif_stripencode = Fax3PreEncode;
tif->tif_encoderow = Fax3Encode;
tif->tif_encodestrip = Fax3PostEncode;
tif->tif_close = Fax3Close;
tif->tif_cleanup = Fax3Cleanup;
tif->tif_options |= FAX3_CLASSF; /* default */
tif->tif_flags |= TIFF_NOBITREV; /* we handle bit reversal */
return(1);
}