📄 deflateencoder.cpp
字号:
//
// Copyright (c) 1997,1998,1999 Colosseum Builders, Inc.
// All rights reserved.
//
// Colosseum Builders, Inc. makes no warranty, expressed or implied
// with regards to this software. It is provided as is.
//
// See the README.TXT file that came with this software for restrictions
// on the use and redistribution of this file or send E-mail to
// info@colosseumbuilders.com
//
//
// Title: Deflate Encoder Class Implementation
//
// Author: John M. Miano miano@colosseumbuilders.com
//
#include <climits>
#include <cstring>
#include "deflateencoder.h"
#include "deflatehuffmanencoder.h"
#include "adler32.h"
#include "deflatepvt.h"
#include "deflateoutputstream.h"
#include "checks.h"
using namespace ColosseumPrivate ;
using namespace std ;
namespace Colosseum
{
// Size definitions for the lookahead buffer.
const unsigned int LOOKAHEADSIZE = (1 << 9) ;
const unsigned int LOOKAHEADMASK = LOOKAHEADSIZE - 1 ;
// Hash Table size definitions.
const unsigned int HASHBITS = 5 ;
const unsigned int HASHTABLESIZE = 1 << (3 * HASHBITS) ;
// End of stream marker for the lookahead buffer.
const unsigned int ENDSTREAM = 0xFFFF ;
namespace
{
//
// Description:
//
// This function advances a lookahead buffer index.
//
// Parameter:
//
// position : The index to advance (in/out)
//
inline void AdvanceLookaheadPosition (unsigned int &position)
{
++ position ;
position &= LOOKAHEADMASK ;
return ;
}
//
// Description:
//
// This function advances an LZ buffer index.
//
// Parameter:
//
// position : The index to advance (in/out)
//
inline void AdvanceWindowPosition (unsigned int &position)
{
++ position ;
position &= DEFLATEWINDOWMASK ;
return ;
}
//
// Description:
//
// This function converts an LZ window position and offset to
// a position in the LZ window.
//
// Parameters:
//
// windowposition : The current position in the LZ Window
// offset : The LZ window offset
//
// Return Value:
//
// The window position
//
inline unsigned int WindowOffsetToPosition (unsigned int windowposition,
unsigned int offset)
{
unsigned int result = (DEFLATEWINDOWSIZE + windowposition - offset)
& DEFLATEWINDOWMASK ;
return result ;
}
//
// Description
//
// This is the hash function used by compressor. It converts
// a 3-byte sequence into an integer.
//
// Parameters:
//
// v1, v2, v3 : The 3-byte sequence to hash.
//
// Return Value:
//
// The hash value in the range (0 .. HASHTABLESIZE - 1)
//
inline unsigned int Hash (UBYTE1 v1, UBYTE1 v2, UBYTE1 v3)
{
const unsigned int mask = (1 << HASHBITS) - 1 ;
unsigned int value = (v1 & mask )
| ((v2 & mask) << HASHBITS)
| ((v3 & mask) << (2 * HASHBITS)) ;
return value ;
}
//
// Description:
//
// This function converts a distance value into a code,
// count of extra bits, and extra bits.
//
// Parameters:
//
// distance : The distance value to convert
// code : The corresponding distance code
// extra : The number of extra bits
// value : The extra bit value
//
void DistanceToCode (unsigned int distance, unsigned int &code,
unsigned int &extra, unsigned int &value)
{
// maxvalue [n] is the maximum distance value for the code n.
static const unsigned int maxvalue [DEFLATEMAXDISTANCECODES] =
{
1, 2, 3, 4, 6, 8, 12, 16, 24, 32,
48, 64, 96, 128, 192, 256, 384, 512, 768, 1024,
1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768,
} ;
// extras [n] is the number of extra bits for the code n.
static const unsigned int extras [DEFLATEMAXDISTANCECODES] =
{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
} ;
// bases [n] is the smallest distance value for code n.
static const unsigned int bases [DEFLATEMAXDISTANCECODES] =
{
1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
} ;
for (code = 0 ; code < DEFLATEMAXDISTANCECODES ; ++ code)
{
if (distance <= maxvalue [code])
break ;
}
extra = extras [code] ;
value = distance - bases [code] ;
return ;
}
//
// Description:
//
// This function converts a length value to a length code,
// count of extra bits, and extra bit value.
//
// Parameters:
//
// length : The value to convert
// code : The corresponding length code
// extra : The number of extra bits
// value : The extra bit value
//
inline static void LengthToCode (unsigned int length, unsigned int &code,
unsigned int &extra, unsigned int &value)
{
ASSERT (length <= DEFLATELONGESTLENGTH) ;
// codes [n] is the length for for length n - 3.
static const UBYTE2 codes [DEFLATELONGESTLENGTH-2] =
{
257, 258, 259, 260, 261, 262, 263, 264,
265, 265, 266, 266, 267, 267, 268, 268,
269, 269, 269, 269, 270, 270, 270, 270,
271, 271, 271, 271, 272, 272, 272, 272,
273, 273, 273, 273, 273, 273, 273, 273,
274, 274, 274, 274, 274, 274, 274, 274,
275, 275, 275, 275, 275, 275, 275, 275,
276, 276, 276, 276, 276, 276, 276, 276,
277, 277, 277, 277, 277, 277, 277, 277,
277, 277, 277, 277, 277, 277, 277, 277,
278, 278, 278, 278, 278, 278, 278, 278,
278, 278, 278, 278, 278, 278, 278, 278,
279, 279, 279, 279, 279, 279, 279, 279,
279, 279, 279, 279, 279, 279, 279, 279,
280, 280, 280, 280, 280, 280, 280, 280,
280, 280, 280, 280, 280, 280, 280, 280,
281, 281, 281, 281, 281, 281, 281, 281,
281, 281, 281, 281, 281, 281, 281, 281,
281, 281, 281, 281, 281, 281, 281, 281,
281, 281, 281, 281, 281, 281, 281, 281,
282, 282, 282, 282, 282, 282, 282, 282,
282, 282, 282, 282, 282, 282, 282, 282,
282, 282, 282, 282, 282, 282, 282, 282,
282, 282, 282, 282, 282, 282, 282, 282,
283, 283, 283, 283, 283, 283, 283, 283,
283, 283, 283, 283, 283, 283, 283, 283,
283, 283, 283, 283, 283, 283, 283, 283,
283, 283, 283, 283, 283, 283, 283, 283,
284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 284,
284, 284, 284, 284, 284, 284, 284, 285,
} ;
// extras [n] is the number of extra bits for code n.
static const UBYTE1 extras [DEFLATEMAXLENGTHCODES - DEFLATEFIRSTLENGTHCODE] =
{
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4,
5, 5, 5, 5, 0,
} ;
static const UBYTE2 basevalues [DEFLATEMAXLENGTHCODES - DEFLATEFIRSTLENGTHCODE] =
{
3, 4, 5, 6, 7, 8, 9, 10,
11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115,
131, 163, 195, 227, 258,
} ;
code = codes [length - 3] ;
extra = extras [code - DEFLATEFIRSTLENGTHCODE] ;
value = length - basevalues [code - DEFLATEFIRSTLENGTHCODE] ;
return ;
}
} // End Namespace
//
// Description:
//
// Class Default Constructor
//
DeflateEncoder::DeflateEncoder ()
: compression_level (DEFAULTCOMPRESSION),
lz_window (0),
lookahead_buffer (0),
block_buffer (0),
block_buffer_size (0x4000),
distance_table (DEFLATEMAXDISTANCECODES),
length_table (DEFLATEMAXLENGTHCODES),
length_length_table (DEFLATEMAXLENGTHLENGTHCODES),
compression_in_progress (false)
{
return ;
}
//
// Description:
//
// Class Destructor
//
DeflateEncoder::~DeflateEncoder ()
{
freeBuffers () ;
return ;
}
//
// Description:
//
// This function frees the buffers allocated during the encoding
// process.
//
void DeflateEncoder::freeBuffers ()
{
delete [] lz_window ; lz_window = 0 ;
delete [] lookahead_buffer ; lookahead_buffer = 0 ;
delete [] hash_values ; hash_values = 0 ;
delete [] hash_table ; hash_table = 0 ;
delete [] block_buffer ; block_buffer = 0 ;
return ;
}
//
// Description:
//
// This function returns the current block size setting.
//
// Return Value:
//
// The current block size.
//
unsigned long DeflateEncoder::getBlockSize () const
{
return block_buffer_size ;
}
//
// Description:
//
// This function sets the block buffer size.
//
// Parameters:
//
// value : The new block buffer size
//
// Restrictions:
//
// This function may not be called when compression is underway.
//
void DeflateEncoder::setBlockSize (unsigned long value)
{
if (compression_in_progress)
throw DeflateError ("Compression In Progress") ;
if (value < 500)
block_buffer_size = 500 ;
else
block_buffer_size = value ;
return ;
}
//
// Description:
//
// This function sets the compression level used. The compression level
// determines the depth to which hash chains are searched.
//
// Parameters:
//
// value: The new compression level
//
// Restrictions:
//
// This function may be called when compression is underway, but
// it has no effect for the current compression operation.
//
void DeflateEncoder::setCompressionLevel (
DeflateEncoder::CompressionLevel value)
{
if (value < 0 || value > 3)
throw DeflateError ("Invalid Compression Level") ;
compression_level = value ;
return ;
}
//
// Description:
//
// The function returns the current compression level.
//
// Return Value:
//
// The compresion level.
//
DeflateEncoder::CompressionLevel DeflateEncoder::getCompressionLevel () const
{
return compression_level ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -