📄 exif.pas
字号:
{==============================================================================
Component simple read Exif section in Jpeg/Jfif Files.
More information about Exif at www.exif.org
裲mponent written by SimBa aka Dimoniusis
You may use this component absolutely free.
You may talk with me via
e-mail: dimonius@mail333.com
ICQ: 11152101
Web: http://dimonius.da.ru
Changes:
Version 1.3
- some more ifd tags implemented
- some bugs fixes
Version 1.2 (Some code by Jim Wood, e-mail: jwood@visithink.com)
- some more ifd tags implemented
- corrected work with ReadOnly files
Version 1.1 (By Ive, e-mail: ive@lilysoft.com)
- works now with Motorola and Intel byte order tags
- better offset calculation
- some more ifd tags implemented
- some format functions for rational values
- naming convention changed a little
NOTE: far away from being complete but it seems to
work with all example files from www.exif.org
- Ive (c) 2003
==============================================================================}
unit Exif;
interface
uses
Classes, SysUtils;
type
TIfdTag = packed record
ID : Word; //Tag number
Typ : Word; //Type tag
Count : Cardinal; //tag length
Offset : Cardinal; //Offset / Value
end;
TExif = class(TObject)
private
FImageDesc : String; //Picture description
FMake : String; //Camera manufacturer
FModel : String; //Camere model
FOrientation : Byte; //Image orientation - 1 normal
FOrientationDesc : String; //Image orientation description
FCopyright : String; //Copyright
FValid : Boolean; //Has valid Exif header
FDateTime : String; //Date and Time of Change
FDateTimeOriginal : String; //Original Date and Time
FDateTimeDigitized : String; //Camshot Date and Time
FUserComments : String; //User Comments
FExposure : String; //Exposure
FFstops : String;
FShutterSpeed : string;
FAperture : string;
FMaxAperture : string;
FExposureProgram : Byte;
FExposureProgramDesc: string;
FPixelXDimension : Cardinal;
FPixelYDimension : Cardinal;
FXResolution : Cardinal;
FYResolution : Cardinal;
FMeteringMode : byte;
FMeteringMethod : string;
FLightSource : Byte;
FLightSourceDesc : string;
FFlash : Byte;
FFlashDesc : string;
FISO : Word;
FSoftware : string;
FArtist : string;
FCompressedBPP : string;
f : File;
ifdp : Cardinal;
FSwap : boolean;
function ReadAsci(const Offset, Count: Cardinal): String;
function ReadRatio(const Offset: Cardinal; frac: boolean): String; overload;
function ReadRatio(const Offset: Cardinal): single; overload;
procedure ReadTag(var tag: TIfdTag);
procedure Init;
function ReadLongIntValue(const Offset: Cardinal): LongInt;
public
constructor Create;
procedure ReadFromFile(const FileName: AnsiString);
property Valid: Boolean read FValid;
property ImageDesc: String read FImageDesc;
property Make: String read FMake;
property Model: String read FModel;
property Orientation: Byte read FOrientation;
property OrientationDesc: String read FOrientationDesc;
property Copyright: String read FCopyright;
property DateTime: String read FDateTime;
property DateTimeOriginal: String read FDateTimeOriginal;
property DateTimeDigitized: String read FDateTimeDigitized;
property UserComments: String read FUserComments;
property Software: String read FSoftware;
property Artist: String read FArtist;
property Exposure: String read FExposure;
property ExposureProgram: byte read FExposureProgram;
property ExposureProgramDesc: string read FExposureProgramDesc;
property FStops: String read FFStops;
property ShutterSpeed: String read FShutterSpeed;
property Aperture: String read FAperture;
property MaxAperture: String read FMaxAperture;
property CompressedBPP: String read FCompressedBPP;
property PixelXDimension: Cardinal read FPixelXDimension;
property PixelYDimension: Cardinal read FPixelYDimension;
property XResolution: Cardinal read FXResolution;
property YResolution: Cardinal read FYResolution;
property MeteringMode: byte read FMeteringMode;
property MeteringMethod: string read FMeteringMethod;
property LightSource: byte read FLightSource;
property LightSourceDesc: string read FLightSourceDesc;
property Flash: byte read FFlash;
property FlashDesc: string read FFlashDesc;
property ISO: Word read FISO;
end;
implementation
uses
Math;
type
TMarker = packed record
Marker : Word; //Section marker
Len : Word; //Length Section
Indefin : Array [0..4] of Char; //Indefiner - "Exif" 00, "JFIF" 00 and ets
Pad : Char; //0x00
end;
TIFDHeader = packed record
pad : Byte; //00h
ByteOrder : Word; //II (4D4D) or MM
i42 : Word; //2A00 (magic number from the 'Hitchhikers Guide'
Offset : Cardinal; //0th offset IFD
Count : Word; // number of IFD entries
end;
function SwapLong(Value: Cardinal): Cardinal;
asm bswap eax end;
procedure TExif.ReadTag(var tag: TIfdTag);
begin
BlockRead(f,tag,12);
if FSwap then with tag do begin // motorola or intel byte order ?
ID := Swap(ID);
Typ := Swap(Typ);
Count := SwapLong(Count);
if (Typ=1) or (Typ=3) then
Offset := (Offset shr 8) and $FF
else
Offset := SwapLong(Offset);
end
else with tag do begin
if ID<>$8827 then //ISO Metering Mode not need conversion
if (Typ=1) or (Typ=3) then
Offset := Offset and $FF; // other bytes are undefined but maybe not zero
end;
end;
function TExif.ReadAsci(const Offset, Count: Cardinal): String;
var
fp: LongInt;
i: Word;
begin
SetLength(Result,Count);
fp:=FilePos(f); //Save file offset
Seek(f, Offset);
try
i:=1;
repeat
BlockRead(f,Result[i],1);
inc(i);
until (i>=Count) or (Result[i-1]=#0);
if i<=Count then Result:=Copy(Result,1,i-1);
except
Result:='';
end;
Result:=TrimRight(Result);
Seek(f,fp); //Restore file offset
end;
function TExif.ReadLongIntValue(const Offset: Cardinal): LongInt;
var
fp: LongInt;
begin
fp:=FilePos(f); //Save file offset
Seek(f, Offset);
try
BlockRead(f, Result, sizeof(Result));
if FSwap then Result:=SwapLong(Result);
except
Result:=0;
end;
Seek(f, fp); //Restore file offset
end;
function TExif.ReadRatio(const Offset: Cardinal; frac: boolean): String;
var
fp: LongInt;
nom,denom: cardinal;
begin
fp:=FilePos(f); //Save file offset
Seek(f, Offset);
try
BlockRead(f,nom,4);
BlockRead(f,denom,4);
if FSwap then begin // !!!
nom := SwapLong(nom);
denom := SwapLong(denom);
end;
if frac then begin
str((nom/denom):1:2, result);
if (length(result)>0) and (result[length(result)]='0') then Result:=copy(Result,1,length(Result)-1);
end else
if denom<>1000000 then
Result:=inttostr(nom)+'/'+inttostr(denom)
else Result:='0';
except
Result:='';
end;
Seek(f,fp); //Restore file offset
end;
function TExif.ReadRatio(const Offset: Cardinal): single;
var
fp: LongInt;
nom,denom: cardinal;
begin
fp:=FilePos(f); //Save file offset
Seek(f, Offset);
try
BlockRead(f,nom,4);
BlockRead(f,denom,4);
if FSwap then begin // !!!
nom := SwapLong(nom);
denom := SwapLong(denom);
end;
Result:=nom/denom;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -