OFFIS DCMTK  Version 3.6.0
decodstr.h
1 //
2 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
3 //
4 
5 #ifndef CHARLS_DECODERSTATEGY
6 #define CHARLS_DECODERSTATEGY
7 
8 #include "streams.h"
9 #include "procline.h"
10 #include "config.h"
11 #include "util.h"
12 
13 // Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy
14 
15 
16 
18 {
19 public:
20  DecoderStrategy(const JlsParameters& info) :
21  _info(info),
22  _processLine(0),
23  _readCache(0),
24  _validBits(0),
25  _position(0)
26  {
27  }
28 
29  virtual ~DecoderStrategy()
30  {
31  }
32 
33  virtual void SetPresets(const JlsCustomParameters& presets) = 0;
34  virtual size_t DecodeScan(void* outputData, const JlsRect& size, const void* compressedData, size_t byteCount, bool bCheck) = 0;
35 
36  void Init(BYTE* compressedBytes, size_t byteCount)
37  {
38  _validBits = 0;
39  _readCache = 0;
40  _position = compressedBytes;
41  _endPosition = compressedBytes + byteCount;
42  _nextFFPosition = FindNextFF();
43  MakeValid();
44  }
45 
46  inlinehint void Skip(LONG length)
47  {
48  _validBits -= length;
49  _readCache = _readCache << length;
50  }
51 
52 
53  void OnLineBegin(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/)
54  {}
55 
56 
57  void OnLineEnd(LONG pixelCount, const void* ptypeBuffer, LONG pixelStride)
58  {
59  _processLine->NewLineDecoded(ptypeBuffer, pixelCount, pixelStride);
60  }
61 
62  void EndScan()
63  {
64  if ((*_position) != 0xFF)
65  {
66  ReadBit();
67 
68  if ((*_position) != 0xFF)
69  throw JlsException(TooMuchCompressedData);
70  }
71 
72  if (_readCache != 0)
73  throw JlsException(TooMuchCompressedData);
74  }
75 
76 
77  inlinehint bool OptimizedRead()
78  {
79  // Easy & fast: if there is no 0xFF byte in sight, we can read without bitstuffing
80  if (_position < _nextFFPosition - (sizeof(bufType)-1))
81  {
82  _readCache |= FromBigEndian<bufType>::Read(_position) >> _validBits;
83  int bytesToRead = (bufferbits - _validBits) >> 3;
84  _position += bytesToRead;
85  _validBits += bytesToRead * 8;
86  ASSERT(_validBits >= bufferbits - 8);
87  return true;
88  }
89  return false;
90  }
91 
92  typedef size_t bufType;
93 
94  enum {
95  bufferbits = sizeof( bufType ) * 8
96  };
97 
98  void MakeValid()
99  {
100  ASSERT(_validBits <=bufferbits - 8);
101 
102  if (OptimizedRead())
103  return;
104 
105  do
106  {
107  if (_position >= _endPosition)
108  {
109  if (_validBits <= 0)
110  throw JlsException(InvalidCompressedData);
111 
112  return;
113  }
114 
115  bufType valnew = _position[0];
116 
117  if (valnew == 0xFF)
118  {
119  // JPEG bitstream rule: no FF may be followed by 0x80 or higher
120  if (_position == _endPosition - 1 || (_position[1] & 0x80) != 0)
121  {
122  if (_validBits <= 0)
123  throw JlsException(InvalidCompressedData);
124 
125  return;
126  }
127  }
128 
129  _readCache |= valnew << (bufferbits - 8 - _validBits);
130  _position += 1;
131  _validBits += 8;
132 
133  if (valnew == 0xFF)
134  {
135  _validBits--;
136  }
137  }
138  while (_validBits < bufferbits - 8);
139 
140  _nextFFPosition = FindNextFF();
141  return;
142 
143  }
144 
145 
146  BYTE* FindNextFF()
147  {
148  BYTE* pbyteNextFF = _position;
149 
150  while (pbyteNextFF < _endPosition)
151  {
152  if (*pbyteNextFF == 0xFF)
153  {
154  break;
155  }
156  pbyteNextFF++;
157  }
158 
159 
160  return pbyteNextFF;
161  }
162 
163 
164  BYTE* GetCurBytePos() const
165  {
166  LONG validBits = _validBits;
167  BYTE* compressedBytes = _position;
168 
169  for (;;)
170  {
171  LONG cbitLast = compressedBytes[-1] == 0xFF ? 7 : 8;
172 
173  if (validBits < cbitLast )
174  return compressedBytes;
175 
176  validBits -= cbitLast;
177  compressedBytes--;
178  }
179  }
180 
181 
182  inlinehint LONG ReadValue(LONG length)
183  {
184  if (_validBits < length)
185  {
186  MakeValid();
187  if (_validBits < length)
188  throw JlsException(InvalidCompressedData);
189  }
190 
191  ASSERT(length != 0 && length <= _validBits);
192  ASSERT(length < 32);
193  LONG result = LONG(_readCache >> (bufferbits - length));
194  Skip(length);
195  return result;
196  }
197 
198 
199  inlinehint LONG PeekByte()
200  {
201  if (_validBits < 8)
202  {
203  MakeValid();
204  }
205 
206  return _readCache >> (bufferbits - 8);
207  }
208 
209 
210 
211  inlinehint bool ReadBit()
212  {
213  if (_validBits <= 0)
214  {
215  MakeValid();
216  }
217 
218  bool bSet = (_readCache & (bufType(1) << (bufferbits - 1))) != 0;
219  Skip(1);
220  return bSet;
221  }
222 
223 
224 
225  inlinehint LONG Peek0Bits()
226  {
227  if (_validBits < 16)
228  {
229  MakeValid();
230  }
231  bufType valTest = _readCache;
232 
233  for (LONG count = 0; count < 16; count++)
234  {
235  if ((valTest & (bufType(1) << (bufferbits - 1))) != 0)
236  return count;
237 
238  valTest <<= 1;
239  }
240  return -1;
241  }
242 
243 
244 
245  inlinehint LONG ReadHighbits()
246  {
247  LONG count = Peek0Bits();
248  if (count >= 0)
249  {
250  Skip(count + 1);
251  return count;
252  }
253  Skip(15);
254 
255  for (LONG highbits = 15; ; highbits++)
256  {
257  if (ReadBit())
258  return highbits;
259  }
260  }
261 
262 
263  LONG ReadLongValue(LONG length)
264  {
265  if (length <= 24)
266  return ReadValue(length);
267 
268  return (ReadValue(length - 24) << 24) + ReadValue(24);
269  }
270 
271 protected:
272  JlsParameters _info;
273  OFauto_ptr<ProcessLine> _processLine;
274 
275 private:
276  // decoding
277  bufType _readCache;
278  LONG _validBits;
279  BYTE* _position;
280  BYTE* _nextFFPosition;
281  BYTE* _endPosition;
282 };
283 
284 
285 #endif


Generated on Thu Dec 20 2012 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.8.2