在百度知道待解决问题中找到的一题。提问者要求将多张图片保存到一个bat文件中,并可以在读取出来分别显示在TImage控件中。
借此好好温习了一下TMemoryStream的用法,并以此例贴上该类的使用方法:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
//THeader:
// 为了保存一个标志和需要保存的Image对象的size,方便在读取的时候作为Buffer大小读出
// 还可以增加额外需要保存的信息
// 在你的应用程序中使用这种结构,可以方便以后程序的扩展。
type
THeader = packed record
Marker: array[0..5] of Char;
Size: Integer;
end;
type
TForm1 = class(TForm)
btnSave: TButton;
Image1: TImage;
Image2: TImage;
Image3: TImage;
Image4: TImage;
btnLoad: TButton;
procedure btnSaveClick(Sender: TObject);
procedure btnLoadClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
const
vFile = 'D:\Test.dat';
implementation
{$R *.dfm}
//保存按钮,为了测试,这里只用了2个Image
procedure TForm1.btnSaveClick(Sender: TObject);
var
sStream, sStream1: TMemoryStream;
AHeader: THeader;
procedure SaveBitmapToStream(vImage: TImage);
begin
sStream1.Clear;
vImage.Picture.Bitmap.SaveToStream(sStream1);
//准备头
ZeroMemory(@Aheader, SizeOf(THeader));
StrCopy(AHeader.Marker, PChar('Bitmap'));//将String字串保存到char数组中。
AHeader.Size := sStream1.Size;
//写头
sStream.WriteBuffer(AHeader, SizeOf(THeader));
//WriteBuffer方法:将Buffer数据写到流中,第一位是要写的数据,第二位为内容长度
//保存image1
vImage.Picture.Bitmap.SaveToStream(sStream);
end;
begin
sStream := TMemoryStream.Create;
sStream1 := TMemoryStream.Create;
sStream.Seek(0, soFromBeginning);
SaveBitmapToStream(Image1);
SaveBitmapToStream(Image2);
sStream.SaveToFile(vFile);
sStream1.Free;
sStream.Free;
end;
//读取图片
// 因为要读2张分别放到不同的Timage中,所以使用的固定的读取。
// 如果你的图片量大,可以采取循环读取的方式。
procedure TForm1.btnLoadClick(Sender: TObject);
var
sStream, sStream1: TMemoryStream;
sHeader: THeader;
imgList: TList;
vBitmap: TBitmap;
i: Integer;
begin
sStream := TMemoryStream.Create;
sStream1 := TMemoryStream.Create;
imgList := TList.create;
sStream.LoadFromFile(vFile);
sStream.Position := 0;
while sStream.Position < sStream.Size do/
//遍历这个流文件,直到最后读完。
//Position不需要手动加,使用ReadBuffer方法会自动指到当前读的位置
begin
ZeroMemory(@sheader, SizeOf(THeader));
sStream.ReadBuffer(sHeader, SizeOf(THeader));
if sHeader.Size > 0 then
begin
sStream1.CopyFrom(sStream, sHeader.Size);
vBitmap := TBitmap.Create;
sStream1.Position := 0;//因为sStream1当前的位置已经指到最后,所以必须把位置设为0,才能正确读取出流数据。
vBitmap.LoadFromStream(sStream1);
imgList.Add(vBitmap);//为了更好的通用性,将读取的图片放到一个TList中,这样可以不受2个图片的固定限制。
end;
sStream1.Clear;
end;
if imgList.Count >= 2 then
begin
Image3.Picture.Bitmap := TBitmap(imgList[0]);
Image4.Picture.Bitmap := TBitmap(imgList[1]);
end;
sStream.Free;
sStream1.Free;
for i := 0 to imgList.Count - 1 do
TBitmap(imgList[i]).Free;
imgList.Free;
end;
end.