dlib C++ Library - entropy_decoder_kernel_1.cpp

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

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