【转】[Delphi]使用TMemoryStream保存多张图片到文件,并读取

来源:互联网 发布:淘宝收藏领券怎么设置 编辑:程序博客网 时间:2024/05/16 03:17

在百度知道待解决问题中找到的一题。提问者要求将多张图片保存到一个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.

0 0