Reading Exif information requires a simple understanding of JPEG and Exif formats.
JEGP format please view cloud wind Article http://blog.csdn.net/glock18/archive/2004/09/05/95268.aspx
Exif format please check the article http://dev.csdn.net/article/27/27594.shtm for birds of prey
The following is a class for reading Exif information:
Const
JPEG_BEGIN = $ FFD8;
Pai_app1 = $ FFE1;
Performance_end = $ FFD9;
Pai_exif = (Byte ('E') shl 24) + (Byte ('x') shl 16) + (Byte ('I') shl 8) + Byte ('F ');
BYTE_ODR_ I = (Byte ('I') shl 8) + Byte ('I ');
BYTE_ODR_M = (Byte ('M') shl 8) + Byte ('M ');
Type
U32 = DWORD;
2010= WORD;
S32 = Integer;
U8 = Byte;
PIFDEntry = ^ YIFDEntry;
YIFDEntry = record
U16tag: 002;
U16type: 2010;
U32count: U32;
U32value: U32;
U32rsize: U32; // actual data size --- bytes
U32maddr: PChar; // address of the data in the memory
SDescript: string;
End;
YIFDTagInfo = record
Tag: 2010;
Mean: string;
End;
YExifReader = class (TComponent)
Private
FStream: TFileStream;
FTagInfo: Array of YIFDTagInfo;
FEntrys: Array of YIFDEntry;
FExifBuf: PChar; // memory for storing all Exif values
FBufused: U32 ;//
FInfCount: S32;
Procedure GetEntryData (var ie: YIFDEntry; TiffHdrPos: U32 );
Public
Constructor Create (AOwner: TComponent); override;
Destructor Destroy; override;
Function ReadExif (JpgFileName: string): string;
Function ExifInf (I: S32): string;
Property ExifInfoCount: S32 read FInfCount;
End;
Implementation
Uses Winsock;
Const
EXIF_ATTR_DEF_FILE = 'exifinf. Ini ';
CLRF = #13 #10;
// Calculate the actual size of an Entry
Procedure GetEntrySize (var ie: YIFDEntry );
Begin
Case ie. u16type
1, 2, 7: ie. u32rsize: = 1;
3: ie. u32rsize: = 2;
4, 9: ie. u32rsize: = 4;
5, 10: ie. u32rsize: = 8;
Else
Ie. u32rsize: = 1;
End;
Ie. u32rsize: = ie. u32rsize * ie. u32count;
End;
// Obtain the meaning of an Entry
Procedure GetEntryDescript (var ie: YIFDEntry; const iti: Array of YIFDTagInfo );
Var
I: 2010;
B: BOOL;
Begin
B: = False;
For I: = 0 to Length (iti)-1 do
Begin
If ie. u16tag = iti [I]. Tag then
Begin
Ie. sDescript: = iti [I]. Mean;
B: = True; break;
End;
End;
If not B then
Ie. sDescript: = format ('unknow Tag: %. 4x ', [ie. u16tag]);
End;
Constructor YExifReader. Create (AOwner: TComponent );
Var
S: string;
I, j: S32;
Lst: TStringList;
Begin
Inherited Create (AOwner );
FStream: = nil;
FExifBuf: = AllocMem (1024*100); // first allocate kb memory for backup... enough to store all information
S: = ExtractFilePath (ParamStr (0 ));
If s [Length (s)] <> '/' then
S: = s + '/';
Lst: = TStringList. Create;
Lst. LoadFromFile (s + EXIF_ATTR_DEF_FILE );
For I: = 0 to lst. Count-1 do
Begin
S: = lst. Strings [I];
If s [1] <> '; 'Then
Begin
SetLength (FTagInfo, Length (FTagInfo) + 1 );
J: = Pos (', s );
FTagInfo [Length (FTagInfo)-1]. Tag: = StrToInt (Copy (s, 1, J-1 ));
FTagInfo [Length (FTagInfo)-1]. Mean: = Copy (s, j + 1, Length (s)-j );
End;
End;
End;
Destructor YExifReader. Destroy;
Begin
If FStream <> nil then
FStream. Free;
FreeMem (FExifBuf );
Inherited Destroy;
End;
Procedure YExifReader. GetEntryData (var ie: YIFDEntry; TiffHdrPos: U32 );
Begin
Ie. u32maddr: = FExifBuf + FBufUsed;
If ie. u32count <= 4 then
Begin
Move (ie. u32value, ie. u32maddr ^, ie. u32rsize );
Inc (FBufUsed, ie. u32rsize );
Exit;
End;
FStream. Position: = TiffHdrPos + ie. u32value;
FStream. Read (ie. u32maddr ^, ie. u32rsize );
Inc (FBufUsed, ie. u32rsize );
End;
Function YExifReader. ReadExif (JpgFileName: string): string;
Var
I, w, TiffHeaderPos, IFD_0_EntryCount, IFD_1_EntryCount: 2010;
Dw: U32;
Begin
FStream: = TFileStream. Create (JpgFileName, fmOpenRead );
FBufUsed: = 0;
FInfCount: = 0;
// JEPG file header
FStream. Read (w, sizeof (w ));
If JPEG_BEGIN <> ntohs (w) then
Begin
Result: = 'not A Jpeg Image. '+ CLRF;
FreeAndNil (FStream );
Exit;
End;
// Search segment 'app1' --- Exif attribute information
FStream. Read (w, sizeof (w ));
W: = ntohs (w );
While pai_app1 <> w do
Begin
FStream. Read (w, sizeof (w ));
FStream. Seek (ntohs (w)-sizeof (w), soFromCurrent );
FStream. Read (w, sizeof (w ));
W: = ntohs (w );
If else _end = w then
Begin
Result: = result + 'no Exif info. '+ CLRF;
FreeAndNil (FStream );
Exit;
End;
End;
Result: = result + 'segment APP1 found. '+ CLRF;
FStream. Read (w, sizeof (w ));
W: = ntohs (w );
Result: = result + 'segment APP1 length: '+ format (' %. 4x ', [w]) + CLRF;
// Search Exif sign --- 'exist'
FStream. Read (dw, sizeof (dw ));
Dw: = ntohl (dw );
If pai_exif <> dw then
Begin
Result: = result + 'no Exif in this segment. '+ CLRF;
FreeAndNil (FStream );
Exit;
End;
Result: = result + 'exif sign found... '+ CLRF;
FStream. Read (w, sizeof (w); // two zero
// TIFF Header
Required headerpos: = FStream. Position;
FStream. Read (w, sizeof (w ));
If BYTE_ODR_ I = w then
Begin
Result: = result + 'tiff Header byte order is Intel. '+ CLRF;
End else
Begin // if it is in the Motolora format, it will not be processed ~~~~~~ '
Result: = result + 'tiff Header byte order is Motolora. '+ CLRF;
FreeAndNil (FStream );
Exit;
End;
FStream. Read (w, sizeof (w); // indicates the TIFF file format, always 0x002A
FStream. Read (dw, sizeof (dw); // start position of the first IFD. The offset calculation start point is the start point of the TIFF Header.
FStream. Seek (dw-8, soFromCurrent); // 8 = size of Image File Header
FStream. Read (w, sizeof (w); // IFD.0 Entry Count
Result: = result + 'tiff IFD0 Entry count: '+ format (' %. 4x ', [w]) + CLRF;
IFD_0_EntryCount: = w;
SetLength (FEntrys, IFD_0_EntryCount );
// Read ifd entry
For I: = 0 to IFD_0_EntryCount-1 do
Begin
FStream. Read (FEntrys [I]. u16tag, sizeof (2010 ));
FStream. Read (FEntrys [I]. u16type, sizeof (2010 ));
FStream. Read (FEntrys [I]. u32count, sizeof (u32 ));
FStream. Read (FEntrys [I]. u32value, sizeof (u32 ));
GetEntrySize (FEntrys [I]);
End;
// Read ifd value
For I: = 0 to IFD_0_EntryCount-1 do
Begin
GetEntryDescript (FEntrys [I], FTagInfo );
GetEntryData (FEntrys [I], using headerpos );
End;
// Offset of Exif IFD = The last TIFF IFDEntry value + TIFF header offset
FStream. Position: = Response headerpos + FEntrys [IFD_0_EntryCount-1]. u32value;
FStream. Read (w, sizeof (w); // IFD.1 Entry Count
Result: = result + 'tiff IFD1 Entry count: '+ format (' %. 4x ', [w]) + CLRF;
Ifd_incluentrycount: = w;
SetLength (FEntrys, IFD_0_EntryCount + IFD_1_EntryCount );
For I: = IFD_0_EntryCount to Length (FEntrys)-1 do
Begin
FStream. Read (FEntrys [I]. u16tag, sizeof (2010 ));
FStream. Read (FEntrys [I]. u16type, sizeof (2010 ));
FStream. Read (FEntrys [I]. u32count, sizeof (u32 ));
FStream. Read (FEntrys [I]. u32value, sizeof (u32 ));
GetEntrySize (FEntrys [I]);
End;
For I: = IFD_0_EntryCount to Length (FEntrys)-1 do
Begin
GetEntryDescript (FEntrys [I], FTagInfo );
GetEntryData (FEntrys [I], using headerpos );
End;
FInfCount: = Length (FEntrys );
FreeAndNil (FStream );
End;
Function YExifReader. ExifInf (I: S32): string;
Var
S: string;
P: PChar;
Begin
If I> = Length (FEntrys) then
Begin
Result: = '';
Exit;
End;
Result: = FEntrys [I]. sDescript + '';
S: = '';
If (FEntrys [I]. u16type = 2) or // Ascii or ExifVersion or FlashPixVersion
(FEntrys [I]. u16tag = $9000) or (FEntrys [I]. u16tag = $ A000) then
Begin
SetLength (s, FEntrys [I]. u32rsize );
Move (FEntrys [I]. u32maddr ^, s [1], FEntrys [I]. u32rsize );
End else
Begin
If (FEntrys [I]. u16tag = $ 927C) or (FEntrys [I]. u16tag = $9286) then
Begin // MakerNote or UserComment
S: = 'not Read .';
Result: = result + s;
Exit;
End;
P: = AllocMem (FEntrys [I]. u32rsize * 2 + 1 );
BinToHex (FEntrys [I]. u32maddr, p, FEntrys [I]. u32rsize );
S: = p;
FreeMem (p );
End;
Result: = result + s;
End;
End.
; **************************************** *****************************
;
; TIFF Rev. 6.0 Attribute Information
;
; **************************************** *****************************
;
;
; A. Tags relating to image data structure
;
256 100 Image width-
257 101 Image height-
258 102 Number of bits per component-
259 103 Compression-
262 106 Pixel composition-
274 112 Orientation of image-
277 115 Number of components-
284 11C Image data arrangement-
530 212 Subsampling ratio of Y to C-
531 213 Y and C positioning-
282 11A Image resolution in width direct-
283 11B Image resolution in height direct-
296 128 Unit of X and Y resolution-
;
; B. Tags relating to recording offset
;
273 111 Image data location-
278 116 Number of rows per strip-
279 117 Bytes per compressed strip-
513 201 Offset to jpeg soi-
514 202 Bytes of JPEG data-
;
C. Tags relating to image data characteristics
;
301 12D Transfer function-
318 13E White point chromaticity-
319 13F Chromaticities of primaries-
529 211 Color space transformation matrix-
532 214 Pair of black and white reference-
;
; D. Other tags
;
306 132 File change date and time-
270 10E Image Description-
271 10F Image input equipment maker-
272 110 Image input equipment model-
305 131 Software used-
315 13B Person who created the image-
3432 8298 Copyright holder-
;
;
; **************************************** *****************************
;
; Exif IFD Attribute Information v2.1
;
; **************************************** *****************************
;
; A. Tags Relating to Version
;
36864 9000 Exif version-
40960 A000 Supported FlashPix version-
;
; B. Tag Relating to Image Data Characteristics
;
40961 A001 Color space information-
;
C. Tags Relating to Image Configuration
;
37121 9101 Meaning of each component-
37122 9102 Image compression mode-
40962 A002 Valid image width-
40963 A003 Valid image height-
;
; D. Tags Relating to User Information
;
37500 927C Manufacturer notes-
37510 9286 User comments-
;
; E. Tag Relating to Related File Information
;
40964 A004 Related audio file-
;
; F. Tags Relating to Date and Time
;
36867 9003 Date and time of original data-
36868 9004 Date and time of digital data-
37520 9290 DateTime subseconds-
37521 9291 DateTimeOriginal subseconds-
37522 9292 DateTimeDigitized subseconds-
;
; G. Tags Relating to Picture-Taking Conditions
;
33434 829A Exposure time-
33437 829D F number-
34850 8822 Exposure program-
34852 8824 Spectral sensiti.pdf-
34855 8827 ISO speed rating-
34856 8828 Optoelectric conversion factor-
37377 9201 Shutter speed-
37378 9202 Aperture-
37379 9203 Brightness-
37380 9204 Exposure bias-
37381 9205 Maximum lens aperture-
37382 9206 Subject distance-
37383 9207 Metering mode-
37384 9208 Light source-
37385 9209 Flash-
37386 920A Lens focal length-
41483 A20B Flash energy-
41484 A20C Spatial frequency response-
41486 A20E Focal plane X resolution-
41487 A20F Focal plane Y resolution-
41488 A210 Focal plane resolution unit-
41492 A214 Subject location-
41493 A215 Exposure index ExposureIndex-
41495 A217 Sensing method-
41728 A300 File source-
41729 A301 Scene type-
41730 A302 CFA pattern-
;
; H. Tags Relating to Date and Time
;
40965 A005 Pointer of Interoperability IFD-
;
34665 8769 Exif IFD Pointer-
34853 8825 GPS Info IFD Pointer-
40965 A005 Interoperability IFD Pointer-
; END