【问题标题】:How to display BLOB Image from database in the TAdvStringGrid with the help of DataSet如何借助 DataSet 在 TAdvStringGrid 中显示数据库中的 BLOB 图像
【发布时间】:2013-09-06 09:58:25
【问题描述】:

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

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.CreatePictureCreatePicture 过程的格式如下所示),我想在该特定列中显示图像。

在 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 上。如何纠正这个错误?

【问题讨论】:

  • 绝对确定 blob 字段具有您期望的图像?例如,如果您在表单上放置一个 TDBImage 并将其链接到您的 blob 字段,组件会显示该图像吗?
  • 是的,SQLite 数据库中已经有一个图像。问题出在 TPicture 上。因为我们可以借助以下函数和程序在 TAdvSTringGRid 上显示图片
    function CreatePicture(aCol,aRow:integer;transparent:boolean;stretchmode:TStretchMode;padding:integer;hal:TCellHalign;val:TCellValign):tpicture; procedure AddPicture(aCol,aRow:integer;apicture:tpicture;transparent:boolean;stretchmode:TStretchMode;padding:integer;hal:TCellHalign;val:TCellValign); procedure RemovePicture(aCol,aRow:integer); function GetPicture(aCol,aRow:integer):tpicture;
  • Tpicture 没有任何LoadFromStream 程序或函数。如何获取加载到 TPicture 中的流 blob 图像数据。
  • try Picture.Graphic.LoadFromStream(Stream); sg.AddPicture(i, j, Picture, true, ShrinkWithAspectRatio, 20, haCenter, vaAboveText) finally Stream.Free; 这是我刚刚完成的。它不会给出调试错误,但会给出 SQLException 错误 $C000000005,在 0x00409250 处出现访问冲突;读取地址 0xfffdffcd

标签: delphi delphi-xe3


【解决方案1】:

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;

【讨论】:

    【解决方案2】:

    我意识到这有点晚了,但我想做出贡献。我很简单地做了以下事情,不必担心图像格式(.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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-26
      • 2013-01-23
      • 2012-10-24
      • 1970-01-01
      • 2014-10-03
      • 2013-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多