// Copyright (C) 2003 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_ENTROPY_DECODER_KERNEL_1_CPp_ #define DLIB_ENTROPY_DECODER_KERNEL_1_CPp_ #include "entropy_decoder_kernel_1.h" #include <iostream> #include <streambuf> #include <sstream> #include "../assert.h" namespace dlib { // ---------------------------------------------------------------------------------------- entropy_decoder_kernel_1:: entropy_decoder_kernel_1( ) : initial_low(0x00000001), initial_high(0xffffffff), in(0), low(initial_low), high(initial_high), buf(0), buf_used(0), target(0x00000000), r(0) { } // ---------------------------------------------------------------------------------------- entropy_decoder_kernel_1:: ~entropy_decoder_kernel_1 ( ) { } // ---------------------------------------------------------------------------------------- void entropy_decoder_kernel_1:: clear( ) { in = 0; buf_used = 0; buf = 0; r = 0; low = initial_low; high = initial_high; target = 0x00000000; } // ---------------------------------------------------------------------------------------- void entropy_decoder_kernel_1:: set_stream ( std::istream& in_ ) { buf_used = 0; buf = 0; 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_1:: stream_is_set ( ) const { if (in != 0) return true; else return false; } // ---------------------------------------------------------------------------------------- std::istream& entropy_decoder_kernel_1:: get_stream ( ) const { return *in; } // ---------------------------------------------------------------------------------------- void entropy_decoder_kernel_1:: 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 the highest order bit in high and low is the same if ( low >= 0x80000000 || high < 0x80000000) { // make sure buf isn't empty if (buf_used == 0) { buf_used = 8; 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; } } // we will be taking one bit from buf to replace the one we threw away --buf_used; // roll off the bit in target target <<= 1; // roll off the bit high <<= 1; low <<= 1; high |= 1; // note that it is ok to add one 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; // take a bit from buf to fill in the one we threw away target += (buf>>buf_used)&0x01; } // if the distance between high and low is small and there aren't // any bits we can roll off then round low up or high down. else if (high-low < 0x10000) { if (high == 0x80000000) high = 0x7fffffff; else low = 0x80000000; } else { break; } } // while (true) } // ---------------------------------------------------------------------------------------- bool entropy_decoder_kernel_1:: get_target_called ( ) const { return (r != 0); } // ---------------------------------------------------------------------------------------- uint32 entropy_decoder_kernel_1:: 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_1_CPp_