如何将任意图像从BLOB流加载到TImage中?
如果我理解正确,TImage.LoadFromFile
将根据文件扩展名确定图片的类型。如何将任意图像从BLOB流加载到TImage中?
有没有什么办法从TBlobStream
自动检测图像类型与原始图像?
我当前的代码:
procedure LoadImageFromStream(AImage: TImage; ADataSet: TDataSet);
var
Stream: TStream;
begin
Stream := ADataSet.CreateBlobStream(Field, bmRead);
try
AImage.Picture.Graphic.LoadFromStream(Stream);
finally
Stream.Free;
end;
end
查看此SO answer用于从标头检索文件内容。
或者您可以使用我们的TSynPicture
class,它将在一个单独的类中使用Gdi +库处理所有类型的图片(bmp/gif/tiff/jpg/png)。所以你的TPicture
可以是这个独特的类,适用于任何类型的图片。与Jpeg或PNG Delphi单元相比,代码开销更少。
var Pic: TSynPicture;
Pic := TSynPicture.Create;
Pic.LoadFromStream(aStream); // will load bmp/gif/tiff/jpeg/png content
AImage.Picture.Graphic := Pic;
....
事实上,它是TPicture.LoadFromFile
检测文件类型,它只是使用的文件扩展名。所以你需要读取流的头部来检测文件类型。另一方面,如果您知道将BLOB放入数据库时的格式是什么,您可以始终将该信息作为您自己的BLOB专用标题包含在内。
“读数据流首部”和有克里斯Rolliston博客文章解决问题:) – RBA 2011-06-06 11:51:06
看似魔法 TPicture任意图像格式狡猾的处理其实很简单(不说粗品)。从文件加载依赖于文件扩展名。从剪贴板加载 - 在剪贴板格式指示器上。看到?总是有格式标签指示TPicture哪个TGraphicClass在数据上使用,TGraphic基类本身没有提供机制来识别除了试错法之外的“自己”的数据流。如何TPicture负载本身从DFM流,但它不是一个例外,其中一个可能会好奇,这里是从执行相关摘录(仅供说明用途版权的代码):
procedure TPicture.ReadData(Stream: TStream);
var
{...}
GraphicClass: TGraphicClass;
LClassName: string;
LBytes: TBytes;
LNameLen: Byte;
begin
Stream.Read(LNameLen, 1);
SetLength(LBytes, LNameLen);
Stream.Read(LBytes{$IFNDEF CLR}[0]{$ENDIF}, LNameLen);
LClassName := TEncoding.UTF8.GetString(LBytes);
GraphicClass := FileFormats.FindClassName(LClassName);
...所以它从DFM流中读取相应的TPicture类名,而不是使用图片二进制头。所以你不能混合实例Jpeg加载库,或者你必须命名所有实现'TJpegImage'(这就是我为* SynGdiPlus *所做的与用户代码和DFM中的标准'Jpeg'单元兼容加载)。 – 2011-06-06 14:44:30
如果你想TSynPicture加载GIF/PNG/JPG/TIFF图像,请在SynGdiPlus.pas的源代码中注释NOTSYNPICTUREREGISTER的定义。 – 2014-04-16 09:10:05