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

Delphi 使用 Zlib 實現圖像數據壓縮:屏幕截圖 BMP 壓縮解壓完整實例

     編輯:Delphi

背景

Delphi 5 安裝盤 \Info\Extras\Zlib 目錄提供 Zlib.pas、ZlibConst.pas 及 .obj 文件,封裝了 zlib 1.1.3 庫,提供 TCompressionStream/TDecompressionStream 類,可輕鬆實現高壓縮比的數據壓縮,無需第三方組件。

核心類與屬性

類關鍵構造/屬性/事件
TCompressionStreamCreate(CompressionLevel: TCompressionLevel; Dest: TStream)、CompressionRate (只讀,壓縮比)、OnProgress (進度回調)
TDecompressionStreamCreate(Source: TStream)、OnProgress
TCompressionLevelclNone, clFastest, clDefault, clMax (0~9 級)

實戰流程:屏幕截圖 → 內存 BMP → 壓縮存檔 → 解壓還原 BMP

1. 捕獲全屏幕到 TBitmap

procedure GetScreen(var Bmp: TBitmap);
var DC: HDC; Canvas: TCanvas; Rect: TRect;
begin
  DC := GetWindowDC(0); // 桌面 DC
  Canvas := TCanvas.Create;
  try
    Canvas.Handle := DC;
    Rect := Rect(0, 0, Screen.Width, Screen.Height);
    Bmp.PixelFormat := pf24bit; // 24 位真彩色
    Bmp.Width := Rect.Right; Bmp.Height := Rect.Bottom;
    Bmp.Canvas.CopyRect(Rect, Canvas, Rect); // BitBlt 複製
  finally
    Canvas.Handle := 0; Canvas.Free; ReleaseDC(0, DC);
  end;
end;

2. 壓縮流並保存 (自定義格式:原始大小 4 字節 + 壓縮數據)

procedure CompressBitmap(var CompressedStream: TMemoryStream; Level: TCompressionLevel = clDefault);
var SourceStream: TCompressionStream; DestStream: TMemoryStream; OrigSize: Integer;
begin
  OrigSize := CompressedStream.Size; // 原始 BMP 流大小
  DestStream := TMemoryStream.Create;
  try
    SourceStream := TCompressionStream.Create(Level, DestStream);
    try
      CompressedStream.SaveToStream(SourceStream); // 寫入壓縮流
    finally SourceStream.Free; end; // 必須 Free 才會刷新 zlib 尾部校驗和
    CompressedStream.Clear;
    CompressedStream.WriteBuffer(OrigSize, SizeOf(OrigSize)); // 寫入原始大小 (解壓需知)
    CompressedStream.CopyFrom(DestStream, 0); // 追加壓縮數據
  finally DestStream.Free; end;
end;

3. 解壓還原 BMP

procedure UnCompressBitmap(const CompressedStream: TFileStream; var Bmp: TBitmap);
var SourceStream: TDecompressionStream; DestStream: TMemoryStream; Buffer: PChar; OrigSize: Integer;
begin
  CompressedStream.ReadBuffer(OrigSize, SizeOf(OrigSize)); // 讀取原始大小
  GetMem(Buffer, OrigSize);
  DestStream := TMemoryStream.Create;
  try
    SourceStream := TDecompressionStream.Create(CompressedStream);
    try
      SourceStream.ReadBuffer(Buffer^, OrigSize); // 解壓到緩衝區
    finally SourceStream.Free; end;
    DestStream.WriteBuffer(Buffer^, OrigSize); // 寫入目標流
    DestStream.Position := 0;
    Bmp.LoadFromStream(DestStream); // 還原 BMP
  finally FreeMem(Buffer); DestStream.Free; end;
end;

4. 按鈕事件綁定

procedure TForm1.Button1Click(Sender: TObject); // 壓縮按鈕
var Bmp: TBitmap; CompressedStream: TMemoryStream;
begin
  Bmp := TBitmap.Create; CompressedStream := TMemoryStream.Create;
  try
    GetScreen(Bmp);
    Bmp.SaveToStream(CompressedStream); // BMP -> 內存流
    CompressBitmap(CompressedStream, clDefault);
    CompressedStream.SaveToFile('C:\cj.dat'); // 自定義壓縮文件
  finally Bmp.Free; CompressedStream.Free; end;
end;

procedure TForm1.Button2Click(Sender: TObject); // 解壓按鈕
var Bmp: TBitmap; CompressedStream: TFileStream;
begin
  Bmp := TBitmap.Create;
  CompressedStream := TFileStream.Create('C:\cj.dat', fmOpenRead);
  try
    UnCompressBitmap(CompressedStream, Bmp);
    Bmp.SaveToFile('C:\cj.bmp'); // 還原 BMP 文件
  finally Bmp.Free; CompressedStream.Free; end;
end;

進階功能:壓縮率顯示與進度條

// 壓縮時顯示比率
procedure TForm1.CompressBitmap(...);
var SourceStream: TCompressionStream; ...
begin
  ...
  SourceStream := TCompressionStream.Create(Level, DestStream);
  SourceStream.OnProgress := CompressionProgress; // 綁定進度事件
  ...
  // 壓縮完成後讀取比率
  Label1.Caption := Format('壓縮比: %.2f%%', [SourceStream.CompressionRate * 100]);
end;

procedure TForm1.CompressionProgress(Sender: TObject; Position: Integer);
begin
  ProgressBar1.Position := Position; // Position 為已處理字節數
  Application.ProcessMessages;
end;

注意事項

  1. TCompressionStream.Free **必須**在讀取 CompressionRate 或 DestStream 數據前調用,否則 zlib 流未正確結束 (缺少 Adler-32 校驗和)。
  2. 自定義文件格式必須存儲原始數據大小,因解壓流無法自動知曉目標大小 (zlib 流不包含原始長度)。
  3. 大數據量 (如視頻、大圖) 建議分塊壓縮或使用 clFastest 平衡速度/比率。
  4. Delphi 2009+ 字符串為 Unicode,壓縮二進制數據請用 TBytesStream/TMemoryStream,避免字符串類型混淆。

總結

Delphi 內置 Zlib 單元提供了工業級壓縮能力。通過 TCompressionStream/TDecompressionStream 配合 TMemoryStream/TFileStream,僅需十幾行代碼即可實現「截圖 → 高壓縮存儲 → 完美還原」全流程。掌握流操作與自定義文件頭 (存原始長度) 是正確使用的關鍵。

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