PNGZLIB.pas
上传用户:zdp402
上传日期:2022-05-07
资源大小:101k
文件大小:18k
源码类别:

图片显示

开发平台:

Delphi

  1. unit PNGZLIB;
  2. { Delphi 3 compatibility by Paul TOTH <tothpaul@free.fr> }
  3. interface
  4. uses
  5.   Sysutils, Classes;
  6. const
  7.   ZLIB_VERSION = '1.1.3';
  8. type
  9.   TZAlloc = function (opaque: Pointer; items, size: Integer): Pointer;
  10.   TZFree  = procedure (opaque, block: Pointer);
  11.   TZCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
  12.   {** TZStreamRec ***********************************************************}
  13.   TZStreamRec = packed record
  14.     next_in  : PChar;     // next input byte
  15.     avail_in : Longint;   // number of bytes available at next_in
  16.     total_in : Longint;   // total nb of input bytes read so far
  17.     next_out : PChar;     // next output byte should be put here
  18.     avail_out: Longint;   // remaining free space at next_out
  19.     total_out: Longint;   // total nb of bytes output so far
  20.     msg      : PChar;     // last error message, NULL if no error
  21.     state    : Pointer;   // not visible by applications
  22.     zalloc   : TZAlloc;   // used to allocate the internal state
  23.     zfree    : TZFree;    // used to free the internal state
  24.     opaque   : Pointer;   // private data object passed to zalloc and zfree
  25.     data_type: Integer;   // best guess about the data type: ascii or binary
  26.     adler    : Longint;   // adler32 value of the uncompressed data
  27.     reserved : Longint;   // reserved for future use
  28.   end;
  29.   {** TCustomZStream ********************************************************}
  30.   TCustomZStream = class(TStream)
  31.   private
  32.     FStream    : TStream;
  33.     FStreamPos : Integer;
  34.     FOnProgress: TNotifyEvent;
  35.     FZStream   : TZStreamRec;
  36.     FBuffer    : Array [Word] of Char;
  37.   protected
  38.     constructor Create(stream: TStream);
  39.     procedure DoProgress; dynamic;
  40.     property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
  41.   end;
  42.   {** TZCompressionStream ***************************************************}
  43.   TZCompressionStream = class(TCustomZStream)
  44.   private
  45.     function GetCompressionRate: Single;
  46.   public
  47.     constructor Create(dest: TStream; compressionLevel: TZCompressionLevel {Paul= zcDefault{});
  48.     destructor  Destroy; override;
  49.     function  Read(var buffer; count: Longint): Longint; override;
  50.     function  Write(const buffer; count: Longint): Longint; override;
  51.     function  Seek(offset: Longint; origin: Word): Longint; override;
  52.     property CompressionRate: Single read GetCompressionRate;
  53.     property OnProgress;
  54.   end;
  55.   {** TZDecompressionStream *************************************************}
  56.   TZDecompressionStream = class(TCustomZStream)
  57.   public
  58.     constructor Create(source: TStream);
  59.     destructor  Destroy; override;
  60.     function  Read(var buffer; count: Longint): Longint; override;
  61.     function  Write(const buffer; count: Longint): Longint; override;
  62.     function  Seek(offset: Longint; origin: Word): Longint; override;
  63.     property OnProgress;
  64.   end;
  65. {** zlib public routines ****************************************************}
  66. {*****************************************************************************
  67. *  ZCompress                                                                 *
  68. *                                                                            *
  69. *  pre-conditions                                                            *
  70. *    inBuffer  = pointer to uncompressed data                                *
  71. *    inSize    = size of inBuffer (bytes)                                    *
  72. *    outBuffer = pointer (unallocated)                                       *
  73. *    level     = compression level                                           *
  74. *                                                                            *
  75. *  post-conditions                                                           *
  76. *    outBuffer = pointer to compressed data (allocated)                      *
  77. *    outSize   = size of outBuffer (bytes)                                   *
  78. *****************************************************************************}
  79. procedure ZCompress(const inBuffer: Pointer; inSize: Integer;
  80.   out outBuffer: Pointer; out outSize: Integer;
  81.   level: TZCompressionLevel { Paul = zcDefault});
  82. {*****************************************************************************
  83. *  ZDecompress                                                               *
  84. *                                                                            *
  85. *  pre-conditions                                                            *
  86. *    inBuffer    = pointer to compressed data                                *
  87. *    inSize      = size of inBuffer (bytes)                                  *
  88. *    outBuffer   = pointer (unallocated)                                     *
  89. *    outEstimate = estimated size of uncompressed data (bytes)               *
  90. *                                                                            *
  91. *  post-conditions                                                           *
  92. *    outBuffer = pointer to decompressed data (allocated)                    *
  93. *    outSize   = size of outBuffer (bytes)                                   *
  94. *****************************************************************************}
  95. procedure ZDecompress(const inBuffer: Pointer; inSize: Integer;
  96.  out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer {Paul = 0});
  97. {** string routines *********************************************************}
  98. function ZCompressStr(const s: String; level: TZCompressionLevel {Paul= zcDefault}): String;
  99. function ZDecompressStr(const s: String): String;
  100. type
  101.   EZLibError = class(Exception);
  102.   EZCompressionError = class(EZLibError);
  103.   EZDecompressionError = class(EZLibError);
  104. implementation
  105. {** link zlib code **********************************************************}
  106. {$L deflate.obj}
  107. {$L inflate.obj}
  108. {$L infblock.obj}
  109. {$L inftrees.obj}
  110. {$L infcodes.obj}
  111. {$L infutil.obj}
  112. {$L inffast.obj}
  113. {$L trees.obj}
  114. {$L adler32.obj}
  115. {*****************************************************************************
  116. *  note: do not reorder the above -- doing so will result in external        *
  117. *  functions being undefined                                                 *
  118. *****************************************************************************}
  119. const
  120.   {** flush constants *******************************************************}
  121.   Z_NO_FLUSH      = 0;
  122.   Z_PARTIAL_FLUSH = 1;
  123.   Z_SYNC_FLUSH    = 2;
  124.   Z_FULL_FLUSH    = 3;
  125.   Z_FINISH        = 4;
  126.   {** return codes **********************************************************}
  127.   Z_OK            = 0;
  128.   Z_STREAM_END    = 1;
  129.   Z_NEED_DICT     = 2;
  130.   Z_ERRNO         = (-1);
  131.   Z_STREAM_ERROR  = (-2);
  132.   Z_DATA_ERROR    = (-3);
  133.   Z_MEM_ERROR     = (-4);
  134.   Z_BUF_ERROR     = (-5);
  135.   Z_VERSION_ERROR = (-6);
  136.   {** compression levels ****************************************************}
  137.   Z_NO_COMPRESSION       =   0;
  138.   Z_BEST_SPEED           =   1;
  139.   Z_BEST_COMPRESSION     =   9;
  140.   Z_DEFAULT_COMPRESSION  = (-1);
  141.   {** compression strategies ************************************************}
  142.   Z_FILTERED            = 1;
  143.   Z_HUFFMAN_ONLY        = 2;
  144.   Z_DEFAULT_STRATEGY    = 0;
  145.   {** data types ************************************************************}
  146.   Z_BINARY   = 0;
  147.   Z_ASCII    = 1;
  148.   Z_UNKNOWN  = 2;
  149.   {** compression methods ***************************************************}
  150.   Z_DEFLATED = 8;
  151.   {** return code messages **************************************************}
  152.   _z_errmsg: array[0..9] of PChar = (
  153.     'need dictionary',      // Z_NEED_DICT      (2)
  154.     'stream end',           // Z_STREAM_END     (1)
  155.     '',                     // Z_OK             (0)
  156.     'file error',           // Z_ERRNO          (-1)
  157.     'stream error',         // Z_STREAM_ERROR   (-2)
  158.     'data error',           // Z_DATA_ERROR     (-3)
  159.     'insufficient memory',  // Z_MEM_ERROR      (-4)
  160.     'buffer error',         // Z_BUF_ERROR      (-5)
  161.     'incompatible version', // Z_VERSION_ERROR  (-6)
  162.     ''
  163.   );
  164.   ZLevels: array [TZCompressionLevel] of Shortint = (
  165.     Z_NO_COMPRESSION,
  166.     Z_BEST_SPEED,
  167.     Z_DEFAULT_COMPRESSION,
  168.     Z_BEST_COMPRESSION
  169.   );
  170.   SZInvalid = 'Invalid ZStream operation!';
  171. {** deflate routines ********************************************************}
  172. function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
  173.   recsize: Integer): Integer; external;
  174. function deflate(var strm: TZStreamRec; flush: Integer): Integer;
  175.   external;
  176. function deflateEnd(var strm: TZStreamRec): Integer; external;
  177. {** inflate routines ********************************************************}
  178. function inflateInit_(var strm: TZStreamRec; version: PChar;
  179.   recsize: Integer): Integer; external;
  180. function inflate(var strm: TZStreamRec; flush: Integer): Integer;
  181.   external;
  182. function inflateEnd(var strm: TZStreamRec): Integer; external;
  183. function inflateReset(var strm: TZStreamRec): Integer; external;
  184. {** zlib function implementations *******************************************}
  185. function zcalloc(opaque: Pointer; items, size: Integer): Pointer;
  186. begin
  187.   GetMem(result,items * size);
  188. end;
  189. procedure zcfree(opaque, block: Pointer);
  190. begin
  191.   FreeMem(block);
  192. end;
  193. {** c function implementations **********************************************}
  194. procedure _memset(p: Pointer; b: Byte; count: Integer); cdecl;
  195. begin
  196.   FillChar(p^,count,b);
  197. end;
  198. procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
  199. begin
  200.   Move(source^,dest^,count);
  201. end;
  202. {** custom zlib routines ****************************************************}
  203. function DeflateInit(var stream: TZStreamRec; level: Integer): Integer;
  204. begin
  205.   result := DeflateInit_(stream,level,ZLIB_VERSION,SizeOf(TZStreamRec));
  206. end;
  207. // function DeflateInit2(var stream: TZStreamRec; level, method, windowBits,
  208. //   memLevel, strategy: Integer): Integer;
  209. // begin
  210. //   result := DeflateInit2_(stream,level,method,windowBits,memLevel,
  211. //     strategy,ZLIB_VERSION,SizeOf(TZStreamRec));
  212. // end;
  213. function InflateInit(var stream: TZStreamRec): Integer;
  214. begin
  215.   result := InflateInit_(stream,ZLIB_VERSION,SizeOf(TZStreamRec));
  216. end;
  217. // function InflateInit2(var stream: TZStreamRec; windowBits: Integer): Integer;
  218. // begin
  219. //   result := InflateInit2_(stream,windowBits,ZLIB_VERSION,SizeOf(TZStreamRec));
  220. // end;
  221. {****************************************************************************}
  222. function ZCompressCheck(code: Integer): Integer;
  223. begin
  224.   result := code;
  225.   if code < 0 then
  226.   begin
  227.     raise EZCompressionError.Create(_z_errmsg[2 - code]);
  228.   end;
  229. end;
  230. function ZDecompressCheck(code: Integer): Integer;
  231. begin
  232.   Result := code;
  233.   if code < 0 then
  234.   begin
  235.     raise EZDecompressionError.Create(_z_errmsg[2 - code]);
  236.   end;
  237. end;
  238. procedure ZCompress(const inBuffer: Pointer; inSize: Integer;
  239.   out outBuffer: Pointer; out outSize: Integer;
  240.   level: TZCompressionLevel);
  241. const
  242.   delta = 256;
  243. var
  244.   zstream: TZStreamRec;
  245. begin
  246.   FillChar(zstream,SizeOf(TZStreamRec),0);
  247.   outSize := ((inSize + (inSize div 10) + 12) + 255) and not 255;
  248.   GetMem(outBuffer,outSize);
  249.   try
  250.     zstream.next_in := inBuffer;
  251.     zstream.avail_in := inSize;
  252.     zstream.next_out := outBuffer;
  253.     zstream.avail_out := outSize;
  254.     ZCompressCheck(DeflateInit(zstream,ZLevels[level]));
  255.     try
  256.       while ZCompressCheck(deflate(zstream,Z_FINISH)) <> Z_STREAM_END do
  257.       begin
  258.         Inc(outSize,delta);
  259.         ReallocMem(outBuffer,outSize);
  260.         zstream.next_out := PChar(Integer(outBuffer) + zstream.total_out);
  261.         zstream.avail_out := delta;
  262.       end;
  263.     finally
  264.       ZCompressCheck(deflateEnd(zstream));
  265.     end;
  266.     ReallocMem(outBuffer,zstream.total_out);
  267.     outSize := zstream.total_out;
  268.   except
  269.     FreeMem(outBuffer);
  270.     raise;
  271.   end;
  272. end;
  273. procedure ZDecompress(const inBuffer: Pointer; inSize: Integer;
  274.   out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
  275. var
  276.   zstream: TZStreamRec;
  277.   delta  : Integer;
  278. begin
  279.   FillChar(zstream,SizeOf(TZStreamRec),0);
  280.   delta := (inSize + 255) and not 255;
  281.   if outEstimate = 0 then outSize := delta
  282.   else outSize := outEstimate;
  283.   GetMem(outBuffer,outSize);
  284.   try
  285.     zstream.next_in := inBuffer;
  286.     zstream.avail_in := inSize;
  287.     zstream.next_out := outBuffer;
  288.     zstream.avail_out := outSize;
  289.     ZDecompressCheck(InflateInit(zstream));
  290.     try
  291.       while ZDecompressCheck(inflate(zstream,Z_NO_FLUSH)) <> Z_STREAM_END do
  292.       begin
  293.         Inc(outSize,delta);
  294.         ReallocMem(outBuffer,outSize);
  295.         zstream.next_out := PChar(Integer(outBuffer) + zstream.total_out);
  296.         zstream.avail_out := delta;
  297.       end;
  298.     finally
  299.       ZDecompressCheck(inflateEnd(zstream));
  300.     end;
  301.     ReallocMem(outBuffer,zstream.total_out);
  302.     outSize := zstream.total_out;
  303.   except
  304.     FreeMem(outBuffer);
  305.     raise;
  306.   end;
  307. end;
  308. function ZCompressStr(const s: String; level: TZCompressionLevel): String;
  309. var
  310.   buffer: Pointer;
  311.   size  : Integer;
  312. begin
  313.   ZCompress(PChar(s),Length(s),buffer,size,level);
  314.   SetLength(result,size);
  315.   Move(buffer^,result[1],size);
  316.   FreeMem(buffer);
  317. end;
  318. function ZDecompressStr(const s: String): String;
  319. var
  320.   buffer: Pointer;
  321.   size  : Integer;
  322. begin
  323.   ZDecompress(PChar(s),Length(s),buffer,size,0);
  324.   SetLength(result,size);
  325.   Move(buffer^,result[1],size);
  326.   FreeMem(buffer);
  327. end;
  328. {** TCustomZStream **********************************************************}
  329. constructor TCustomZStream.Create(stream: TStream);
  330. begin
  331.   inherited Create;
  332.   FStream := stream;
  333.   FStreamPos := stream.Position;
  334. end;
  335. procedure TCustomZStream.DoProgress;
  336. begin
  337.   if Assigned(FOnProgress) then FOnProgress(Self);
  338. end;
  339. {** TZCompressionStream *****************************************************}
  340. constructor TZCompressionStream.Create(dest: TStream;
  341.   compressionLevel: TZCompressionLevel);
  342. begin
  343.   inherited Create(dest);
  344.   FZStream.next_out := FBuffer;
  345.   FZStream.avail_out := SizeOf(FBuffer);
  346.   ZCompressCheck(DeflateInit(FZStream,ZLevels[compressionLevel]));
  347. end;
  348. destructor TZCompressionStream.Destroy;
  349. begin
  350.   FZStream.next_in := Nil;
  351.   FZStream.avail_in := 0;
  352.   try
  353.     if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
  354.     while ZCompressCheck(deflate(FZStream,Z_FINISH)) <> Z_STREAM_END do
  355.     begin
  356.       FStream.WriteBuffer(FBuffer,SizeOf(FBuffer) - FZStream.avail_out);
  357.       FZStream.next_out := FBuffer;
  358.       FZStream.avail_out := SizeOf(FBuffer);
  359.     end;
  360.     if FZStream.avail_out < SizeOf(FBuffer) then
  361.     begin
  362.       FStream.WriteBuffer(FBuffer,SizeOf(FBuffer) - FZStream.avail_out);
  363.     end;
  364.   finally
  365.     deflateEnd(FZStream);
  366.   end;
  367.   inherited Destroy;
  368. end;
  369. function TZCompressionStream.Read(var buffer; count: Longint): Longint;
  370. begin
  371.   raise EZCompressionError.Create(SZInvalid);
  372. end;
  373. function TZCompressionStream.Write(const buffer; count: Longint): Longint;
  374. begin
  375.   FZStream.next_in := @buffer;
  376.   FZStream.avail_in := count;
  377.   if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
  378.   while FZStream.avail_in > 0 do
  379.   begin
  380.     ZCompressCheck(deflate(FZStream,Z_NO_FLUSH));
  381.     if FZStream.avail_out = 0 then
  382.     begin
  383.       FStream.WriteBuffer(FBuffer,SizeOf(FBuffer));
  384.       FZStream.next_out := FBuffer;
  385.       FZStream.avail_out := SizeOf(FBuffer);
  386.       FStreamPos := FStream.Position;
  387.       DoProgress;
  388.     end;
  389.   end;
  390.   result := Count;
  391. end;
  392. function TZCompressionStream.Seek(offset: Longint; origin: Word): Longint;
  393. begin
  394.   if (offset = 0) and (origin = soFromCurrent) then
  395.   begin
  396.     result := FZStream.total_in;
  397.   end
  398.   else raise EZCompressionError.Create(SZInvalid);
  399. end;
  400. function TZCompressionStream.GetCompressionRate: Single;
  401. begin
  402.   if FZStream.total_in = 0 then result := 0
  403.   else result := (1.0 - (FZStream.total_out / FZStream.total_in)) * 100.0;
  404. end;
  405. {** TZDecompressionStream ***************************************************}
  406. constructor TZDecompressionStream.Create(source: TStream);
  407. begin
  408.   inherited Create(source);
  409.   FZStream.next_in := FBuffer;
  410.   FZStream.avail_in := 0;
  411.   ZDecompressCheck(InflateInit(FZStream));
  412. end;
  413. destructor TZDecompressionStream.Destroy;
  414. begin
  415.   inflateEnd(FZStream);
  416.   inherited Destroy;
  417. end;
  418. function TZDecompressionStream.Read(var buffer; count: Longint): Longint;
  419. begin
  420.   FZStream.next_out := @buffer;
  421.   FZStream.avail_out := count;
  422.   if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
  423.   while FZStream.avail_out > 0 do
  424.   begin
  425.     if FZStream.avail_in = 0 then
  426.     begin
  427.       FZStream.avail_in := FStream.Read(FBuffer,SizeOf(FBuffer));
  428.       if FZStream.avail_in = 0 then
  429.       begin
  430.         result := count - FZStream.avail_out;
  431.         Exit;
  432.       end;
  433.       FZStream.next_in := FBuffer;
  434.       FStreamPos := FStream.Position;
  435.       DoProgress;
  436.     end;
  437.     ZDecompressCheck(inflate(FZStream,Z_NO_FLUSH));
  438.   end;
  439.   result := Count;
  440. end;
  441. function TZDecompressionStream.Write(const Buffer; Count: Longint): Longint;
  442. begin
  443.   raise EZDecompressionError.Create(SZInvalid);
  444. end;
  445. function TZDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
  446. var
  447.   buf: Array [0..4095] of Char;
  448.   i  : Integer;
  449. begin
  450.   if (offset = 0) and (origin = soFromBeginning) then
  451.   begin
  452.     ZDecompressCheck(inflateReset(FZStream));
  453.     FZStream.next_in := FBuffer;
  454.     FZStream.avail_in := 0;
  455.     FStream.Position := 0;
  456.     FStreamPos := 0;
  457.   end
  458.   else if ((offset >= 0) and (origin = soFromCurrent)) or
  459.           (((offset - FZStream.total_out) > 0) and (origin = soFromBeginning)) then
  460.   begin
  461.     if origin = soFromBeginning then Dec(offset,FZStream.total_out);
  462.     if offset > 0 then
  463.     begin
  464.       for i := 1 to offset div SizeOf(buf) do ReadBuffer(buf,SizeOf(buf));
  465.       ReadBuffer(buf,offset mod SizeOf(buf));
  466.     end;
  467.   end
  468.   else raise EZDecompressionError.Create(SZInvalid);
  469.   result := FZStream.total_out;
  470. end;
  471. end.