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

原创 2004年05月09日 11:10:00

EXIF格式分析及通过XML处理<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

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

(待续)

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

 EXIF格式分析及通过XML处理 猛禽[Mental Studio](个人专栏)(BLOG)http://mental.mentsu.com 起始长度(Bytes)内容0x002Number of ...
  • Raptor
  • Raptor
  • 2004年05月09日 11:09
  • 3251

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

EXIF格式分析及通过XML处理 猛禽[Mental Studio](个人专栏)(BLOG)http://mental.mentsu.com 转换后的XML大致如下:  Exif      II   ...
  • Raptor
  • Raptor
  • 2004年05月09日 11:10
  • 2987

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

EXIF格式分析及通过XML处理 猛禽[Mental Studio](个人专栏)(BLOG)http://mental.mentsu.com 下面是一个典型的EXIF JPEG文件格式分析结果(源文件...
  • Raptor
  • Raptor
  • 2004年05月09日 11:10
  • 4013

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

EXIF格式分析及通过XML处理 猛禽[Mental Studio](个人专栏)(BLOG)http://mental.mentsu.com 随着数码相机的普及,EXIF已经被大多数图像处理软件所支持...
  • Raptor
  • Raptor
  • 2004年05月09日 11:10
  • 5404

jpg文件格式分析

JPEG格式格式:JFIF(JPEG档的交换格式)压缩:JPEG(灰阶影像压缩比约为10:1;彩色影像约为20:1)以JPEG文件格式保存的图像实际上是2个不同格式的混合物:JPEG格式规范本身,用来...
  • bluesky_sunshine
  • bluesky_sunshine
  • 2011年02月13日 19:39
  • 9741

Exif格式分析

大概翻译了一下,非常的粗糙,慢慢修正。请高手自动飘过~因为做图像压缩时会损失相机写入的如光圈、快门等信息,所以自己写了个图像压缩小玩意,顺便研究了一下Exif。原文地址:Exif file forma...
  • lsiyun
  • lsiyun
  • 2010年03月04日 17:36
  • 8914

提取Exif信息中GPS经纬度,转化为double方法

我用的是网上的一个叫DealExif的CPP文件(可以自行去网上下载),使用它的方法阅读JPG图片的Exif信息。完整过程如下: 1、引入DealExif头文件。 2、 在合适的位置加入两行代码 ...
  • zby22013
  • zby22013
  • 2013年07月22日 22:28
  • 2457

JPEG系列二 JPEG文件中的EXIF(下)

本文介绍EXIF中都保存了哪些数据,这些数据的内容和格式,最后介绍一下EXIF中的缩略图信息。 EXIF JPEG文件将EXIF信息存储在JFIF的APP1标记中。 EXIF主要保存拍摄照片时的相机...
  • shelldon
  • shelldon
  • 2017年01月13日 12:52
  • 2555

jpg图片的Exif及gps信息和示例分析

转自:http://www.verydemo.com/demo_c173_i10439.html jpg图片的Exif及gps信息和示例分析 分类: 操作系...
  • yapingmcu
  • yapingmcu
  • 2016年02月05日 17:24
  • 7921

20170227. EXIF信息的说明(opencv320 ApplyExifOrientation)

在opencv3.2.0中,对imread函数做了修改 Mat imread( const String& filename, int flags ) { /// create the ba...
  • u014488388
  • u014488388
  • 2017年02月27日 16:00
  • 247
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:EXIF格式分析及通过XML处理(4)
举报原因:
原因补充:

(最多只允许输入30个字)