#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WITH_GIF
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#define TRUE 1
#define FALSE 0
typedef int code_int;
static int colorstobpp(int colors);
static void BumpPixel (void);
static int GIFNextPixel (gdImagePtr im);
static void GIFEncode (gdIOCtx *ctx, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
static void compress (int, gdIOCtx *, gdImagePtr, int);
static void output (code_int code);
static void init_statics(void);
void gdImageGif(gdImagePtr im, FILE *outFile)
{
gdIOCtx *out = gdNewFileCtx(outFile);
gdImageGifCtx(im, out);
out->gd_free(out);
}
void* gdImageGifPtr(gdImagePtr im, int *size)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
gdImageGifCtx(im, out);
rv = gdDPExtractData(out, size);
out->gd_free(out);
return rv;
}
void gdImageGifCtx(gdImagePtr im, gdIOCtx *out)
{
int interlace, transparent, BitsPerPixel;
interlace = im->interlace;
transparent = im->transparent;
BitsPerPixel = colorstobpp(im->colorsTotal);
init_statics();
GIFEncode(
out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
im->red, im->green, im->blue, im);
}
static int
colorstobpp(int colors)
{
int bpp = 0;
if ( colors <= 2 )
bpp = 1;
else if ( colors <= 4 )
bpp = 2;
else if ( colors <= 8 )
bpp = 3;
else if ( colors <= 16 )
bpp = 4;
else if ( colors <= 32 )
bpp = 5;
else if ( colors <= 64 )
bpp = 6;
else if ( colors <= 128 )
bpp = 7;
else if ( colors <= 256 )
bpp = 8;
return bpp;
}
#define TRUE 1
#define FALSE 0
static int Width, Height;
static int curx, cury;
static long CountDown;
static int Pass = 0;
static int Interlace;
static void
BumpPixel(void)
{
++curx;
if( curx == Width ) {
curx = 0;
if( !Interlace )
++cury;
else {
switch( Pass ) {
case 0:
cury += 8;
if( cury >= Height ) {
++Pass;
cury = 4;
}
break;
case 1:
cury += 8;
if( cury >= Height ) {
++Pass;
cury = 2;
}
break;
case 2:
cury += 4;
if( cury >= Height ) {
++Pass;
cury = 1;
}
break;
case 3:
cury += 2;
break;
}
}
}
}
static int
GIFNextPixel(gdImagePtr im)
{
int r;
if( CountDown == 0 )
return EOF;
--CountDown;
r = gdImageGetPixel(im, curx, cury);
BumpPixel();
return r;
}
static void
GIFEncode(gdIOCtx *ctx, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
{
int B;
int RWidth, RHeight;
int LeftOfs, TopOfs;
int Resolution;
int ColorMapSize;
int InitCodeSize;
int i;
Interlace = GInterlace;
ColorMapSize = 1 << BitsPerPixel;
RWidth = Width = GWidth;
RHeight = Height = GHeight;
LeftOfs = TopOfs = 0;
Resolution = BitsPerPixel;
CountDown = (long)Width * (long)Height;
Pass = 0;
if( BitsPerPixel <= 1 )
InitCodeSize = 2;
else
InitCodeSize = BitsPerPixel;
curx = cury = 0;
gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, ctx );
Putword( RWidth, ctx );
Putword( RHeight, ctx );
B = 0x80;
B |= (Resolution - 1) << 4;
B |= (BitsPerPixel - 1);
Putchar( B, ctx );
Putchar( Background, ctx );
Putchar( 0, ctx );
for( i=0; i<ColorMapSize; ++i ) {
Putchar( Red[i], ctx );
Putchar( Green[i], ctx );
Putchar( Blue[i], ctx );
}
if ( Transparent >= 0 ) {
Putchar( '!', ctx );
Putchar( 0xf9, ctx );
Putchar( 4, ctx );
Putchar( 1, ctx );
Putchar( 0, ctx );
Putchar( 0, ctx );
Putchar( (unsigned char) Transparent, ctx );
Putchar( 0, ctx );
}
Putchar( ',', ctx );
Putword( LeftOfs, ctx );
Putword( TopOfs, ctx );
Putword( Width, ctx );
Putword( Height, ctx );
if( Interlace )
Putchar( 0x40, ctx );
else
Putchar( 0x00, ctx );
Putchar( InitCodeSize, ctx );
compress( InitCodeSize+1, ctx, im, Background );
Putchar( 0, ctx );
Putchar( ';', ctx );
}
#define GIFBITS 12
static int rl_pixel;
static int rl_basecode;
static int rl_count;
static int rl_table_pixel;
static int rl_table_max;
static int just_cleared;
static int out_bits;
static int out_bits_init;
static int out_count;
static int out_bump;
static int out_bump_init;
static int out_clear;
static int out_clear_init;
static int max_ocodes;
static int code_clear;
static int code_eof;
static unsigned int obuf;
static int obits;
static gdIOCtx *octx;
static unsigned char oblock[256];
static int oblen;
#ifdef DEBUGGING_ENVARS
static int verbose_set = 0;
static int verbose;
#define VERBOSE (verbose_set?verbose:set_verbose())
static int set_verbose(void)
{
verbose = !!getenv("GIF_VERBOSE");
verbose_set = 1;
return(verbose);
}
#else
#define VERBOSE 0
#endif
static const char *binformat(unsigned int v, int nbits)
{
static char bufs[8][64];
static int bhand = 0;
unsigned int bit;
int bno;
char *bp;
bhand --;
if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
bp = &bufs[bhand][0];
for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1)
{ *bp++ = (v & bit) ? '1' : '0';
if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
}
*bp = '\0';
return(&bufs[bhand][0]);
}
static void write_block(void)
{
int i;
if (VERBOSE)
{ printf("write_block %d:",oblen);
for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
printf("\n");
}
Putchar(oblen,octx);
gdPutBuf(&oblock[0],oblen,octx);
oblen = 0;
}
static void block_out(unsigned char c)
{
if (VERBOSE) printf("block_out %s\n",binformat(c,8));
oblock[oblen++] = c;
if (oblen >= 255) write_block();
}
static void block_flush(void)
{
if (VERBOSE) printf("block_flush\n");
if (oblen > 0) write_block();
}
static void output(int val)
{
if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
obuf |= val << obits;
obits += out_bits;
while (obits >= 8)
{ block_out(obuf&0xff);
obuf >>= 8;
obits -= 8;
}
if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
}
static void output_flush(void)
{
if (VERBOSE) printf("output_flush\n");
if (obits > 0) block_out(obuf);
block_flush();
}
static void did_clear(void)
{
if (VERBOSE) printf("did_clear\n");
out_bits = out_bits_init;
out_bump = out_bump_init;
out_clear = out_clear_init;
out_count = 0;
rl_table_max = 0;
just_cleared = 1;
}
static void output_plain(int c)
{
if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
just_cleared = 0;
output(c);
out_count ++;
if (out_count >= out_bump)
{ out_bits ++;
out_bump += 1 << (out_bits - 1);
}
if (out_count >= out_clear)
{ output(code_clear);
did_clear();
}
}
static unsigned int isqrt(unsigned int x)
{
unsigned int r;
unsigned int v;
if (x < 2) return(x);
for (v=x,r=1;v;v>>=2,r<<=1) ;
while (1)
{ v = ((x / r) + r) / 2;
if ((v == r) || (v == r+1)) return(r);
r = v;
}
}
static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes)
{
unsigned int perrep;
unsigned int cost;
cost = 0;
perrep = (nrepcodes * (nrepcodes+1)) / 2;
while (count >= perrep)
{ cost += nrepcodes;
count -= perrep;
}
if (count > 0)
{ unsigned int n;
n = isqrt(count);
while ((n*(n+1)) >= 2*count) n --;
while ((n*(n+1)) < 2*count) n ++;
cost += n;
}
return(cost);
}
static void max_out_clear(void)
{
out_clear = max_ocodes;
}
static void reset_out_clear(void)
{
out_clear = out_clear_init;
if (out_count >= out_clear)
{ output(code_clear);
did_clear();
}
}
static void rl_flush_fromclear(int count)
{
int n;
if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
max_out_clear();
rl_table_pixel = rl_pixel;
n = 1;
while (count > 0)
{ if (n == 1)
{ rl_table_max = 1;
output_plain(rl_pixel);
count --;
}
else if (count >= n)
{ rl_table_max = n;
output_plain(rl_basecode+n-2);
count -= n;
}
else if (count == 1)
{ rl_table_max ++;
output_plain(rl_pixel);
count = 0;
}
else
{ rl_table_max ++;
output_plain(rl_basecode+count-2);
count = 0;
}
if (out_count == 0) n = 1; else n ++;
}
reset_out_clear();
if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
}
static void rl_flush_clearorrep(int count)
{
int withclr;
if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
withclr = 1 + compute_triangle_count(count,max_ocodes);
if (withclr < count)
{ output(code_clear);
did_clear();
rl_flush_fromclear(count);
}
else
{ for (;count>0;count--) output_plain(rl_pixel);
}
}
static void rl_flush_withtable(int count)
{
int repmax;
int repleft;
int leftover;
if (VERBOSE) printf("rl_flush_withtable %d\n",count);
repmax = count / rl_table_max;
leftover = count % rl_table_max;
repleft = (leftover ? 1 : 0);
if (out_count+repmax+repleft > max_ocodes)
{ repmax = max_ocodes - out_count;
leftover = count - (repmax * rl_table_max);
repleft = 1 + compute_triangle_count(leftover,max_ocodes);
}
if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft)
{ output(code_clear);
did_clear();
rl_flush_fromclear(count);
return;
}
max_out_clear();
for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
if (leftover)
{ if (just_cleared)
{ rl_flush_fromclear(leftover);
}
else if (leftover == 1)
{ output_plain(rl_pixel);
}
else
{ output_plain(rl_basecode+leftover-2);
}
}
reset_out_clear();
}
static void rl_flush(void)
{
if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
if (rl_count == 1)
{ output_plain(rl_pixel);
rl_count = 0;
if (VERBOSE) printf("rl_flush ]\n");
return;
}
if (just_cleared)
{ rl_flush_fromclear(rl_count);
}
else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
{ rl_flush_clearorrep(rl_count);
}
else
{ rl_flush_withtable(rl_count);
}
if (VERBOSE) printf("rl_flush ]\n");
rl_count = 0;
}
static void compress(int init_bits, gdIOCtx *ctx, gdImagePtr im, int background)
{
int c;
octx = ctx;
obuf = 0;
obits = 0;
oblen = 0;
code_clear = 1 << (init_bits - 1);
code_eof = code_clear + 1;
rl_basecode = code_eof + 1;
out_bump_init = (1 << (init_bits - 1)) - 1;
out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
#ifdef DEBUGGING_ENVARS
{ const char *ocienv;
ocienv = getenv("GIF_OUT_CLEAR_INIT");
if (ocienv)
{ out_clear_init = atoi(ocienv);
if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
}
}
#endif
out_bits_init = init_bits;
max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
did_clear();
output(code_clear);
rl_count = 0;
while (1)
{ c = GIFNextPixel(im);
if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
if (c == EOF) break;
if (rl_pixel == c)
{ rl_count ++;
}
else
{ rl_pixel = c;
rl_count = 1;
}
}
output(code_eof);
output_flush();
}
static void init_statics(void) {
Width = 0;
Height = 0;
curx = 0;
cury = 0;
CountDown = 0;
Pass = 0;
Interlace = 0;
}
#define MAXCOLORMAPSIZE 256
#define TRUE 1
#define FALSE 0
#define CM_RED 0
#define CM_GREEN 1
#define CM_BLUE 2
#define MAX_LWZ_BITS 12
#define INTERLACE 0x40
#define LOCALCOLORMAP 0x80
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
#define LM_to_uint(a,b) (((b)<<8)|(a))
#if 0
static struct {
unsigned int Width;
unsigned int Height;
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
unsigned int BitPixel;
unsigned int ColorResolution;
unsigned int Background;
unsigned int AspectRatio;
} GifScreen;
#endif
#if 0
static struct {
int transparent;
int delayTime;
int inputFlag;
int disposal;
} Gif89 = { -1, -1, -1, 0 };
#endif
static int ReadColorMap (FILE *fd, int number, unsigned char (*buffer)[256]);
static int DoExtension (FILE *fd, int label, int *Transparent);
static int GetDataBlock (FILE *fd, unsigned char *buf);
static int GetCode (FILE *fd, int code_size, int flag);
static int LWZReadByte (FILE *fd, int flag, int input_code_size);
static void ReadImage (gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore);
int ZeroDataBlock;
gdImagePtr
gdImageCreateFromGif(FILE *fd)
{
int imageNumber;
int BitPixel;
#if 0
int ColorResolution;
int Background;
int AspectRatio;
#endif
int Transparent = (-1);
unsigned char buf[16];
unsigned char c;
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
int imw, imh;
int useGlobalColormap;
int bitPixel;
int imageCount = 0;
char version[4];
gdImagePtr im = 0;
ZeroDataBlock = FALSE;
imageNumber = 1;
if (! ReadOK(fd,buf,6)) {
return 0;
}
if (strncmp((char *)buf,"GIF",3) != 0) {
return 0;
}
strncpy(version, (char *)buf + 3, 3);
version[3] = '\0';
if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
return 0;
}
if (! ReadOK(fd,buf,7)) {
return 0;
}
BitPixel = 2<<(buf[4]&0x07);
#if 0
ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
Background = buf[5];
AspectRatio = buf[6];
#endif
if (BitSet(buf[4], LOCALCOLORMAP)) {
if (ReadColorMap(fd, BitPixel, ColorMap)) {
return 0;
}
}
for (;;) {
if (! ReadOK(fd,&c,1)) {
return 0;
}
if (c == ';') {
int i;
if (imageCount < imageNumber) {
return 0;
}
if (!im) {
return 0;
}
for (i=((im->colorsTotal-1)); (i>=0); i--) {
if (im->open[i]) {
im->colorsTotal--;
} else {
break;
}
}
return im;
}
if (c == '!') {
if (! ReadOK(fd,&c,1)) {
return 0;
}
DoExtension(fd, c, &Transparent);
continue;
}
if (c != ',') {
continue;
}
++imageCount;
if (! ReadOK(fd,buf,9)) {
return 0;
}
useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
bitPixel = 1<<((buf[8]&0x07)+1);
imw = LM_to_uint(buf[4],buf[5]);
imh = LM_to_uint(buf[6],buf[7]);
if (!(im = gdImageCreate(imw, imh))) {
return 0;
}
im->interlace = BitSet(buf[8], INTERLACE);
if (! useGlobalColormap) {
if (ReadColorMap(fd, bitPixel, localColorMap)) {
return 0;
}
ReadImage(im, fd, imw, imh, localColorMap,
BitSet(buf[8], INTERLACE),
imageCount != imageNumber);
} else {
ReadImage(im, fd, imw, imh,
ColorMap,
BitSet(buf[8], INTERLACE),
imageCount != imageNumber);
}
if (Transparent != (-1)) {
gdImageColorTransparent(im, Transparent);
}
}
}
static int
ReadColorMap(FILE *fd, int number, unsigned char (*buffer)[256])
{
int i;
unsigned char rgb[3];
for (i = 0; i < number; ++i) {
if (! ReadOK(fd, rgb, sizeof(rgb))) {
return TRUE;
}
buffer[CM_RED][i] = rgb[0] ;
buffer[CM_GREEN][i] = rgb[1] ;
buffer[CM_BLUE][i] = rgb[2] ;
}
return FALSE;
}
static int
DoExtension(FILE *fd, int label, int *Transparent)
{
static unsigned char buf[256];
switch (label) {
case 0xf9:
(void) GetDataBlock(fd, (unsigned char*) buf);
#if 0
Gif89.disposal = (buf[0] >> 2) & 0x7;
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
#endif
if ((buf[0] & 0x1) != 0)
*Transparent = buf[3];
while (GetDataBlock(fd, (unsigned char*) buf) != 0)
;
return FALSE;
default:
break;
}
while (GetDataBlock(fd, (unsigned char*) buf) != 0)
;
return FALSE;
}
static int
GetDataBlock_(FILE *fd, unsigned char *buf)
{
unsigned char count;
if (! ReadOK(fd,&count,1)) {
return -1;
}
ZeroDataBlock = count == 0;
if ((count != 0) && (! ReadOK(fd, buf, count))) {
return -1;
}
return count;
}
static int
GetDataBlock(FILE *fd, unsigned char *buf)
{
int rv;
int i;
rv = GetDataBlock_(fd,buf);
if (VERBOSE)
{ printf("[GetDataBlock returning %d",rv);
if (rv > 0)
{ printf(":");
for (i=0;i<rv;i++) printf(" %02x",buf[i]);
}
printf("]\n");
}
return(rv);
}
static int
GetCode_(FILE *fd, int code_size, int flag)
{
static unsigned char buf[280];
static int curbit, lastbit, done, last_byte;
int i, j, ret;
unsigned char count;
if (flag) {
curbit = 0;
lastbit = 0;
done = FALSE;
return 0;
}
if ( (curbit+code_size) >= lastbit) {
if (done) {
if (curbit >= lastbit) {
}
return -1;
}
buf[0] = buf[last_byte-2];
buf[1] = buf[last_byte-1];
if ((count = GetDataBlock(fd, &buf[2])) == 0)
done = TRUE;
last_byte = 2 + count;
curbit = (curbit - lastbit) + 16;
lastbit = (2+count)*8 ;
}
ret = 0;
for (i = curbit, j = 0; j < code_size; ++i, ++j)
ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
curbit += code_size;
return ret;
}
static int
GetCode(FILE *fd, int code_size, int flag)
{
int rv;
rv = GetCode_(fd,code_size,flag);
if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
return(rv);
}
static int
LWZReadByte_(FILE *fd, int flag, int input_code_size)
{
static int fresh = FALSE;
int code, incode;
static int code_size, set_code_size;
static int max_code, max_code_size;
static int firstcode, oldcode;
static int clear_code, end_code;
static int table[2][(1<< MAX_LWZ_BITS)];
static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
register int i;
if (flag) {
set_code_size = input_code_size;
code_size = set_code_size+1;
clear_code = 1 << set_code_size ;
end_code = clear_code + 1;
max_code_size = 2*clear_code;
max_code = clear_code+2;
GetCode(fd, 0, TRUE);
fresh = TRUE;
for (i = 0; i < clear_code; ++i) {
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1<<MAX_LWZ_BITS); ++i)
table[0][i] = table[1][0] = 0;
sp = stack;
return 0;
} else if (fresh) {
fresh = FALSE;
do {
firstcode = oldcode =
GetCode(fd, code_size, FALSE);
} while (firstcode == clear_code);
return firstcode;
}
if (sp > stack)
return *--sp;
while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
if (code == clear_code) {
for (i = 0; i < clear_code; ++i) {
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1<<MAX_LWZ_BITS); ++i)
table[0][i] = table[1][i] = 0;
code_size = set_code_size+1;
max_code_size = 2*clear_code;
max_code = clear_code+2;
sp = stack;
firstcode = oldcode =
GetCode(fd, code_size, FALSE);
return firstcode;
} else if (code == end_code) {
int count;
unsigned char buf[260];
if (ZeroDataBlock)
return -2;
while ((count = GetDataBlock(fd, buf)) > 0)
;
if (count != 0)
return -2;
}
incode = code;
if (code >= max_code) {
*sp++ = firstcode;
code = oldcode;
}
while (code >= clear_code) {
*sp++ = table[1][code];
if (code == table[0][code]) {
}
code = table[0][code];
}
*sp++ = firstcode = table[1][code];
if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
table[0][code] = oldcode;
table[1][code] = firstcode;
++max_code;
if ((max_code >= max_code_size) &&
(max_code_size < (1<<MAX_LWZ_BITS))) {
max_code_size *= 2;
++code_size;
}
}
oldcode = incode;
if (sp > stack)
return *--sp;
}
return code;
}
static int
LWZReadByte(FILE *fd, int flag, int input_code_size)
{
int rv;
rv = LWZReadByte_(fd,flag,input_code_size);
if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
return(rv);
}
static void
ReadImage(gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore)
{
unsigned char c;
int v;
int xpos = 0, ypos = 0, pass = 0;
int i;
for (i=0; (i<gdMaxColors); i++) {
im->red[i] = cmap[CM_RED][i];
im->green[i] = cmap[CM_GREEN][i];
im->blue[i] = cmap[CM_BLUE][i];
im->open[i] = 1;
}
im->colorsTotal = gdMaxColors;
if (! ReadOK(fd,&c,1)) {
return;
}
if (LWZReadByte(fd, TRUE, c) < 0) {
return;
}
if (ignore) {
while (LWZReadByte(fd, FALSE, c) >= 0)
;
return;
}
while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
if (im->open[v]) {
im->open[v] = 0;
}
gdImageSetPixel(im, xpos, ypos, v);
++xpos;
if (xpos == len) {
xpos = 0;
if (interlace) {
switch (pass) {
case 0:
case 1:
ypos += 8; break;
case 2:
ypos += 4; break;
case 3:
ypos += 2; break;
}
if (ypos >= height) {
++pass;
switch (pass) {
case 1:
ypos = 4; break;
case 2:
ypos = 2; break;
case 3:
ypos = 1; break;
default:
goto fini;
}
}
} else {
++ypos;
}
}
if (ypos >= height)
break;
}
fini:
if (LWZReadByte(fd,FALSE,c)>=0) {
}
}
#endif