borland公司推出的 rad开发工具 delphi 5.0作为 windows平台上的主流开发工具,其可视化的开发环境和面向对象编程的强大功能已经吸引了无数的开发人员。但是,一些程序员在实际的开发过程中却时常为对大量的数据进行压缩而伤透脑筋,不得不去查找一些高效的压缩算法或在网上查找第三方的控件来实现压缩。难道 delphi本身没有提供这个功能吗?其实 delphi的程序设计师早就考虑到了这一点,他们提供了 zlib.pas和 zlibconst.pas两个单元文件来解决数据压缩问题,实现了很高的数据压缩比率。这两个文件保存在 delphi 5.0安装光盘上 infoextraszlib目录下,此外,在 infoextraszlibobj目录中还保存了 zlib.pas单元引用的 obj文件。下面本文以压缩一个屏幕拷贝为例介绍如何使用这项功能。
解决思路
首先利用屏幕拷贝捕捉到当前整个屏幕的图像,然后在内存中保存为 bmp文件格式。压缩时,使用 tcompressionstream对象对原始图像进行压缩并且保存为自定义的文件格式;解压缩时,使用 tdecompressionstream对象对被压缩的图像进行解压缩,还原为 bmp格式的图像文件。
具体实现
新建一个项目文件,在主单元的接口部分引用 zlib.pas,在主表单上放置两个按钮 button1、 button2,在它们的 onclick事件中写上相应的过程调用代码。
部分程序源代码如下:
unit unit1;
interface
uses
windows, messages, sysutils, classes, graphics, controls, forms, dialogs,stdctrls, zlib;
type
tform1 = class(tform)
button1: tbutton;
button2: tbutton;
procedure button1click(sender: tobject);
procedure button2click(sender: tobject);
private
{ private declarations }
public
{ public declarations }
end;
var
form1: tform1;
implementation
{$ r* .dfm}
1.捕捉全屏幕图像
procedure getscreen(var bmp: tbitmap);
var
dc: hdc;
mycanvas: tcanvas;
myrect: trect;
begin
dc := getwindowdc(0);
mycanvas := tcanvas.create;
try
mycanvas.handle := dc;
myrect:=rect(0, 0,screen.width, screen.height);
file://图像为 24位真彩色,也可根据实际需要调整
bmp.pixelformat := pf24bit;
bmp.width := myrect.right;
bmp.height := myrect.bottom;
file://捕捉整个屏幕图像
bmp.canvas.copyrect(myrect, mycanvas, myrect);
finally
mycanvas.handle := 0;
mycanvas.free;
releasedc(0, dc);
end;
end;
2.压缩图像
procedure compressbitmap(var compressedstream: tmemorystream;const compressionlevel: tcompressionlevel);
var
sourcestream: tcompressionstream;
deststream: tmemorystream;
count: integer;
begin
file://获得图像流的原始尺寸
count := compressedstream.size;
deststream := tmemorystream.create;
sourcestream:=tcompressionstream.create
(compressionlevel, deststream);
try
file://sourcestream中保存着原始的图像流
compressedstream.savetostream(sourcestream);
file://将原始图像流进行压缩, deststream中保存着压缩后的图像流
sourcestream.free;
compressedstream.clear;
file://写入原始图像的尺寸
compressedstream.writebuffer(count, sizeof
(count));
file://写入经过压缩的图像流
compressedstream.copyfrom(deststream, 0);
finally
deststream.free;
end;
3.还原被压缩图像
procedure uncompressbitmap(const compressedstream: tfilestream; var bmp: tbitmap);
var
sourcestream: tdecompressionstream;
deststream: tmemorystream;
buffer: pchar;
count: integer;
begin
file://从被压缩的图像流中读出原始图像的尺寸
compressedstream.readbuffer(count, sizeof(count));
file://根据图像尺寸大小为将要读入的原始图像流分配内存块
getmem(buffer, count);
deststream := tmemorystream.create;
sourcestream := tdecompressionstream.create(compressedstream);
try
file://将被压缩的图像流解压缩,然后存入 buffer内存块中
sourcestream.readbuffer(buffer^, count);
file://将原始图像流保存至 deststream流中
deststream.writebuffer(buffer^, count);
deststream.position := 0;//复位流指针
//从 deststream流中载入原始图像流
bmp.loadfromstream(deststream);
finally
freemem(buffer);
deststream.free;
end;
end;
4.压缩按钮 onclick事件
procedure tform1.button1click(sender: tobject);
var
bmp: tbitmap;
compressedstream: tmemorystream;
begin
bmp := tbitmap.create;
compressedstream := tmemorystream.create;
try
file://捕获当前整个屏幕 ,将图像保存至 bmp对象中 getscreen(bmp);
file://将 bmp对象中的图像保存至内存流中
bmp.savetostream(compressedstream);
file://按缺省的压缩比例对原始图像流进行压缩
compressbitmap(compressedstream, cldefault);
file://将压缩之后的图像流保存为自定义格式的文件
compressedstream.savetofile(‘ c:cj.dat’ );
finally
bmp.free;
compressedstream.free;
end;
end;
5.解压缩按钮 onclick事件
procedure tform1.button2click(sender: tobject);
var
compressedstream: tfilestream;
bmp: tbitmap;
begin
bmp := tbitmap.create;
file://以文件流的只读方式打开自定义的压缩格式文件
compressedstream := tfilestream.create(‘ c:cj.dat’ , fmopenread);
try
file://将被压缩的图像流进行解压缩
uncompressbitmap(compressedstream, bmp);
file://将原始图像流还原为指定的 bmp文件
bmp.savetofile(‘ c:cj.bmp’ );
finally
bmp.free;
compressedstream.free;
end;
end;
此外 tcompressionstream对象还提供了 compressionrate属性,该属性用于描述对原始数据进行压缩后的压缩比率,而 onprogress事件在压缩与解压缩过程中都会被触发,开发人员可以在该事件中编写用于显示进度的代码。
以上代码在 delphi 5.0中调试运行通过。