王朝网络
分享
 
 
 

EXIF格式分析及通过XML处理(4)

王朝system·作者佚名  2006-12-17
宽屏版  字体: |||超大  

EXIF格式分析及通过XML处理(4)

EXIF格式分析及通过XML处理(4) EXIF格式分析及通过XML处理

猛禽[Mental Studio](个人专栏)(BLOG)

http://mental.mentsu.com

下面的代码片断(Borland C++ Builder)实现了从EXIF数据到XML的转换:

//---------------------------------------------------------------------------

#include <pshpack1.h>

typedef struct {

WORD EntryTag;

WORD EntryType;

DWORD EntrySize;

DWORD EntryValue;

} TIFDEntry;

#include <poppack.h>

//---------------------------------------------------------------------------

BYTE * __fastcall TExifXML::GetIFD(_di_IXMLNode aNode, BYTE * aTIFFHeader, 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 = IntToStr( 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 )( BYTE )ent.EntryValue ) ) );

else

throw Exception( "Unsupported!" );

break;

case 2 : // ASCII

if ( ent.EntrySize <= 4 )

pChild->Text = reinterpret_cast<LPSTR>( &ent.EntryValue );

else

pChild->Text = reinterpret_cast<LPSTR>( aTIFFHeader + ent.EntryValue );

break;

case 3 : // SHORT

if ( ent.EntrySize == 1 )

pChild->Text = Format( "0x%.04X", ARRAYOFCONST( ( ( int )( WORD )ent.EntryValue ) ) );

else

throw Exception( "Unsupported!" );

break;

case 5 : // RATIONAL

pChild->Text = FloatToStr( *reinterpret_cast<DWORD *>( aTIFFHeader + ent.EntryValue )

/ ( double )( *reinterpret_cast<DWORD *>( aTIFFHeader + ent.EntryValue + sizeof ( DWORD ) ) ) );

break;

case 7 : // UNDEFINED

if ( ent.EntrySize <= 4 )

pTemp = reinterpret_cast<BYTE *>( &ent.EntryValue );

else

pTemp = aTIFFHeader + ent.EntryValue;

pChild->Text = "";

for ( int j = 0; j < ( int )ent.EntrySize; ++j )

{

pChild->Text = pChild->Text

+ Format( " 0x%.02X", ARRAYOFCONST( ( ( int )( BYTE )( *pTemp ) ) ) );

pTemp++;

if ( j % 16 == 15 )

pChild->Text = pChild->Text + "\r\n";

}

break;

case 9 : // SLONG

if ( ent.EntrySize == 1 )

pChild->Text = IntToStr( ent.EntryValue );

else

throw Exception( "Unsupported!" );

break;

case 10: // SRATIONAL

pChild->Text = FloatToStr( *reinterpret_cast<int *>( aTIFFHeader + ent.EntryValue )

/ ( double )( *reinterpret_cast<int *>( aTIFFHeader + ent.EntryValue + sizeof ( int ) ) ) );

break;

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, aTIFFHeader, ent.EntryValue, "InterOp" );

break;

}

}

return p;

}

//---------------------------------------------------------------------------

void __fastcall TExifXML::GetTIFFHeader(_di_IXMLNode aNode, BYTE * aTIFFHeader)

{

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 ( nPointer ) );

int i = 0;

while ( nPointer > 0 )

{

p = GetIFD( aNode, aTIFFHeader, nPointer, AnsiString( "IFD" ) + IntToStr( i++ ) );

if ( !p )

break;

memcpy( &nPointer, p, sizeof ( nPointer ) );

}

}

//---------------------------------------------------------------------------

int __fastcall TExifXML::LoadFromStream(TStream * aStream)

{

if ( !FXMLDoc )

throw Exception( "XMLDoc property is null!" );

TMauto_ptr<TMemoryStream> ms( new TMemoryStream( ) );

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<BYTE *>( ms->Memory ) + ( int )ms->Position;

GetTIFFHeader( pChild, pHeader );

return ms->Size;

}

其中FXMLDoc是一个TXMLDocument控件,用于生成XML。LoadFromStream方法读入的内容为JPEG APP1这个Marker Segment的内容(注意,不是JPEG文件)。GetTIFFHeader方法用于读出TIFFHeader的内容,包括Image File Header和IFD链表。GetIFD则是用于解读IFD的具体内容,其中包括对EXIF的三个扩充IFD的递归解读,并且其中包含了将各种数据类型转换为字符串的部分,特别是对不定长的UNDEFINED类型的处理(其结果见下面转换后的XML)。

(待续)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有