如何在DataSet的帮助下在TAdvStringGrid中显示数据库中的BLOB图像

时间:2013-09-06 09:58:26

标签: delphi delphi-xe3

我一直在Delphi XE3上申请。我试图将值从数据库显示到表单上放置的TAdvStringGrid组件。我正在使用数据集在TAdvSTringGRid显示结果(代码如下)。除数据库中的图像外,所有其他值都显示完美。在预期显示图像的地方,它显示垃圾字符。如何在TAdvStringGrid上完美地从DataBase显示图像。

SQLConnection1: TSQLConnection;
SQLMonitor1: TSQLMonitor;
DataSource1: TDataSource;
ADOConnection1: TADOConnection;
ClientDataSet1: TClientDataSet;
AdvStringGrid1: TAdvStringGrid;
procedure Button1Click(Sender: TObject);
procedure ShowSelectResults(results: TDataSet; sg: TAdvSTringGrid);
procedure FormCreate(Sender: TObject);


procedure TForm2.FormCreate(Sender: TObject);
var
    results: TDataSet;
begin
    SQLConnection1.Params.Add('Database=E:\playdb.s3db');
    try
        SQLConnection1.Connected := true;

        SQLMonitor1.Active := True;

        SQLConnection1.Execute('Select * from plays', nil, results);


    except
        on E: EDatabaseError do
          ShowMessage('Exception raised with message' + E.Message);
    end;
    ShowSelectResults(results, advstringgrid1);
 end;

调用

下的ShowSelectResult
procedure TForm2.ShowSelectResults(results: TDataSet; sg: TAdvStringGrid);
var
  names: TStringList;
  i,j,k, rc: Integer;
  resultsfield: variant;
  Field: TblobField;
  Stream: TStream;
  Jpg: TJPEGImage;
  Picture: TPicture;

begin
    if not results.IsEmpty then

    //Prints Data in the TAdvStringGrid
    results.First;
    j := 1;
    while not results.EOF do
    begin
      if (j>sg.rowcount) then
        sg.rowcount := sg.rowcount + 1;
      for i := 0 to results.fields.Count - 1 do
      begin
        if i=0 then

        else if i = 4 then
        //Here I want to display image from db
          Field := TBlobField(results.FieldByName(names[i]).AsString);
          Stream := results.CreateBlobStream(Field, bmRead);
          sg.CreatePicture(i, j, true, ShrinkWithAspectRatio, 20, haCenter, vaAboveText).Picture
        else
        sg.cells[i,j] := results.FieldByName(names[i]).AsString;
      end;
      results.Next;
      inc(j);
    end;
end;

问题发生在else if i=4的上述代码中的sg.CreatePicture循环(下面给出CreatePicture过程的格式),我希望在该特定列中显示图像。< / p>

在TAdvStringGrid手册中,他们提到了以下网格单元格图片显示方法

Grid.CreatePicture(2,3,True,Shrink,0,haLeft,vaTop).LoadFromFile(‘TST.JPG’);
procedure AddPicture(ACol,ARow: Integer;APicture:TPicture;transparent: Boolean; stretchmode:TStretchMode; padding: Integer; hal:TCellHalign; val:TCellValign);
function GetPicture(ACol,ARow: Integer): TPicture;
Grid.CreateFilePicture(2,3,True,Shrink,0,haLeft,vaTop).Filename := ‘TST.JPG’;

但是没有提到如何将它与DataSet一起使用。我正在搞乱TAdvStringGRid的CreatePicture过程,而不是使用DataSet来解决它。

最新发展

最后,我在Bummi等学者的帮助下找到方法将JPEG图像保存到memorystream然后再显示。

我的最新代码如下

procedure TForm2.ShowSelectResults(results: TDataSet; sg: TAdvStringGrid);
var
  names: TStringList;
  Field: TblobField;
  //Stream: TStream;
  Stream: TMemoryStream;
  //blobType := TBlobType;
  Jpg: TJPEGImage;
  Picture: TPicture;
  Image: TImage;
  Graphic: TGraphic;

