这份代码跟
上一次相比,修正了以下部分:
1、可修改的Window Size。压缩流会把Window Size写进去,解压流能够自动获取。
2、发现冗余的地方,每一个标记的压缩块节省了一位。
3、如果用户一次性写入的字节不够多则会缓存起来,上一版本则是直接压缩完。这样会丢失某些原本可以压缩的数据,因此修正。
这次修改主要用于缩小压缩后的数据的尺寸。
头文件:
1 /*******************************************************************************
2 Vczh Library++ 2.0
3 数据结构::压缩流
4 开发者:陈梓瀚
5
6 接口:
7 类:
8 VL_CompressedStream :压缩流
9 VL_LZ77Stream :LZ77压缩流
10 VL_LZWStream :LZW压缩流
11 VL_HuffmanStream :Canonical Huffman压缩流
12 函数:
13 *******************************************************************************/
14 #ifndef VL_COMPRESSION
15 #define VL_COMPRESSION
16
17 #include "VL_Stream.h"
18 #include "VL_DataAccess.h"
19
20 namespace vl
21 {
22 namespace stream
23 {
24 using namespace collection;
25
26 /*********************************************************************************************************
27 压缩流
28 *********************************************************************************************************/
29
30 class VL_CompressedStream : public VL_Base , public IVL_Stream
31 {
32 public:
33 enum VLE_OpenMode
34 {
35 vomRead,
36 vomWrite,
37 };
38
39 class Compressor : public IVL_Interface
40 {
41 public:
42 virtual void SetStream(IVL_Stream* Stream)=0;
43 virtual VInt Write(VPointer Data , VInt ByteCount)=0;
44 };
45
46 class Decompressor : public IVL_Interface
47 {
48 public:
49 virtual void SetStream(IVL_Stream* Stream)=0;
50 virtual VInt Read(VPointer Data , VInt ByteCount)=0;
51 };
52 protected:
53 IVL_Stream* FStream;
54 VBool FOwned;
55 VLE_OpenMode FMode;
56 VSize FPosition;
57 Compressor* FCompressor;
58 Decompressor* FDecompressor;
59
60 VBuffer FPeekBuffer;
61 VInt FPeekBufferSize;
62 VInt FAvailablePeekSize;
63
64 void Init(IVL_Stream* Stream , VBool Owned , Compressor* aCompressor);
65 void Init(IVL_Stream* Stream , VBool Owned , Decompressor* aDecompressor);
66
67 VL_CompressedStream();
68 public:
69 ~VL_CompressedStream();
70
71 VBool CanRead();
72 VBool CanPeek();
73 VBool CanWrite();
74 VBool CanClose();
75 VBool CanSeek();
76 VBool CanGrow();
77 VInt Read(VPointer Data , VInt ByteCount);
78 VInt Peek(VPointer Data , VInt ByteCount);
79 VInt Write(VPointer Data , VInt ByteCount);
80 void Close();
81 VBool IsAvailable();
82 VSize Position();
83 VSize Size();
84 VSize MaxWriteSize();
85 void SeekFromBegin(VSize Offset);
86 void SeekFromEnd(VSize Offset);
87 void Seek(VSize Offset);
88 VBool IsEnd();
89 };
90
91 class VL_LZ77Stream : public VL_CompressedStream
92 {
93 public:
94 enum VLE_WindowMode
95 {
96 vwm128=7,
97 vwm256,
98 vwm512,
99 vwm1024,
100 vwm2048,
101 vwmAuto=0,
102 vwmMin=vwm128,
103 vwmMax=vwm2048
104
105 };
106
107 VL_LZ77Stream(IVL_Stream* Stream , VLE_OpenMode OpenMode , VLE_WindowMode WindowMode=vwmAuto , VBool Owned=false);
108 };
109
110 /*********************************************************************************************************
111 LZ77压缩算法
112
113 第一个字节:window level, window size = 2 ^ window level
114 压缩块描述:
115 [0:wild][A:byte count-1][data]
116 [1:encoded][A:byte count-1][B:index]
117 A : 0 - (WindowSize-1)
118 B : 0 - (WindowSize-1)
119 *********************************************************************************************************/
120
121 namespace LZ77Algorithms
122 {
123 class AlgorithmBase : public VL_Base
124 {
125 protected:
126
127 VInt WindowSize;
128 VInt MaxBlockSize;
129 VInt DoubleMaxBlockSize;
130 VInt ByteCountBitCount;
131 VInt ByteIndexBitCount;
132
133 VBuffer FWindow; /*滑动窗口,尺寸=WindowSize*3*/
134 VSize FPosition; /*当前位置*/
135 VInt FUsedWindowSize; /*窗口有效数据大小*/
136 VSize FWindowStartPosition; /*窗口的起始位置*/
137
138 AlgorithmBase(VInt WindowSizeLevel); /*窗口尺寸为2的WindowSizeLevel次方*/
139 ~AlgorithmBase();
140 };
141
142 class Compressor : public AlgorithmBase , public VL_CompressedStream::Compressor
143 {
144 protected:
145 VL_BitWriter* FBitWriter;
146 VInt FUsedFullWindowSize; /*缓冲区有效数据大小*/
147
148 VInt CompressAndWrite(VInt ByteCount);
149 public:
150 Compressor(VInt WindowSizeLevel);
151 ~Compressor();
152
153 void SetStream(IVL_Stream* Stream);
154 VInt Write(VPointer Data , VInt ByteCount);
155 };
156
157 class Decompressor : public AlgorithmBase , public VL_CompressedStream::Decompressor
158 {
159 protected:
160 VL_BitReader* FReader;
161
162 VInt DecompressBlock();
163 public:
164 Decompressor(VInt WindowSizeLevel);
165 ~Decompressor();
166
167 void SetStream(IVL_Stream* Stream);
168 VInt Read(VPointer Data , VInt ByteCount);
169 };
170
171 }
172 }
173 }
174
175 #endif
实现文件:
1 #include "VL_Compression.h"
2
3 namespace vl
4 {
5 namespace stream
6 {
7
8 /*********************************************************************************************************
9 VL_CompressedStream
10 *********************************************************************************************************/
11
12 void VL_CompressedStream::Init(IVL_Stream* Stream , VBool Owned , Compressor* aCompressor)
13 {
14 FStream=Stream;
15 FOwned=Owned;
16 FMode=vomWrite;
17 FCompressor=aCompressor;
18 FCompressor->SetStream(FStream);
19 FDecompressor=0;
20 }
21
22 void VL_CompressedStream::Init(IVL_Stream* Stream , VBool Owned , Decompressor* aDecompressor)
23 {
24 FStream=Stream;
25 FOwned=Owned;
26 FMode=vomRead;
27 FCompressor=0;
28 FDecompressor=aDecompressor;
29 FDecompressor->SetStream(FStream);
30 }
31
32 VL_CompressedStream::VL_CompressedStream()
33 {
34 FStream=0;
35 FOwned=false;
36 FPosition=0;
37
38 FPeekBuffer=0;
39 FPeekBufferSize=0;
40 FAvailablePeekSize=0;
41 }
42
43 VL_CompressedStream::~VL_CompressedStream()
44 {
45 Close();
46 }
47
48 VBool VL_CompressedStream::CanRead()
49 {
50 return IsAvailable() && (FMode==vomRead) && FStream->CanRead();
51 }
52
53 VBool VL_CompressedStream::CanPeek()
54 {
55 return IsAvailable() && (FMode==vomRead) && FStream->CanRead();
56 }
57
58 VBool VL_CompressedStream::CanWrite()
59 {
60 return IsAvailable() && (FMode==vomWrite) && FStream->CanWrite();
61 }
62
63 VBool VL_CompressedStream::CanClose()
64 {
65 return IsAvailable() && FStream->CanClose();
66 }
67
68 VBool VL_CompressedStream::CanSeek()
69 {
70 return false;
71 }
72
73 VBool VL_CompressedStream::CanGrow()
74 {
75 return CanWrite();
76 }
77
78 VInt VL_CompressedStream::Read(VPointer Data , VInt ByteCount)
79 {
80 if(CanRead())
81 {
82 if(!FAvailablePeekSize)
83 {
84 ByteCount=FDecompressor->Read(Data,ByteCount);
85 FPosition+=ByteCount;
86 return ByteCount;
87 }
88 else if(FAvailablePeekSize>=ByteCount)
89 {
90 memcpy(Data,FPeekBuffer,ByteCount);
91 FAvailablePeekSize-=ByteCount;
92 memmove(FPeekBuffer,FPeekBuffer+ByteCount,FAvailablePeekSize);
93 FPosition+=ByteCount;
94 return ByteCount;
95 }
96 else
97 {
98 VBuffer DataBuffer=(VBuffer)Data;
99 memcpy(DataBuffer,FPeekBuffer,FAvailablePeekSize);
100 ByteCount=FAvailablePeekSize+FDecompressor->Read(DataBuffer+FAvailablePeekSize,ByteCount-FAvailablePeekSize);
101 FAvailablePeekSize=0;
102 FPosition+=ByteCount;
103 return ByteCount;
104 }
105 }
106 else
107 {
108 return -1;
109 }
110 }
111
112 VInt VL_CompressedStream::Peek(VPointer Data , VInt ByteCount)
113 {
114 if(CanPeek())
115 {
116 VInt ExtendSize=ByteCount-FAvailablePeekSize;
117 if(ExtendSize>0)
118 {
119 if(FPeekBufferSize<ByteCount)
120 {
121 VBuffer NewPeekBuffer=new VByte[ByteCount];
122 if(FPeekBuffer)
123 {
124 memcpy(NewPeekBuffer,FPeekBuffer,FAvailablePeekSize);
125 delete[] FPeekBuffer;
126 }
127 FPeekBuffer=NewPeekBuffer;
128 FPeekBufferSize=ByteCount;
129 }
130 FAvailablePeekSize+=FDecompressor->Read(FPeekBuffer+FAvailablePeekSize,ExtendSize);
131 }
132 if(FAvailablePeekSize<ByteCount)
133 {
134 ByteCount=FAvailablePeekSize;
135 }
136 memcpy(Data,FPeekBuffer,ByteCount);
137 return ByteCount;
138 }
139 else
140 {
141 return -1;
142 }
143 }
144
145 VInt VL_CompressedStream::Write(VPointer Data , VInt ByteCount)
146 {
147 if(CanWrite())
148 {
149 ByteCount=FCompressor->Write(Data,ByteCount);
150 FPosition+=ByteCount;
151 return ByteCount;
152 }
153 else
154 {
155 return -1;
156 }
157 }
158
159 void VL_CompressedStream::Close()
160 {
161 if(FCompressor)
162 {
163 delete FCompressor;
164 FCompressor=0;
165 }
166 if(FDecompressor)
167 {
168 delete FDecompressor;
169 FDecompressor=0;
170 }
171 if(FPeekBuffer)
172 {
173 delete[] FPeekBuffer;
174 FPeekBuffer=0;
175 }
176 if(FStream)
177 {
178 if(FOwned)
179 {
180 FStream->Close();
181 delete FStream;
182 FOwned=false;
183 }
184 FStream=0;
185 }
186 }
187
188 VBool VL_CompressedStream::IsAvailable()
189 {
190 return FStream && FStream->IsAvailable();
191 }
192
193 VSize VL_CompressedStream::Position()
194 {
195 return IsAvailable()?FPosition:-1;
196 }
197
198 VSize VL_CompressedStream::Size()
199 {
200 return -1;
201 }
202
203 VSize VL_CompressedStream::MaxWriteSize()
204 {
205 return -1;
206 }
207
208 void VL_CompressedStream::SeekFromBegin(VSize Offset)
209 {
210 }
211
212 void VL_CompressedStream::SeekFromEnd(VSize Offset)
213 {
214 }
215
216 void VL_CompressedStream::Seek(VSize Offset)
217 {
218 }
219
220 VBool VL_CompressedStream::IsEnd()
221 {
222 return IsAvailable()?FStream->IsEnd():true;
223 }
224
225 /*********************************************************************************************************
226 VL_LZ77Stream
227 *********************************************************************************************************/
228
229 VL_LZ77Stream::VL_LZ77Stream(IVL_Stream* Stream , VLE_OpenMode OpenMode , VLE_WindowMode WindowMode , VBool Owned)
230 {
231 switch(OpenMode)
232 {
233 case vomRead:
234 if(WindowMode==vwmAuto)
235 {
236 VByte BitCount=0;
237 if(Stream->Read(&BitCount,sizeof(BitCount))==sizeof(BitCount))
238 {
239 if(BitCount>=vwmMin && BitCount<=vwmMax)
240 {
241 Init(Stream,Owned,new LZ77Algorithms::Decompressor(BitCount));
242 }
243 }
244 }
245 break;
246 case vomWrite:
247 if(WindowMode==vwmAuto)
248 {
249 WindowMode=vwm1024;
250 }
251 if(WindowMode>=vwmMin && WindowMode<=vwmMax)
252 {
253 VByte BitCount=(VByte)WindowMode;
254 Stream->Write(&BitCount,sizeof(BitCount));
255 Init(Stream,Owned,new LZ77Algorithms::Compressor(WindowMode));
256 }
257 break;
258 }
259 }
260
261 /*********************************************************************************************************
262 LZ77Algorithms::AlgorithmBase
263 *********************************************************************************************************/
264
265 namespace LZ77Algorithms
266 {
267
268 AlgorithmBase::AlgorithmBase(VInt WindowSizeLevel)
269 {
270 WindowSize=1<<WindowSizeLevel;
271 MaxBlockSize=WindowSize;
272 DoubleMaxBlockSize=MaxBlockSize*2;
273 ByteCountBitCount=WindowSizeLevel;
274 ByteIndexBitCount=WindowSizeLevel;
275
276 FWindow=new VByte[WindowSize*3];
277 FPosition=0;
278 FUsedWindowSize=0;
279 FWindowStartPosition=0;
280 }
281
282 AlgorithmBase::~AlgorithmBase()
283 {
284 delete[] FWindow;
285 }
286
287 /*********************************************************************************************************
288 LZ77Algorithms::Compressor
289 *********************************************************************************************************/
290
291 struct CompressionRecord
292 {
293 VBool Compressed;
294 VInt Start;
295 VInt Size;
296 };
297
298 // 2 <= compressed size <= extended size
299 CompressionRecord TestCompression(VBuffer Window , VInt WindowSize , VInt ExtendedSize)
300 {
301 CompressionRecord Record;
302 Record.Compressed=false;
303 Record.Start=0;
304 Record.Size=1;
305 for(VInt i=0;i<WindowSize;i++)
306 {
307 VBuffer Read1=Window+i;
308 VBuffer Read2=Window+WindowSize;
309 VInt CurrentSize=0;
310 while(CurrentSize<ExtendedSize && *Read1++==*Read2++)
311 {
312 CurrentSize++;
313 }
314 if(CurrentSize>Record.Size)
315 {
316 Record.Compressed=true;
317 Record.Start=i;
318 Record.Size=CurrentSize;
319 if(CurrentSize==ExtendedSize)
320 {
321 break;
322 }
323 }
324 }
325 return Record;
326 }
327
328 // 1 <= byte count <= window size
329 // 0 <= compressed index < window size
330 // 2 <= compressed size <= window size
331 // 1 <= uncompressed size <= window size
332 VInt Compressor::CompressAndWrite(VInt ByteCount)
333 {
334 VInt SelectedStart=-1;
335 VInt EncodedLength=-1;
336 if(ByteCount>DoubleMaxBlockSize)
337 {
338 ByteCount=DoubleMaxBlockSize;
339 }
340
341 VInt UncompressedBlockSize=0;
342 VInt CompressedBlockStart=0;
343 VInt CompressedBlockSize=0;
344 VInt MaxUncompressedSize=MaxBlockSize<ByteCount?MaxBlockSize:ByteCount;
345 while(UncompressedBlockSize<MaxUncompressedSize)
346 {
347 VInt ExtendedSize=ByteCount-UncompressedBlockSize;
348 if(ExtendedSize>MaxBlockSize)
349 {
350 ExtendedSize=MaxBlockSize;
351 }
352
353 VBuffer VirtualWindow=FWindow;
354 VInt VirtualWindowSize=FUsedWindowSize+UncompressedBlockSize;
355 if(VirtualWindowSize>WindowSize)
356 {
357 VirtualWindow+=VirtualWindowSize-WindowSize;
358 VirtualWindowSize=WindowSize;
359 }
360
361 CompressionRecord Record=TestCompression(VirtualWindow,VirtualWindowSize,ExtendedSize);
362 if(Record.Compressed)
363 {
364 CompressedBlockStart=Record.Start;
365 CompressedBlockSize=Record.Size;
366 break;
367 }
368 else
369 {
370 UncompressedBlockSize++;
371 }
372 }
373
374 if(UncompressedBlockSize)
375 {
376 FBitWriter->WriteBit(false);
377 FBitWriter->WriteNumber(UncompressedBlockSize-1,ByteCountBitCount);
378 for(VInt i=0;i<UncompressedBlockSize;i++)
379 {
380 FBitWriter->WriteNumber(FWindow[FUsedWindowSize+i],8);
381 }
382 FPosition+=UncompressedBlockSize;
383 }
384 if(CompressedBlockSize)
385 {
386 FBitWriter->WriteBit(true);
387 FBitWriter->WriteNumber(CompressedBlockSize-1,ByteCountBitCount);
388 FBitWriter->WriteNumber(CompressedBlockStart,ByteIndexBitCount);
389 FPosition+=CompressedBlockSize;
390 }
391
392 ByteCount=UncompressedBlockSize+CompressedBlockSize;
393 FUsedWindowSize+=ByteCount;
394 if(FUsedWindowSize>WindowSize)
395 {
396 VInt Remain=FUsedWindowSize-WindowSize;
397 VInt CopySize=FUsedFullWindowSize-Remain;
398
399 memmove(FWindow,FWindow+Remain,CopySize);
400 FUsedWindowSize=WindowSize;
401 FWindowStartPosition+=Remain;
402 FUsedFullWindowSize=CopySize;
403 }
404 return ByteCount;
405 }
406
407 Compressor::Compressor(VInt WindowSizeLevel):AlgorithmBase(WindowSizeLevel)
408 {
409 FBitWriter=0;
410 FUsedFullWindowSize=0;
411 }
412
413 Compressor::~Compressor()
414 {
415 while(FUsedFullWindowSize>FUsedWindowSize)
416 {
417 VInt Size=CompressAndWrite(FUsedFullWindowSize-FUsedWindowSize);
418 if(Size==0)
419 {
420 break;
421 }
422 }
423 SetStream(0);
424 }
425
426 void Compressor::SetStream(IVL_Stream* Stream)
427 {
428 if(FBitWriter)
429 {
430 delete FBitWriter;
431 FBitWriter=0;
432 }
433 if(Stream)
434 {
435 FBitWriter=new VL_BitWriter(Stream,false);
436 }
437 }
438
439 VInt Compressor::Write(VPointer Data , VInt ByteCount)
440 {
441 VInt WrittenCount=0;
442 VBuffer DataBuffer=(VBuffer)Data;
443 while(WrittenCount<ByteCount)
444 {
445 VInt CopySize=WindowSize*3-FUsedFullWindowSize;
446 if(CopySize)
447 {
448 VInt DataSize=ByteCount-WrittenCount;
449 if(CopySize>DataSize)
450 {
451 CopySize=DataSize;
452 }
453 memcpy(FWindow+FUsedFullWindowSize,DataBuffer,CopySize);
454 DataBuffer+=CopySize;
455 FUsedFullWindowSize+=CopySize;
456 WrittenCount+=CopySize;
457 }
458
459 VInt Size=CompressAndWrite(FUsedFullWindowSize-FUsedWindowSize);
460 if(Size==0)
461 {
462 break;
463 }
464 }
465 return WrittenCount;
466 }
467
468 /*********************************************************************************************************
469 LZ77Algorithms::Decompressor
470 *********************************************************************************************************/
471
472 VInt Decompressor::DecompressBlock()
473 {
474 VBool BlockCompressed=false;
475 VUInt BlockSize=0;
476 if(!FReader->ReadBit(BlockCompressed))
477 {
478 return 0;
479 }
480 if(!FReader->ReadNumber(BlockSize,ByteCountBitCount))
481 {
482 return 0;
483 }
484 BlockSize++;
485 if(BlockCompressed)
486 {
487 VUInt BlockStart=0;
488 if(!FReader->ReadNumber(BlockStart,ByteIndexBitCount))
489 {
490 return 0;
491 }
492 VBuffer Dest=FWindow+FUsedWindowSize;
493 VBuffer Src=FWindow+BlockStart;
494 VInt Counter=BlockSize;
495 while(Counter--)
496 {
497 *Dest++=*Src++;
498 }
499 }
500 else
501 {
502 VUInt ByteContent=0;
503 VBuffer WriteEntry=FWindow+FUsedWindowSize;
504 VInt Counter=BlockSize;
505 while(Counter--)
506 {
507 if(!FReader->ReadNumber(ByteContent,8))
508 {
509 return 0;
510 }
511 *WriteEntry++=(VByte)ByteContent;
512 }
513 }
514 FUsedWindowSize+=BlockSize;
515 if(FUsedWindowSize>WindowSize)
516 {
517 VInt MoveSize=FUsedWindowSize-WindowSize;
518 memmove(FWindow,FWindow+MoveSize,WindowSize);
519 FUsedWindowSize=WindowSize;
520 FWindowStartPosition+=MoveSize;
521 }
522 return BlockSize;
523 }
524
525 Decompressor::Decompressor(VInt WindowSizeLevel):AlgorithmBase(WindowSizeLevel)
526 {
527 FReader=0;
528 }
529
530 Decompressor::~Decompressor()
531 {
532 SetStream(0);
533 }
534
535 void Decompressor::SetStream(IVL_Stream* Stream)
536 {
537 if(FReader)
538 {
539 delete FReader;
540 FReader=0;
541 }
542 if(Stream)
543 {
544 FReader=new VL_BitReader(Stream,false);
545 }
546 }
547
548 VInt Decompressor::Read(VPointer Data , VInt ByteCount)
549 {
550 VBuffer Buffer=(VBuffer)Data;
551 VInt WrittenCount=0;
552 while(WrittenCount<ByteCount)
553 {
554 if(FWindowStartPosition+FUsedWindowSize==FPosition)
555 {
556 if(DecompressBlock()==0)
557 {
558 break;
559 }
560 }
561
562 VInt NeedCount=ByteCount-WrittenCount;
563 VInt AllowSize=(VInt)(FWindowStartPosition+FUsedWindowSize-FPosition);
564 VInt ReadSize=NeedCount<AllowSize?NeedCount:AllowSize;
565 if(ReadSize)
566 {
567 memcpy(Buffer,FWindow+(FPosition-FWindowStartPosition),ReadSize);
568 WrittenCount+=ReadSize;
569 Buffer+=ReadSize;
570 FPosition+=ReadSize;
571 }
572 else
573 {
574 break;
575 }
576 }
577 return WrittenCount;
578 }
579
580 }
581
582 }
583 }
posted on 2009-01-06 23:35
陈梓瀚(vczh) 阅读(2992)
评论(6) 编辑 收藏 引用 所属分类:
C++