EXIF format analysis and through XML processing
Raptor [Mental Studio] (Personal Column) (Blog)
Http://eental.mentsu.com
The following code snippet (Borland C Builder implements the conversion from EXIF data to XML:
/ / -------------------------------------------------------------------------------------------- ---------------------------
#include
Typedef struct {
Word entrytag;
Word EntryType;
DWORD ENTRYSIZE;
DWORD ENTRYVALUE;
} Tifdiff;
#include
/ / -------------------------------------------------------------------------------------------- ---------------------------
BYTE * __FASTCALL TEXIFXML :: Getifd (_di_ixmlnode anode, byte * atifheader, int aposition, ANSISTRING Aname)
{
_DI_ixmlnode pifd = anode-> addchild ("ifd");
IF (aname! = "")
PIFD-> Attributes ["name"] = aname
BYTE * P = Atiffheader aposition;
Word nword;
Memcpy (& nWord, P, Sizeof (nword));
P = SizeOf (nWORD);
_DI_ixmlnode pchild = pifd-> addchild ("count");
PCHILD-> text = format ("0x% x", arrayofconst ((int) nword));
TifdenTry Ent;
_DI_IXMLNode Pentry;
BYTE * PTEMP;
For (int i = nword; i> 0; --I)
{
Memcpy (& Ent, P, SizeOf (ENT));
P = SizeOf (ent);
PENTRY = PIFD-> AddChild ("entry");
PCHILD = PENTRY-> AddChild ("tag");
PCHILD-> text = format ("0x% x", arrayofconst ((int) ent.entrytag)))))
PCHILD = PENTRY-> AddChild ("Type");
PCHILD-> text = INTOSTR (ent.EnTryType);
PCHILD = PENTRY-> AddChild ("size");
PCHILD-> text = format ("0x% x", arrayofconst ((int) ent.EntrySize)))
PCHILD = PENTRY-> AddChild ("Value");
Switch (ent.enTryType) {
Case 1: // Byte
IF (ent.EnTrySize == 1)
PCHILD-> text = format ("0x% .02x", arrayofconst ((int) ent.EntryValue)))))); ELSE
Throw Exception ("unsupported!");
Break;
Case 2: // ASCII
ENT.EnTrySize <= 4)
PCHILD-> text = reinterpret_cast
Else
PCHILD-> text = reinterpret_cast
Break;
Case 3: // short
IF (ent.EnTrySize == 1)
PCHILD-> text = format ("0x% .04x", arrayofconst ((int) ent.EntryValue))));
Else
Throw Exception ("unsupported!");
Break;
Case 5: // ruleal
PCHILD-> text = floattostr (* reinterpret_cast
/ (* Reinterpret_cast
Break;
Case 7: // undefined
ENT.EnTrySize <= 4)
PTEMP = Reinterpret_cast
Else
PTEMP = AtiffHeader Ent.EntryValue;
PCHILD-> text = ""
For (int J = 0; j <(int) ent.EnTrySize; J)
{
PCHILD-> text = pchild-> text = PCHILD-> Text
Format ("0x% .02x", arrayofconst ((int)))))))));
PTEMP ;
IF (j% 16 == 15)
PCHILD-> text = pchild-> text "/ r / n";
}
Break;
Case 9: // slong
IF (ent.EnTrySize == 1)
PCHILD-> Text = INTOSTR (ENT.EnTryValue);
Else
Throw Exception ("unsupported!");
Break;
Case 10: // srtational
PCHild-> text = floattostr (* reinterpret_cast
/ (* Reinterpret_cast
Default: // long & other unknown type
PCHILD-> text = format ("0x% .08X", arrayofconst ((int) ent.EntryValue)))))
Break;
}
Switch (ent.entrytag) {
Case 0x8769: // EXIF IFD
Getifd (Anode, Atiffheader, Ent.EnTryValue, "EXIF");
Break;
Case 0x8805: // GPS IFD
GetIfd (Anode, Atiffheader, Ent.EntryValue, "GPS");
Break;
Case 0xa005: // Interoperability IFD
Getifd (Anode, Atifheader, Ent.EnTryValue, "Interop");
Break;
}
}
Return P;
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
Void __fastcall texifxml :: gettiffheader (_di_ixmlnode anode, byte * atifheader)
{
BYTE * P = atiffheader;
Char sbyteorder [3];
Memcpy (sbyteorder, p, 2);
P = 2;
Sbyteorder [2] = 0;
_DI_ixmlnode pchild = anode-> addchild ("byteorder");
PCHILD-> text = sbyteorder;
Word nflag;
Memcpy (& NFLAG, P, SIZEOF (NFLAG));
P = SizeOf (NFLAG);
PCHILD = anode-> addchild ("flag");
PCHILD-> text = format ("0x% .04x", arrayofconst ((int) nflag));
DWORD NPOINTER;
Memcpy (& NPointer, P, Sizeof (npoint));
INT i = 0;
While (npointer> 0)
{
P = Getifd (Anode, Atiffheader, Npoint, Ansistring ("IFD") INTOSTR (i ));
IF (! p)
Break;
Memcpy (& NPointer, P, Sizeof (npoint));
}
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
INT __FASTCALL TEXIFXML :: LoadFromstream (TSTREAM * ASTREAM)
{
IF (! fxmldoc)
Throw Exception ("XMLDoc Property Is Null!");
TMAUTO_PTR
MS-> CopyFrom (Astream, ASTREAM-> SIZE);
MS-> Seek (0, SOFROMBEGINNING);
FXMLDOC-> filename = "";
FXMLDOC-> Active = True;
FXMLDOC-> Version = "1.0";
FXMLDOC-> Encoding = "GB2312";
_di_ixmlnode pnode = fxmldoc-> addchild ("eXifApp1");
_di_ixmlnode pchild = pnode-> addchild ("eXiFID");
Char sexifid [6];
MS-> Read (SexiFID, 6);
PCHILD-> Text = sexifid;
PCHILD = PNODE-> AddChild ("Tiffheader");
BYTE * PHEADER = static_cast
GetTiffheader (PCHILD, PHEADER);
Return ms-> size;
}
Where fxmldoc is a TXMLDocument control for generating XML. The content read in the LoadFromstream method is the content of the JPEG App1 this Marker Segment (note, not a JPEG file). The GetTiffHeader method is used to read the contents of TiffHeader, including Image File Header and IFD Links. Getifd is used to interpret the specific content of the IFD, including recursive interpretation of the three expansion IFDs of Exif, and contains part of the various data types into a string, particularly for unmissible undefined types. (The result is shown in the XML after the conversion).
(to be continued)