#include <X11/Xfuncproto.h>
#include <X11/extensions/lbximage.h>
#define PutByte(byte,bufptr,bytesLeft) \
{ \
if (*bytesLeft < 1) {\
*outbuf = outptr; \
return (0); \
} \
*bufptr++ = byte; \
(*bytesLeft)--; \
}
static int
EncodePackBits (char *inbuf,
int numPixels,
char **outbuf,
int *bytesLeft)
{
register int pixelsLeft = numPixels;
register char *outptr = *outbuf;
register char *lastliteral;
register int n, b;
enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
state = BASE;
lastliteral = 0;
while (pixelsLeft > 0)
{
b = *inbuf++, pixelsLeft--, n = 1;
for (; pixelsLeft > 0 && b == *inbuf; pixelsLeft--, inbuf++)
n++;
again:
switch (state)
{
case BASE:
if (n > 1)
{
state = RUN;
if (n > 128)
{
PutByte (-127, outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
n -= 128;
goto again;
}
PutByte (-(n-1), outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
}
else
{
lastliteral = outptr;
PutByte (0, outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
state = LITERAL;
}
break;
case LITERAL:
if (n > 1)
{
state = LITERAL_RUN;
if (n > 128)
{
PutByte (-127, outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
n -= 128;
goto again;
}
PutByte (-(n-1), outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
}
else
{
if (++(*lastliteral) == 127)
state = BASE;
PutByte (b, outptr, bytesLeft);
}
break;
case RUN:
if (n > 1)
{
if (n > 128)
{
PutByte (-127, outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
n -= 128;
goto again;
}
PutByte (-(n-1), outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
}
else
{
lastliteral = outptr;
PutByte (0, outptr, bytesLeft);
PutByte (b, outptr, bytesLeft);
state = LITERAL;
}
break;
case LITERAL_RUN:
if (n == 1 && outptr[-2] == (char)-1 && *lastliteral < 126)
{
state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
outptr[-2] = outptr[-1];
}
else
state = RUN;
goto again;
}
}
*outbuf = outptr;
return (1);
}
int
LbxImageEncodePackBits (char *inbuf,
char *outbuf,
int outbufSize,
int format,
int depth,
int num_scan_lines,
int scan_line_size,
int *bytesCompressed)
{
char *outbuf_start = outbuf;
int padded_scan_line_size = (scan_line_size % 4) ?
scan_line_size + (4 - scan_line_size % 4) : scan_line_size;
int bytesLeft = outbufSize;
while (num_scan_lines > 0)
{
if (!EncodePackBits (inbuf, scan_line_size, &outbuf, &bytesLeft))
return (LBX_IMAGE_COMPRESS_NOT_WORTH_IT);
inbuf += padded_scan_line_size;
num_scan_lines--;
}
*bytesCompressed = outbuf - outbuf_start;
return (LBX_IMAGE_COMPRESS_SUCCESS);
}