ftp.nice.ch/pub/next/unix/network/www/wwwcount.2.3.NIHS.bs.tar.gz#/wwwcount2.3/combine/lzwenc.c

This is lzwenc.c in view mode; [Download] [Up]

/*
 *	LZWEncodeImage()	-	description
 *
 *	RCS:
 *		$Revision: 2.3 $
 *		$Date: 1996/05/03 02:21:34 $
 *
 *	Security:
 *		Unclassified
 *
 *	Description:
 *		Taken from ImageMagick 3.3
 *
 *	Input Parameters:
 *		type	identifier	description
 *
 *		text
 *
 *	Output Parameters:
 *		type	identifier	description
 *
 *		text
 *
 *	Return Values:
 *		value	description
 *
 *	Side Effects:
 *		text
 *
 *	Limitations and Comments:
 *		text
 *
 *	Development History:
 *		when	who		why
 */
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   L Z W E n c o d e I m a g e                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function LZWEncodeImage compresses an image via LZW-coding.
%
%  The format of the LZWEncodeImage routine is:
%
%      status=LZWEncodeImage(image,data_size)
%
%  A description of each parameter follows:
%
%    o status:  Function LZWEncodeImage returns True if all the pixels are
%      compressed without error, otherwise False.
%
%    o image: The address of a structure of type Image.
%
%
*/

#include "combine.h"
#include "defines.h"

unsigned int LZWEncodeImage(image,data_size)
Image
  *image;

unsigned int
  data_size;
{
#define MaxCode(number_bits)  ((1 << (number_bits))-1)
#define MaxHashTable  5003
#define MaxLZWBits  12
#define MaxLZWTable  (1 << MaxLZWBits)
#define LZWOutputCode(code) \
{ \
  /*  \
    Emit a code. \
  */ \
  if (bits > 0) \
    datum|=((long) code << bits); \
  else \
    datum=(long) code; \
  bits+=number_bits; \
  while (bits >= 8)  \
  { \
    /*  \
      Add a character to current packet. \
    */ \
    packet[byte_count++]=(unsigned char) (datum & 0xff); \
    if (byte_count >= 254) \
      { \
        (void) fputc(byte_count,image->fp); \
        (void) fwrite((char *) packet,1,byte_count,image->fp); \
        byte_count=0; \
      } \
    datum>>=8; \
    bits-=8; \
  } \
  if (free_code > max_code)  \
    { \
      number_bits++; \
      if (number_bits == MaxLZWBits) \
        max_code=MaxLZWTable; \
      else \
        max_code=MaxCode(number_bits); \
    } \
}

  int
    bits,
    byte_count,
    next_pixel,
    number_bits;

  long
    datum;

  register int
    displacement,
    i,
    j;

  register Runlength
    *p;

  short
    clear_code,
    end_of_information_code,
    free_code,
    *hash_code,
    *hash_prefix,
    index,
    max_code,
    waiting_code;

  unsigned char
    *packet,
    *hash_suffix;

  /*
    Uncompress image.
  */
  if (!UncompressImage(image))
    return(False);
  /*
    Allocate encoder tables.
  */
  packet=(unsigned char *) malloc(256*sizeof(unsigned char));
  hash_code=(short *) malloc(MaxHashTable*sizeof(short));
  hash_prefix=(short *) malloc(MaxHashTable*sizeof(short));
  hash_suffix=(unsigned char *) malloc(MaxHashTable*sizeof(unsigned char));
  if ((packet == (unsigned char *) NULL) || (hash_code == (short *) NULL) ||
      (hash_prefix == (short *) NULL) ||
      (hash_suffix == (unsigned char *) NULL))
    return(False);
  /*
    Initialize LZW encoder.
  */
  number_bits=data_size;
  max_code=MaxCode(number_bits);
  clear_code=((short) 1 << (data_size-1));
  end_of_information_code=clear_code+1;
  free_code=clear_code+2;
  byte_count=0;
  datum=0;
  bits=0;
  for (i=0; i < MaxHashTable; i++)
    hash_code[i]=0;
  LZWOutputCode(clear_code);
  /*
    Encode pixels.
  */
  p=image->pixels;
  waiting_code=p->index;
  for (i=1; i < (image->columns*image->rows); i++)
  {
    /*
      Probe hash table.
    */
    p++;
    index=p->index & 0xff;
    j=(int) ((int) index << (MaxLZWBits-8))+waiting_code;
    if (j >= MaxHashTable)
      j-=MaxHashTable;
    if (hash_code[j] > 0)
      {
        if ((hash_prefix[j] == waiting_code) && (hash_suffix[j] == index))
          {
            waiting_code=hash_code[j];
            continue;
          }
        if (j == 0)
          displacement=1;
        else
          displacement=MaxHashTable-j;
        next_pixel=False;
        for ( ; ; )
        {
          j-=displacement;
          if (j < 0)
            j+=MaxHashTable;
          if (hash_code[j] == 0)
            break;
          if ((hash_prefix[j] == waiting_code) && (hash_suffix[j] == index))
            {
              waiting_code=hash_code[j];
              next_pixel=True;
              break;
            }
        }
        if (next_pixel == True)
          continue;
      }
    LZWOutputCode(waiting_code);
    if (free_code < MaxLZWTable)
      {
        hash_code[j]=free_code++;
        hash_prefix[j]=waiting_code;
        hash_suffix[j]=index;
      }
    else
      {
        /*
          Fill the hash table with empty entries.
        */
        for (j=0; j < MaxHashTable; j++)
          hash_code[j]=0;
        /*
          Reset compressor and issue a clear code.
        */
        free_code=clear_code+2;
        LZWOutputCode(clear_code);
        number_bits=data_size;
        max_code=MaxCode(number_bits);
      }
    waiting_code=index;
  }
  /*
    Flush out the buffered code.
  */
  LZWOutputCode(waiting_code);
  LZWOutputCode(end_of_information_code);
  if (bits > 0)
    {
      /*
        Add a character to current packet.
      */
      packet[byte_count++]=(unsigned char) (datum & 0xff);
      if (byte_count >= 254)
        {
          (void) fputc(byte_count,image->fp);
          (void) fwrite((char *) packet,1,byte_count,image->fp);
          byte_count=0;
        }
    }
  /*
    Flush accumulated data.
  */
  if (byte_count > 0)
    {
      (void) fputc(byte_count,image->fp);
      (void) fwrite((char *) packet,1,byte_count,image->fp);
    }
  /*
    Free encoder memory.
  */
  (void) free((char *) hash_suffix);
  (void) free((char *) hash_prefix);
  (void) free((char *) hash_code);
  (void) free((char *) packet);
  if (i < image->packets)
    return(False);
  return(True);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.