// Copyright (C) 2004 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_ENTROPY_DECODER_KERNEL_2_CPp_ #define DLIB_ENTROPY_DECODER_KERNEL_2_CPp_ #include "entropy_decoder_kernel_2.h" #include <iostream> #include <streambuf> #include <sstream> #include "../assert.h" namespace dlib { // ---------------------------------------------------------------------------------------- entropy_decoder_kernel_2:: entropy_decoder_kernel_2( ) : initial_low(0x00000001), initial_high(0xffffffff), in(0), low(initial_low), high(initial_high), target(0x00000000), r(0) { } // ---------------------------------------------------------------------------------------- entropy_decoder_kernel_2:: ~entropy_decoder_kernel_2 ( ) { } // ---------------------------------------------------------------------------------------- void entropy_decoder_kernel_2:: clear( ) { in = 0; r = 0; low = initial_low; high = initial_high; target = 0x00000000; } // ---------------------------------------------------------------------------------------- void entropy_decoder_kernel_2:: set_stream ( std::istream& in_ ) { r = 0; low = initial_low; high = initial_high; target = 0x00000000; in = &in_; streambuf = in_.rdbuf(); unsigned char ch; streambuf->sgetn((char*)&ch,1); target = ch; target <<= 8; if (streambuf->sgetn((char*)&ch,1)) target += ch; target <<= 8; if (streambuf->sgetn((char*)&ch,1)) target += ch; target <<= 8; if (streambuf->sgetn((char*)&ch,1)) target += ch; } // ---------------------------------------------------------------------------------------- bool entropy_decoder_kernel_2:: stream_is_set ( ) const { if (in != 0) return true; else return false; } // ---------------------------------------------------------------------------------------- std::istream& entropy_decoder_kernel_2:: get_stream ( ) const { return *in; } // ---------------------------------------------------------------------------------------- void entropy_decoder_kernel_2:: decode ( uint32 low_count, uint32 high_count ) { // note that we must subtract 1 to preserve the convention that // high == the real upper range - 1 high = low + r*high_count - 1; low = low + r*low_count; r = 0; while (true ) { // if high and low don't have the same 8 high order bits if ((high&0xFF000000) != (low&0xFF000000)) { // if the distance between high and low is small and there aren't // any bits we can roll off then force high and low to have common high // order bits. if ((high-low < 0x10000)) { if (high-low > 0x1000) { high>>=1; low>>=1; high = low = high+low; high += 0xFF; low -= 0xFF; } else /**/ { high>>=1; low>>=1; high = low = high+low; } } else { // there are no bits to roll off and high and low are not // too close so just quit the loop break; } } // else if there are 8 bits we can roll off else { unsigned char buf; if (streambuf->sgetn(reinterpret_cast<char*>(&buf),1)==0) { // if there isn't anything else in the streambuffer then just // make buf zero. buf = 0; } // also roll off the bits in target target <<= 8; // roll off the bits high <<= 8; low <<= 8; high |= 0xFF; // note that it is ok to add 0xFF to high here because // of the convention that high == real upper range - 1. // so that means that if we want to shift the upper range // left by one then we must shift a one into high also // since real upper range == high + 0.999999999... // make sure low is never zero if (low == 0) low = 1; // put the new bits into target target |= static_cast<uint32>(buf); } } // while (true) } // ---------------------------------------------------------------------------------------- bool entropy_decoder_kernel_2:: get_target_called ( ) const { return (r != 0); } // ---------------------------------------------------------------------------------------- uint32 entropy_decoder_kernel_2:: get_target ( uint32 total ) { // note that we must add one because of the convention that // high == the real upper range minus 1 r = (high-low+1)/total; uint32 temp = (target-low)/r; if (temp < total) return temp; else return total-1; } // ---------------------------------------------------------------------------------------- } #endif // DLIB_ENTROPY_DECODER_KERNEL_2_CPp_