RangeCoder.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Compress/RangeCoder/RangeCoder.h
  2. #ifndef __COMPRESS_RANGECODER_H
  3. #define __COMPRESS_RANGECODER_H
  4. #include "../../Common/InBuffer.h"
  5. #include "../../Common/OutBuffer.h"
  6. namespace NCompress {
  7. namespace NRangeCoder {
  8. const int kNumTopBits = 24;
  9. const UInt32 kTopValue = (1 << kNumTopBits);
  10. class CEncoder
  11. {
  12. UInt32 _cacheSize;
  13. Byte _cache;
  14. public:
  15. UInt64 Low;
  16. UInt32 Range;
  17. COutBuffer Stream;
  18. bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
  19. void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
  20. void Init()
  21. {
  22. Stream.Init();
  23. Low = 0;
  24. Range = 0xFFFFFFFF;
  25. _cacheSize = 1;
  26. _cache = 0;
  27. }
  28. void FlushData()
  29. {
  30. // Low += 1;
  31. for(int i = 0; i < 5; i++)
  32. ShiftLow();
  33. }
  34. HRESULT FlushStream() { return Stream.Flush(); }
  35. void ReleaseStream() { Stream.ReleaseStream(); }
  36. void Encode(UInt32 start, UInt32 size, UInt32 total)
  37. {
  38. Low += start * (Range /= total);
  39. Range *= size;
  40. while (Range < kTopValue)
  41. {
  42. Range <<= 8;
  43. ShiftLow();
  44. }
  45. }
  46. void ShiftLow()
  47. {
  48. if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)
  49. {
  50. Byte temp = _cache;
  51. do
  52. {
  53. Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
  54. temp = 0xFF;
  55. }
  56. while(--_cacheSize != 0);
  57. _cache = (Byte)((UInt32)Low >> 24);
  58. }
  59. _cacheSize++;
  60. Low = (UInt32)Low << 8;
  61. }
  62. void EncodeDirectBits(UInt32 value, int numTotalBits)
  63. {
  64. for (int i = numTotalBits - 1; i >= 0; i--)
  65. {
  66. Range >>= 1;
  67. if (((value >> i) & 1) == 1)
  68. Low += Range;
  69. if (Range < kTopValue)
  70. {
  71. Range <<= 8;
  72. ShiftLow();
  73. }
  74. }
  75. }
  76. void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
  77. {
  78. UInt32 newBound = (Range >> numTotalBits) * size0;
  79. if (symbol == 0)
  80. Range = newBound;
  81. else
  82. {
  83. Low += newBound;
  84. Range -= newBound;
  85. }
  86. while (Range < kTopValue)
  87. {
  88. Range <<= 8;
  89. ShiftLow();
  90. }
  91. }
  92. UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
  93. };
  94. class CDecoder
  95. {
  96. public:
  97. CInBuffer Stream;
  98. UInt32 Range;
  99. UInt32 Code;
  100. bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
  101. void Normalize()
  102. {
  103. while (Range < kTopValue)
  104. {
  105. Code = (Code << 8) | Stream.ReadByte();
  106. Range <<= 8;
  107. }
  108. }
  109. void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
  110. void Init()
  111. {
  112. Stream.Init();
  113. Code = 0;
  114. Range = 0xFFFFFFFF;
  115. for(int i = 0; i < 5; i++)
  116. Code = (Code << 8) | Stream.ReadByte();
  117. }
  118. void ReleaseStream() { Stream.ReleaseStream(); }
  119. UInt32 GetThreshold(UInt32 total)
  120. {
  121. return (Code) / ( Range /= total);
  122. }
  123. void Decode(UInt32 start, UInt32 size)
  124. {
  125. Code -= start * Range;
  126. Range *= size;
  127. Normalize();
  128. }
  129. UInt32 DecodeDirectBits(int numTotalBits)
  130. {
  131. UInt32 range = Range;
  132. UInt32 code = Code;
  133. UInt32 result = 0;
  134. for (int i = numTotalBits; i != 0; i--)
  135. {
  136. range >>= 1;
  137. /*
  138. result <<= 1;
  139. if (code >= range)
  140. {
  141. code -= range;
  142. result |= 1;
  143. }
  144. */
  145. UInt32 t = (code - range) >> 31;
  146. code -= range & (t - 1);
  147. result = (result << 1) | (1 - t);
  148. if (range < kTopValue)
  149. {
  150. code = (code << 8) | Stream.ReadByte();
  151. range <<= 8;
  152. }
  153. }
  154. Range = range;
  155. Code = code;
  156. return result;
  157. }
  158. UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
  159. {
  160. UInt32 newBound = (Range >> numTotalBits) * size0;
  161. UInt32 symbol;
  162. if (Code < newBound)
  163. {
  164. symbol = 0;
  165. Range = newBound;
  166. }
  167. else
  168. {
  169. symbol = 1;
  170. Code -= newBound;
  171. Range -= newBound;
  172. }
  173. Normalize();
  174. return symbol;
  175. }
  176. UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
  177. };
  178. }}
  179. #endif