dcmjpls/libcharls/decodstr.h

00001 //
00002 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
00003 //
00004 
00005 #ifndef CHARLS_DECODERSTATEGY
00006 #define CHARLS_DECODERSTATEGY
00007 
00008 #include "streams.h"
00009 #include "procline.h"
00010 #include "config.h"
00011 #include "util.h"
00012 
00013 // Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy
00014 
00015 
00016 
00017 class DecoderStrategy
00018 {
00019 public:
00020     DecoderStrategy(const JlsParameters& info) :
00021           _info(info),
00022           _processLine(0),
00023           _readCache(0),
00024           _validBits(0),
00025           _position(0)
00026       {
00027       }
00028 
00029       virtual ~DecoderStrategy()
00030       {
00031       }
00032 
00033       virtual void SetPresets(const JlsCustomParameters& presets) = 0;
00034       virtual size_t DecodeScan(void* outputData, const JlsRect& size, const void* compressedData, size_t byteCount, bool bCheck) = 0;
00035 
00036       void Init(BYTE* compressedBytes, size_t byteCount)
00037       {
00038           _validBits = 0;
00039           _readCache = 0;
00040           _position = compressedBytes;
00041           _endPosition = compressedBytes + byteCount;
00042           _nextFFPosition = FindNextFF();
00043           MakeValid();
00044       }
00045 
00046       inlinehint void Skip(LONG length)
00047       {
00048           _validBits -= length;
00049           _readCache = _readCache << length;
00050       }
00051 
00052 
00053       void OnLineBegin(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/)
00054       {}
00055 
00056 
00057       void OnLineEnd(LONG pixelCount, const void* ptypeBuffer, LONG pixelStride)
00058       {
00059             _processLine->NewLineDecoded(ptypeBuffer, pixelCount, pixelStride);
00060       }
00061 
00062       void EndScan()
00063       {
00064           if ((*_position) != 0xFF)
00065           {
00066             ReadBit();
00067 
00068             if ((*_position) != 0xFF)
00069                 throw JlsException(TooMuchCompressedData);
00070           }
00071 
00072           if (_readCache != 0)
00073              throw JlsException(TooMuchCompressedData);
00074       }
00075 
00076 
00077       inlinehint bool OptimizedRead()
00078       {
00079           // Easy & fast: if there is no 0xFF byte in sight, we can read without bitstuffing
00080           if (_position < _nextFFPosition - (sizeof(bufType)-1))
00081           {
00082               _readCache         |= FromBigEndian<bufType>::Read(_position) >> _validBits;
00083               int bytesToRead = (bufferbits - _validBits) >> 3;
00084               _position += bytesToRead;
00085               _validBits += bytesToRead * 8;
00086               ASSERT(_validBits >= bufferbits - 8);
00087               return true;
00088           }
00089           return false;
00090       }
00091 
00092       typedef size_t bufType;
00093 
00094       enum {
00095           bufferbits = sizeof( bufType ) * 8
00096       };
00097 
00098       void MakeValid()
00099       {
00100           ASSERT(_validBits <=bufferbits - 8);
00101 
00102           if (OptimizedRead())
00103               return;
00104 
00105           do
00106           {
00107               if (_position >= _endPosition)
00108               {
00109                   if (_validBits <= 0)
00110                       throw JlsException(InvalidCompressedData);
00111 
00112                   return;
00113               }
00114 
00115               bufType valnew      = _position[0];
00116 
00117               if (valnew == 0xFF)
00118               {
00119                   // JPEG bitstream rule: no FF may be followed by 0x80 or higher
00120                  if (_position == _endPosition - 1 || (_position[1] & 0x80) != 0)
00121                  {
00122                      if (_validBits <= 0)
00123                         throw JlsException(InvalidCompressedData);
00124 
00125                      return;
00126                  }
00127               }
00128 
00129               _readCache         |= valnew << (bufferbits - 8  - _validBits);
00130               _position   += 1;
00131               _validBits         += 8;
00132 
00133               if (valnew == 0xFF)
00134               {
00135                   _validBits--;
00136               }
00137           }
00138           while (_validBits < bufferbits - 8);
00139 
00140           _nextFFPosition = FindNextFF();
00141           return;
00142 
00143       }
00144 
00145 
00146       BYTE* FindNextFF()
00147       {
00148           BYTE* pbyteNextFF = _position;
00149 
00150           while (pbyteNextFF < _endPosition)
00151           {
00152               if (*pbyteNextFF == 0xFF)
00153               {
00154                   break;
00155               }
00156               pbyteNextFF++;
00157           }
00158 
00159 
00160           return pbyteNextFF;
00161       }
00162 
00163 
00164       BYTE* GetCurBytePos() const
00165       {
00166           LONG  validBits = _validBits;
00167           BYTE* compressedBytes = _position;
00168 
00169           for (;;)
00170           {
00171               LONG cbitLast = compressedBytes[-1] == 0xFF ? 7 : 8;
00172 
00173               if (validBits < cbitLast )
00174                   return compressedBytes;
00175 
00176               validBits -= cbitLast;
00177               compressedBytes--;
00178           }
00179       }
00180 
00181 
00182       inlinehint LONG ReadValue(LONG length)
00183       {
00184           if (_validBits < length)
00185           {
00186               MakeValid();
00187               if (_validBits < length)
00188                   throw JlsException(InvalidCompressedData);
00189           }
00190 
00191           ASSERT(length != 0 && length <= _validBits);
00192           ASSERT(length < 32);
00193           LONG result = LONG(_readCache >> (bufferbits - length));
00194           Skip(length);
00195           return result;
00196       }
00197 
00198 
00199       inlinehint LONG PeekByte()
00200       {
00201           if (_validBits < 8)
00202           {
00203               MakeValid();
00204           }
00205 
00206           return _readCache >> (bufferbits - 8);
00207       }
00208 
00209 
00210 
00211       inlinehint bool ReadBit()
00212       {
00213           if (_validBits <= 0)
00214           {
00215               MakeValid();
00216           }
00217 
00218           bool bSet = (_readCache & (bufType(1) << (bufferbits - 1))) != 0;
00219           Skip(1);
00220           return bSet;
00221       }
00222 
00223 
00224 
00225       inlinehint LONG Peek0Bits()
00226       {
00227           if (_validBits < 16)
00228           {
00229               MakeValid();
00230           }
00231           bufType valTest = _readCache;
00232 
00233           for (LONG count = 0; count < 16; count++)
00234           {
00235               if ((valTest & (bufType(1) << (bufferbits - 1))) != 0)
00236                   return count;
00237 
00238               valTest <<= 1;
00239           }
00240           return -1;
00241       }
00242 
00243 
00244 
00245       inlinehint LONG ReadHighbits()
00246       {
00247           LONG count = Peek0Bits();
00248           if (count >= 0)
00249           {
00250               Skip(count + 1);
00251               return count;
00252           }
00253           Skip(15);
00254 
00255           for (LONG highbits = 15; ; highbits++)
00256           {
00257               if (ReadBit())
00258                   return highbits;
00259           }
00260       }
00261 
00262 
00263       LONG ReadLongValue(LONG length)
00264       {
00265           if (length <= 24)
00266               return ReadValue(length);
00267 
00268           return (ReadValue(length - 24) << 24) + ReadValue(24);
00269       }
00270 
00271 protected:
00272     JlsParameters _info;
00273     OFauto_ptr<ProcessLine> _processLine;
00274 
00275 private:
00276     // decoding
00277     bufType _readCache;
00278     LONG _validBits;
00279     BYTE* _position;
00280     BYTE* _nextFFPosition;
00281     BYTE* _endPosition;
00282 };
00283 
00284 
00285 #endif


Generated on 6 Jan 2011 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.5.1