#include <X11/Xos.h>
#include <X11/Xfuncproto.h>
#include <stdlib.h>
#include "lbxfax.h"
#include <X11/extensions/lbximage.h>
#include "lbxbwcodes.h"
static short sp_data, sp_bit;
static tableentry horizcode =
{ 3, 0x1 };
static tableentry passcode =
{ 4, 0x1 };
static tableentry vcodes[7] = {
{ 7, 0x03 },
{ 6, 0x03 },
{ 3, 0x03 },
{ 1, 0x1 },
{ 3, 0x2 },
{ 6, 0x02 },
{ 7, 0x02 }
};
typedef struct {
unsigned char *bufStart;
unsigned char *bufPtr;
int bufSize;
int bytesLeft;
} Buffer;
static int
flushbits (Buffer *outbuf)
{
if (outbuf->bytesLeft > 0)
{
*(outbuf->bufPtr++) = sp_data;
outbuf->bytesLeft--;
sp_data = 0;
sp_bit = 8;
return (1);
}
else
return (0);
}
static int
putbits (unsigned int bits,
unsigned int length,
Buffer *outbuf)
{
static int mask[9] =
{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
while (length > sp_bit)
{
sp_data |= bits >> (length - sp_bit);
length -= sp_bit;
if (!flushbits (outbuf))
return (0);
}
sp_data |= (bits & mask[length]) << (sp_bit - length);
sp_bit -= length;
if (sp_bit == 0)
{
if (!flushbits (outbuf))
return (0);
}
return (1);
}
static int
putcode (tableentry *te,
Buffer *outbuf)
{
return (putbits (te->code, te->length, outbuf));
}
static int
putspan (int span,
tableentry *tab,
Buffer *outbuf)
{
while (span >= 2624)
{
tableentry *te = &tab[63 + (2560 >> 6)];
if (!putcode (te, outbuf))
return (0);
span -= te->runlen;
}
if (span >= 64)
{
tableentry *te = &tab[63 + (span >> 6)];
if (!putcode (te, outbuf))
return (0);
span -= te->runlen;
}
if (!putcode (&tab[span], outbuf))
return (0);
return (1);
}
#define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1)
static int
EncodeFaxG42D (unsigned char *inbuf,
unsigned char *refline,
int bits,
Buffer *outbuf)
{
short white = 1;
int a0 = 0;
int a1 = (PIXEL (inbuf, 0) != white ?
0 : LbxImageFindDiff (inbuf, 0, bits, white));
int b1 = (PIXEL (refline, 0) != white ?
0 : LbxImageFindDiff (refline, 0, bits, white));
int a2, b2;
for (;;)
{
b2 = LbxImageFindDiff (refline, b1, bits, PIXEL (refline, b1));
if (b2 >= a1)
{
int d = b1 - a1;
if (!(-3 <= d && d <= 3))
{
a2 = LbxImageFindDiff (inbuf, a1, bits, PIXEL (inbuf, a1));
if (!putcode (&horizcode, outbuf))
return (0);
if (a0 + a1 == 0 || PIXEL (inbuf, a0) == white)
{
if (!putspan(a1 - a0, TIFFFaxWhiteCodes, outbuf))
return (0);
if (!putspan(a2 - a1, TIFFFaxBlackCodes, outbuf))
return (0);
}
else
{
if (!putspan (a1 - a0, TIFFFaxBlackCodes, outbuf))
return (0);
if (!putspan (a2 - a1, TIFFFaxWhiteCodes, outbuf))
return (0);
}
a0 = a2;
}
else
{
if (!putcode (&vcodes[d+3], outbuf))
return (0);
a0 = a1;
}
}
else
{
if (!putcode (&passcode, outbuf))
return (0);
a0 = b2;
}
if (a0 >= bits)
break;
a1 = LbxImageFindDiff (inbuf, a0, bits, PIXEL (inbuf, a0));
b1 = LbxImageFindDiff (refline, a0, bits, !PIXEL (inbuf, a0));
b1 = LbxImageFindDiff (refline, b1, bits, PIXEL (inbuf, a0));
}
return (1);
}
int
LbxImageEncodeFaxG42D (unsigned char *inbuf,
unsigned char *outbuf,
int outbufSize,
int image_bytes,
int pixels_per_line,
int padded_bytes_per_scanline,
int reverse_bits,
int *bytesCompressed)
{
int bytes_per_scanline = ROUNDUP8 (pixels_per_line);
unsigned char *refline, *refptr;
unsigned char *save_inbuf = inbuf;
int bytes_left = image_bytes;
Buffer OutBuf;
int status, i;
OutBuf.bufStart = OutBuf.bufPtr = outbuf;
OutBuf.bufSize = OutBuf.bytesLeft = outbufSize;
if (!(refline = (unsigned char *) malloc (bytes_per_scanline + 1)))
return (LBX_IMAGE_COMPRESS_BAD_MALLOC);
refptr = refline + 1;
for (i = 0; i < bytes_per_scanline + 1; i++)
refline[i] = 0xff;
if (reverse_bits)
LbxReverseBits (inbuf, image_bytes);
sp_bit = 8;
sp_data = 0;
while (bytes_left > 0)
{
if (!(status = EncodeFaxG42D (inbuf, refptr,
pixels_per_line, &OutBuf)))
{
goto bad;
}
memcpy (refptr, inbuf, bytes_per_scanline);
inbuf += padded_bytes_per_scanline;
bytes_left -= padded_bytes_per_scanline;
}
status = putbits (EOL, 12, &OutBuf);
if (status)
status = putbits (EOL, 12, &OutBuf);
if (status && sp_bit != 8)
{
status = flushbits (&OutBuf);
}
bad:
free ((char *) refline);
if (reverse_bits)
LbxReverseBits (save_inbuf, image_bytes);
if (status)
{
*bytesCompressed = OutBuf.bufPtr - OutBuf.bufStart;
if (OutBuf.bytesLeft > 0)
return (LBX_IMAGE_COMPRESS_SUCCESS);
else
return (LBX_IMAGE_COMPRESS_NOT_WORTH_IT);
}
else
return (LBX_IMAGE_COMPRESS_NOT_WORTH_IT);
}