Minor refactoring of the IFF and box-format parsers
[deark.git] / foreign / uncompface.h
blob73105aa475f6318ad0b6fbdcb60d9c05780f4917
1 // See the file readme-compface.txt for more information about this file.
2 // Modifications for Deark are Copyright (C) 2017 Jason Summers.
3 //
4 // This file contains portions of the original files compface_private.h,
5 // compface.h, data.h, file.c, arith.c, gen.c, compress.c, uncompface.c, and
6 // uncmain.c.
7 // --------------------------------------------------------------------------
9 /*
10 * Compface - 48x48x1 image compression and decompression
12 * Copyright (c) James Ashton - Sydney University - June 1990.
14 * Written 11th November 1989.
16 * Permission is given to distribute these sources, as long as the
17 * copyright messages are not removed, and no monies are exchanged.
19 * No responsibility is taken for any errors on inaccuracies inherent
20 * either to the comments or the code of this program, but if reported
21 * to me, then an attempt will be made to fix them.
24 //========================= compface_private.h begin =========================
26 //========================= compface.h begin =========================
28 /* define the face size - 48x48x1 */
29 #define XFACE_WIDTH 48
30 #define XFACE_HEIGHT XFACE_WIDTH
32 /* total number of pixels */
33 #define PIXELS (XFACE_WIDTH * XFACE_HEIGHT)
35 /* compressed output uses the full range of printable characters.
36 * in ascii these are in a contiguous block so we just need to know
37 * the first and last. The total number of printables is needed too */
38 #define FIRSTPRINT '!'
39 #define LASTPRINT '~'
40 #define NUMPRINTS (LASTPRINT - FIRSTPRINT + 1)
42 /* Portable, very large unsigned integer arithmetic is needed.
43 * Implementation uses arrays of WORDs. COMPs must have at least
44 * twice as many bits as WORDs to handle intermediate results */
45 #define XFACE_WORD unsigned char
46 #define XFACE_COMP u32
47 #define BITSPERWORD 8
48 #define WORDCARRY (1 << BITSPERWORD)
49 #define WORDMASK (WORDCARRY - 1)
50 #define MAXWORDS ((PIXELS * 2 + BITSPERWORD - 1) / BITSPERWORD)
52 typedef struct bigint
54 int b_words;
55 XFACE_WORD b_word[MAXWORDS];
56 } BigInt;
58 /* This is the guess the next pixel table. Normally there are 12 neighbour
59 * pixels used to give 1<<12 cases but in the upper left corner lesser
60 * numbers of neighbours are available, leading to 6231 different guesses */
61 typedef struct guesses
63 const u8 g_00[/*1<<12*/ 1<<9];
64 const u8 g_01[/*1<<7 */ 1<<4];
65 const u8 g_02[/*1<<2 */ 1 ];
66 const u8 g_10[/*1<<9 */ 1<<6];
67 const u8 g_20[/*1<<6 */ 1<<3];
68 #if 0 // See comment for Gen(), below.
69 const u8 g_30[/*1<<8 */ 1<<5];
70 #endif
71 const u8 g_40[/*1<<10*/ 1<<7];
72 const u8 g_11[/*1<<5 */ 1<<2];
73 const u8 g_21[/*1<<3 */ 1<<0];
74 #if 0
75 const u8 g_31[/*1<<5 */ 1<<2];
76 #endif
77 const u8 g_41[/*1<<6 */ 1<<3];
78 const u8 g_12[/*1<<1 */ 1 ];
79 const u8 g_22[/*1<<0 */ 1 ];
80 #if 0
81 const u8 g_32[/*1<<2 */ 1 ];
82 #endif
83 const u8 g_42[/*1<<2 */ 1 ];
84 } Guesses;
86 /* Data of varying probabilities are encoded by a value in the range 0 - 255.
87 * The probability of the data determines the range of possible encodings.
88 * Offset gives the first possible encoding of the range */
89 typedef struct prob
91 XFACE_WORD p_range;
92 XFACE_WORD p_offset;
93 } Prob;
95 /* Each face is encoded using 9 octrees of 16x16 each. Each level of the
96 * trees has varying probabilities of being white, grey or black.
97 * The table below is based on sampling many faces */
99 #define BLACK 0
100 #define GREY 1
101 #define WHITE 2
103 //========================= compface.h end =========================
105 /* data.h was established by sampling over 1000 faces and icons */
106 static const Guesses gg_G
108 //========================= data.h begin =========================
110 { // 00
111 0x00,0x00,0x01,0x01,0x00,0x00,0xe3,0xdf,0x05,0x17,0x05,0x0f,0x00,0x1b,0x0f,0xdf,
112 0x00,0x04,0x00,0x00,0x0d,0x0f,0x03,0x7f,0x00,0x00,0x00,0x01,0x00,0x1d,0x45,0x2f,
113 0x00,0x00,0x00,0x0d,0x00,0x0a,0xff,0xff,0x00,0x04,0x00,0x05,0x01,0x3f,0xcf,0xff,
114 0x10,0x01,0x80,0xc9,0x0f,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x1b,0x1f,0xff,0xff,
115 0x4f,0x54,0x07,0x1f,0x57,0x47,0xd7,0x3d,0xff,0xff,0x5f,0x1f,0x7f,0xff,0x7f,0x7f,
116 0x05,0x0f,0x01,0x0f,0x0f,0x5f,0x9b,0xdf,0x7f,0xff,0x5f,0x1d,0x5f,0xff,0x0f,0x1f,
117 0x0f,0x5f,0x03,0x1f,0x4f,0x5f,0xf7,0x7f,0x7f,0xff,0x0d,0x0f,0xfb,0xff,0xf7,0xbf,
118 0x0f,0x4f,0xd7,0x3f,0x4f,0x7f,0xff,0xff,0x67,0xbf,0x56,0x25,0x1f,0x7f,0x9f,0xff,
119 0x00,0x00,0x00,0x05,0x5f,0x7f,0x01,0xdf,0x14,0x00,0x05,0x0f,0x07,0xa2,0x09,0x0f,
120 0x00,0x00,0x00,0x00,0x0f,0x5f,0x18,0xd7,0x94,0x71,0x00,0x05,0x1f,0xb7,0x0c,0x07,
121 0x0f,0x0f,0x00,0x0f,0x0f,0x1f,0x84,0x8f,0x05,0x15,0x05,0x0f,0x4f,0xff,0x87,0xdf,
122 0x05,0x01,0x10,0x00,0x0f,0x0f,0x00,0x08,0x05,0x04,0x04,0x01,0x4f,0xff,0x9f,0x8f,
123 0x4a,0x40,0x5f,0x5f,0xff,0xfe,0xdf,0xff,0x7f,0xf7,0xff,0x7f,0xff,0xff,0x7b,0xff,
124 0x0f,0xfd,0xd7,0x5f,0x4f,0x7f,0x7f,0xdf,0xff,0xff,0xff,0xff,0xff,0x77,0xdf,0x7f,
125 0x4f,0xef,0xff,0xff,0x77,0xff,0xff,0xff,0x6f,0xff,0x0f,0x4f,0xff,0xff,0x9d,0xff,
126 0x0f,0xef,0xff,0xdf,0x6f,0xff,0xff,0xff,0x4f,0xff,0xcd,0x0f,0x4f,0xff,0xff,0xdf,
127 0x00,0x00,0x00,0x0b,0x05,0x02,0x02,0x0f,0x04,0x00,0x00,0x0c,0x01,0x06,0x00,0x0f,
128 0x20,0x03,0x00,0x00,0x05,0x0f,0x40,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x0c,0x0f,
129 0x01,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x14,0x01,0x05,0x01,0x15,0xaf,0x0f,
130 0x00,0x01,0x10,0x00,0x08,0x00,0x46,0x0c,0x20,0x00,0x88,0x00,0x0f,0x15,0xff,0xdf,
131 0x02,0x00,0x00,0x0f,0x7f,0x5f,0xdb,0xff,0x4f,0x3e,0x05,0x0f,0x7f,0xf7,0x95,0x4f,
132 0x0d,0x0f,0x01,0x0f,0x4f,0x5f,0x9f,0xdf,0x25,0x0e,0x0d,0x0d,0x4f,0x7f,0x8f,0x0f,
133 0x0f,0xfa,0x04,0x4f,0x4f,0xff,0xf7,0x77,0x47,0xed,0x05,0x0f,0xff,0xff,0xdf,0xff,
134 0x4f,0x6f,0xd8,0x5f,0x0f,0x7f,0xdf,0x5f,0x07,0x0f,0x94,0x0d,0x1f,0xff,0xff,0xff,
135 0x00,0x02,0x00,0x03,0x46,0x57,0x01,0x0d,0x01,0x08,0x01,0x0f,0x47,0x6c,0x0d,0x0f,
136 0x02,0x00,0x00,0x00,0x0b,0x4f,0x00,0x08,0x05,0x00,0x95,0x01,0x0f,0x7f,0x0c,0x0f,
137 0x01,0x0e,0x00,0x00,0x0f,0x41,0x00,0x00,0x04,0x24,0x0d,0x0f,0x0f,0x7f,0xcf,0xdf,
138 0x00,0x00,0x00,0x00,0x04,0x40,0x00,0x00,0x06,0x26,0xcf,0x05,0xcf,0x7f,0xdf,0xdf,
139 0x00,0x00,0x17,0x5f,0xff,0xfd,0xff,0xff,0x46,0x09,0x4f,0x5f,0x7f,0xfd,0xdf,0xff,
140 0x0a,0x88,0xa7,0x7f,0x7f,0xff,0xff,0xff,0x0f,0x04,0xdf,0x7f,0x4f,0xff,0x9f,0xff,
141 0x0e,0xe6,0xdf,0xff,0x7f,0xff,0xff,0xff,0x0f,0xec,0x8f,0x4f,0x7f,0xff,0xdf,0xff,
142 0x0f,0xcf,0xdf,0xff,0x6f,0x7f,0xff,0xff,0x03,0x0c,0x9d,0x0f,0x7f,0xff,0xff,0xff
144 { // 01
145 0x37,0x73,0x00,0x19,0x57,0x7f,0xf5,0xfb,0x70,0x33,0xf0,0xf9,0x7f,0xff,0xff,0xff
147 { // 02
148 0x50
150 { // 10
151 0x00,0x00,0x00,0x00,0x50,0x00,0xf3,0x5f,0x84,0x04,0x17,0x9f,0x04,0x23,0x05,0xff,
152 0x00,0x00,0x00,0x02,0x03,0x03,0x33,0xd7,0x05,0x03,0x5f,0x3f,0x17,0x33,0xff,0xff,
153 0x00,0x80,0x02,0x04,0x12,0x00,0x11,0x57,0x05,0x25,0x05,0x03,0x35,0xbf,0x9f,0xff,
154 0x07,0x6f,0x20,0x40,0x17,0x06,0xfa,0xe8,0x01,0x07,0x1f,0x9f,0x1f,0xff,0xff,0xff
156 { // 20
157 0x04,0x00,0x01,0x01,0x43,0x2e,0xff,0x3f
159 #if 0 // See comment for Gen(), below.
160 { // 30
161 0x11,0x11,0x11,0x11,0x51,0x11,0x13,0x11,0x11,0x11,0x13,0x11,0x11,0x11,0x33,0x11,
162 0x13,0x11,0x13,0x13,0x13,0x13,0x31,0x31,0x11,0x01,0x11,0x11,0x71,0x11,0x11,0x75
164 #endif
165 { // 40
166 0x00,0x0f,0x00,0x09,0x00,0x0d,0x00,0x0d,0x00,0x0f,0x00,0x4e,0xe4,0x0d,0x10,0x0f,
167 0x00,0x0f,0x44,0x4f,0x00,0x1e,0x0f,0x0f,0xae,0xaf,0x45,0x7f,0xef,0xff,0x0f,0xff,
168 0x00,0x09,0x01,0x11,0x00,0x01,0x1c,0xdd,0x00,0x15,0x00,0xff,0x00,0x10,0x00,0xfd,
169 0x00,0x0f,0x4f,0x5f,0x3d,0xff,0xff,0xff,0x4f,0xff,0x1c,0xff,0xdf,0xff,0x8f,0xff,
170 0x00,0x0d,0x00,0x00,0x00,0x15,0x01,0x07,0x00,0x01,0x02,0x1f,0x01,0x11,0x05,0x7f,
171 0x00,0x1f,0x41,0x57,0x1f,0xff,0x05,0x77,0x0d,0x5f,0x4d,0xff,0x4f,0xff,0x0f,0xff,
172 0x00,0x00,0x02,0x05,0x00,0x11,0x05,0x7d,0x10,0x15,0x2f,0xff,0x40,0x50,0x0d,0xfd,
173 0x04,0x0f,0x07,0x1f,0x07,0x7f,0x0f,0xbf,0x0d,0x7f,0x0f,0xff,0x4d,0x7d,0x0f,0xff
175 { // 11
176 0x01,0x13,0x03,0x7f
178 { // 21
179 0x17
181 #if 0
182 { // 31
183 0x55,0x57,0x57,0x7f
185 #endif
186 { // 41
187 0x01,0x01,0x01,0x1f,0x03,0x1f,0x3f,0xff
189 { // 12
190 0x40
192 { // 22
193 0x00
195 #if 0
196 { // 32
197 0x10
199 #endif
200 { // 42
201 0x40
204 //========================= data.h end =========================
207 /* A stack of probability values */
209 static const Prob gg_levels[4][3]
212 {{1, 255}, {251, 0}, {4, 251}}, /* Top of tree almost always grey */
213 {{1, 255}, {200, 0}, {55, 200}},
214 {{33, 223}, {159, 0}, {64, 159}},
215 {{131, 0}, {0, 0}, {125, 131}} /* Grey disallowed at bottom */
219 /* At the bottom of the octree 2x2 elements are considered black if any
220 * pixel is black. The probabilities below give the distribution of the
221 * 16 possible 2x2 patterns. All white is not really a possibility and
222 * has a probability range of zero. Again, experimentally derived data */
224 static const Prob gg_freqs[16]
227 {0, 0}, {38, 0}, {38, 38}, {13, 152},
228 {38, 76}, {13, 165}, {13, 178}, {6, 230},
229 {38, 114}, {13, 191}, {13, 204}, {6, 236},
230 {13, 217}, {6, 242}, {5, 248}, {3, 253}
234 //========================= compface_private.h end =========================
236 struct xfacectx {
237 deark *c;
238 int errflag;
240 dbuf *inf;
241 i64 inf_fpos;
243 BigInt gg_B;
245 /* internal face representation - 1 char per pixel is faster */
246 char gg_F[PIXELS];
248 // fbuf stores the contents of the source file, plus a NUL terminator.
249 // (Originally, fbuf was overloaded and used for other things as well.)
250 /* the buffer is longer than needed to handle sparse input formats */
251 #define FACEBUFLEN 2048
252 char gg_fbuf[FACEBUFLEN];
255 static int BigPop(struct xfacectx *ctx, const Prob *);
256 static void ReadBuf(struct xfacectx *ctx);
257 static void uncompface(struct xfacectx *ctx);
258 static void BigAdd(struct xfacectx *ctx, unsigned char);
259 static void BigClear(struct xfacectx *ctx);
260 static void BigRSH(struct xfacectx *ctx, XFACE_WORD *r);
261 static void BigMul(struct xfacectx *ctx, unsigned char);
262 static void BigRead(struct xfacectx *ctx, const char *);
263 static void PopGreys(struct xfacectx *ctx, char *, int, int);
264 static void UnCompAll(struct xfacectx *ctx);
265 static void UnCompress(struct xfacectx *ctx, char *, int, int, int);
266 static void WriteFace(struct xfacectx *ctx);
268 //========================= file.c begin =========================
270 // Reads ctx->gg_fbuf into gg_B, as a big int.
271 static void
272 BigRead(struct xfacectx *ctx, const char *fbuf)
274 int c;
276 while (*fbuf != '\0')
278 c = *(fbuf++);
279 if ((c < FIRSTPRINT) || (c > LASTPRINT))
280 continue;
281 BigMul(ctx, NUMPRINTS);
282 if(ctx->errflag) return;
283 BigAdd(ctx, (XFACE_WORD)(c - FIRSTPRINT));
284 if(ctx->errflag) return;
288 // Create an image file using the raw data in gg_F.
289 // (Originally, this wrote a text file to gg_fbuf.)
290 static void
291 WriteFace(struct xfacectx *ctx)
293 i64 i, j;
294 de_bitmap *img = NULL;
296 img = de_bitmap_create(ctx->c, XFACE_WIDTH, XFACE_HEIGHT, 1);
298 for(j=0; j<XFACE_HEIGHT; j++) {
299 for(i=0; i<XFACE_WIDTH; i++) {
300 if(ctx->gg_F[j*XFACE_WIDTH + i] == 0) {
301 de_bitmap_setpixel_gray(img, i, j, 255);
306 de_bitmap_write_to_file_finfo(img, NULL, 0);
307 de_bitmap_destroy(img);
310 //========================= file.c end =========================
312 //========================= arith.c begin =========================
314 static int
315 BigPop(struct xfacectx *ctx, const Prob *p)
317 XFACE_WORD tmp = 0;
318 int i;
320 BigRSH(ctx, &tmp);
321 i = 0;
322 while ((tmp < p->p_offset) || (tmp >= p->p_range + p->p_offset))
324 p++;
325 i++;
327 BigMul(ctx, p->p_range);
328 if(ctx->errflag) return 0;
329 BigAdd(ctx, tmp - p->p_offset);
330 if(ctx->errflag) return 0;
331 return i;
334 // This is what's left of the original BigDiv() function.
335 // It's only needed for the right-shift operation.
336 // (Stores the remainder in the word pointed to by r)
337 static void
338 BigRSH(struct xfacectx *ctx, XFACE_WORD *r)
340 int i;
341 XFACE_WORD *w;
343 if (ctx->gg_B.b_words == 0)
345 *r = 0;
346 return;
350 i = --ctx->gg_B.b_words;
351 w = ctx->gg_B.b_word;
352 *r = *w;
353 while (i--)
355 *w = *(w + 1);
356 w++;
358 *w = 0;
362 /* Multiply a by ctx->gg_B storing the result in ctx->gg_B
364 static void
365 BigMul(struct xfacectx *ctx, XFACE_WORD a)
367 int i;
368 XFACE_WORD *w;
369 XFACE_COMP c;
371 a &= WORDMASK;
372 if ((a == 1) || (ctx->gg_B.b_words == 0))
373 return;
374 if (a == 0) /* treat this as a == WORDCARRY */
375 { /* and just shift everything left a XFACE_WORD */
376 if ((i = ctx->gg_B.b_words++) >= MAXWORDS - 1) {
377 de_err(ctx->c, "xface: Internal error (1)");
378 ctx->errflag = 1;
379 return;
381 w = ctx->gg_B.b_word + i;
382 while (i--)
384 *w = *(w - 1);
385 w--;
387 *w = 0;
388 return;
390 i = ctx->gg_B.b_words;
391 w = ctx->gg_B.b_word;
392 c = 0;
393 while (i--)
395 c += (XFACE_COMP)*w * (XFACE_COMP)a;
396 *(w++) = (XFACE_WORD)(c & WORDMASK);
397 c >>= BITSPERWORD;
399 if (c)
401 if (ctx->gg_B.b_words++ >= MAXWORDS) {
402 de_err(ctx->c, "Invalid or oversized X-Face image");
403 ctx->errflag = 1;
404 return;
406 *w = (XFACE_COMP)(c & WORDMASK);
410 /* Add to a to ctx->gg_B storing the result in ctx->gg_B
412 static void
413 BigAdd(struct xfacectx *ctx, XFACE_WORD a)
415 int i;
416 XFACE_WORD *w;
417 XFACE_COMP c;
419 a &= WORDMASK;
420 if (a == 0)
421 return;
422 i = 0;
423 w = ctx->gg_B.b_word;
424 c = a;
425 while ((i < ctx->gg_B.b_words) && c)
427 c += (XFACE_COMP)*w;
428 *w++ = (XFACE_WORD)(c & WORDMASK);
429 c >>= BITSPERWORD;
430 i++;
432 if ((i == ctx->gg_B.b_words) && c)
434 if (ctx->gg_B.b_words++ >= MAXWORDS) {
435 de_err(ctx->c, "xface: Internal error (3)");
436 ctx->errflag = 1;
437 return;
439 *w = (XFACE_COMP)(c & WORDMASK);
443 static void
444 BigClear(struct xfacectx *ctx)
446 ctx->gg_B.b_words = 0;
449 //========================= arith.c end =========================
451 //========================= gen.c begin =========================
453 static void gen_helper(struct xfacectx *ctx, const u8 *arr, size_t arr_len,
454 int h, int k)
456 size_t arr_idx = 0;
458 if(k<0 || h<0 || h>=(int)sizeof(ctx->gg_F)) {
459 return;
461 arr_idx = (size_t)(k/8);
462 if(arr_idx>=arr_len) {
463 return;
465 if((arr[arr_idx]>>(7-(k%8)))&0x1) {
466 ctx->gg_F[h] ^= 1;
470 // I guess that Gen() is where prediction is done.
471 // It has what appears to be a programming error, considering that the
472 // "case XFACE_WIDTH" code cannot be reached, because i is never larger
473 // than XFACE_WIDTH-1. I suspect that, in fact, all of the "cases" are off by
474 // 1. But it's not like I can "fix" it, because that would change the format
475 // in an incompatible way. -JS
477 static void
478 Gen(struct xfacectx *ctx, char *f, size_t f_len)
480 int m, l, k, j, i, h;
482 #define XFACE_GEN(g) gen_helper(ctx, gg_G.g, sizeof(gg_G.g), h, k); break
484 for (j = 0; j < XFACE_HEIGHT; j++)
486 for (i = 0; i < XFACE_WIDTH; i++)
488 h = i + j * XFACE_WIDTH;
489 k = 0;
490 for (l = i - 2; l <= i + 2; l++)
491 for (m = j - 2; m <= j; m++)
493 if ((l >= i) && (m == j))
494 continue;
495 if ((l > 0) && (l <= XFACE_WIDTH) && (m > 0)) {
496 if((l + m * XFACE_WIDTH < 0) || (l + m * XFACE_WIDTH >= (int)f_len)) {
497 de_err(ctx->c, "xface: Internal error (4)");
498 ctx->errflag = 1;
499 return;
501 k = f[l + m * XFACE_WIDTH] ? k * 2 + 1 : k * 2;
504 switch (i)
506 case 1 :
507 switch (j)
509 case 1 : XFACE_GEN(g_22);
510 case 2 : XFACE_GEN(g_21);
511 default : XFACE_GEN(g_20);
513 break;
514 case 2 :
515 switch (j)
517 case 1 : XFACE_GEN(g_12);
518 case 2 : XFACE_GEN(g_11);
519 default : XFACE_GEN(g_10);
521 break;
522 case XFACE_WIDTH - 1 :
523 switch (j)
525 case 1 : XFACE_GEN(g_42);
526 case 2 : XFACE_GEN(g_41);
527 default : XFACE_GEN(g_40);
529 break;
530 #if 0
531 case XFACE_WIDTH :
532 switch (j)
534 case 1 : XFACE_GEN(g_32);
535 case 2 : XFACE_GEN(g_31);
536 default : XFACE_GEN(g_30);
538 break;
539 #endif
540 default :
541 switch (j)
543 case 1 : XFACE_GEN(g_02);
544 case 2 : XFACE_GEN(g_01);
545 default : XFACE_GEN(g_00);
547 break;
552 #undef XFACE_GEN
555 //========================= gen.c end =========================
557 //========================= compress.c begin =========================
559 static void
560 PopGreys(struct xfacectx *ctx, char *f, int wid, int hei)
562 if (wid > 3)
564 wid /= 2;
565 hei /= 2;
566 PopGreys(ctx, f, wid, hei);
567 if(ctx->errflag) return;
568 PopGreys(ctx, &f[wid], wid, hei);
569 if(ctx->errflag) return;
570 PopGreys(ctx, &f[XFACE_WIDTH * hei], wid, hei);
571 if(ctx->errflag) return;
572 PopGreys(ctx, &f[XFACE_WIDTH * hei + wid], wid, hei);
573 if(ctx->errflag) return;
575 else
577 wid = BigPop(ctx, gg_freqs);
578 if(ctx->errflag) return;
579 if (wid & 1)
580 f[0] = 1;
581 if (wid & 2)
582 f[1] = 1;
583 if (wid & 4)
584 f[XFACE_WIDTH] = 1;
585 if (wid & 8)
586 f[XFACE_WIDTH + 1] = 1;
590 static void
591 UnCompress(struct xfacectx *ctx, char *f, int wid, int hei, int lev)
593 int ret;
595 ret = BigPop(ctx, &gg_levels[lev][0]);
596 if(ctx->errflag) return;
598 switch (ret)
600 case WHITE :
601 return;
602 case BLACK :
603 PopGreys(ctx, f, wid, hei);
604 return;
605 default :
606 wid /= 2;
607 hei /= 2;
608 lev++;
609 UnCompress(ctx, f, wid, hei, lev);
610 if(ctx->errflag) return;
611 UnCompress(ctx, &f[wid], wid, hei, lev);
612 if(ctx->errflag) return;
613 UnCompress(ctx, &f[hei * XFACE_WIDTH], wid, hei, lev);
614 if(ctx->errflag) return;
615 UnCompress(ctx, &f[wid + hei * XFACE_WIDTH], wid, hei, lev);
616 return;
620 // Decompresses image from ctx->gg_fbuf to ctx->gg_F.
621 // Assumes ctx->gg_F is initialized to all zero bytes.
622 static void
623 UnCompAll(struct xfacectx *ctx)
625 BigClear(ctx);
626 BigRead(ctx, ctx->gg_fbuf);
628 UnCompress(ctx, ctx->gg_F, 16, 16, 0);
629 if(ctx->errflag) return;
630 UnCompress(ctx, ctx->gg_F + 16, 16, 16, 0);
631 if(ctx->errflag) return;
632 UnCompress(ctx, ctx->gg_F + 32, 16, 16, 0);
633 if(ctx->errflag) return;
634 UnCompress(ctx, ctx->gg_F + XFACE_WIDTH * 16, 16, 16, 0);
635 if(ctx->errflag) return;
636 UnCompress(ctx, ctx->gg_F + XFACE_WIDTH * 16 + 16, 16, 16, 0);
637 if(ctx->errflag) return;
638 UnCompress(ctx, ctx->gg_F + XFACE_WIDTH * 16 + 32, 16, 16, 0);
639 if(ctx->errflag) return;
640 UnCompress(ctx, ctx->gg_F + XFACE_WIDTH * 32, 16, 16, 0);
641 if(ctx->errflag) return;
642 UnCompress(ctx, ctx->gg_F + XFACE_WIDTH * 32 + 16, 16, 16, 0);
643 if(ctx->errflag) return;
644 UnCompress(ctx, ctx->gg_F + XFACE_WIDTH * 32 + 32, 16, 16, 0);
645 if(ctx->errflag) return;
648 //========================= compress.c end =========================
650 //========================= uncompface.c begin =========================
652 static void
653 uncompface(struct xfacectx *ctx)
655 UnCompAll(ctx);
656 if(ctx->errflag) return;
657 Gen(ctx, ctx->gg_F, sizeof(ctx->gg_F));
658 if(ctx->errflag) return;
659 WriteFace(ctx);
662 //========================= uncompface.c end =========================
664 //========================= uncmain.c begin =========================
666 static void
667 uncompface_main(deark *c)
669 struct xfacectx *ctx = NULL;
671 ctx = de_malloc(c, sizeof(struct xfacectx));
672 ctx->c = c;
673 ctx->inf = c->infile;
675 ReadBuf(ctx);
676 uncompface(ctx);
678 de_free(c, ctx);
681 // Read the file into ctx->gg_fbuf.
682 static void
683 ReadBuf(struct xfacectx *ctx)
685 i64 amt_to_read;
686 i64 startpos;
688 startpos = 0;
689 amt_to_read = ctx->inf->len;
690 if(amt_to_read > FACEBUFLEN-1)
691 amt_to_read = FACEBUFLEN-1;
693 // Handle a possible "X-Face:" prefix.
694 if(amt_to_read>=8 && has_x_header(ctx->inf)) {
695 de_dbg(ctx->c, "found X-Face prefix");
696 startpos += 8;
697 amt_to_read -= 8;
700 dbuf_read(ctx->inf, (u8*)ctx->gg_fbuf, startpos, amt_to_read);
702 ctx->gg_fbuf[amt_to_read] = '\0';
705 //========================= uncmain.c end =========================