1 // See the file readme-compface.txt for more information about this file.
2 // Modifications for Deark are Copyright (C) 2017 Jason Summers.
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
7 // --------------------------------------------------------------------------
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 '!'
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
48 #define WORDCARRY (1 << BITSPERWORD)
49 #define WORDMASK (WORDCARRY - 1)
50 #define MAXWORDS ((PIXELS * 2 + BITSPERWORD - 1) / BITSPERWORD)
55 XFACE_WORD b_word
[MAXWORDS
];
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];
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];
75 const u8 g_31
[/*1<<5 */ 1<<2];
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 ];
81 const u8 g_32
[/*1<<2 */ 1 ];
83 const u8 g_42
[/*1<<2 */ 1 ];
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 */
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 */
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 =========================
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
145 0x37,0x73,0x00,0x19,0x57,0x7f,0xf5,0xfb,0x70,0x33,0xf0,0xf9,0x7f,0xff,0xff,0xff
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
157 0x04,0x00,0x01,0x01,0x43,0x2e,0xff,0x3f
159 #if 0 // See comment for Gen(), below.
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
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
187 0x01,0x01,0x01,0x1f,0x03,0x1f,0x3f,0xff
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 =========================
245 /* internal face representation - 1 char per pixel is faster */
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.
272 BigRead(struct xfacectx
*ctx
, const char *fbuf
)
276 while (*fbuf
!= '\0')
279 if ((c
< FIRSTPRINT
) || (c
> LASTPRINT
))
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.)
291 WriteFace(struct xfacectx
*ctx
)
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 =========================
315 BigPop(struct xfacectx
*ctx
, const Prob
*p
)
322 while ((tmp
< p
->p_offset
) || (tmp
>= p
->p_range
+ p
->p_offset
))
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;
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)
338 BigRSH(struct xfacectx
*ctx
, XFACE_WORD
*r
)
343 if (ctx
->gg_B
.b_words
== 0)
350 i
= --ctx
->gg_B
.b_words
;
351 w
= ctx
->gg_B
.b_word
;
362 /* Multiply a by ctx->gg_B storing the result in ctx->gg_B
365 BigMul(struct xfacectx
*ctx
, XFACE_WORD a
)
372 if ((a
== 1) || (ctx
->gg_B
.b_words
== 0))
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)");
381 w
= ctx
->gg_B
.b_word
+ i
;
390 i
= ctx
->gg_B
.b_words
;
391 w
= ctx
->gg_B
.b_word
;
395 c
+= (XFACE_COMP
)*w
* (XFACE_COMP
)a
;
396 *(w
++) = (XFACE_WORD
)(c
& WORDMASK
);
401 if (ctx
->gg_B
.b_words
++ >= MAXWORDS
) {
402 de_err(ctx
->c
, "Invalid or oversized X-Face image");
406 *w
= (XFACE_COMP
)(c
& WORDMASK
);
410 /* Add to a to ctx->gg_B storing the result in ctx->gg_B
413 BigAdd(struct xfacectx
*ctx
, XFACE_WORD a
)
423 w
= ctx
->gg_B
.b_word
;
425 while ((i
< ctx
->gg_B
.b_words
) && c
)
428 *w
++ = (XFACE_WORD
)(c
& WORDMASK
);
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)");
439 *w
= (XFACE_COMP
)(c
& WORDMASK
);
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
,
458 if(k
<0 || h
<0 || h
>=(int)sizeof(ctx
->gg_F
)) {
461 arr_idx
= (size_t)(k
/8);
462 if(arr_idx
>=arr_len
) {
465 if((arr
[arr_idx
]>>(7-(k
%8)))&0x1) {
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
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
;
490 for (l
= i
- 2; l
<= i
+ 2; l
++)
491 for (m
= j
- 2; m
<= j
; m
++)
493 if ((l
>= i
) && (m
== j
))
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)");
501 k
= f
[l
+ m
* XFACE_WIDTH
] ? k
* 2 + 1 : k
* 2;
509 case 1 : XFACE_GEN(g_22
);
510 case 2 : XFACE_GEN(g_21
);
511 default : XFACE_GEN(g_20
);
517 case 1 : XFACE_GEN(g_12
);
518 case 2 : XFACE_GEN(g_11
);
519 default : XFACE_GEN(g_10
);
522 case XFACE_WIDTH
- 1 :
525 case 1 : XFACE_GEN(g_42
);
526 case 2 : XFACE_GEN(g_41
);
527 default : XFACE_GEN(g_40
);
534 case 1 : XFACE_GEN(g_32
);
535 case 2 : XFACE_GEN(g_31
);
536 default : XFACE_GEN(g_30
);
543 case 1 : XFACE_GEN(g_02
);
544 case 2 : XFACE_GEN(g_01
);
545 default : XFACE_GEN(g_00
);
555 //========================= gen.c end =========================
557 //========================= compress.c begin =========================
560 PopGreys(struct xfacectx
*ctx
, char *f
, int wid
, int hei
)
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;
577 wid
= BigPop(ctx
, gg_freqs
);
578 if(ctx
->errflag
) return;
586 f
[XFACE_WIDTH
+ 1] = 1;
591 UnCompress(struct xfacectx
*ctx
, char *f
, int wid
, int hei
, int lev
)
595 ret
= BigPop(ctx
, &gg_levels
[lev
][0]);
596 if(ctx
->errflag
) return;
603 PopGreys(ctx
, f
, wid
, hei
);
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
);
620 // Decompresses image from ctx->gg_fbuf to ctx->gg_F.
621 // Assumes ctx->gg_F is initialized to all zero bytes.
623 UnCompAll(struct xfacectx
*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 =========================
653 uncompface(struct xfacectx
*ctx
)
656 if(ctx
->errflag
) return;
657 Gen(ctx
, ctx
->gg_F
, sizeof(ctx
->gg_F
));
658 if(ctx
->errflag
) return;
662 //========================= uncompface.c end =========================
664 //========================= uncmain.c begin =========================
667 uncompface_main(deark
*c
)
669 struct xfacectx
*ctx
= NULL
;
671 ctx
= de_malloc(c
, sizeof(struct xfacectx
));
673 ctx
->inf
= c
->infile
;
681 // Read the file into ctx->gg_fbuf.
683 ReadBuf(struct xfacectx
*ctx
)
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");
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 =========================