/* * Compface - 48x48x1 image compression and decompression * * Copyright (c) James Ashton - Sydney University - June 1990. * * Written 11th November 1989. * * Permission is given to distribute these sources, as long as the * copyright messages are not removed, and no monies are exchanged. * * No responsibility is taken for any errors on inaccuracies inherent * either to the comments or the code of this program, but if reported * to me, then an attempt will be made to fix them. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "compface.h" int Same(f, wid, hei) register char *f; register int wid, hei; { register char val, *row; register int x; val = *f; while (hei--) { row = f; x = wid; while (x--) if (*(row++) != val) return(0); f += WIDTH; } return 1; } int AllBlack(f, wid, hei) char *f; int wid, hei; { if (wid > 3) { wid /= 2; hei /= 2; return (AllBlack(f, wid, hei) && AllBlack(f + wid, wid, hei) && AllBlack(f + WIDTH * hei, wid, hei) && AllBlack(f + WIDTH * hei + wid, wid, hei)); } else return (*f || *(f + 1) || *(f + WIDTH) || *(f + WIDTH + 1)); } int AllWhite(f, wid, hei) char *f; int wid, hei; { return ((*f == 0) && Same(f, wid, hei)); } void PopGreys(f, wid, hei) char *f; int wid, hei; { if (wid > 3) { wid /= 2; hei /= 2; PopGreys(f, wid, hei); PopGreys(f + wid, wid, hei); PopGreys(f + WIDTH * hei, wid, hei); PopGreys(f + WIDTH * hei + wid, wid, hei); } else { wid = BigPop(freqs); if (wid & 1) *f = 1; if (wid & 2) *(f + 1) = 1; if (wid & 4) *(f + WIDTH) = 1; if (wid & 8) *(f + WIDTH + 1) = 1; } } void PushGreys(f, wid, hei) char *f; int wid, hei; { if (wid > 3) { wid /= 2; hei /= 2; PushGreys(f, wid, hei); PushGreys(f + wid, wid, hei); PushGreys(f + WIDTH * hei, wid, hei); PushGreys(f + WIDTH * hei + wid, wid, hei); } else RevPush(freqs + *f + 2 * *(f + 1) + 4 * *(f + WIDTH) + 8 * *(f + WIDTH + 1)); } void UnCompress(f, wid, hei, lev) register char *f; register int wid, hei, lev; { switch (BigPop(&levels[lev][0])) { case WHITE : return; case BLACK : PopGreys(f, wid, hei); return; default : wid /= 2; hei /= 2; lev++; UnCompress(f, wid, hei, lev); UnCompress(f + wid, wid, hei, lev); UnCompress(f + hei * WIDTH, wid, hei, lev); UnCompress(f + wid + hei * WIDTH, wid, hei, lev); return; } } void Compress(f, wid, hei, lev) register char *f; register int wid, hei, lev; { if (AllWhite(f, wid, hei)) { RevPush(&levels[lev][WHITE]); return; } if (AllBlack(f, wid, hei)) { RevPush(&levels[lev][BLACK]); PushGreys(f, wid, hei); return; } RevPush(&levels[lev][GREY]); wid /= 2; hei /= 2; lev++; Compress(f, wid, hei, lev); Compress(f + wid, wid, hei, lev); Compress(f + hei * WIDTH, wid, hei, lev); Compress(f + wid + hei * WIDTH, wid, hei, lev); } void UnCompAll(fbuf) char *fbuf; { register char *p; BigClear(); BigRead(fbuf); p = F; while (p < F + PIXELS) *(p++) = 0; UnCompress(F, 16, 16, 0); UnCompress(F + 16, 16, 16, 0); UnCompress(F + 32, 16, 16, 0); UnCompress(F + WIDTH * 16, 16, 16, 0); UnCompress(F + WIDTH * 16 + 16, 16, 16, 0); UnCompress(F + WIDTH * 16 + 32, 16, 16, 0); UnCompress(F + WIDTH * 32, 16, 16, 0); UnCompress(F + WIDTH * 32 + 16, 16, 16, 0); UnCompress(F + WIDTH * 32 + 32, 16, 16, 0); } void CompAll(fbuf) char *fbuf; { Compress(F, 16, 16, 0); Compress(F + 16, 16, 16, 0); Compress(F + 32, 16, 16, 0); Compress(F + WIDTH * 16, 16, 16, 0); Compress(F + WIDTH * 16 + 16, 16, 16, 0); Compress(F + WIDTH * 16 + 32, 16, 16, 0); Compress(F + WIDTH * 32, 16, 16, 0); Compress(F + WIDTH * 32 + 16, 16, 16, 0); Compress(F + WIDTH * 32 + 32, 16, 16, 0); BigClear(); while (NumProbs > 0) BigPush(ProbBuf[--NumProbs]); BigWrite(fbuf); }