9 #define CLOCKS_PER_SEC CLK_TCK
12 /* ---------------------------- Error codes --------------------------- */
15 #define COMP_ERR_NONE 0 /* everything is OK */
16 #define COMP_ERR_READ 2 /* input file read error */
17 #define COMP_ERR_NOMEM 5 /* no enough memory */
18 #define COMP_ERR_BROKEN 6 /* damaged compressed data */
19 #define COMP_ERR_PARAM 7 /* incorrect function parameter */
20 #define COMP_ERR_INTERNAL 9 /* everything else is internal error */
21 /* hopefully it should never happen */
23 /* Almost all functions listed further return one as its result on of */
24 /* codes given above: if no error occured then COMP_ERR_NONE (i.e. 0) */
25 /* is returned, otherwise functions return error code plus number of */
26 /* line in "comp.c" where the error was detected multiplied by 256; */
27 /* line number may be used for exact specification of a place where */
28 /* error was detected thus making debugging slightly simpler. */
30 /* Thus, "(code & 0xff)" gives proper error code, and "(code >> 8)" */
31 /* gives number of line where the error was raised. */
33 /* -------------------------------------------------------------------- */
35 /* Compress/decompress some chess tables */
37 /* Copyright (c) 1991--1998 Andrew Kadatch */
39 /* The Limited-Reference variant of Lempel-Ziv algorithm implemented */
40 /* here was first described in my B.Sc. thesis "Efficient algorithms */
41 /* for image compression", Novosibirsk State University, 1992, and */
42 /* cannot be used in any product distributed in Russia or CIS without */
43 /* written permission from the author. */
45 /* Most of the code listed below is significantly simplified code from */
46 /* the PRS data compression library and therefore it should not be used */
47 /* in any product (software or hardware, commercial or not, and so on) */
48 /* without written permission from the author. */
50 /* -------------------------------------------------------------------- */
52 /* ---------------------------- Debugging ----------------------------- */
60 #define assert(cond) ((cond) ? (void) 0 : _local_assert (__LINE__))
61 static void _local_assert(int lineno)
63 fprintf(stderr, "assertion at line %u failed\n", lineno);
68 #define dprintf(x) printf x
71 #define assert(cond) ((void) 0)
73 #define debug(x) ((void) 0)
74 #define dprintf(x) ((void) 0)
79 int cbEGTBCompBytes = 0;
82 int cbEGTBCompBytes = 0;
85 /* --------------------- Constants, types, etc. ----------------------- */
86 /* ---------------------- */
87 #define MIN_BLOCK_BITS 8 /* LOG2 (min size of block to compress) */
88 #define MAX_BLOCK_BITS 16 /* LOG2 (max size of block to compress) */
89 /* max. integer we can take LOG2 by table */
90 #define MAX_BITS_HALF ((MAX_BLOCK_BITS + 1) >> 1)
91 #define MAX_BITS (MAX_BITS_HALF * 2)
92 /* assume that integer is at least 32 bits wide */
97 #define uchar unsigned char
99 #define HEADER_SIZE 80 /* number of reserved bytes */
100 #define STOP_SEARCH_LENGTH 256 /* terminate search if match */
101 /* length exceeds that value */
102 #define MAX_LENGTH_BITS 5
103 #define MAX_LENGTH (1 << MAX_LENGTH_BITS)
105 #define LONG_LENGTH (MAX_BLOCK_BITS - LONG_BITS)
106 #define LONG_QUICK (MAX_LENGTH - LONG_LENGTH)
107 #if LONG_LENGTH > (MAX_BLOCK_BITS - LONG_BITS)
109 # define LONG_LENGTH (MAX_BLOCK_BITS - LONG_BITS)
111 #if LONG_LENGTH >= MAX_LENGTH || LONG_LENGTH <= 0
112 #error LONG_LENGTH is out of range
115 #error LONG_BITS must be positive
117 #define DELTA (LONG_BITS + LONG_QUICK - 1)
118 #if (MAX_LENGTH - 1) - (LONG_LENGTH - LONG_BITS) != DELTA
121 #define MAX_DISTANCES 24
122 #define LOG_MAX_DISTANCES 6 /* see check below */
123 #if MAX_DISTANCES > (1 << LOG_MAX_DISTANCES)
124 #error MAX_DISTANCES should not exceed (1 << LOG_MAX_DISTANCES)
126 #define ALPHABET_SIZE (256 + (MAX_DISTANCES << MAX_LENGTH_BITS))
127 #define MAX_ALPHABET ALPHABET_SIZE /* max. alphabet handled by */
128 /* Huffman coding routines */
130 /* 0 - use Fletcher's checksum, != 0 - use proper CRC32 */
131 static uchar header_title[64] =
132 "Compressed by DATACOMP v 1.0 (c) 1991--1998 Andrew Kadatch\r\n\0";
134 #define RET(n) ((n) + __LINE__ * 256)
136 /* ------------------------- CRC32 routines --------------------------- */
141 static unsigned CRC32_table[256];
142 static int CRC32_initialized = 0;
144 static void CRC32_init(void)
147 unsigned k, m = (unsigned) 0xedb88320L;
149 if (CRC32_initialized)
151 for (i = 0; i < 256; ++i) {
165 CRC32_initialized = 1;
168 static unsigned CRC32(uchar * p, int n, unsigned k)
170 unsigned *table = CRC32_table;
174 # define X(i) k = table[((uchar) k) ^ p[i]] ^ (k >> 8)
195 k = table[((uchar) k) ^ *p++] ^ (k >> 8);
203 static unsigned CRC32(uchar * p, int n, unsigned k1)
205 unsigned k0 = k1 & 0xffff;
208 k1 = (k1 >> 16) & 0xffff;
210 # define X(i) k0 += p[i]; k1 += k0;
228 k0 = (k0 & 0xffff) + (k0 >> 16);
229 k1 = (k1 & 0xffff) + (k1 >> 16);
236 k0 = (k0 & 0xffff) + (k0 >> 16);
237 k1 = (k1 & 0xffff) + (k1 >> 16);
238 k0 = (k0 & 0xffff) + (k0 >> 16);
239 k1 = (k1 & 0xffff) + (k1 >> 16);
240 assert(((k0 | k1) >> 16) == 0);
241 return (k0 + (k1 << 16));
244 #endif /* USE_CRC32 */
246 /* ------------------------ Bit IO interface -------------------------- */
247 /* ---------------- */
249 #define BITIO_LOCALS \
258 #define BITIO_ENTER(p) do { \
264 #define BITIO_LEAVE(p) do { \
270 #define BIORD_START(from) do { \
271 _ptr = (uchar *) (from); \
272 _bits = sizeof (_mask); \
275 _mask = (_mask << 8) | *_ptr++; \
276 while (--_bits != 0); \
280 /* read [1, 17] bits at once */
281 #define BIORD(bits) \
282 (_mask >> (8 * sizeof (_mask) - (bits)))
284 #define BIORD_MORE(bits) do { \
286 if ((_bits -= (bits)) <= 0) \
288 _mask |= ((_ptr[0] << 8) + _ptr[1]) << (-_bits); \
289 _ptr += 2; _bits += 16; \
293 /* ------------------------ Huffman coding ---------------------------- */
296 #if MAX_ALPHABET <= 0xffff
297 # if MAX_ALPHABET <= 1024
298 /* positive value takes 15 bits => symbol number occupies <= 10 bits */
299 # define huffman_decode_t short
301 # define huffman_decode_t int
304 # define huffman_decode_t int
307 #define HUFFMAN_DECODE(ch,table,start_bits) do { \
308 (ch) = table[BIORD (start_bits)]; \
309 if (((int) (ch)) >= 0) \
311 BIORD_MORE ((ch) & 31); \
315 BIORD_MORE (start_bits); \
318 (ch) = table[BIORD (1) - (ch)]; \
321 while (((int) (ch)) < 0); \
324 #define HUFFMAN_TABLE_SIZE(n,start_bits) \
325 ((1 << (start_bits)) + ((n) << 1))
327 static int huffman_decode_create(huffman_decode_t * table, uchar * length,
328 int n, int start_bits)
330 int i, j, k, last, freq[32], sum[32];
332 /* calculate number of codewords */
333 memset(freq, 0, sizeof(freq));
334 for (i = 0; i < n; ++i) {
335 if ((k = length[i]) > 31)
336 return RET(COMP_ERR_BROKEN);
340 /* handle special case(s) -- 0 and 1 symbols in alphabet */
342 memset(table, 0, sizeof(table[0]) << start_bits);
345 if (freq[0] == n - 1) {
347 return RET(COMP_ERR_BROKEN);
348 for (i = 0; length[i] == 0;)
351 for (k = 1 << start_bits; --k >= 0;)
352 *table++ = (huffman_decode_t) i;
356 /* save frequences */
357 memcpy(sum, freq, sizeof(sum));
359 /* check code correctness */
361 for (i = 32; --i != 0;) {
362 if ((k += freq[i]) & 1)
363 return RET(COMP_ERR_BROKEN);
367 return RET(COMP_ERR_BROKEN);
371 for (i = 1; i < 32; ++i)
372 freq[i] = (k += freq[i]);
373 last = freq[31]; /* preserve number of symbols in alphabet */
374 for (i = n; --i >= 0;) {
375 if ((k = length[i]) != 0)
376 table[--freq[k]] = (huffman_decode_t) i;
379 /* now create decoding table */
380 k = i = (1 << start_bits) + (n << 1);
381 for (n = 32; --n > start_bits;) {
384 table[--i] = (huffman_decode_t) - (k -= 2);
385 for (k = sum[n]; --k >= 0;)
386 table[--i] = table[--last];
393 table[--i] = (huffman_decode_t) - (k -= 2);
396 for (k = sum[n]; --k >= 0;) {
397 assert(last <= i && last > 0);
398 j = i - (1 << (start_bits - n));
399 n |= table[--last] << 5;
401 table[--i] = (huffman_decode_t) n;
406 assert((i | last) == 0);
411 /* -------------------- Read/write Huffman code ----------------------- */
412 /* ----------------------- */
417 #error MIN_REPT must exceed 1
420 #define TEMP_TABLE_BITS 8
422 static int huffman_read_length(bitio_t * bitio, uchar * length, int n)
425 huffman_decode_t table[2][HUFFMAN_TABLE_SIZE(64, TEMP_TABLE_BITS)];
433 memset(length, 0, n);
440 for (i = 0; i < n;) {
441 length[i] = (uchar) BIORD(k);
443 if (length[i++] == 0) {
447 return RET(COMP_ERR_BROKEN);
456 i = huffman_read_length(bitio, bits, 128);
459 i = huffman_decode_create(table[0], bits, 64, TEMP_TABLE_BITS);
462 i = huffman_decode_create(table[1], bits + 64, 64, TEMP_TABLE_BITS);
467 for (i = 0; i < n;) {
468 HUFFMAN_DECODE(k, table[0], TEMP_TABLE_BITS);
470 length[i++] = (uchar) k;
474 HUFFMAN_DECODE(j, table[1], TEMP_TABLE_BITS);
481 j += BIORD(16) << (jj - 16);
491 return RET(COMP_ERR_BROKEN);
493 length[i] = (uchar) k;
502 /* ----------------------- Proper compression ------------------------- */
503 /* ------------------ */
505 #if MIN_BLOCK_BITS > MAX_BLOCK_BITS || MAX_BLOCK_BITS > MAX_BITS_HALF*2
506 #error condition MIN_BLOCK_BITS <= MAX_BLOCK_BITS <= MAX_BITS_HALF*2 failed
509 #define DECODE_MAGIC ((int) 0x5abc947fL)
510 #define BLOCK_MAGIC ((int) 0x79a3f29dL)
512 #define START_BITS 13
514 #define SHORT_INDEX 8u
517 huffman_decode_t table[HUFFMAN_TABLE_SIZE(ALPHABET_SIZE, START_BITS)];
518 int distance[MAX_DISTANCES];
519 unsigned *crc, *blk_u;
520 unsigned short *blk_s;
521 int block_size_log, /* block_size is integral power of 2 */
522 block_size, /* 1 << block_size_log */
523 last_block_size, /* [original] size of last block */
524 n_blk, /* total number of blocks */
525 comp_block_size, /* size of largest compressed block+32 */
526 check_crc; /* check CRC32? */
532 unsigned char *ptr; /* pointer to the first decoded byte */
533 int decoded; /* number of bytes decoded so far */
534 int total; /* total number of bytes in block */
535 int number; /* number of this block */
538 /* Pointer to compressed data block */
555 static int calculate_offset(decode_info * info, unsigned n)
559 i = n / (2 * SHORT_INDEX);
561 return info->blk_u[i + 1] - info->blk_s[n];
563 return info->blk_u[i] + info->blk_s[n];
566 static void do_decode(decode_info * info, decode_block * block, uchar * e)
572 if ((p = block->emit.ptr) >= e)
574 if (p == block->orig.first) {
575 BIORD_START(block->comp.first);
576 block->emit.rept = 0;
578 BITIO_ENTER(block->bitio);
579 if ((ch = block->emit.rept) != 0) {
580 block->emit.rept = 0;
585 #define OVER if (p < e) goto over; break
588 HUFFMAN_DECODE(ch, info->table, START_BITS);
589 if ((ch -= 256) < 0) {
594 s = p + info->distance[ch >> MAX_LENGTH_BITS];
596 ch &= MAX_LENGTH - 1;
604 } else if (ch >= LONG_LENGTH) {
605 ch -= LONG_LENGTH - LONG_BITS;
606 #if (MAX_BLOCK_BITS - 1) + (LONG_LENGTH - LONG_BITS) >= MAX_LENGTH
617 n += BIORD(16) << (ch -= 16);
624 ch += LONG_LENGTH - (1 << LONG_BITS);
630 block->emit.rept = ch - (int) (e - p);
635 # define X(i) p[i] = s[i]
656 while ((ch -= 16) > 16);
661 # define X(i) case i: p[-i] = s[-i]
685 BITIO_LEAVE(block->bitio);
689 static int comp_open_file(decode_info ** res, FILE * fd, int check_crc)
693 uchar temp[ALPHABET_SIZE >= HEADER_SIZE ? ALPHABET_SIZE : HEADER_SIZE];
695 int header_size, block_size, block_size_log, n_blk, i, n, n_s, n_u;
696 unsigned *blk_u, *blk;
697 unsigned short *blk_s;
701 return RET(COMP_ERR_PARAM);
707 if (fread(temp, 1, HEADER_SIZE, fd) != HEADER_SIZE)
708 return RET(COMP_ERR_READ);
710 if (memcmp(temp, header_title, 64) != 0)
711 return RET(COMP_ERR_READ);
715 ((ptr[i] << 24) + (ptr[(i) + 1] << 16) + (ptr[(i) + 2] << 8) + (ptr[(i) + 3]))
717 header_size = R4(64);
718 block_size_log = ptr[70];
719 if (block_size_log > MAX_BITS || header_size < 84)
720 return RET(COMP_ERR_BROKEN);
721 block_size = 1 << block_size_log;
722 if (ptr[71] != MAX_DISTANCES)
723 return RET(COMP_ERR_BROKEN);
726 (ALPHABET_SIZE << 12) + (LONG_BITS << 8) + (LONG_LENGTH << 4) +
728 return RET(COMP_ERR_BROKEN);
730 if ((ptr = (uchar *) malloc(header_size)) == 0)
731 return RET(COMP_ERR_NOMEM);
733 if (fread(ptr + HEADER_SIZE, 1, header_size - HEADER_SIZE, fd) !=
734 (size_t) (header_size - HEADER_SIZE)) {
736 return RET(COMP_ERR_NOMEM);
738 memcpy(ptr, temp, HEADER_SIZE);
740 if (CRC32(ptr, header_size, 0) != (unsigned) R4(header_size)) {
742 return RET(COMP_ERR_BROKEN);
747 blk = (unsigned *) malloc (sizeof (unsigned) * (1 + n_blk));
749 n = sizeof(unsigned) * (1 + n_blk);
750 if (n < 4 * 1024 * 1024)
752 blk = (unsigned *) malloc(n);
756 return RET(COMP_ERR_NOMEM);
758 n = sizeof(info->crc[0]) * (1 + (check_crc ? (2 * n_blk) : 0));
759 n_u = sizeof(unsigned) * (2 + n_blk / (2 * SHORT_INDEX));
760 n_s = sizeof(unsigned short) * (1 + n_blk);
761 if ((info = (decode_info *) malloc(sizeof(*info) + n + n_u + n_s)) == 0) {
764 return RET(COMP_ERR_NOMEM);
766 cbEGTBCompBytes += sizeof(*info) + n + n_s + n_u;
767 info->crc = (unsigned *) (info + 1);
769 blk_u = info->blk_u = info->crc + 2 * n_blk;
771 blk_u = info->blk_u = info->crc;
772 blk_s = info->blk_s =
773 (unsigned short *) (blk_u + 2 + n_blk / (2 * SHORT_INDEX));
775 info->check_crc = check_crc;
776 info->block_size_log = block_size_log;
777 info->block_size = block_size;
783 for (n = 0; n < n_blk; ++n) {
784 info->crc[n] = R4(i);
790 i = HEADER_SIZE + (n_blk << 3);
791 BIORD_START(ptr + i);
793 info->comp_block_size = 0;
794 for (n = 0; n <= n_blk; ++n) {
795 if ((blk[n] = BIORD(block_size_log)) == 0)
797 if (info->comp_block_size < (int) (blk[n]))
798 info->comp_block_size = (int) (blk[n]);
799 BIORD_MORE(block_size_log);
801 info->comp_block_size += 32;
803 for (n = 0; n < MAX_DISTANCES; ++n) {
804 info->distance[n] = -((int) BIORD(block_size_log));
805 BIORD_MORE(block_size_log);
808 i += ((n_blk + 1 + MAX_DISTANCES) * block_size_log + 7) >> 3;
809 BIORD_START(ptr + i);
811 if (huffman_read_length(&Bitio, temp, ALPHABET_SIZE) != 0) {
815 return RET(COMP_ERR_BROKEN);
818 if (huffman_decode_create(info->table, temp, ALPHABET_SIZE, START_BITS) != 0) {
822 return RET(COMP_ERR_BROKEN);
825 info->last_block_size = blk[n_blk];
827 for (n = 0; n <= n_blk; ++n) {
829 blk[n] = header_size;
831 if (0 == n % (2 * SHORT_INDEX))
832 blk_u[n / (2 * SHORT_INDEX)] = blk[n];
834 blk_u[n_blk / (2 * SHORT_INDEX) + 1] = blk[n_blk];
836 for (n = 0; n <= n_blk; ++n) {
837 i = n / (2 * SHORT_INDEX);
839 blk_s[n] = blk_u[i + 1] - blk[n];
841 blk_s[n] = blk[n] - blk_u[i];
847 info->magic = DECODE_MAGIC;
850 return (COMP_ERR_NONE);
853 static int comp_tell_blocks(decode_info * info)
855 if (info == 0 || info->magic != DECODE_MAGIC)
857 return (info->n_blk);
860 static int comp_init_block(decode_block * block, int block_size, uchar * orig)
863 return RET(COMP_ERR_PARAM);
864 block->orig.first = orig;
865 block->comp.first = (uchar *) (block + 1);
867 block->b.decoded = -1;
869 block->b.number = -1;
871 block->magic = BLOCK_MAGIC;
872 return (COMP_ERR_NONE);
875 static int comp_alloc_block(decode_block ** ret_block, int block_size)
880 return RET(COMP_ERR_PARAM);
882 if ((block = (decode_block *) malloc(sizeof(*block) + block_size)) == 0)
883 return RET(COMP_ERR_NOMEM);
884 cbEGTBCompBytes += sizeof(*block) + block_size;
885 if (0 != comp_init_block(block, block_size, NULL))
886 return RET(COMP_ERR_PARAM);
888 return (COMP_ERR_NONE);
892 return ((n) == COMP_ERR_NONE ? COMP_ERR_NONE : RET (n));
894 static int comp_read_block(decode_block * block, decode_info * info, FILE * fd,
897 int comp_size, orig_size, comp_start;
900 if (block == 0 || block->magic != BLOCK_MAGIC)
901 return RET(COMP_ERR_PARAM);
902 assert(info->magic == DECODE_MAGIC);
903 if ((unsigned) n >= (unsigned) info->n_blk)
904 RETURN(COMP_ERR_PARAM);
905 comp = block->comp.first;
907 orig = block->orig.first;
908 orig_size = info->block_size;
909 if (n == info->n_blk - 1)
910 orig_size = info->last_block_size;
911 block->orig.size = orig_size;
912 comp_start = calculate_offset(info, n);
913 block->comp.size = comp_size = calculate_offset(info, n + 1) - comp_start;
914 if (fseek(fd, comp_start, SEEK_SET) != 0)
915 RETURN(COMP_ERR_READ);
916 if (fread(comp, 1, comp_size, fd) != (size_t) comp_size)
917 RETURN(COMP_ERR_READ);
919 && info->crc[(n << 1) + 1] != CRC32(block->comp.first, comp_size, 0))
920 RETURN(COMP_ERR_BROKEN);
921 block->emit.rept = 0;
922 if (comp_size == orig_size) {
923 memcpy(orig, comp, comp_size);
924 block->emit.ptr = orig + comp_size;
925 block->b.decoded = comp_size;
927 block->emit.ptr = orig;
928 block->b.decoded = 0;
932 block->b.total = orig_size;
934 RETURN(COMP_ERR_NONE);
937 static int comp_decode_and_check_crc(decode_block * block, decode_info * info,
938 int n, int check_crc)
940 if (block == 0 || block->magic != BLOCK_MAGIC)
941 return RET(COMP_ERR_PARAM);
942 assert(info->magic == DECODE_MAGIC);
943 if ((unsigned) (n - 1) > (unsigned) (block->orig.size - 1))
944 RETURN(COMP_ERR_PARAM);
946 n = block->orig.size;
947 do_decode(info, block, block->orig.first + n);
948 block->b.ptr = block->orig.first;
949 block->b.total = block->orig.size;
950 if (block->b.decoded >= block->b.total) {
951 if (block->b.decoded > block->b.total)
952 RETURN(COMP_ERR_BROKEN);
953 if (block->emit.rept != 0)
954 RETURN(COMP_ERR_BROKEN);
956 if (check_crc && info->check_crc
957 && info->crc[block->n << 1] != CRC32(block->orig.first, block->orig.size,
959 RETURN(COMP_ERR_BROKEN);
961 RETURN(COMP_ERR_NONE);
964 #if !defined (COLOR_DECLARED)
972 int main(int argc, char *argv[])
978 decode_info *comp_info;
979 decode_block *comp_block;
980 clock_t tStart, tEnd;
982 uchar rgbBuf[8192 + 32];
985 printf("Invalid arguments\n");
988 fp = fopen(argv[1], "rb");
990 printf("Unable to open file\n");
993 result = comp_open_file(&comp_info, fp, CRC_CHECK);
995 printf("Unable to read file (1): %d\n", result);
998 if (8192 != comp_info->block_size) {
999 printf("Invalid block size: %d\n", comp_info->block_size);
1002 result = comp_alloc_block(&comp_block, comp_info->block_size);
1004 printf("Unable to allocate block: %d\n", result);
1010 for (i = 0; i < comp_info->n_blk; i++) {
1012 (result = comp_init_block(comp_block, comp_info->block_size, rgbBuf))) {
1013 printf("Unable to init block: %d\n", result);
1016 if (0 != (result = comp_read_block(comp_block, comp_info, fp, i))) {
1017 printf("Unable to read block: %d\n", result);
1020 size += comp_block->orig.size;
1023 comp_decode_and_check_crc(comp_block, comp_info, comp_block->orig.size,
1025 printf("Unable to decode block: %d\n", result);
1030 dSeconds = (double) (tEnd - tStart) / CLOCKS_PER_SEC;
1031 printf("Total memory allocated: %dKb\n", (cbEGTBCompBytes + 1023) / 1024);
1032 printf("%g seconds, %dMb, %gMb/sec)\n", dSeconds, size / (1024 * 1024),
1033 size / (1024 * 1024) / dSeconds);