Begin
    //k := results.FieldCount;
    //sg.Rowcount := rc;

    results.First;
    j := 1;
    while not results.EOF do
    begin
      if (j>sg.rowcount) then
        sg.rowcount := sg.rowcount + 1;
      for i := 0 to results.fields.Count - 1 do
      begin
        if i=0 then

        else if i = 4 then  // Column 5 for Image
          begin
           try
           if ((results.FieldByName(names[i]).AsString) <> '') then
           Begin
               Stream := TMemoryStream.Create;
               Image := Timage.Create(Self);
               Jpg := TJPEGImage.Create;
               Picture := TPicture.Create;
               Field := TBlobField(results.FieldByName('image'));
               Stream := results.CreateBlobStream(Field, bmReadWrite);
               //Field.SaveToStream(Stream);
               Stream.Position := 0;
               Jpg.LoadFromStream(Stream);
               Picture.Assign(Jpg); 

              //Jpg.LoadFromFile('C:\Sample Pictures\Cabo.jpg');
              //Picture.Assign(Jpg);

              sg.AddPicture(i,j,Picture,True,ShrinkWithAspectRatio,0,haLeft,vaTop);
            end;
           finally
              Jpg.Free;
              Stream.Free;
           end;
         end
        else
        //Prints data in other columns
        sg.cells[i.j] := results.FieldByName(names[i]).AsString;

        inc(j);
       end;   
end;

现在我在线Jpg.LoadFromStream(Stream);处面临一些记忆问题 它是错误代码JPEG Error #53,我才知道上面这样的错误代码仅在您尝试通过内存流访问的图像被破坏时显示但我确保图像没有损坏并且在其他软件的帮助下正确显示从类似的数据库中提取我也在数据库中更新了图像。我仍然得到JPEG Error #53的原因。问题主要在Jpg.LoadFromStream(Stream)

请注意带注释的代码

Jpg.LoadFromFile('C:\Sample Pictures\Cabo.jpg'); 
Picture.Assign(Jpg);
sg.AddPicture(i,j,Picture,True,ShrinkWithAspectRatio,0,haLeft,vaTop); 

从静态文件中提取它时效果很好。问题仅出在MemoryStream上。如何纠正这个错误?

2 个答案:

答案 0 :(得分:4)

CreateBlobStream正在创建一个TStream对象,而不是TMemoryStream 由于您不想将JPG写入数据库,因此应使用bmRead而不是bmReadWrite。
我不习惯SQLite,但你必须确保使用合适的二进制日期类型(BLOB)。

  JPG := TJpegImage.Create;
  Picture:= TPicture.Create;
  try
    st := results.CreateBlobStream(TBlobField(results.FieldByName('image')), bmRead);
    try
      JPG.LoadFromStream(st);
      Picture.Assign(JPG);
      sg.AddPicture(i,j,Picture,True,ShrinkWithAspectRatio,0,haLeft,vaTop);
    finally
      st.Free;
    end;
  finally
    JPG.Free;
    Picture.Free;
  end;

为了确保存储的图像真的是JPG,您应该编写JPG以进行测试,例如:

var
  ms: TMemoryStream;
begin
  ads.Open;
  ads.Append;
  ms := TMemoryStream.Create;
  try
    Image1.Picture.Graphic.SaveToStream(ms); // make sure having loaded a JPG
    ms.Position := 0;
    TBlobField(ads.FieldByName('image')).LoadFromStream(ms);
  finally
    ms.Free;
  end;
  ads.Post;
end;

答案 1 :(得分:0)

我意识到这有点迟了,但是我想做出贡献。我非常简单地执行了以下操作,不必担心图像格式(.jpg,.png等)。我只是创建一个TStream对象,将BLOB流加载到其中,然后从该流加载Image。简短而甜美,对我来说很棒。

   var
     Stream : TStream;
   begin
     try
       Stream := TStream.Create;
       Stream := Dataset.CreateBlobStream(Dataset.FieldByName('SIGNATURE'), bmRead);
       Stream.Position := 0;
       lblPicSize.Caption := 'Picture is ' + IntToStr(Stream.Size) + ' Bytes';
       if Stream.Size <= 0 then
         pnlPic.Caption := '<No Signature>'
       else
         pnlPic.Caption := '';

       try
         imgSignature.Picture.LoadFromStream(Stream);
       except
         on E:Exception do
           begin
             ShowMessage(E.Message);
           end;
       end;

 finally
   Stream.Free;
 end;
end;