1 // Copyright (C) 2003 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_ENTROPY_DECODER_KERNEL_1_CPp_ 4 #define DLIB_ENTROPY_DECODER_KERNEL_1_CPp_ 5 #include "entropy_decoder_kernel_1.h" 6 #include <iostream> 7 #include <streambuf> 8 #include <sstream> 9 10 #include "../assert.h" 11 12 namespace dlib 13 { 14 15 // ---------------------------------------------------------------------------------------- 16 17 entropy_decoder_kernel_1:: entropy_decoder_kernel_1()18 entropy_decoder_kernel_1( 19 ) : 20 initial_low(0x00000001), 21 initial_high(0xffffffff), 22 in(0), 23 low(initial_low), 24 high(initial_high), 25 buf(0), 26 buf_used(0), 27 target(0x00000000), 28 r(0) 29 { 30 } 31 32 // ---------------------------------------------------------------------------------------- 33 34 entropy_decoder_kernel_1:: ~entropy_decoder_kernel_1()35 ~entropy_decoder_kernel_1 ( 36 ) 37 { 38 } 39 40 // ---------------------------------------------------------------------------------------- 41 42 void entropy_decoder_kernel_1:: clear()43 clear( 44 ) 45 { 46 in = 0; 47 buf_used = 0; 48 buf = 0; 49 r = 0; 50 low = initial_low; 51 high = initial_high; 52 target = 0x00000000; 53 } 54 55 // ---------------------------------------------------------------------------------------- 56 57 void entropy_decoder_kernel_1:: set_stream(std::istream & in_)58 set_stream ( 59 std::istream& in_ 60 ) 61 { 62 buf_used = 0; 63 buf = 0; 64 r = 0; 65 low = initial_low; 66 high = initial_high; 67 target = 0x00000000; 68 69 in = &in_; 70 streambuf = in_.rdbuf(); 71 72 73 74 unsigned char ch; 75 76 77 streambuf->sgetn((char*)&ch,1); 78 target = ch; 79 80 target <<= 8; 81 if (streambuf->sgetn((char*)&ch,1)) 82 target += ch; 83 84 85 target <<= 8; 86 if (streambuf->sgetn((char*)&ch,1)) 87 target += ch; 88 89 90 target <<= 8; 91 if (streambuf->sgetn((char*)&ch,1)) 92 target += ch; 93 94 } 95 96 // ---------------------------------------------------------------------------------------- 97 98 bool entropy_decoder_kernel_1:: stream_is_set() const99 stream_is_set ( 100 ) const 101 { 102 if (in != 0) 103 return true; 104 else 105 return false; 106 } 107 108 // ---------------------------------------------------------------------------------------- 109 110 std::istream& entropy_decoder_kernel_1:: get_stream() const111 get_stream ( 112 ) const 113 { 114 return *in; 115 } 116 117 // ---------------------------------------------------------------------------------------- 118 119 void entropy_decoder_kernel_1:: decode(uint32 low_count,uint32 high_count)120 decode ( 121 uint32 low_count, 122 uint32 high_count 123 ) 124 { 125 // note that we must subtract 1 to preserve the convention that 126 // high == the real upper range - 1 127 high = low + r*high_count - 1; 128 low = low + r*low_count; 129 r = 0; 130 131 132 133 while (true) 134 { 135 136 // if the highest order bit in high and low is the same 137 if ( low >= 0x80000000 || high < 0x80000000) 138 { 139 // make sure buf isn't empty 140 if (buf_used == 0) 141 { 142 buf_used = 8; 143 if (streambuf->sgetn(reinterpret_cast<char*>(&buf),1)==0) 144 { 145 // if there isn't anything else in the streambuffer then just 146 // make buf zero. 147 buf = 0; 148 } 149 } 150 151 // we will be taking one bit from buf to replace the one we threw away 152 --buf_used; 153 154 // roll off the bit in target 155 target <<= 1; 156 157 // roll off the bit 158 high <<= 1; 159 low <<= 1; 160 high |= 1; // note that it is ok to add one to high here because 161 // of the convention that high == real upper range - 1. 162 // so that means that if we want to shift the upper range 163 // left by one then we must shift a one into high also 164 // since real upper range == high + 0.999999999... 165 166 // make sure low is never zero 167 if (low == 0) 168 low = 1; 169 170 // take a bit from buf to fill in the one we threw away 171 target += (buf>>buf_used)&0x01; 172 } 173 // if the distance between high and low is small and there aren't 174 // any bits we can roll off then round low up or high down. 175 else if (high-low < 0x10000) 176 { 177 if (high == 0x80000000) 178 high = 0x7fffffff; 179 else 180 low = 0x80000000; 181 } 182 else 183 { 184 break; 185 } 186 } // while (true) 187 188 } 189 190 // ---------------------------------------------------------------------------------------- 191 192 bool entropy_decoder_kernel_1:: get_target_called() const193 get_target_called ( 194 ) const 195 { 196 return (r != 0); 197 } 198 199 // ---------------------------------------------------------------------------------------- 200 201 uint32 entropy_decoder_kernel_1:: get_target(uint32 total)202 get_target ( 203 uint32 total 204 ) 205 { 206 // note that we must add one because of the convention that 207 // high == the real upper range minus 1 208 r = (high-low+1)/total; 209 uint32 temp = (target-low)/r; 210 if (temp < total) 211 return temp; 212 else 213 return total-1; 214 } 215 216 // ---------------------------------------------------------------------------------------- 217 218 } 219 #endif // DLIB_ENTROPY_DECODER_KERNEL_1_CPp_ 220 221