dlib C++ Library - entropy_decoder_kernel_2.cpp

// 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_

AltStyle によって変換されたページ (->オリジナル) /