LightweightCompression.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idLib/precompiled.h"
  22. #include "LightweightCompression.h"
  23. /*
  24. ========================
  25. HashIndex
  26. ========================
  27. */
  28. static int HashIndex( int w, int k ) {
  29. return ( w ^ k ) & idLZWCompressor::HASH_MASK;
  30. }
  31. /*
  32. ========================
  33. idLZWCompressor::Start
  34. ========================
  35. */
  36. void idLZWCompressor::Start( uint8 * data_, int maxSize_, bool append ) {
  37. // Clear hash
  38. ClearHash();
  39. if ( append ) {
  40. assert( lzwData->nextCode > LZW_FIRST_CODE );
  41. int originalNextCode = lzwData->nextCode;
  42. lzwData->nextCode = LZW_FIRST_CODE;
  43. // If we are appending, then fill up the hash
  44. for ( int i = LZW_FIRST_CODE; i < originalNextCode; i++ ) {
  45. AddToDict( lzwData->dictionaryW[i], lzwData->dictionaryK[i] );
  46. }
  47. assert( originalNextCode == lzwData->nextCode );
  48. } else {
  49. for ( int i = 0; i < LZW_FIRST_CODE; i++ ) {
  50. lzwData->dictionaryK[i] = (uint8)i;
  51. lzwData->dictionaryW[i] = 0xFFFF;
  52. }
  53. lzwData->nextCode = LZW_FIRST_CODE;
  54. lzwData->codeBits = LZW_START_BITS;
  55. lzwData->codeWord = -1;
  56. lzwData->tempValue = 0;
  57. lzwData->tempBits = 0;
  58. lzwData->bytesWritten = 0;
  59. }
  60. oldCode = -1; // Used by DecompressBlock
  61. data = data_;
  62. blockSize = 0;
  63. blockIndex = 0;
  64. bytesRead = 0;
  65. maxSize = maxSize_;
  66. overflowed = false;
  67. savedBytesWritten = 0;
  68. savedCodeWord = 0;
  69. saveCodeBits = 0;
  70. savedTempValue = 0;
  71. savedTempBits = 0;
  72. }
  73. /*
  74. ========================
  75. idLZWCompressor::ReadBits
  76. ========================
  77. */
  78. int idLZWCompressor::ReadBits( int bits ) {
  79. int bitsToRead = bits - lzwData->tempBits;
  80. while ( bitsToRead > 0 ) {
  81. if ( bytesRead >= maxSize ) {
  82. return -1;
  83. }
  84. lzwData->tempValue |= (uint64)data[bytesRead++] << lzwData->tempBits;
  85. lzwData->tempBits += 8;
  86. bitsToRead -= 8;
  87. }
  88. int value = (int)lzwData->tempValue & ( ( 1 << bits ) - 1 );
  89. lzwData->tempValue >>= bits;
  90. lzwData->tempBits -= bits;
  91. return value;
  92. }
  93. /*
  94. ========================
  95. idLZWCompressor::WriteBits
  96. ========================
  97. */
  98. void idLZWCompressor::WriteBits( uint32 value, int bits ) {
  99. // Queue up bits into temp value
  100. lzwData->tempValue |= (uint64)value << lzwData->tempBits;
  101. lzwData->tempBits += bits;
  102. // Flush 8 bits (1 byte) at a time ( leftovers will get caught in idLZWCompressor::End() )
  103. while ( lzwData->tempBits >= 8 ) {
  104. if ( lzwData->bytesWritten >= maxSize ) {
  105. overflowed = true;
  106. return;
  107. }
  108. data[lzwData->bytesWritten++] = (uint8)( lzwData->tempValue & 255 );
  109. lzwData->tempValue >>= 8;
  110. lzwData->tempBits -= 8;
  111. }
  112. }
  113. /*
  114. ========================
  115. idLZWCompressor::WriteChain
  116. The chain is stored backwards, so we have to write it to a buffer then output the buffer in
  117. reverse.
  118. ========================
  119. */
  120. int idLZWCompressor::WriteChain( int code ) {
  121. byte chain[lzwCompressionData_t::LZW_DICT_SIZE];
  122. int firstChar = 0;
  123. int i = 0;
  124. do {
  125. assert( i < lzwCompressionData_t::LZW_DICT_SIZE && code < lzwCompressionData_t::LZW_DICT_SIZE && code >= 0 );
  126. chain[i++] = (byte)lzwData->dictionaryK[code];
  127. code = lzwData->dictionaryW[code];
  128. } while ( code != 0xFFFF );
  129. firstChar = chain[--i];
  130. for ( ; i >= 0; i-- ) {
  131. block[blockSize++] = chain[i];
  132. }
  133. return firstChar;
  134. }
  135. /*
  136. ========================
  137. idLZWCompressor::DecompressBlock
  138. ========================
  139. */
  140. void idLZWCompressor::DecompressBlock() {
  141. assert( blockIndex == blockSize ); // Make sure we've read all we can
  142. blockIndex = 0;
  143. blockSize = 0;
  144. int firstChar = -1;
  145. while ( blockSize < LZW_BLOCK_SIZE - lzwCompressionData_t::LZW_DICT_SIZE ) {
  146. assert( lzwData->codeBits <= lzwCompressionData_t::LZW_DICT_BITS );
  147. int code = ReadBits( lzwData->codeBits );
  148. if ( code == -1 ) {
  149. break;
  150. }
  151. if ( oldCode == -1 ) {
  152. assert( code < 256 );
  153. block[blockSize++] = (uint8)code;
  154. oldCode = code;
  155. firstChar = code;
  156. continue;
  157. }
  158. if ( code >= lzwData->nextCode ) {
  159. assert( code == lzwData->nextCode );
  160. firstChar = WriteChain( oldCode );
  161. block[blockSize++] = (uint8)firstChar;
  162. } else {
  163. firstChar = WriteChain( code );
  164. }
  165. AddToDict( oldCode, firstChar );
  166. if ( BumpBits() ) {
  167. oldCode = -1;
  168. } else {
  169. oldCode = code;
  170. }
  171. }
  172. }
  173. /*
  174. ========================
  175. idLZWCompressor::ReadByte
  176. ========================
  177. */
  178. int idLZWCompressor::ReadByte( bool ignoreOverflow ) {
  179. if ( blockIndex == blockSize ) {
  180. DecompressBlock();
  181. }
  182. if ( blockIndex == blockSize ) { //-V581 DecompressBlock() updates these values, the if() isn't redundant
  183. if ( !ignoreOverflow ) {
  184. overflowed = true;
  185. assert( !"idLZWCompressor::ReadByte overflowed!" );
  186. }
  187. return -1;
  188. }
  189. return block[blockIndex++];
  190. }
  191. /*
  192. ========================
  193. idLZWCompressor::WriteByte
  194. ========================
  195. */
  196. void idLZWCompressor::WriteByte( uint8 value ) {
  197. int code = Lookup( lzwData->codeWord, value );
  198. if ( code >= 0 ) {
  199. lzwData->codeWord = code;
  200. } else {
  201. WriteBits( lzwData->codeWord, lzwData->codeBits );
  202. if ( !BumpBits() ) {
  203. AddToDict( lzwData->codeWord, value );
  204. }
  205. lzwData->codeWord = value;
  206. }
  207. if ( lzwData->bytesWritten >= maxSize - ( lzwData->codeBits + lzwData->tempBits + 7 ) / 8 ) {
  208. overflowed = true; // At any point, if we can't perform an End call, then trigger an overflow
  209. return;
  210. }
  211. }
  212. /*
  213. ========================
  214. idLZWCompressor::Lookup
  215. ========================
  216. */
  217. int idLZWCompressor::Lookup( int w, int k ) {
  218. if ( w == -1 ) {
  219. return k;
  220. } else {
  221. int i = HashIndex( w, k );
  222. for ( int j = hash[i]; j != 0xFFFF; j = nextHash[j] ) {
  223. assert( j < lzwCompressionData_t::LZW_DICT_SIZE );
  224. if ( lzwData->dictionaryK[j] == k && lzwData->dictionaryW[j] == w ) {
  225. return j;
  226. }
  227. }
  228. }
  229. return -1;
  230. }
  231. /*
  232. ========================
  233. idLZWCompressor::AddToDict
  234. ========================
  235. */
  236. int idLZWCompressor::AddToDict( int w, int k ) {
  237. assert( w < 0xFFFF - 1 );
  238. assert( k < 256 );
  239. assert( lzwData->nextCode < lzwCompressionData_t::LZW_DICT_SIZE );
  240. lzwData->dictionaryK[lzwData->nextCode] = (uint8)k;
  241. lzwData->dictionaryW[lzwData->nextCode] = (uint16)w;
  242. int i = HashIndex( w, k );
  243. nextHash[lzwData->nextCode] = hash[i];
  244. hash[i] = (uint16)lzwData->nextCode;
  245. return lzwData->nextCode++;
  246. }
  247. /*
  248. ========================
  249. idLZWCompressor::BumpBits
  250. Possibly increments codeBits.
  251. return: bool - true, if the dictionary was cleared.
  252. ========================
  253. */
  254. bool idLZWCompressor::BumpBits() {
  255. if ( lzwData->nextCode == ( 1 << lzwData->codeBits ) ) {
  256. lzwData->codeBits ++;
  257. if ( lzwData->codeBits > lzwCompressionData_t::LZW_DICT_BITS ) {
  258. lzwData->nextCode = LZW_FIRST_CODE;
  259. lzwData->codeBits = LZW_START_BITS;
  260. ClearHash();
  261. return true;
  262. }
  263. }
  264. return false;
  265. }
  266. /*
  267. ========================
  268. idLZWCompressor::End
  269. ========================
  270. */
  271. int idLZWCompressor::End() {
  272. assert( lzwData->tempBits < 8 );
  273. assert( lzwData->bytesWritten < maxSize - ( lzwData->codeBits + lzwData->tempBits + 7 ) / 8 );
  274. assert( ( Length() > 0 ) == ( lzwData->codeWord != -1 ) );
  275. if ( lzwData->codeWord != -1 ) {
  276. WriteBits( lzwData->codeWord, lzwData->codeBits );
  277. }
  278. if ( lzwData->tempBits > 0 ) {
  279. if ( lzwData->bytesWritten >= maxSize ) {
  280. overflowed = true;
  281. return -1;
  282. }
  283. data[lzwData->bytesWritten++] = (uint8)lzwData->tempValue & ( ( 1 << lzwData->tempBits ) - 1 );
  284. }
  285. return Length() > 0 ? Length() : -1; // Total bytes written (or failure)
  286. }
  287. /*
  288. ========================
  289. idLZWCompressor::Save
  290. ========================
  291. */
  292. void idLZWCompressor::Save() {
  293. assert( !overflowed );
  294. // Check and make sure we are at a good spot (can call End)
  295. assert( lzwData->bytesWritten < maxSize - ( lzwData->codeBits + lzwData->tempBits + 7 ) / 8 );
  296. savedBytesWritten = lzwData->bytesWritten;
  297. savedCodeWord = lzwData->codeWord;
  298. saveCodeBits = lzwData->codeBits;
  299. savedTempValue = lzwData->tempValue;
  300. savedTempBits = lzwData->tempBits;
  301. }
  302. /*
  303. ========================
  304. idLZWCompressor::Restore
  305. ========================
  306. */
  307. void idLZWCompressor::Restore() {
  308. lzwData->bytesWritten = savedBytesWritten;
  309. lzwData->codeWord = savedCodeWord;
  310. lzwData->codeBits = saveCodeBits;
  311. lzwData->tempValue = savedTempValue;
  312. lzwData->tempBits = savedTempBits;
  313. }
  314. /*
  315. ========================
  316. idLZWCompressor::ClearHash
  317. ========================
  318. */
  319. void idLZWCompressor::ClearHash() {
  320. memset( hash, 0xFF, sizeof( hash ) );
  321. }
  322. /*
  323. ========================
  324. idZeroRunLengthCompressor
  325. Simple zero based run length encoder/decoder
  326. ========================
  327. */
  328. void idZeroRunLengthCompressor::Start( uint8 * dest_, idLZWCompressor * comp_, int maxSize_ ) {
  329. zeroCount = 0;
  330. dest = dest_;
  331. comp = comp_;
  332. compressed = 0;
  333. maxSize = maxSize_;
  334. }
  335. bool idZeroRunLengthCompressor::WriteRun() {
  336. if ( zeroCount > 0 ) {
  337. assert( zeroCount <= 255 );
  338. if ( compressed + 2 > maxSize ) {
  339. maxSize = -1;
  340. return false;
  341. }
  342. if ( comp != NULL ) {
  343. comp->WriteByte( 0 );
  344. comp->WriteByte( (uint8)zeroCount );
  345. } else {
  346. *dest++ = 0;
  347. *dest++ = (uint8)zeroCount;
  348. }
  349. compressed += 2;
  350. zeroCount = 0;
  351. }
  352. return true;
  353. }
  354. bool idZeroRunLengthCompressor::WriteByte( uint8 value ) {
  355. if ( value != 0 || zeroCount >= 255 ) {
  356. if ( !WriteRun() ) {
  357. maxSize = -1;
  358. return false;
  359. }
  360. }
  361. if ( value != 0 ) {
  362. if ( compressed + 1 > maxSize ) {
  363. maxSize = -1;
  364. return false;
  365. }
  366. if ( comp != NULL ) {
  367. comp->WriteByte( value );
  368. } else {
  369. *dest++ = value;
  370. }
  371. compressed++;
  372. } else {
  373. zeroCount++;
  374. }
  375. return true;
  376. }
  377. byte idZeroRunLengthCompressor::ReadByte() {
  378. // See if we need to possibly read more data
  379. if ( zeroCount == 0 ) {
  380. int value = ReadInternal();
  381. if ( value == -1 ) {
  382. assert( 0 );
  383. }
  384. if ( value != 0 ) {
  385. return (byte)value; // Return non zero values immediately
  386. }
  387. // Read the number of zeroes
  388. zeroCount = ReadInternal();
  389. }
  390. assert( zeroCount > 0 );
  391. zeroCount--;
  392. return 0;
  393. }
  394. void idZeroRunLengthCompressor::ReadBytes( byte * dest, int count ) {
  395. for ( int i = 0; i < count; i++ ) {
  396. *dest++ = ReadByte();
  397. }
  398. }
  399. void idZeroRunLengthCompressor::WriteBytes( uint8 * src, int count ) {
  400. for ( int i = 0; i < count; i++ ) {
  401. WriteByte( *src++ );
  402. }
  403. }
  404. int idZeroRunLengthCompressor::End() {
  405. WriteRun();
  406. if ( maxSize == -1 ) {
  407. return -1;
  408. }
  409. return compressed;
  410. }
  411. int idZeroRunLengthCompressor::ReadInternal() {
  412. compressed++;
  413. if ( comp != NULL ) {
  414. return comp->ReadByte();
  415. }
  416. return *dest++;
  417. }