This is lzwdec.c in view mode; [Download] [Up]
#include "combine.h"
#include "defines.h"
#include "errcds.h"
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% L Z W D e c o d e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Function LZWDecodeImage uncompresses an image via LZW-coding.
%
% The format of the LZWDecodeImage routine is:
%
% status=LZWDecodeImage(image)
%
% A description of each parameter follows:
%
% o status: Function LZWDecodeImage returns True if all the pixels are
% uncompressed without error, otherwise False.
%
% o image: The address of a structure of type Image.
%
%
*/
int LZWDecodeImage(image)
Image
*image;
{
#define MaxStackSize 4096
#define NullCode (-1)
int
available,
clear,
code_mask,
code_size,
end_of_information,
in_code,
old_code,
status;
register int
bits,
code,
count,
i;
register Runlength
*p;
register unsigned char
*c;
register unsigned int
datum;
short
*prefix;
unsigned char
data_size,
first,
*packet,
*pixel_stack,
*suffix,
*top_stack;
int
rc = 0;
/*
Allocate decoder tables.
*/
packet=(unsigned char *) malloc(256*sizeof(unsigned char));
prefix=(short *) malloc(MaxStackSize*sizeof(short));
suffix=(unsigned char *) malloc(MaxStackSize*sizeof(unsigned char));
pixel_stack=(unsigned char *) malloc((MaxStackSize+1)*sizeof(unsigned char));
if ((packet == (unsigned char *) NULL) ||
(prefix == (short *) NULL) ||
(suffix == (unsigned char *) NULL) ||
(pixel_stack == (unsigned char *) NULL))
return(MALLOC_FAILED);
/*
Initialize LZW data stream decoder.
*/
data_size=fgetc(image->fp);
clear=1 << data_size;
end_of_information=clear+1;
available=clear+2;
old_code=NullCode;
code_size=data_size+1;
code_mask=(1 << code_size)-1;
for (code=0; code < clear; code++)
{
prefix[code]=0;
suffix[code]=code;
}
/*
Decode LZW pixel stream.
*/
datum=0;
bits=0;
c=0;
count=0;
first=0;
top_stack=pixel_stack;
p=image->pixels;
for (i=0; i < image->packets; )
{
if (top_stack == pixel_stack)
{
if (bits < code_size)
{
/*
Load bytes until there is enough bits for a code.
*/
if (count == 0)
{
/*
Read a new data block.
*/
count=ReadDataBlock((char *) packet,image->fp);
if (count <= 0)
break;
c=packet;
}
datum+=(*c) << bits;
bits+=8;
c++;
count--;
continue;
}
/*
Get the next code.
*/
code=datum & code_mask;
datum>>=code_size;
bits-=code_size;
/*
Interpret the code
*/
if ((code > available) || (code == end_of_information))
break;
if (code == clear)
{
/*
Reset decoder.
*/
code_size=data_size+1;
code_mask=(1 << code_size)-1;
available=clear+2;
old_code=NullCode;
continue;
}
if (old_code == NullCode)
{
*top_stack++=suffix[code];
old_code=code;
first=code;
continue;
}
in_code=code;
if (code == available)
{
*top_stack++=first;
code=old_code;
}
while (code > clear)
{
*top_stack++=suffix[code];
code=prefix[code];
}
first=suffix[code];
/*
Add a new string to the string table,
*/
if (available >= MaxStackSize)
break;
*top_stack++=first;
prefix[available]=old_code;
suffix[available]=first;
available++;
if (((available & code_mask) == 0) && (available < MaxStackSize))
{
code_size++;
code_mask+=available;
}
old_code=in_code;
}
/*
Pop a pixel off the pixel stack.
*/
top_stack--;
p->index=(unsigned short) *top_stack;
p->length=0;
p++;
i++;
}
/*
Initialize any remaining color packets to a known color.
*/
status=i == image->packets;
if (status == False)
{
rc=1;
}
for ( ; i < image->packets; i++)
{
p->index=0;
p->length=0;
p++;
}
SyncImage(image);
/*
Free decoder memory.
*/
(void) free((char *) pixel_stack);
(void) free((char *) suffix);
(void) free((char *) prefix);
(void) free((char *) packet);
return(rc);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.