9

If I understand it correctly, TImage.LoadFromFile determines the type of picture from the file extension.

Is there any way to detect the image type automatically from a TBlobStream with a raw image in it?

My current code:

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
Jens Mühlenhoff
  • 13,744
  • 6
  • 47
  • 101

4 Answers4

17

See this SO answer for file content retrieval from header.

Or you can use our TSynPicture class, which will handle all kind of pictures (bmp/gif/tiff/jpg/png) using Gdi+ library, in one single class. So your TPicture can be this unique class, for any kind of picture. With less code overhead than the Jpeg or PNG Delphi units.

var Pic: TSynPicture;

Pic := TSynPicture.Create;
Pic.LoadFromStream(aStream); // will load bmp/gif/tiff/jpeg/png content
AImage.Picture.Graphic := Pic;
....
Community
  • 1
  • 1
Arnaud Bouchez
  • 40,947
  • 3
  • 66
  • 152
  • If you want TSynPicture to load GIF/PNG/JPG/TIFF images, comment a definition of NOTSYNPICTUREREGISTER in the source code of SynGdiPlus.pas. – Ivan Z Apr 16 '14 at 09:10
7

starting from here you can easily do it: http://delphihaven.wordpress.com/2011/01/22/tip-detecting-graphic-formats/

RBA
  • 11,762
  • 14
  • 72
  • 118
2

In fact it is TPicture.LoadFromFile that detects file type, and it just uses the file extension. So you'll need to read the header of the stream to detect the file type.

On the other hand, if you know what the format is when you put the BLOB into the database you could always include that information as your own private header to the BLOB.

David Heffernan
  • 572,264
  • 40
  • 974
  • 1,389
  • 2
    "read the header of the stream" and there's Chris Rolliston blog post resolve the problem :) – RBA Jun 06 '11 at 11:51
0

Seemingly magic TPicture cunning handling for arbitrary image formats is actually very simple (not to say crude). Loading from files relies on file extension. Loading from clipboard - on clipboard format indicator. See? There is always format tag which instructs TPicture which TGraphicClass to use on the data, and TGraphic base class itself provides no mechanism to identify "own" data streams besided trial-and-error approach. One might be curious how TPicture loads itself from DFM stream, but it is not an exception, here is relevant excerpt from implementation (copyrighted code provided for illustrative purpose only):

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);
Premature Optimization
  • 1,911
  • 1
  • 15
  • 22
  • ... so it reads the corresponding TPicture class name from the DFM stream, instead of using the Picture binary header. So you can't mix for instance Jpeg loading libraries, or you'll have to name all implementation `TJpegImage` (that's what I've made for *SynGdiPlus* to be compatible with the standard `Jpeg` unit in user code and DFM loading). – Arnaud Bouchez Jun 06 '11 at 14:44