📄 rangecoder.h
字号:
// Compress/RangeCoder/RangeCoder.h#ifndef __COMPRESS_RANGECODER_H#define __COMPRESS_RANGECODER_H#include "../../Common/InBuffer.h"#include "../../Common/OutBuffer.h"namespace NCompress {namespace NRangeCoder {const int kNumTopBits = 24;const UInt32 kTopValue = (1 << kNumTopBits);class CEncoder{ UInt64 Low; UInt32 Range; UInt32 _ffNum; Byte _cache;public: COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _ffNum = 0; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } /* void EncodeDirectBitsDiv(UInt32 value, UInt32 numTotalBits) { Low += value * (Range >>= numTotalBits); Normalize(); } void EncodeDirectBitsDiv2(UInt32 value, UInt32 numTotalBits) { if (numTotalBits <= kNumBottomBits) EncodeDirectBitsDiv(value, numTotalBits); else { EncodeDirectBitsDiv(value >> kNumBottomBits, (numTotalBits - kNumBottomBits)); EncodeDirectBitsDiv(value & ((1 << kBottomValueBits) - 1), kNumBottomBits); } } */ void ShiftLow() { if (Low < (UInt32)0xFF000000 || UInt32(Low >> 32) == 1) { Stream.WriteByte(Byte(_cache + Byte(Low >> 32))); for (;_ffNum != 0; _ffNum--) Stream.WriteByte(Byte(0xFF + Byte(Low >> 32))); _cache = Byte(UInt32(Low) >> 24); } else _ffNum++; Low = UInt32(Low) << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; //if (((value >> i) & 1) == 1) if (((value >> i) & 1) == 0) /* !!! */ Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; //if (symbol == 0) if (symbol != 0) /* !!! */ Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _ffNum; }};class CDecoder{public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } /* UInt32 DecodeDirectBitsDiv(UInt32 numTotalBits) { Range >>= numTotalBits; UInt32 threshold = Code / Range; Code -= threshold * Range; Normalize(); return threshold; } UInt32 DecodeDirectBitsDiv2(UInt32 numTotalBits) { if (numTotalBits <= kNumBottomBits) return DecodeDirectBitsDiv(numTotalBits); UInt32 result = DecodeDirectBitsDiv(numTotalBits - kNumBottomBits) << kNumBottomBits; return (result | DecodeDirectBitsDiv(kNumBottomBits)); } */ UInt32 DecodeDirectBits(UInt32 numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (UInt32 i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); // range = rangeTmp + ((range & 1) & (1 - t));// result = (result << 1) | (1 - t); result += result + t; /* !!! */ if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { //symbol = 0; symbol = 0^1; /* !!! */ Range = newBound; } else { //symbol = 1; symbol = 1^1; /* !!! */ Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }};}}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -