======================================================
注:本文源代码点此下载
======================================================
转自:http://www.delphitop.com/html/yasuo/180.html
软件开发者不免都要遇到压缩数据的问题!经常使用delphi的朋友都知道,它为我们提供了两个流类(tcompressionstream和tdecompressionstream)来完成数据的压缩和解压缩,但美中不足的是,该流在delphi 的帮助中没有详细的说明,使得它们在使用起来有一定得困难。其实在delphi系统中提供了这两个类的源代码和库。保存在delphi 光盘的\info\extras\zlib\ src和\info\extras\zlib\obj目录中(其中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中调试通过
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/