bits.c
上传用户:ykyjsl
上传日期:2022-01-30
资源大小:145k
文件大小:6k
源码类别:

压缩解压

开发平台:

C/C++

  1. /******************************************************************************
  2. File: bits.c
  3. Authors:  John Carpinelli   (johnfc@ecr.mu.oz.au)
  4.   Wayne Salamonsen  (wbs@mundil.cs.mu.oz.au)
  5. Lang Stuiver   (langs@cs.mu.oz.au)
  6. Purpose: Data compression using an nth order binary model and revised 
  7. arithmetic coding method.
  8. Based on:  A. Moffat, R. Neal, I.H. Witten, "Arithmetic Coding Revisited",
  9. Proc. IEEE Data Compression Conference, Snowbird, Utah, 
  10. March 1995.
  11. Copyright 1995 John Carpinelli and Wayne Salamonsen, All Rights Reserved.
  12. These programs are supplied free of charge for research purposes only,
  13. and may not sold or incorporated into any commercial product.  There is
  14. ABSOLUTELY NO WARRANTY of any sort, nor any undertaking that they are
  15. fit for ANY PURPOSE WHATSOEVER.  Use them at your own risk.  If you do
  16. happen to find a bug, or have modifications to suggest, please report
  17. the same to Alistair Moffat, alistair@cs.mu.oz.au.  The copyright
  18. notice above and this statement of conditions must remain an integral
  19. part of each and every copy made of these files.
  20. ******************************************************************************/
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include "bitio.h"
  24. #include "arith.h"
  25. #include "stats.h"
  26. #include "main.h"
  27. /* global variables */
  28. int bits_context=DEFAULT_BITS_CONTEXT;     /* no. bits in binary contexts */
  29. static unsigned int non_null_contexts = 0;  /* count of contexts used */
  30. #ifdef RCSID
  31. static char
  32.    rcsid[] = "$Id: bits.c,v 1.1 1996/08/07 01:34:11 langs Exp $";
  33. #endif
  34. /*
  35.  *
  36.  * print the results of compressing/decompressing a file
  37.  *
  38.  */
  39. void print_results_bits(int decode)
  40. {
  41.     fprintf(stderr, "Context bits           : %10dn", bits_context);
  42.     fprintf(stderr, "Number of contexts     : %10un", 
  43.     non_null_contexts);
  44. }
  45. /*
  46.  *
  47.  * compress data using i/o in bitio.c, compressing
  48.  * each bit with probabilities derived from the previous bits
  49.  *
  50.  */
  51. void encode_bits(void)
  52. {
  53.     unsigned int i, j, cur_context, closest_context;
  54.     unsigned int  mask, bit;
  55.     int bits_to_go, buffer;
  56.     binary_context **contexts;
  57.     binary_context *still_coding;
  58.     OUTPUT_BYTE(bits_context);
  59.     /* initialise context array */
  60.     contexts = (binary_context **)do_malloc(sizeof(binary_context *) * 
  61.   (1 << bits_context));
  62.     if (contexts == NULL)
  63.     {
  64. fprintf(stderr, "bits: not enough memory to allocate context arrayn");
  65. exit(1);
  66.     }
  67.     still_coding = create_binary_context();
  68.     /* initialise contexts to NULL */
  69.     for (i=0; i < 1 << bits_context; i++)
  70. contexts[i] = NULL;
  71.     /* initalise variables */
  72.     cur_context = 0;
  73.     mask = (1 << bits_context) - 1;
  74.     
  75. /* Ensure context '0' is created, as it is implicitly
  76.     * assumed to exist in the main loop that follows
  77.  */
  78.     if (get_memory(sizeof(binary_context)) != NOMEMLEFT)
  79.     {
  80.          contexts[0] = create_binary_context();
  81.          non_null_contexts++;
  82.     }
  83.     else
  84.     {
  85. fprintf(stderr,"bits: not enough memory to allocate initial contextn");
  86. exit(1);
  87.     }
  88.     startoutputtingbits();
  89.     start_encode();
  90.     while ((buffer = INPUT_BYTE()) != EOF)
  91.     {
  92. binary_encode(still_coding, 1);
  93.    
  94. for (bits_to_go = 7; bits_to_go >= 0; bits_to_go--)
  95. {
  96.     if (contexts[cur_context] == NULL)
  97.     {
  98. if (get_memory(sizeof(binary_context)) != NOMEMLEFT)
  99. {
  100.     contexts[cur_context] = create_binary_context();
  101.     non_null_contexts++;
  102. }
  103. else 
  104.     /* 
  105.      * determine closest existing context to current one
  106.      * by stripping off the leading bits of the context
  107.      * guaranteed to get contexts[0] if nothing closer
  108.      */
  109. {
  110.     closest_context = cur_context;
  111.     j = 1;
  112.     do
  113.     {
  114. closest_context &= (mask >> j);
  115. j++;
  116.     } while (contexts[closest_context] == NULL);
  117.     contexts[cur_context] = contexts[closest_context];
  118. }
  119.     }
  120.     bit = (buffer >> bits_to_go) & 1;
  121.     binary_encode(contexts[cur_context], bit);
  122.     cur_context = ((cur_context << 1) | bit) & mask;
  123. }
  124.     
  125.     }
  126.     /* encode end of message flag */
  127.     binary_encode(still_coding, 0);
  128.     finish_encode();
  129.     doneoutputtingbits();
  130. }
  131. /*
  132.  *
  133.  * decode a compressed file using a bit context model,
  134.  * using bitio.c i/o
  135.  *
  136.  */
  137. void decode_bits(void)
  138. {
  139.     int i, j, cur_context, closest_context, buffer, bits_to_go;
  140.     int  mask, bit;
  141.     binary_context **contexts;
  142.     binary_context *still_coding;
  143.     bits_context = INPUT_BYTE();
  144.     /* initialise context array */
  145.     contexts = (binary_context **)do_malloc(sizeof(binary_context *) * 
  146.   (1 << bits_context));
  147.     if (contexts == NULL)
  148.     {
  149. fprintf(stderr, "bits: unable to malloc %d bytesn",
  150. (int)sizeof(binary_context *) * (1 << bits_context)); 
  151. exit(1);
  152.     }
  153.     still_coding = create_binary_context();
  154.     
  155.     /* initialise contexts to NULL */
  156.     for (i=0; i < 1 << bits_context; i++)
  157. contexts[i] = (binary_context *)NULL;
  158.     /* initalise variables */
  159.     cur_context = 0;
  160.     mask = (1 << bits_context) - 1;
  161.     startinputtingbits();
  162.     start_decode();
  163.     /* decode the file */
  164.     while (binary_decode(still_coding))
  165.     {
  166. buffer = 0;
  167. for (bits_to_go = 7; bits_to_go >= 0; bits_to_go--)
  168. {
  169.     if (contexts[cur_context] == (binary_context *)NULL)
  170.     {
  171. if (get_memory(sizeof(binary_context)) != NOMEMLEFT)
  172. {
  173.     contexts[cur_context] = create_binary_context();
  174.     non_null_contexts++;
  175. }
  176. else 
  177. {   /* 
  178.      * determine closest existing context to current one
  179.      * by stripping off the leading bits of the context
  180.      * guaranteed to get contexts[0] if nothing closer
  181.      */
  182.     closest_context = cur_context;
  183.     j = 1;
  184.     do
  185.     {
  186. closest_context &= (mask >> j);
  187. j++;
  188.     } while (contexts[closest_context] == NULL);
  189.     contexts[cur_context] = contexts[closest_context];
  190. }
  191.     }
  192.     bit = binary_decode(contexts[cur_context]);
  193.     buffer = (buffer << 1) | bit;
  194.     cur_context = ((cur_context << 1) | bit) & mask;
  195. }     
  196. OUTPUT_BYTE(buffer);
  197.     }
  198.     finish_decode();
  199.     doneinputtingbits();
  200. }