Lzw.cpp
上传用户:deer201011
上传日期:2022-06-24
资源大小:10k
文件大小:6k
源码类别:

压缩解压

开发平台:

Visual C++

  1. // Lzw.cpp
  2. #include "CompressedFile.h"
  3. #define END_OF_STREAM 256
  4. #ifdef UNUSED
  5. #undef UNUSED
  6. #endif
  7. #define UNUSED -1
  8. CLzwFile::CLzwFile()
  9. {
  10. m_bStorageAllocated = FALSE;
  11. }
  12. CLzwFile::~CLzwFile()
  13. {
  14. DeleteStorage();
  15. }
  16. BOOL CLzwFile::Open( const char *pszFileName, unsigned int nOpenFlags, CFileException *pError )
  17. {
  18. m_nCompressionType = LZW;
  19. m_bStarted = FALSE;
  20. for( long i=0; i<TABLE_SIZE; i++ ) m_cbDecodeStack[i] = 0;
  21. m_nNextCode = 0;
  22. m_nCurrentCodeBits = 0;
  23. m_nNextBumpCode = 0;
  24. m_nCharacter = 0;
  25. m_nEntryPoint = 0;
  26. m_nStringCode = 0;
  27. m_nIndex = 0;
  28. m_nNewCode = m_nOldCode = 0;
  29. m_nCount = 0;
  30. AllocateStorage();
  31. if( !m_bStorageAllocated) return( FALSE );
  32. InitializeDictionary();
  33. return( CCompressedFile::Open( pszFileName, nOpenFlags, pError ) );
  34. }
  35. void CLzwFile::Close( void )
  36. {
  37. if( m_nFlags != CFile::modeRead ){
  38. OutputBits( (DWORD) m_nStringCode, m_nCurrentCodeBits );
  39. OutputBits( (DWORD) END_OF_STREAM, m_nCurrentCodeBits );
  40. }
  41. CCompressedFile::Close();
  42. if( m_nFlags == ( CFile::modeCreate | CFile::modeWrite ) || m_nFlags == CFile::modeWrite ){
  43. CFile cf;
  44. cf.Open( m_szFilename, CFile::modeWrite );
  45. cf.Seek( m_dwSeekTo, CFile::begin );
  46. cf.Write( &m_dwUncompressedSize, sizeof( DWORD ) );
  47. cf.Write( &m_dwCompressedSize, sizeof( DWORD ) );
  48. cf.Close();
  49. }
  50. }
  51. unsigned int CLzwFile::Read( void far *lpBuf, unsigned int nCount )
  52. {
  53. unsigned int nBytesRead = 0;
  54. unsigned char *pTransfer;
  55. unsigned int i = 0;
  56. pTransfer = (unsigned char *) lpBuf;
  57. if( m_nEntryPoint == 1 ) goto LZW_ENTRY1a;
  58. if( m_nEntryPoint == 2 ) goto LZW_ENTRY2a;
  59. for( ; ; ){
  60. m_nEntryPoint = 1;
  61. InitializeDictionary();
  62. m_nOldCode = (unsigned int) InputBits( m_nCurrentCodeBits );
  63. if( m_nOldCode == END_OF_STREAM ) return( nBytesRead );
  64. m_nCharacter = m_nOldCode;
  65. pTransfer[i++] = (unsigned char) m_nOldCode;
  66. if( i >= nCount ) return( nBytesRead );
  67. LZW_ENTRY1a:
  68. m_nEntryPoint = 2;
  69. for( ; ; ){
  70. m_nNewCode = (unsigned int) InputBits( m_nCurrentCodeBits );
  71. if( m_nNewCode == END_OF_STREAM ) return( nBytesRead );
  72. if( m_nNewCode == FLUSH_CODE ) break;
  73. if( m_nNewCode == BUMP_CODE ){
  74. m_nCurrentCodeBits++;
  75. continue;
  76. }
  77. if( m_nNewCode >= (int) m_nNextCode ){
  78. m_cbDecodeStack[0] = (char) m_nCharacter;
  79. m_nCount = DecodeString( 1, m_nOldCode );
  80. }
  81. else m_nCount = DecodeString( 0, m_nNewCode );
  82. m_nCharacter = m_cbDecodeStack[m_nCount-1];
  83. while( m_nCount > 0 ){
  84. pTransfer[i++] = m_cbDecodeStack[--m_nCount];
  85. if( i >= nCount ) return( nBytesRead );
  86. LZW_ENTRY2a:
  87. ;
  88. }
  89. DICT( m_nNextCode ).nParentCode = m_nOldCode;
  90. DICT( m_nNextCode ).nCharacter = (char) m_nCharacter;
  91. m_nNextCode++;
  92. m_nOldCode = m_nNewCode;
  93. }
  94. }
  95. return( nBytesRead);
  96. }
  97. void CLzwFile::Write( void *lpBuf, unsigned int nCount )
  98. {
  99. unsigned char *pTransfer;
  100. unsigned int nStart = 0;
  101. pTransfer = (unsigned char *) lpBuf;
  102. m_dwUncompressedSize += (DWORD) nCount;
  103. if( !m_bStarted ){
  104. m_nStringCode = (int) pTransfer[nStart++];
  105. m_nStringCode &= 0x00ff;
  106. m_bStarted = TRUE;
  107. }
  108. for( unsigned int i=nStart; i<nCount; i++ ){
  109. m_nCharacter = (int) pTransfer[i];
  110. m_nCharacter &= 0x00ff;
  111. m_nIndex = FindChildNode( m_nStringCode, m_nCharacter );
  112. if( DICT( m_nIndex ).nCodeValue != -1 ) m_nStringCode = DICT( m_nIndex ).nCodeValue;
  113. else{
  114. DICT( m_nIndex ).nCodeValue = m_nNextCode++;
  115. DICT( m_nIndex ).nParentCode = m_nStringCode;
  116. DICT( m_nIndex ).nCharacter = (char) m_nCharacter;
  117. OutputBits( (DWORD) m_nStringCode, m_nCurrentCodeBits );
  118. m_nStringCode = m_nCharacter;
  119. if( m_nNextCode > MAX_CODE ){
  120. OutputBits( (DWORD) FLUSH_CODE, m_nCurrentCodeBits );
  121. InitializeDictionary();
  122. }
  123. else if( m_nNextCode > m_nNextBumpCode ){
  124. OutputBits( (DWORD) BUMP_CODE, m_nCurrentCodeBits );
  125. m_nCurrentCodeBits++;
  126. m_nNextBumpCode <<= 1;
  127. m_nNextBumpCode |= 1;
  128. }
  129. }
  130. }
  131. }
  132. void CLzwFile::InitializeDictionary( void )
  133. {
  134. unsigned int i;
  135. for( i=0; i<TABLE_SIZE; i++ ) DICT( i ).nCodeValue = UNUSED;
  136. m_nNextCode = FIRST_CODE;
  137. m_nCurrentCodeBits = 9;
  138. m_nNextBumpCode = 511;
  139. }
  140. void CLzwFile::AllocateStorage( void )
  141. {
  142. int i;
  143. if( m_bStorageAllocated ) DeleteStorage();
  144. for( i=0; i<TABLE_BANKS; i++ ) m_Dict[i] = NULL;
  145. for( i=0; i<TABLE_BANKS; i++){
  146. m_Dict[i] = (DICTIONARY *) new DICTIONARY [256];
  147. if( !m_Dict[i] ) return;
  148. memset( m_Dict[i], 0, sizeof( DICTIONARY ) * 256 );
  149. }
  150. m_bStorageAllocated = TRUE;
  151. }
  152. void CLzwFile::DeleteStorage( void )
  153. {
  154. int i;
  155. for( i=0; i<TABLE_BANKS; i++ ){
  156. if( m_Dict[i] ) delete [] m_Dict[i];
  157. m_Dict[i] = NULL;
  158. }
  159. m_bStorageAllocated = FALSE;
  160. }
  161. unsigned int CLzwFile::FindChildNode( int nParentNode, int nChildCharacter )
  162. {
  163. unsigned int nIndex;
  164. int nOffset;
  165. nIndex = ( nChildCharacter << ( BITS - 8 ) ) ^ nParentNode;
  166. if( !nIndex ) nOffset = 1;
  167. else nOffset = (int) ( TABLE_SIZE - nIndex );
  168. for( ; ; ){
  169. if( DICT( nIndex ).nCodeValue == UNUSED) return( (unsigned int) nIndex );
  170. if( DICT( nIndex ).nParentCode == nParentNode && DICT( nIndex ).nCharacter == (char) nChildCharacter ) return( (unsigned int) nIndex );
  171. if( nIndex >= (unsigned int) nOffset ) nIndex -= (unsigned int) nOffset;
  172. else nIndex += (unsigned int) ( TABLE_SIZE - nOffset );
  173. }
  174. return( 0 );
  175. }
  176. unsigned int CLzwFile::DecodeString( unsigned int nCount, unsigned int nCode )
  177. {
  178. while( nCode > 255 ){
  179. m_cbDecodeStack[nCount++] = DICT( nCode ).nCharacter;
  180. nCode = DICT( nCode ).nParentCode;
  181. }
  182. m_cbDecodeStack[nCount++] = (char) nCode;
  183. return( nCount);
  184. }