Advertisement
alexx876

Untitled

Dec 6th, 2018
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.17 KB | None | 0 0
  1. /*
  2.  arith_adapt.cpp
  3.  Адаптивное арифметическое кодирование.
  4.  Демонстративная программа.
  5.  Использование:
  6.    arith_adapt e(ncode)|d(ecode) infile outfile
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <process.h>
  11.  
  12. // Количество битов в регистре
  13. #define BITS_IN_REGISTER 16
  14.  
  15. // Максимально возможное значение в регистре
  16. #define TOP_VALUE (((long) 1 << BITS_IN_REGISTER) - 1)
  17.  
  18. // Диапазоны
  19. #define FIRST_QTR (TOP_VALUE / 4 + 1)
  20. #define HALF (2 * FIRST_QTR)
  21. #define THIRD_QTR (3 * FIRST_QTR)
  22.  
  23. // Количество символов алфавита
  24. #define NO_OF_CHARS 256
  25. // Специальный символ КонецФайла
  26. #define EOF_SYMBOL    (NO_OF_CHARS + 1)
  27. // Всего символов в модели
  28. #define NO_OF_SYMBOLS (NO_OF_CHARS + 1)
  29.  
  30. // Порог частоты для масштабирования
  31. #define MAX_FREQUENCY 16383
  32.  
  33. // Таблицы перекодировки
  34. unsigned char index_to_char[NO_OF_SYMBOLS];
  35. int char_to_index[NO_OF_CHARS];
  36.  
  37. // Таблицы частот
  38. int cum_freq[NO_OF_SYMBOLS + 1];
  39. int freq[NO_OF_SYMBOLS + 1];
  40.  
  41. // Регистры границ и кода
  42. long low, high;
  43. long value;
  44.  
  45. // Поддержка побитлвых операций с файлами
  46. long bits_to_follow;
  47. int buffer;
  48. int bits_to_go;
  49. int garbage_bits;
  50.  
  51. // Обрабатываемые файлы
  52. FILE *in, *out;
  53.  
  54. //------------------------------------------------------------
  55. // Инициализация адаптивной модели
  56. void start_model(void)
  57. {
  58.     int i;
  59.  
  60.     for (i = 0; i < NO_OF_CHARS; i++)
  61.     {
  62.         char_to_index[i] = i + 1;
  63.         index_to_char[i + 1] = i;
  64.     }
  65.     for (i = 0; i <= NO_OF_SYMBOLS; i++)
  66.     {
  67.         freq[i] = 1;
  68.         cum_freq[i] = NO_OF_SYMBOLS - i;
  69.     }
  70.     freq[0] = 0;
  71. }
  72.  
  73. //------------------------------------------------------------
  74. // Обновление модели очередным символом
  75. void update_model(int symbol)
  76. {
  77.     int i;
  78.     int ch_i, ch_symbol;
  79.     int cum;
  80.  
  81.     // проверка на переполнение счетчика частоты
  82.     if (cum_freq[0] == MAX_FREQUENCY)
  83.     {
  84.         cum = 0;
  85.         // масштабирование частот при переполнении
  86.         for (i = NO_OF_SYMBOLS; i >= 0; i--)
  87.         {
  88.             freq[i] = (freq[i] + 1) / 2;
  89.             cum_freq[i] = cum;
  90.             cum += freq[i];
  91.         }
  92.     }
  93.  
  94.     for (i = symbol; freq[i] == freq[i - 1]; i--);
  95.     if (i < symbol)
  96.     {
  97.         ch_i = index_to_char[i];
  98.         ch_symbol = index_to_char[symbol];
  99.         index_to_char[i] = ch_symbol;
  100.         index_to_char[symbol] = ch_i;
  101.         char_to_index[ch_i] = symbol;
  102.         char_to_index[ch_symbol] = i;
  103.     }
  104.  
  105.     // обновление значений в таблицах частот
  106.     freq[i] += 1;
  107.     while (i > 0)
  108.     {
  109.         i -= 1;
  110.         cum_freq[i] += 1;
  111.     }
  112. }
  113.  
  114. //------------------------------------------------------------
  115. // Инициализация побитового ввода
  116. void start_inputing_bits(void)
  117. {
  118.     bits_to_go = 0;
  119.     garbage_bits = 0;
  120. }
  121.  
  122. //------------------------------------------------------------
  123. // Ввод очередного бита сжатой информации
  124. int input_bit(void)
  125. {
  126.     int t;
  127.  
  128.     if (bits_to_go == 0)
  129.     {
  130.         buffer = getc(in);
  131.         if (buffer == EOF)
  132.         {
  133.             garbage_bits += 1;
  134.             if (garbage_bits > BITS_IN_REGISTER - 2)
  135.             {
  136.                 printf("Ошибка в сжатом файле\n");
  137.                 exit(-1);
  138.             }
  139.         }
  140.         bits_to_go = 8;
  141.     }
  142.     t = buffer & 1;
  143.     buffer >>= 1;
  144.     bits_to_go -= 1;
  145.     return t;
  146. }
  147.  
  148. //------------------------------------------------------------
  149. // Инициализация побитового вывода
  150. void start_outputing_bits(void)
  151. {
  152.     buffer = 0;
  153.     bits_to_go = 8;
  154. }
  155.  
  156. //------------------------------------------------------------
  157. // Вывод очередного бита сжатой информации
  158. void output_bit(int bit)
  159. {
  160.     buffer >>= 1;
  161.     if (bit)
  162.         buffer |= 0x80;
  163.     bits_to_go -= 1;
  164.     if (bits_to_go == 0)
  165.     {
  166.         putc(buffer, out);
  167.         bits_to_go = 8;
  168.     }
  169. }
  170.  
  171. //------------------------------------------------------------
  172. // Очистка буфера побитового вывода
  173. void done_outputing_bits(void)
  174. {
  175.     putc(buffer >> bits_to_go, out);
  176. }
  177.  
  178. //------------------------------------------------------------
  179. // Вывод указанного бита и отложенных ранее
  180. void output_bit_plus_follow(int bit)
  181. {
  182.     output_bit(bit);
  183.     while (bits_to_follow > 0)
  184.     {
  185.         output_bit(!bit);
  186.         bits_to_follow--;
  187.     }
  188. }
  189.  
  190. //------------------------------------------------------------
  191. // Инициализация регистров границ и кода перед началом сжатия
  192. void start_encoding(void)
  193. {
  194.     low = 0l;
  195.     high = TOP_VALUE;
  196.     bits_to_follow = 0l;
  197. }
  198.  
  199. //------------------------------------------------------------
  200. // Очистка побитового вывода
  201. void done_encoding(void)
  202. {
  203.     bits_to_follow++;
  204.     if (low < FIRST_QTR)
  205.         output_bit_plus_follow(0);
  206.     else
  207.         output_bit_plus_follow(1);
  208. }
  209.  
  210. //------------------------------------------------------------
  211. /* Инициализация регистров перед декодированием.
  212.    Загрузка начала сжатого сообщения
  213. */
  214. void start_decoding(void)
  215. {
  216.     int i;
  217.  
  218.     value = 0l;
  219.     for (i = 1; i <= BITS_IN_REGISTER; i++)
  220.         value = 2 * value + input_bit();
  221.     low = 0l;
  222.     high = TOP_VALUE;
  223. }
  224.  
  225. //------------------------------------------------------------
  226. // Кодирование очередного символа
  227. void encode_symbol(int symbol)
  228. {
  229.     long range;
  230.  
  231.     // пересчет значений границ
  232.     range = (long)(high - low) + 1;
  233.     high = low + (range * cum_freq[symbol - 1]) / cum_freq[0] - 1;
  234.     low = low + (range * cum_freq[symbol]) / cum_freq[0];
  235.     // выдвигание очередных битов
  236.     for (;;)
  237.     {
  238.         if (high < HALF)
  239.             output_bit_plus_follow(0);
  240.         else if (low >= HALF)
  241.         {
  242.             output_bit_plus_follow(1);
  243.             low -= HALF;
  244.             high -= HALF;
  245.         }
  246.         else if (low >= FIRST_QTR && high < THIRD_QTR)
  247.         {
  248.             bits_to_follow += 1;
  249.             low -= FIRST_QTR;
  250.             high -= FIRST_QTR;
  251.         }
  252.         else
  253.             break;
  254.         // сдвиг влево с "втягиванием" очередного бита
  255.         low = 2 * low;
  256.         high = 2 * high + 1;
  257.     }
  258. }
  259.  
  260. //------------------------------------------------------------
  261. // Декодирование очередного символа
  262. int decode_symbol(void)
  263. {
  264.     long range;
  265.     int cum, symbol;
  266.  
  267.     // определение текущего масштаба частот
  268.     range = (long)(high - low) + 1;
  269.     // масштабирование значения в регистре кода
  270.     cum = (int)
  271.         ((((long)(value - low) + 1) * cum_freq[0] - 1) / range);
  272.     // поиск соответствующего символа в таблице частот
  273.     for (symbol = 1; cum_freq[symbol] > cum; symbol++);
  274.     // пересчет границ
  275.     high = low + (range * cum_freq[symbol - 1]) / cum_freq[0] - 1;
  276.     low = low + (range * cum_freq[symbol]) / cum_freq[0];
  277.     // удаление очередного символа из входного потока
  278.     for (;;)
  279.     {
  280.         if (high < HALF)
  281.         {
  282.         }
  283.         else if (low >= HALF)
  284.         {
  285.             value -= HALF;
  286.             low -= HALF;
  287.             high -= HALF;
  288.         }
  289.         else if (low >= FIRST_QTR && high < THIRD_QTR)
  290.         {
  291.             value -= FIRST_QTR;
  292.             low -= FIRST_QTR;
  293.             high -= FIRST_QTR;
  294.         }
  295.         else
  296.             break;
  297.         // сдвиг влево с "втягиванием очередного бита
  298.         low = 2 * low;
  299.         high = 2 * high + 1;
  300.         value = 2 * value + input_bit();
  301.     }
  302.     return symbol;
  303. }
  304.  
  305. //------------------------------------------------------------
  306. // Собственно адаптивное арифметическое кодирование
  307. void encode(char *infile, char *outfile)
  308. {
  309.     int ch, symbol;
  310.  
  311.     in = fopen(infile, "rb");
  312.     out = fopen(outfile, "wb");
  313.     if (in == NULL || out == NULL)
  314.         return;
  315.     start_model();
  316.     start_outputing_bits();
  317.     start_encoding();
  318.     for (;;)
  319.     {
  320.         ch = getc(in);
  321.         if (ch == EOF)
  322.             break;
  323.         symbol = char_to_index[ch];
  324.         encode_symbol(symbol);
  325.         update_model(symbol);
  326.     }
  327.     encode_symbol(EOF_SYMBOL);
  328.     done_encoding();
  329.     done_outputing_bits();
  330.     fclose(in);
  331.     fclose(out);
  332. }
  333.  
  334. //------------------------------------------------------------
  335. // Собственно адаптивное арифметическое декодирование
  336. void decode(char *infile, char *outfile)
  337. {
  338.     int ch, symbol;
  339.  
  340.     in = fopen(infile, "rb");
  341.     out = fopen(outfile, "wb");
  342.     if (in == NULL || out == NULL)
  343.         return;
  344.     start_model();
  345.     start_inputing_bits();
  346.     start_decoding();
  347.     for (;;)
  348.     {
  349.         symbol = decode_symbol();
  350.         if (symbol == EOF_SYMBOL)
  351.             break;
  352.         ch = index_to_char[symbol];
  353.         putc(ch, out);
  354.         update_model(symbol);
  355.     }
  356.     fclose(in);
  357.     fclose(out);
  358. }
  359.  
  360. //------------------------------------------------------------
  361. // Головная процедура
  362. int main(int argc, char * argv[])
  363. {
  364.     if (argc < 4)
  365.     {
  366.         printf("\n Using: Arith_adapt e|d infile outfile\n");
  367.         exit(0);
  368.     }
  369.     if (argv[1][0] == 'e')
  370.         encode(argv[2], argv[3]);
  371.     else if (argv[1][0] == 'd')
  372.         decode(argv[2], argv[3]);
  373.     exit(0);
  374.  
  375.     return 0;
  376. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement