Delphi 內建 TCompressionStream 與 TDecompressionStream (基於 Zlib),提供記憶體級的資料壓縮/解壓縮能力。雖說明文件較少,但原始碼隨產品附贈 (\Info\Extras\Zlib\Src)。本文詳細解析類別架構、關鍵屬性方法、壓縮等級選擇,並附上「螢幕截圖壓縮傳輸」完整實戰範例。
TCustomZlibStream (基類)
├─ TCompressionStream (壓縮:唯寫)
└─ TDecompressionStream (解壓縮:唯讀)
property OnProgress: TNotifyEvent:壓縮/解壓過程中觸發,可更新進度條。constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream)TCompressionLevel = (clNone, clFastest, clDefault, clMax):無壓縮/最快/預設/最大壓縮率。property CompressionRate: Single:唯讀,回傳壓縮比 (壓縮後大小 / 原始大小)。function Write(const Buffer; Count: Longint): Longint:寫入資料並即時壓縮至 Dest 串流。不可呼叫 Read,否則拋出 "Error" 例外。constructor Create(Source: TStream):來源為含壓縮資料的串流。function Read(var Buffer; Count: Longint): Longint:讀取並即時解壓縮至 Buffer。不可呼叫 Write。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;
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;
OnProgress 事件參數 Sender 即為壓縮/解壓串流本身,可讀取 Position/Size 計算進度。clMax;即時影像串流建議 clFastest。Delphi 的 Zlib 串流類別雖屬輕量封裝,卻足以應付大多數記憶體資料壓縮需求。掌握「建立 → 寫入/讀取 → 釋放順序」與「封包格式設計」,即可在 Client/Server、資料庫 Blob 儲存、檔案打包等場合高效運用。