如何从TGraphicField中提取位图?

时间:2013-12-28 19:41:33

标签: delphi bitmap

我疯了。

这就是我正在做的事情

  1. 在表单上删除TClientDataset,TImage和TButton。
  2. 将Clientdataset1.Filename设置为biolife.xml
  3. 双击按钮并添加以下代码:

    procedure TForm31.Button1Click(Sender: TObject);
    var
      BF: TBlobField;
      BS: TStream;
      BM: TBitmap;
    begin
      ClientDataset1.Open;
      ClientDataset1.First;
      BF :=  ClientDataSet1.FieldByName('Graphic') as TBlobField;
      BS := ClientDataSet1.CreateBlobStream(BF, bmRead);
      BS.Position := 0;
      BM := TBitmap.Create;
      try
        BM.LoadFromStream(BS);
      finally
        BM.Free;
      end;
    end;
    
  4. 运行它。当我这样做时,我得到“位图图像无效”。

    咦?这些数据多年来一直是位图 - 出了什么问题?

2 个答案:

答案 0 :(得分:7)

如果将TGraphicField保存到文件(使用它的SaveToFile方法)并使用十六进制查看器查看该文件,它确实是一个位图。问题是在开头有一个描述文件类型的blob头。这在documentation中有所提及,有些模糊。我还在docs中的TBlobField.GraphicHeader属性说明中找到了对它的引用。

如果您将Stream.Position设置为8而不是0,则会正确读入TBitmap

BS.Position := 8;
BM.LoadFromStream(BS);

答案 1 :(得分:4)

  

图形字段是二进制大对象(BLOB)字段的一种形式   数据包含一个描述编码的BLOB标题   图形值。

“BLOB标题”在那里有误导性,它似乎是图形备忘录的Paradox存储格式的残余。

(* from DB *)

{ Paradox graphic BLOB header }
type
  TGraphicHeader = record
    Count: Word;                { Fixed at 1 }
    HType: Word;                { Fixed at $0100 }
    Size: Longint;              { Size not including header }
  end;


procedure TForm1.FormClick(Sender: TObject);
const
  HeaderSize = SizeOf(TGraphicHeader);
var
  Field: TGraphicField;
  Stream: TClientBlobStream;
begin
  Field := ClientDataSet1.FieldByName('Graphic') as TGraphicField;
  Stream := ClientDataSet1.CreateBlobStream(Field, bmRead) as TClientBlobStream;
  Stream.SaveToFile('dump.bin');            // examine BLOB and see extra bytes preceding BITMAPFILEHEADER
  Assert(Stream.Position = 0);
  Stream.Seek(+HeaderSize, soFromCurrent);  // discard header, it does not contain anything of use anyways
  Image1.Picture.Bitmap.LoadFromStream(Stream);

  ClientDataSet1.Next;
end;