萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 編程語言綜合 >> Delphi壓縮流和解壓流的應用

Delphi壓縮流和解壓流的應用

  軟件開發者不免都要遇到壓縮數據的問題!經常使用Delphi的朋友都知道,它為我們提供了兩個流類(TCompressionStream和TDecompressionStream)來完成數據的壓縮和解壓縮,但美中不足的是,該流在Delphi 的幫助中沒有詳細的說明,使得它們在使用起來有一定得困難。其實在Delphi系統中提供了這兩個類的源代碼和庫。保存在Delphi 光盤的InfoExtraslib Src和InfoExtraslibObj目錄中(其中OBJ目錄中保存的是庫,Src目錄中保存的是源代碼,感興趣的朋友可以看看)。本人在使用的過程中,對它們有了一定的了解。

  一、 類的說明

  1、 基類 TCustomZlibStream:類TCustomZlibStream 是類TCompressionStream和TDecompressionStream 類的基類,它主要有一個屬性: OnProgress,在類進行壓縮或解壓縮的過程中會發生這個的事件 ,它的定義如下:

  Procedure OnProgress (Sender: TObject); dynamic;

  2、 壓縮類TCompressionStream:類TCompressionStream除了繼承了基類的 OnProgress 屬性外,又增加了一個屬性:CompressionRate,它的定義如下:

  Property CompressionRate: Single read GetCompressionRate;通過這個屬性,可以得到壓縮比。

  它的幾個重要的方法定義如下:

  Constructor TCompressionStream.Create (CompressionLevel: TCompressionLevel; Dest: TStream);

  其中:TcompressionLevel(壓縮類型),它由如下幾個定義:

  ①、 clNone :不進行數據壓縮;

  ②、 clFastest:進行快速壓縮,犧牲壓縮效率;

  ③、 clDefault:進行正常壓縮;

  ④、 clMax: 進行最大化壓縮,犧牲速度;

  Dest:目的流,用於存放壓縮過的數據。

  Function TCompressionStream.Write (const Buffer; Count: Longint): Longint;

  其中:Buffer:需要壓縮的數據;

  Count: 需要壓縮的數據的字節數;

  函數返回寫入流的字節數。

  壓縮類TCompressionStream的數據只能是寫入的,如果試圖從其內部讀取數據,將發生一個"Error "異常。需要壓縮的數據通過方法 Write寫入流中,在寫入的過程中就被壓縮,並保存在由構造函數提供的內存流(TmemoryStream)中,同時觸發 OnProcess 事件。

  3、 解壓縮類 TDecompressionStream :和壓縮類TcompressionStream 相反,它的數據是只能讀出的,如果試圖往其內部寫數據,將發生一個"Error "異常。它的幾個重要方法定義如下:

  構造函數:Constructor Create(Source: TStream);

  其中:Source 是保存著壓縮數據的流;

  Function Read(var Buffer; Count: Longint): Longint;

  數據讀出函數,Buffer: 存數據緩沖區;

  Count: 緩沖區的大小;

  函數返回讀出的字節數。

  數據在讀出的過程中,數據被解壓縮,並觸發 OnProcess 事件。

  二、 類的使用

  通過類TCompressionStream和TdecompressionStream的配合使用,我們可以非常方便地完成數據的壓縮和解壓,下面就是本人在編寫屏幕拷貝程序中的使用例子:

  Procedure TClientForm.GetScreen;

  Var

  SourceDC,DestDC:HDC;

  Bhandle:HBITMAP;

  BitMap:TBitMap;

  BmpStream,Deststream:TMemoryStream;

  SourceStream:TCompressionStream;

  Count:Integer;

  Begin

  SourceDC:=CreateDC('display','','',nil);

  {得到屏幕的 DC}

  DestDC:=CreateCompatibleDC(SourceDC);

  {建立臨時 DC}

  Bhandle:=CreateCompatibleBitmap(SourceDC,Screen.Width, Screen.Height);

  {建立位圖}

  SelectObject(DestDC,Bhandle);

  {選擇位圖DC}

  BitBlt(DestDC,0,0,Screen.Width, Screen.Height,SourceDC,0,0,SRCCOPY);

  {拷貝整個屏幕}

  BitMap:=TBitMap.Create;

  BitMap.Handle := Bhandle;

  {保存屏幕位圖到 BitMap中}

  BmpStream:=TMemoryStream.Create;

  BitMap.SaveToStream(BmpStream);

  {建立位圖數據的內存流}

  count:=BmpStream.Size;

  {保存位圖的大小}

  DestStream:=TMemoryStream.Create;

  {目標流,保存壓縮數據}

  SourceStream:=TCompressionStream.Create(clMax, DestStream);

  {構建壓縮流,采用最大化壓縮,並保存到目標流中}

  try

  BmpStream.SaveToStream(SourceStream);

  {壓縮位圖流}

  SourceStream.Free;

  {完成壓縮,釋放壓縮流}

  BmpStream.Clear;

  {清空原來位圖流}

  BmpStream.WriteBuffer(Count, Sizeof(Count));

  {將原來位圖的大小保存到新的位圖流中,以便使用}

  BmpStream.CopyFrom(DestStream, 0);

  {將壓縮數據附加到新的位圖流後面}

  BmpStream.Position := 0;

  NMStrm.PostIt(BmpStream);

  {發送位圖流}

  finally

  DestStream.Free;

  BmpStream.Destroy ;

  BitMap.Destroy;

  DeleteDC(SourceDC);

  ReleaseDC(Bhandle,SourceDC);

  end;

  {釋放有關資源}

  End;

  該過程得到整個屏幕的圖象拷貝,並利用壓縮流SourceStream和內存流 Deststream將位圖壓縮,並重新把位圖大小和壓縮數據流保存到位圖流中,發送出去,發送位圖大小的目的是在解壓前來確定需要的內存空間。

  procedure TServerForm.NMStrmServMSG(Sender: TComponent;

  const sFrom: String; strm: TStream);

  Var

  StreamStr,DestStream:TMemoryStream;

  SourceStream:TDecompressionStream;

  count:Integer;

  buffer:pointer;

  begin

  ScreenImage.Picture.Bitmap:=nil;

  If Strm Is TMemoryStream Then

  StreamStr := Strm AS TMemoryStream

  Else

  Exit;

  StreamStr.Position := 0;

  StreamStr.ReadBuffer(Count, Sizeof(Count));

  {得到位圖的大小}

  GetMem(Buffer,Count);

  {申請數據空間}

  DestStream := TMemoryStream.Create;

  SourceStream := TDecompressionStream.Create(StreamStr);

  {構建解壓流,壓縮數據由StreamStr 流得到}

  StatusBar.SimpleText := '正在處理圖象';

  Try

  SourceStream.ReadBuffer(Buffer^,Count);

  {讀出解壓數據}

  DestStream.WriteBuffer(Buffer^,Count);

  {保存到位圖流中}

  DestStream.Position := 0;

  ScreenImage.Picture.Bitmap.LoadFromStream(DestStream);

  {顯示到屏幕上}

  Finally

  FreeMem(Buffer);

  DestStream.Destroy;

  SourceStream.Destroy;

  End;

  end;

  該過程首先從得到的數據流中取得位圖大小,並申請內存空間,然後建立解壓流,並將解壓數據保存到位圖流中,然後顯示到屏幕上。

  本文程序在Delphi6.0中調試通過。

copyright © 萬盛學電腦網 all rights reserved