在抓屏中,如何解决BMP-JPG图压缩的失真(50分)

J

jeefong

Unregistered / Unconfirmed
GUEST, unregistred user!

我也学写了一个抓屏幕的东东。但有个问题,就是把屏幕抓下来后,再压缩成JPG,保存
到流。跟着再把这个流读出来,显示到Image上,发现图象失真很历害,无论是图片还是文
字,都是模模糊糊的,看不清。
我的设置是:
ScrnBmp->PixelFormat = pf16bit;
....
//转换成JPG,并保存到流
jpgMap->Assign(ScrnBmp);
jpgMap->CompressionQuality = 20;
jpgMap->SaveToStream(tmpStream);

另外,ClientSocket 为什么最大只能收到12288 的包? 一开始客户机没显示抓屏图像,
后来才发现,接收到的流的最大Size 只能是 12288,而抓的每一屏基本都大于这个数,所
以才没显示。
 
不要用JPG压缩。用LZW或ZLIB或RLE都可

总之,用无损压缩
 
哦? “ClientSocket只能接受12288的包” 有这等事情?
我还以为在PC上的Socket没有包的大小限制,还以为在嵌入式系统才会出现
你的Socket是用线程阻塞式还是非阻塞式的?

至于Jpg 我试过只是压缩和解压,没有试过传输,但是没发现有什么太严重的失真
是不是压缩质量的设置有问题
 
把下面这句改改
jpgMap->CompressionQuality = 20;

20改为 90,最大是100,看看图象质量
 

jpgMap->CompressionQuality = 90 ;

倒是可以改进质量,但数据量明显增加了,刷几屏后,便出现:JPEG error#xx。

 
呵呵,建议你用无损压缩。。。

一样可以压得很小的。。。

如果你一定要用JPEG的方式,CompressionQuality不要低于30 。

zlib的压缩率也很高。你可以试试,是无损的
 
请问 wwolf:
zlib 压缩有源码吗? 没弄过,不知道怎样弄。

另外:
怎样校验收到的数据流是否正确? jpeg error#xx 基本上都是接收到的数据流有错,
导致转换成JPEG时出错。
 
zlib在DELPHI里自带有啊。你找一下。
 
Zilb单元在Delphi的安装盘上,而没有装到系统上!李维的多层的系统篇那本书有用法,
到网上搜搜,有详细的用法!
 
uses
Zlib

//压缩
procedure CompressBitmap(var CompressedStream: TMemoryStream;
const CompressionLevel: TCompressionLevel);
var
SourceStream: TCompressionStream;
DestStream: TMemoryStream;
Count: Integer;
Begin
Count := CompressedStream.Size; //获得图像流的原始尺寸
DestStream := TMemoryStream.Create;
SourceStream:=TCompressionStream.Create(CompressionLevel, DestStream);
Try
CompressedStream.SaveToStream(SourceStream); //SourceStream中保存着原始的图像流
//将原始图像流进行压缩,DestStream中保存着压缩后的图像流
SourceStream.Free;
CompressedStream.Clear;
CompressedStream.WriteBuffer(Count, SizeOf(Count)); //写入原始图像的尺寸
CompressedStream.CopyFrom(DestStream, 0); //写入经过压缩的图像流
finally
DestStream.Free;
end;
end;


//解压
procedure UnCompressBitmap(const CompressedStream: TFileStream; var Bmp: TBitmap);
var
SourceStream: TDecompressionStream;
DestStream: TMemoryStream;
Buffer: PChar;
Count: Integer;
Begin
CompressedStream.ReadBuffer(Count, SizeOf(Count)); //从被压缩的图像流中读出原始图像的尺寸
GetMem(Buffer, Count); //根据图像尺寸大小为将要读入的原始图像流分配内存块
DestStream := TMemoryStream.Create;
SourceStream := TDecompressionStream.Create(CompressedStream);
Try
SourceStream.ReadBuffer(Buffer^, Count); //将被压缩的图像流解压缩,然后存入 Buffer内存块中
DestStream.WriteBuffer(Buffer^, Count); //将原始图像流保存至 DestStream流中
DestStream.Position := 0; //复位流指针
Bmp.LoadFromStream(DestStream); //从 DestStream流中载入原始图像流
finally
FreeMem(Buffer);
DestStream.Free;
end;
end;


//压缩按钮 OnClick事件
procedure TForm1.Button1Click(Sender: TObject);
var
Bmp: TBitmap;
CompressedStream: TMemoryStream;
begin
Bmp := TBitmap.Create;
CompressedStream := TMemoryStream.Create;
Try
Bmp.SaveToStream(CompressedStream); //将 Bmp对象中的图像保存至内存流中
CompressBitmap(CompressedStream, clDefault); //按缺省的压缩比例对原始图像流进行压缩
finally
Bmp.Free;
CompressedStream.Free;
end;
end;


//解压缩按钮 OnClick事件
procedure TForm1.Button2Click(Sender: TObject);
var
CompressedStream: TFileStream;
Bmp: TBitmap;
begin
Bmp := TBitmap.Create;
Try
UnCompressBitmap(CompressedStream, Bmp); //将被压缩的图像流进行解压缩
Image1.Picture.Bitmap := Bmp;
finally
Bmp.Free;
CompressedStream.Free;
end;
end;

还能有什么不清楚吗。
 
20%的JPEG質量怎麼看的清啊,65%左右有比較好,數據不太大,質量可以接受
 

对,数量与质量的平衡点是65%。
 
建议装vclzip控件
把图片抓到内存流中
用vclzip压缩内存流
再发送比jpg压缩好
 
顶部