首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 壓縮/解壓縮串流實戰:TCompressionStream 與 TDecompressionStream 完整應用指南

     編輯:Delphi

Delphi 內建 TCompressionStream 與 TDecompressionStream (基於 Zlib),提供記憶體級的資料壓縮/解壓縮能力。雖說明文件較少,但原始碼隨產品附贈 (\Info\Extras\Zlib\Src)。本文詳細解析類別架構、關鍵屬性方法、壓縮等級選擇,並附上「螢幕截圖壓縮傳輸」完整實戰範例。

類別繼承架構

TCustomZlibStream (基類)
  ├─ TCompressionStream  (壓縮:唯寫)
  └─ TDecompressionStream (解壓縮:唯讀)

TCustomZlibStream 共用成員

  • property OnProgress: TNotifyEvent:壓縮/解壓過程中觸發,可更新進度條。

TCompressionStream 關鍵成員

  • constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream)
    TCompressionLevel = (clNone, clFastest, clDefault, clMax):無壓縮/最快/預設/最大壓縮率。
  • property CompressionRate: Single:唯讀,回傳壓縮比 (壓縮後大小 / 原始大小)。
  • function Write(const Buffer; Count: Longint): Longint:寫入資料並即時壓縮至 Dest 串流。不可呼叫 Read,否則拋出 "Error" 例外。

TDecompressionStream 關鍵成員

  • constructor Create(Source: TStream):來源為含壓縮資料的串流。
  • function Read(var Buffer; Count: Longint): Longint:讀取並即時解壓縮至 Buffer。不可呼叫 Write。

實戰範例:螢幕截圖壓縮傳輸 (Client 端)

procedure TClientForm.GetScreen;
var
  SourceDC, DestDC: HDC;
  BHandle: HBITMAP;
  Bitmap: TBitmap;
  BmpStream, DestStream: TMemoryStream;
  CompStream: TCompressionStream;
  ImgSize: Integer;
begin
  // 1. 截取全螢幕到 Bitmap
  SourceDC := CreateDC('DISPLAY', '', '', nil);
  DestDC := CreateCompatibleDC(SourceDC);
  BHandle := CreateCompatibleBitmap(SourceDC, Screen.Width, Screen.Height);
  SelectObject(DestDC, BHandle);
  BitBlt(DestDC, 0, 0, Screen.Width, Screen.Height, SourceDC, 0, 0, SRCCOPY);

  Bitmap := TBitmap.Create;
  Bitmap.Handle := BHandle;

  // 2. Bitmap 存入記憶體串流
  BmpStream := TMemoryStream.Create;
  Bitmap.SaveToStream(BmpStream);
  ImgSize := BmpStream.Size; // 記錄原始大小,供解壓端配置記憶體

  // 3. 壓縮串流
  DestStream := TMemoryStream.Create;
  CompStream := TCompressionStream.Create(clMax, DestStream); // 最大壓縮率
  try
    BmpStream.SaveToStream(CompStream); // 壓縮過程自動觸發 OnProgress
    CompStream.Free; // 必須先釋放壓縮串流以刷新緩衝區

    // 4. 重組傳輸封包:[原始大小:4 bytes][壓縮資料...]
    BmpStream.Clear;
    BmpStream.WriteBuffer(ImgSize, SizeOf(ImgSize));
    BmpStream.CopyFrom(DestStream, 0);
    BmpStream.Position := 0;

    // 5. 發送 (假設 NMStrm 為傳輸元件)
    NMStrm.PostIt(BmpStream);
  finally
    DestStream.Free;
    BmpStream.Free;
    Bitmap.Free;
    DeleteDC(SourceDC);
    ReleaseDC(0, SourceDC); // 注意參數順序
  end;
end;

實戰範例:接收端解壓縮顯示 (Server 端)

procedure TServerForm.NMStrmServMSG(Sender: TComponent; const sFrom: String; Strm: TStream);
var
  SrcStream, DestStream: TMemoryStream;
  DecompStream: TDecompressionStream;
  ImgSize: Integer;
  Buffer: Pointer;
begin
  ScreenImage.Picture.Bitmap := nil;
  if not (Strm is TMemoryStream) then Exit;
  SrcStream := Strm as TMemoryStream;
  SrcStream.Position := 0;

  // 1. 讀取原始影像大小
  SrcStream.ReadBuffer(ImgSize, SizeOf(ImgSize));
  GetMem(Buffer, ImgSize);

  // 2. 解壓縮
  DestStream := TMemoryStream.Create;
  DecompStream := TDecompressionStream.Create(SrcStream); // 來源為剩餘壓縮資料
  try
    DecompStream.ReadBuffer(Buffer^, ImgSize); // 一次讀足夠大小
    DestStream.WriteBuffer(Buffer^, ImgSize);
    DestStream.Position := 0;
    ScreenImage.Picture.Bitmap.LoadFromStream(DestStream);
  finally
    FreeMem(Buffer);
    DestStream.Free;
    DecompStream.Free;
  end;
end;

關鍵技巧總結

  1. 壓縮串流必須先 Free 再讀取 DestStream,否則緩衝區資料未刷新。
  2. 傳輸前附加原始大小,解壓端可預先配置記憶體,避免多次重新配置。
  3. OnProgress 事件參數 Sender 即為壓縮/解壓串流本身,可讀取 Position/Size 計算進度。
  4. 壓縮等級選擇:網路傳輸建議 clMax;即時影像串流建議 clFastest。

小結

Delphi 的 Zlib 串流類別雖屬輕量封裝,卻足以應付大多數記憶體資料壓縮需求。掌握「建立 → 寫入/讀取 → 釋放順序」與「封包格式設計」,即可在 Client/Server、資料庫 Blob 儲存、檔案打包等場合高效運用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved