AWARE [SYSTEMS] Imaging expertise for the Delphi developer
AWare Systems, Imaging expertise for the Delphi developer, Home TechTalks / Format from data
AWare Systems on-line

Home
Custom development
Imaging
TechTalks
    Format from data
    Tiling versus banding
    VCL TGraphic basics
    Unused color
Company
Links

Languages

  English version
  Nederlandse versie

Contact

Information: info@awaresystems.be
Helpdesk: support@awaresystems.be
Sales: sales@awaresystems.be



Valid HTML 4.01!



Determining the file format from the data

> I have a either a .bmp, .jpg, and .gif file in a ClientDataset's Blob field.
> I need to determine what particular format and...

There is no exact solution to this problem. For example, there's absolutely no need for a legitimate JPEG file to start with 255,216, even if many do, and even if checking this is just about the only efficient way to determine whether the data is JPEG format. If you design such database tables yourself, you should include a separate field indicating the particular format, excluding the need for hacky file format detection.

Quoting Ross Finlayson, quoting from Alien:
"They mostly come at night, ... mostly."
"Ahhh!" "Aiiieeee!" "Rip-ley!"

You get the point... You don't want to be eaten alive and/or used as a nest for those ugly creatures, do you? This being said, there are indeed situations where you're simply presented with data without the proper file format indication. So here it is. The following functions take a pointer to the beginning of the data, and return whether it is likely to be a particular format. Functions included detect...

  • BMP (from the first 18 bytes)
  • JPEG (from the first 2 bytes)
  • GIF (from the first 6 bytes)
  • TIFF (from the first 8 bytes)
  • PCX (from the first 4 bytes)
  • PCD-overview (from the first 7 bytes)
  • ZIP (from the first 4 bytes)
  • RAR (from the first 3 bytes)
  • Outlook Express DBX (from the first 4 bytes)

Please drop us a line if you wish to be kept informed about changes and additions to this page.



BMP (from the first 18 bytes)

function AsCodecBmpCheckFileHeader18(const a: Pointer): Boolean;

{$IFDEF DELPHI_5}

type

PCardinal = ^Cardinal;

{$ENDIF}

var

m: Pointer;

begin

Result := False;

if (PBitmapFileHeader(a)^.bfType <> 19778) then exit;

m := Pointer(Cardinal(a)+SizeOf(TBitmapFileHeader));

if (PCardinal(m)^ = SizeOf(TBitmapInfoHeader)) or (PCardinal(m)^ = SizeOf(TBitmapCoreHeader)) then Result := True;

end;



JPEG (from the first 2 bytes)

function AsCodecJpgCheckFileHeader2(const a: Pointer): Boolean;

begin

Result := ((PByte(a)^ = 255) and (PByte(Cardinal(a)+1)^ = 216));

end;



GIF (from the first 6 bytes)

function AsCodecGifCheckFileHeader6(const a: Pointer): Boolean;

const

gifver: array[0..5] of Char = 'GIF87A';

var

m: PByte;

n: Integer;

begin

Result := False;

m := a;

for n := 0 to 5 do

begin

if m^ <> Integer(gifver[n]) then

begin

if n = 3 then

exit

else if n = 4 then

begin

if m^ <> Ord('9') then exit;

end

else

begin

if m^ <> Integer(gifver[n])+32 then exit;

end;

end;

Inc(m);

end;

Result := True;

end;



TIFF (from the first 8 bytes)

function AsCodecTiffCheckFileHeader8(const a: Pointer): Boolean;

type

RAsCodecTiffImageFileHeader = packed record

FByteOrder: array[0..1] of Byte;

FSignature: Word;

FFirstIfdOffset: Cardinal;

end;

PRAsCodecTiffImageFileHeader = ^RAsCodecTiffImageFileHeader;

var

m: Boolean;

n: Integer;

begin

Result := False;

if (PRAsCodecTiffImageFileHeader(a)^.FByteOrder[0] = 73) and (PRAsCodecTiffImageFileHeader(a)^.FByteOrder[1] = 73) then

m := False

else if (PRAsCodecTiffImageFileHeader(a)^.FByteOrder[0] = 77) and (PRAsCodecTiffImageFileHeader(a)^.FByteOrder[1] = 77) then

m := True

else

exit;

n := PRAsCodecTiffImageFileHeader(a)^.FSignature;

if m then n := (((n and 255) shl 8) or ((n and 65280) shr 8));

if n <> 42 then exit;

Result := True;

end;



PCD-overview (from the first 7 bytes)

function AsCodecPcdCheckOverviewFileHeader7(const a: Pointer): Boolean;

const

pcd_opa: array[0..6] of Char = 'PCD_OPA';

var

m: PByte;

n: Integer;

begin

Result := False;

m := a;

for n := 0 to 6 do

begin

if m^ <> Integer(pcd_opa[n]) then exit;

Inc(m);

end;

Result := True;

end;



PCX (from the first 4 bytes)

function AsCodecPcxCheckFileHeader4(const a: Pointer): Boolean;

type

RHeader4 = packed record

FManufacturer: Byte;

FVersion: Byte;

FEncoding: Byte;

FBitsPerPixel: Byte;

end;

PRHeader4 = ^RHeader4;

begin

Result := False;

if PRHeader4(a)^.FManufacturer <> 10 then exit;

if (PRHeader4(a)^.FVersion = 1) or (PRHeader4(a)^.FVersion>5) then exit;

if (PRHeader4(a)^.FEncoding <> 0) and (PRHeader4(a)^.FEncoding <> 1) then exit;

if (PRHeader4(a)^.FBitsPerPixel <> 1) and (PRHeader4(a)^.FBitsPerPixel <> 2) and (PRHeader4(a)^.FBitsPerPixel <> 4) and (PRHeader4(a)^.FBitsPerPixel <> 8) then exit;

Result := True;

end;



ZIP (from the first 4 bytes)

function AsCodecZipCheckFileHeader4(const a: Pointer): Boolean;

{$IFDEF DELPHI_5}

type

PCardinal = ^Cardinal;

{$ENDIF}

begin

Result := (PCardinal(a)^ = $04034B50);

end;



RAR (from the first 3 bytes)

function AsCodecRarCheckFileHeader3(const a: Pointer): Boolean;

begin

Result := ((PByte(a)^ = Ord('R')) and (PByte(Cardinal(a)+1)^ = Ord('a')) and (PByte(Cardinal(a)+2)^ = Ord('r')));

end;



Outlook Express DBX (from the first 4 bytes)

function AsCodecOutlookExpressDbxCheckFileHeader4(const a: Pointer): Boolean;

{$IFDEF DELPHI_5}

type

PCardinal = ^Cardinal;

{$ENDIF}

begin

Result := (PCardinal(a)^ = $FE12ADCF);

end;