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