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