
/*
 *  UnCompface - 48x48x1 image decompression
 *
 *  Copyright (c) James Ashton - Sydney University - June 1990.
 *
 *  Written 11th November 1989.
 *
 *  Permission to use, copy, modify, and distribute this software and its
 *  documentation for any purpose and without fee is hereby granted, provided
 *  that the above copyright notice appear in all copies and that both that
 *  copyright notice and this permission notice appear in supporting
 *  documentation.  This software is provided "as is" without express or
 *  implied warranty.
 */

#ifdef _WIN32
#if !defined(_XFACE_H)
#define _XFACE_H

#include <windows.h>


/* need to know how many bits per hexadecimal digit for io */
#define BITSPERDIG 4
#define BITSPERBYTE 8

/* define the face size - 48x48x1 */
#define WIDTH 48
#define HEIGHT WIDTH
#define BITS 1

/* total number of pixels and digits */
#define PIXELS (WIDTH * HEIGHT)
#define DIGITS (PIXELS / BITSPERDIG)

/* compressed output uses the full range of printable characters.
 * in ascii these are in a contiguous block so we just need to know
 * the first and last.  The total number of printables is needed too */
#define FIRSTPRINT '!'
#define LASTPRINT '~'
#define NUMPRINTS (LASTPRINT - FIRSTPRINT + 1)



/* Portable, very large unsigned integer arithmetic is needed.
 * Implementation uses arrays of unsigned chars.  COMPs must have at least
 * twice as many bits as unsigned chars to handle intermediate results */
//#define DROW unsigned char
#define COMP unsigned long
#define BITSPERWORD 8
#define WORDCARRY (1 << BITSPERWORD)
#define WORDMASK (WORDCARRY - 1)
#define MAXWORDS ((PIXELS * 2 + BITSPERWORD - 1) / BITSPERWORD)

typedef struct bigint
{
    int b_words;
    unsigned char b_word[MAXWORDS];
} BigInt;

/* This is the guess the next pixel table.  Normally there are 12 neighbour
 * pixels used to give 1<<12 cases but in the upper left corner lesser
 * numbers of neighbours are available, leading to 6231 different guesses */
typedef struct guesses
{
    unsigned char g_00[1<<12];
    unsigned char g_01[1<<7];
    unsigned char g_02[1<<2];
    unsigned char g_10[1<<9];
    unsigned char g_20[1<<6];
    unsigned char g_30[1<<8];
    unsigned char g_40[1<<10];
    unsigned char g_11[1<<5];
    unsigned char g_21[1<<3];
    unsigned char g_31[1<<5];
    unsigned char g_41[1<<6];
    unsigned char g_12[1<<1];
    unsigned char g_22[1<<0];
    unsigned char g_32[1<<2];
    unsigned char g_42[1<<2];
} Guesses;

/* Data of varying probabilities are encoded by a value in the range 0 - 255.
 * The probability of the data determines the range of possible encodings.
 * Offset gives the first possible encoding of the range */
typedef struct prob
{
    unsigned char p_range;
    unsigned char p_offset;
} Prob;



/* Each face is encoded using 9 octrees of 16x16 each.  Each level of the
 * trees has varying probabilities of being white, grey or black.
 * The table below is based on sampling many faces */

#define BLACK 0
#define GREY 1
#define WHITE 2



#define ERR_OK      0   /* successful completion */
#define ERR_EXCESS  1   /* completed OK but some input was ignored */
#define ERR_INSUFF  -1  /* insufficient input.  Bad face format? */
#define ERR_INTERNAL    -2  /* Arithmetic overflow or buffer overflow */

#define GEN(g) F[h] ^= G.g[k]; break

class XFaceOb
{

public:
    XFaceOb() : NumProbs(0) {};
    ~XFaceOb() {};



    int Face2BMP( HGLOBAL *phBMP);
    int BMP2Xface( LPSTR szData, int nLen,  HGLOBAL hBmp);
    int Xface2BMP( LPCSTR szData, HGLOBAL *phBMP);
//  int XFace2BMPFile( LPCSTR szData, CBufFile *pOutFile, BOOL bIsFinal =TRUE);


protected:

    int     BigPop (Prob *) ;
    int     uncompface ( const char *) ;
    void    BigAdd(unsigned char);
    void    BigClear(void);
    void    BigDiv(unsigned char, unsigned char *);
    void    BigMul(register unsigned char);
    void    BigRead(const char *);
    void    Gen(unsigned char *);
    void    UnCompAll( const char *);
    void    UnCompress( unsigned char *, int, int, int);
    void    UnGenFace();
    void    PopGreys(unsigned char *, int, int);

#ifdef DO_COMPRESS
    //COMPRESSION ROUTINES
    void    WriteFace(char *);
    int     Same(register unsigned char *f,register int wid, register int hei);
    int     AllBlack(unsigned char *f, int wid, int hei);
    int     AllWhite(unsigned char *f,int wid, int hei);
    void    PushGreys(unsigned char *f,int wid, int hei);
    void    Compress(register unsigned char *f,register int wid, 
                                register int hei, register int lev);
    void    CompAll(char *fbuf);
    void    RevPush(Prob *p);
    void    BigPush(Prob *p);
    void    BigWrite(register char *fbuf);
#endif

protected:

    /* internal face representation - 1 char per pixel is faster */
    unsigned char F[PIXELS];

#ifdef DO_COMPRESS
    unsigned char F2[PIXELS]; // for generating X-Face data
#endif

    /* A stack of probability values */
    Prob *ProbBuf[PIXELS * 2];
    int NumProbs;

    BigInt B;

    static Prob levels[4][3];
    static Prob freqs[16];
    static Guesses G;
    


};

#endif //ifdef _XFACE_H

#endif //_WIN32