spzlibcompress.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       DynamicSkinForm                                             }
  5. {       Version 5.60                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2003 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14. unit spzlibcompress;
  15. {$WARNINGS OFF}
  16. {$HINTS OFF}
  17. interface
  18. uses Sysutils, Classes, spzlib;
  19. const
  20.   BufSize = 4096;
  21.    
  22. type
  23.   TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer;
  24.   TFree = procedure (AppData, Block: Pointer);
  25.   TZStreamRec = z_stream;
  26.   TCustomZlibStream = class(TStream)
  27.   private
  28.     FStrm: TStream;
  29.     FStrmPos: Integer;
  30.     FOnProgress: TNotifyEvent;
  31.     FZRec: TZStreamRec;
  32.     FBuffer: array [0..BufSize - 1] of Char;
  33.   protected
  34.     procedure Progress(Sender: TObject); dynamic;
  35.     property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
  36.     constructor Create(Strm: TStream);
  37.   end;
  38.   TCompressionLevel = (clNone, clFastest, clDefault, clMax);
  39.   TCompressionStream = class(TCustomZlibStream)
  40.   private
  41.     function GetCompressionRate: Single;
  42.   public
  43.     constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
  44.     destructor Destroy; override;
  45.     function Read(var Buffer; Count: Longint): Longint; override;
  46.     function Write(const Buffer; Count: Longint): Longint; override;
  47.     function Seek(Offset: Longint; Origin: Word): Longint; override;
  48.     property CompressionRate: Single read GetCompressionRate;
  49.     property OnProgress;
  50.   end;
  51.   TDecompressionStream = class(TCustomZlibStream)
  52.   public
  53.     constructor Create(Source: TStream);
  54.     destructor Destroy; override;
  55.     function Read(var Buffer; Count: Longint): Longint; override;
  56.     function Write(const Buffer; Count: Longint): Longint; override;
  57.     function Seek(Offset: Longint; Origin: Word): Longint; override;
  58.     property OnProgress;
  59.   end;
  60. const
  61.   zlib_version = '1.1.4';
  62. type
  63.   EZlibError = class(Exception);
  64.   ECompressionError = class(EZlibError);
  65.   EDecompressionError = class(EZlibError);
  66. procedure CompressStream(Stream, SaveStream: TStream);
  67. procedure DeCompressStream(Stream, CompressedStream: TStream);
  68. implementation
  69. const
  70.   Z_NO_FLUSH      = 0;
  71.   Z_PARTIAL_FLUSH = 1;
  72.   Z_SYNC_FLUSH    = 2;
  73.   Z_FULL_FLUSH    = 3;
  74.   Z_FINISH        = 4;
  75.   Z_OK            = 0;
  76.   Z_STREAM_END    = 1;
  77.   Z_NEED_DICT     = 2;
  78.   Z_ERRNO         = (-1);
  79.   Z_STREAM_ERROR  = (-2);
  80.   Z_DATA_ERROR    = (-3);
  81.   Z_MEM_ERROR     = (-4);
  82.   Z_BUF_ERROR     = (-5);
  83.   Z_VERSION_ERROR = (-6);
  84.   Z_NO_COMPRESSION       =   0;
  85.   Z_BEST_SPEED           =   1;
  86.   Z_BEST_COMPRESSION     =   9;
  87.   Z_DEFAULT_COMPRESSION  = (-1);
  88.   Z_FILTERED            = 1;
  89.   Z_HUFFMAN_ONLY        = 2;
  90.   Z_DEFAULT_STRATEGY    = 0;
  91.   Z_BINARY   = 0;
  92.   Z_ASCII    = 1;
  93.   Z_UNKNOWN  = 2;
  94.   Z_DEFLATED = 8;
  95.   _z_errmsg: array[0..9] of PChar = (
  96.     'need dictionary',      // Z_NEED_DICT      (2)
  97.     'stream end',           // Z_STREAM_END     (1)
  98.     '',                     // Z_OK             (0)
  99.     'file error',           // Z_ERRNO          (-1)
  100.     'stream error',         // Z_STREAM_ERROR   (-2)
  101.     'data error',           // Z_DATA_ERROR     (-3)
  102.     'insufficient memory',  // Z_MEM_ERROR      (-4)
  103.     'buffer error',         // Z_BUF_ERROR      (-5)
  104.     'incompatible version', // Z_VERSION_ERROR  (-6)
  105.     ''
  106.   );
  107. procedure _memset(P: Pointer; B: Byte; count: Integer);cdecl;
  108. begin
  109.   FillChar(P^, count, B);
  110. end;
  111. procedure _memcpy(dest, source: Pointer; count: Integer);cdecl;
  112. begin
  113.   Move(source^, dest^, count);
  114. end;
  115. function zcalloc(AppData: Pointer; Items, Size: Integer): Pointer;
  116. begin
  117.   GetMem(Result, Items*Size);
  118. end;
  119. procedure zcfree(AppData, Block: Pointer);
  120. begin
  121.   FreeMem(Block);
  122. end;
  123. function CCheck(code: Integer): Integer;
  124. begin
  125.   Result := code;
  126.   if code < 0 then
  127.     raise ECompressionError.Create('error');  
  128. end;
  129. function DCheck(code: Integer): Integer;
  130. begin
  131.   Result := code;
  132.   if code < 0 then
  133.     raise EDecompressionError.Create('compression error');
  134. end;
  135. constructor TCustomZLibStream.Create(Strm: TStream);
  136. begin
  137.   inherited Create;
  138.   FStrm := Strm;
  139.   FStrmPos := Strm.Position;
  140. end;
  141. procedure TCustomZLibStream.Progress(Sender: TObject);
  142. begin
  143.   if Assigned(FOnProgress) then FOnProgress(Sender);
  144. end;
  145. constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
  146.   Dest: TStream);
  147. const
  148.   Levels: array [TCompressionLevel] of ShortInt =
  149.     (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
  150. begin
  151.   inherited Create(Dest);
  152.   FZRec.next_out := @FBuffer;
  153.   FZRec.avail_out := sizeof(FBuffer);
  154.   CCheck(deflateInit_(@FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
  155. end;
  156. destructor TCompressionStream.Destroy;
  157. begin
  158.   FZRec.next_in := nil;
  159.   FZRec.avail_in := 0;
  160.   try
  161.     if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
  162.     while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
  163.       and (FZRec.avail_out = 0) do
  164.     begin
  165.       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
  166.       FZRec.next_out := @FBuffer;
  167.       FZRec.avail_out := sizeof(FBuffer);
  168.     end;
  169.     if FZRec.avail_out < sizeof(FBuffer) then
  170.       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
  171.   finally
  172.     deflateEnd(FZRec);
  173.   end;
  174.   inherited Destroy;
  175. end;
  176. function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
  177. begin
  178.   raise ECompressionError.Create('Invalid stream operation');
  179. end;
  180. function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
  181. begin
  182.   FZRec.next_in := @Buffer;
  183.   FZRec.avail_in := Count;
  184.   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
  185.   while (FZRec.avail_in > 0) do
  186.   begin
  187.     CCheck(deflate(FZRec, 0));
  188.     if FZRec.avail_out = 0 then
  189.     begin
  190.       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
  191.       FZRec.next_out := @FBuffer;
  192.       FZRec.avail_out := sizeof(FBuffer);
  193.       FStrmPos := FStrm.Position;
  194.       Progress(Self);
  195.     end;
  196.   end;
  197.   Result := Count;
  198. end;
  199. function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
  200. begin
  201.   if (Offset = 0) and (Origin = soFromCurrent) then
  202.     Result := FZRec.total_in
  203.   else
  204.     raise ECompressionError.Create('Invalid stream operation');
  205. end;
  206. function TCompressionStream.GetCompressionRate: Single;
  207. begin
  208.   if FZRec.total_in = 0 then
  209.     Result := 0
  210.   else
  211.     Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
  212. end;
  213. constructor TDecompressionStream.Create(Source: TStream);
  214. begin
  215.   inherited Create(Source);
  216.   FZRec.next_in := @FBuffer;
  217.   FZRec.avail_in := 0;
  218.   DCheck(inflateInit_(@FZRec, zlib_version, sizeof(FZRec)));
  219. end;
  220. destructor TDecompressionStream.Destroy;
  221. begin
  222.   inflateEnd(FZRec);
  223.   inherited Destroy;
  224. end;
  225. function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
  226. begin
  227.   FZRec.next_out := @Buffer;
  228.   FZRec.avail_out := Count;
  229.   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
  230.   while (FZRec.avail_out > 0) do
  231.   begin
  232.     if FZRec.avail_in = 0 then
  233.     begin
  234.       FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
  235.       if FZRec.avail_in = 0 then
  236.         begin
  237.           Result := Count - Longint(FZRec.avail_out);
  238.           Exit;
  239.         end;
  240.       FZRec.next_in := @FBuffer;
  241.       FStrmPos := FStrm.Position;
  242.       Progress(Self);
  243.     end;
  244.     DCheck(inflate(FZRec, 0));
  245.   end;
  246.   Result := Count;
  247. end;
  248. function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
  249. begin
  250.   raise EDecompressionError.Create('Invalid stream operation');
  251. end;
  252. function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
  253. var
  254.   I: Integer;
  255.   Buf: array [0..4095] of Char;
  256. begin
  257.   if (Offset = 0) and (Origin = soFromBeginning) then
  258.   begin
  259.     DCheck(inflateReset(FZRec));
  260.     FZRec.next_in := @FBuffer;
  261.     FZRec.avail_in := 0;
  262.     FStrm.Position := 0;
  263.     FStrmPos := 0;
  264.   end
  265.   else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
  266.           ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
  267.   begin
  268.     if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
  269.     if Offset > 0 then
  270.     begin
  271.       for I := 1 to Offset div sizeof(Buf) do
  272.         ReadBuffer(Buf, sizeof(Buf));
  273.       ReadBuffer(Buf, Offset mod sizeof(Buf));
  274.     end;
  275.   end
  276.   else
  277.     raise EDecompressionError.Create('Invalid stream operation');
  278.   Result := FZRec.total_out;
  279. end;
  280. procedure CompressStream(Stream, SaveStream: TStream);
  281. var
  282.   CompStrm: TCompressionStream;
  283. begin
  284.   CompStrm := TCompressionStream.Create(clMax, SaveStream);
  285.   try
  286.     Stream.Seek(0, 0);
  287.     CompStrm.CopyFrom(Stream, 0);
  288.   finally
  289.     CompStrm.Free;
  290.   end;
  291. end;
  292. procedure DeCompressStream(Stream, CompressedStream: TStream);
  293. var
  294.   Size: LongInt;
  295.   DecompStrm: TDecompressionStream;
  296.   Buf: array[0..BufSize - 1] of Byte;
  297. begin
  298.   CompressedStream.Seek(0, 0);
  299.   DeCompStrm := TDecompressionStream.Create(CompressedStream);
  300.   try
  301.     while True do
  302.     begin
  303.       Size := DecompStrm.Read(Buf, BufSize);
  304.       if Size <> 0 then Stream.WriteBuffer(Buf, Size) else Break;
  305.     end;
  306.   finally
  307.     DecompStrm.Free;
  308.   end;
  309. end;
  310. end.