LightweightCompression.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. #ifndef __LIGHTWEIGHT_COMPRESSION_H__
  21. #define __LIGHTWEIGHT_COMPRESSION_H__
  22. struct lzwCompressionData_t {
  23. static const int LZW_DICT_BITS = 12;
  24. static const int LZW_DICT_SIZE = 1 << LZW_DICT_BITS;
  25. uint8 dictionaryK[LZW_DICT_SIZE];
  26. uint16 dictionaryW[LZW_DICT_SIZE];
  27. int nextCode;
  28. int codeBits;
  29. int codeWord;
  30. uint64 tempValue;
  31. int tempBits;
  32. int bytesWritten;
  33. };
  34. /*
  35. ========================
  36. idLZWCompressor
  37. Simple lzw based encoder/decoder
  38. ========================
  39. */
  40. class idLZWCompressor {
  41. public:
  42. idLZWCompressor( lzwCompressionData_t * lzwData_ ) : lzwData( lzwData_ ) {}
  43. static const int LZW_BLOCK_SIZE = ( 1 << 15 );
  44. static const int LZW_START_BITS = 9;
  45. static const int LZW_FIRST_CODE = ( 1 << ( LZW_START_BITS - 1 ) );
  46. void Start( uint8 * data_, int maxSize, bool append = false );
  47. int ReadBits( int bits );
  48. int WriteChain( int code );
  49. void DecompressBlock();
  50. void WriteBits( uint32 value, int bits );
  51. int ReadByte( bool ignoreOverflow = false );
  52. void WriteByte( uint8 value );
  53. int Lookup( int w, int k );
  54. int AddToDict( int w, int k );
  55. bool BumpBits();
  56. int End();
  57. int Length() const { return lzwData->bytesWritten; }
  58. int GetReadCount() const { return bytesRead; }
  59. void Save();
  60. void Restore();
  61. bool IsOverflowed() { return overflowed; }
  62. int Write( const void * data, int length ) {
  63. uint8 * src = (uint8*)data;
  64. for ( int i = 0; i < length && !IsOverflowed(); i++ ) {
  65. WriteByte( src[i] );
  66. }
  67. return length;
  68. }
  69. int Read( void * data, int length, bool ignoreOverflow = false ) {
  70. uint8 * src = (uint8*)data;
  71. for ( int i = 0; i < length; i++ ) {
  72. int byte = ReadByte( ignoreOverflow );
  73. if ( byte == -1 ) {
  74. return i;
  75. }
  76. src[i] = (uint8)byte;
  77. }
  78. return length;
  79. }
  80. int WriteR( const void * data, int length ) {
  81. uint8 * src = (uint8*)data;
  82. for ( int i = 0; i < length && !IsOverflowed(); i++ ) {
  83. WriteByte( src[length - i - 1] );
  84. }
  85. return length;
  86. }
  87. int ReadR( void * data, int length, bool ignoreOverflow = false ) {
  88. uint8 * src = (uint8*)data;
  89. for ( int i = 0; i < length; i++ ) {
  90. int byte = ReadByte( ignoreOverflow );
  91. if ( byte == -1 ) {
  92. return i;
  93. }
  94. src[length - i - 1] = (uint8)byte;
  95. }
  96. return length;
  97. }
  98. template<class type> ID_INLINE size_t WriteAgnostic( const type & c ) {
  99. return Write( &c, sizeof( c ) );
  100. }
  101. template<class type> ID_INLINE size_t ReadAgnostic( type & c, bool ignoreOverflow = false ) {
  102. size_t r = Read( &c, sizeof( c ), ignoreOverflow );
  103. return r;
  104. }
  105. static const int DICTIONARY_HASH_BITS = 10;
  106. static const int MAX_DICTIONARY_HASH = 1 << DICTIONARY_HASH_BITS;
  107. static const int HASH_MASK = MAX_DICTIONARY_HASH - 1;
  108. private:
  109. void ClearHash();
  110. lzwCompressionData_t * lzwData;
  111. uint16 hash[MAX_DICTIONARY_HASH];
  112. uint16 nextHash[lzwCompressionData_t::LZW_DICT_SIZE];
  113. // Used by DecompressBlock
  114. int oldCode;
  115. uint8 * data; // Read/write
  116. int maxSize;
  117. bool overflowed;
  118. // For reading
  119. int bytesRead;
  120. uint8 block[LZW_BLOCK_SIZE];
  121. int blockSize;
  122. int blockIndex;
  123. // saving/restoring when overflow (when writing).
  124. // Must call End directly after restoring (dictionary is bad so can't keep writing)
  125. int savedBytesWritten;
  126. int savedCodeWord;
  127. int saveCodeBits;
  128. uint64 savedTempValue;
  129. int savedTempBits;
  130. };
  131. /*
  132. ========================
  133. idZeroRunLengthCompressor
  134. Simple zero based run length encoder/decoder
  135. ========================
  136. */
  137. class idZeroRunLengthCompressor {
  138. public:
  139. idZeroRunLengthCompressor() : zeroCount( 0 ), destStart( NULL ) {
  140. }
  141. void Start( uint8 * dest_, idLZWCompressor * comp_, int maxSize_ );
  142. bool WriteRun();
  143. bool WriteByte( uint8 value );
  144. byte ReadByte();
  145. void ReadBytes( byte * dest, int count );
  146. void WriteBytes( uint8 * src, int count );
  147. int End();
  148. int CompressedSize() const { return compressed; }
  149. private:
  150. int ReadInternal();
  151. int zeroCount; // Number of pending zeroes
  152. idLZWCompressor * comp;
  153. uint8 * destStart;
  154. uint8 * dest;
  155. int compressed; // Compressed size
  156. int maxSize;
  157. };
  158. #endif // __LIGHTWEIGHT_COMPRESSION_H__