225 lines
6.0 KiB
C++
225 lines
6.0 KiB
C++
// 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_
|
|
|