imagingmodules/exiflib/src/ExifIfd.cpp
changeset 0 469c91dae73b
equal deleted inserted replaced
-1:000000000000 0:469c91dae73b
       
     1 /*
       
     2 * Copyright (c) 2003, 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Exif IFD structure handling classes.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "ExifRead.h"
       
    21 #include "ExifTagImpl.h"
       
    22 #include "ExifIfd.h"
       
    23 #include "ExifCommon.h"
       
    24 #include "ExifValueTable.h"
       
    25 
       
    26 // ============================ CLASS CExifIfd =================================
       
    27 // ============================ MEMBER FUNCTIONS ===============================
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CExifIfd::CExifIfd
       
    31 // C++ default constructor can NOT contain any code, that
       
    32 // might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CExifIfd::CExifIfd() : iTagArray( sizeof( CExifTagImpl* ) )
       
    36     {
       
    37     }
       
    38 
       
    39 // -----------------------------------------------------------------------------
       
    40 // CExifIfd::ConstructL
       
    41 // Symbian 2nd phase constructor can leave.
       
    42 // -----------------------------------------------------------------------------
       
    43 //
       
    44 void CExifIfd::ConstructL()
       
    45     {
       
    46     }
       
    47 
       
    48 // -----------------------------------------------------------------------------
       
    49 // CExifIfd::NewBaseL
       
    50 // Two-phased constructor. Instantiates and returns the relevant derived class.
       
    51 // -----------------------------------------------------------------------------
       
    52 //
       
    53 CExifIfd* CExifIfd::NewBaseL( TExifIfdType aIfdType )
       
    54     {
       
    55     switch ( aIfdType )
       
    56         {
       
    57         case EIfd0:
       
    58             return CExifIfd0::NewL();
       
    59         case EIfdExif:
       
    60             return CExifIfdExif::NewL();
       
    61         case EIfd1:
       
    62             return CExifIfd1::NewL();
       
    63         case EIfdGps:
       
    64             return CExifIfdGps::NewL();
       
    65         case EIfdIntOp:
       
    66             return CExifIfdIntOp::NewL();
       
    67         default:
       
    68             User::Leave( KErrGeneral );
       
    69         }
       
    70     return NULL;
       
    71     }
       
    72 
       
    73 // Destructor
       
    74 CExifIfd::~CExifIfd()
       
    75     {
       
    76     iTagArray.ResetAndDestroy();
       
    77     }
       
    78 
       
    79 // -----------------------------------------------------------------------------
       
    80 // CExifIfd::IsValid
       
    81 // Checks if the IFD is in valid format, and contains all mandatory tags.
       
    82 // -----------------------------------------------------------------------------
       
    83 //
       
    84 TBool CExifIfd::IsValid() const
       
    85     {
       
    86     if ( iTagArray.Count() )
       
    87         {
       
    88         return ETrue;
       
    89         }
       
    90     return EFalse;
       
    91     }
       
    92 
       
    93 // -----------------------------------------------------------------------------
       
    94 // CExifIfd::TagExists
       
    95 // Checks if specified tag exists in the IFD.
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 TBool CExifIfd::TagExists( TUint16 aTagId ) const
       
    99     {
       
   100     for ( TInt i = 0; i < iTagArray.Count(); ++i )
       
   101         {
       
   102         if ( aTagId == iTagArray[i]->Id() )
       
   103             {
       
   104             return ETrue;
       
   105             }
       
   106         }
       
   107     return EFalse;
       
   108     }
       
   109 
       
   110 // -----------------------------------------------------------------------------
       
   111 // CExifIfd::Size
       
   112 // Returns the size of the IFD structure in bytes.
       
   113 // -----------------------------------------------------------------------------
       
   114 //
       
   115 TUint16 CExifIfd::Size() const
       
   116     {
       
   117     if ( !iTagArray.Count() )
       
   118         {
       
   119         return 0;
       
   120         }
       
   121     // Size of the tags + 6 bytes (the next ifd offset and number of tags info)
       
   122     return STATIC_CAST( TUint16, iSize + 6 ); 
       
   123     }
       
   124 
       
   125 // -----------------------------------------------------------------------------
       
   126 // CExifIfd::SetNextIfdOffset
       
   127 // Sets the next IFD offset.
       
   128 // -----------------------------------------------------------------------------
       
   129 //
       
   130 void CExifIfd::SetNextIfdOffset( TUint32 aIfdOffset )
       
   131     {
       
   132     iNextIfdOffset = aIfdOffset;
       
   133     }
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // CExifIfd::WriteTagsL
       
   137 // Writes the tag data in the IFD structure to the location defined by the 
       
   138 // given pointer and the offset.
       
   139 // -----------------------------------------------------------------------------
       
   140 //
       
   141 void CExifIfd::WriteTagsL( TUint16*& aExifDataPtr, TUint& aPos ) const
       
   142     {
       
   143     if ( !iTagArray.Count() )
       
   144         {
       
   145         User::Leave( KErrNotReady );
       
   146         }
       
   147     *aExifDataPtr++ = STATIC_CAST( TUint16, iTagArray.Count() );
       
   148     TUint16* ifdForwardPtr = aExifDataPtr + ( iTagArray.Count() * 6 ) + 2;
       
   149     TUint32 fwdPos = ( ( iTagArray.Count() * 12 ) - 6 ) + aPos;
       
   150     for ( TInt i = 0; i < iTagArray.Count(); ++i )
       
   151         {
       
   152         CExifTagImpl* tag = iTagArray[i];
       
   153         *aExifDataPtr++ = tag->Id();
       
   154         CExifTag::TExifTagDataType tagType = tag->DataType();
       
   155         *aExifDataPtr++ = STATIC_CAST( TUint16, tagType );
       
   156         TUint32 count = tag->DataCount();
       
   157         TExifCommon::SetUint32( REINTERPRET_CAST( TUint8*, aExifDataPtr ), 
       
   158             count );
       
   159         aExifDataPtr += 2;
       
   160         TUint noBytes = 0;
       
   161         if ( ( tagType == CExifTag::ETagByte ) || 
       
   162             ( tagType == CExifTag::ETagAscii ) || 
       
   163             ( tagType == CExifTag::ETagUndefined ) )
       
   164             {
       
   165             noBytes = 1;
       
   166             }
       
   167         else if ( ( tagType == CExifTag::ETagLong ) || 
       
   168             ( tagType == CExifTag::ETagSlong ) )
       
   169             {
       
   170             noBytes = 4;
       
   171             }
       
   172         else if ( ( tagType == CExifTag::ETagRational ) || 
       
   173             ( tagType == CExifTag::ETagSrational ) )
       
   174             {
       
   175             noBytes = 8;
       
   176             }
       
   177         else
       
   178             {
       
   179             noBytes = 2;
       
   180             }
       
   181         noBytes *= count;
       
   182         TPtrC8 tagBuffer = tag->Data();
       
   183         if ( noBytes < 5 )
       
   184             {
       
   185             TUint32 tagData = 0;
       
   186             switch ( noBytes )
       
   187                 {
       
   188                 case 4:
       
   189                     tagData = TExifCommon::Uint32L( 
       
   190                         CONST_CAST( TUint8*, tagBuffer.Ptr() ) );
       
   191                     break;
       
   192                 case 3:
       
   193                     tagData = TExifCommon::Uint32L( CONST_CAST( 
       
   194                         TUint8*, tagBuffer.Ptr() ) ) & KThreeByteMask;
       
   195                     break;
       
   196                 case 2:
       
   197                     tagData = TExifCommon::Uint32L( CONST_CAST( 
       
   198                         TUint8*, tagBuffer.Ptr() ) ) & KTwoByteMask;
       
   199                     break;
       
   200                 default:
       
   201                     tagData = TExifCommon::Uint32L( CONST_CAST( 
       
   202                         TUint8*, tagBuffer.Ptr() ) ) & KOneByteMask;
       
   203                 }
       
   204             TExifCommon::SetUint32( 
       
   205                 REINTERPRET_CAST( TUint8*, aExifDataPtr ), tagData ); 
       
   206             }
       
   207         else
       
   208             {
       
   209             TPtr8 ptr( REINTERPRET_CAST( TUint8*, ifdForwardPtr ), noBytes );
       
   210             ptr.Copy( tagBuffer.Ptr(), noBytes );
       
   211             TExifCommon::SetUint32( 
       
   212                 REINTERPRET_CAST( TUint8*, aExifDataPtr ), fwdPos ); 
       
   213             if ( noBytes % 2 )
       
   214                 {
       
   215                 ++noBytes;
       
   216                 ifdForwardPtr += ( noBytes / 2 );
       
   217                 *( ( REINTERPRET_CAST( TUint8*, ifdForwardPtr ) ) - 1 ) = 0;
       
   218                 }
       
   219             else
       
   220                 {
       
   221                 ifdForwardPtr += ( noBytes / 2 );
       
   222                 }
       
   223             fwdPos += noBytes;
       
   224             }
       
   225         aExifDataPtr += 2;
       
   226         }
       
   227     TExifCommon::SetUint32( 
       
   228         REINTERPRET_CAST( TUint8*, aExifDataPtr ), iNextIfdOffset ); 
       
   229     aExifDataPtr = ifdForwardPtr;
       
   230     aPos = fwdPos + 12;
       
   231     }
       
   232 
       
   233 // -----------------------------------------------------------------------------
       
   234 // CExifIfd::InsertTagL
       
   235 // Inserts/Replaces the given tag in the IFD structure.
       
   236 // -----------------------------------------------------------------------------
       
   237 //
       
   238 void CExifIfd::InsertTagL( CExifTagImpl* aExifTag, TBool aCheckValidity )
       
   239     {
       
   240     LOGTEXT( _L( "ExifLib: CExifIfd::InsertTagL entering" ));
       
   241     if ( !aExifTag )
       
   242         {
       
   243         LOGTEXT( _L( "ExifLib: CExifIfd::InsertTagL Leaving KErrGeneral" ));
       
   244         User::Leave( KErrGeneral );
       
   245         }
       
   246     TUint16 tagId = aExifTag->Id();
       
   247 
       
   248     if ( aCheckValidity && ( !IsAcceptableTagId( tagId ) ) )
       
   249         {
       
   250         LOGTEXT2( _L( "ExifLib: CExifIfd::InsertTagL Leaving KErrNotSupported, tagId=0x%x" ), tagId);
       
   251         User::Leave( KErrNotSupported );
       
   252         }
       
   253 
       
   254     TInt index = -1;
       
   255     for ( TInt i = 0; ( i < iTagArray.Count() ) && ( index < 0 ); ++i )
       
   256         {
       
   257         if ( iTagArray[i]->Id() > tagId )
       
   258             {
       
   259             index = i;
       
   260             }
       
   261         else if ( iTagArray[i]->Id() == tagId )
       
   262             {
       
   263             iSize = STATIC_CAST( TUint16, iSize - iTagArray[i]->Size() );
       
   264             delete iTagArray[i]; 
       
   265             iTagArray[i] = aExifTag;
       
   266             iSize = STATIC_CAST( TUint16, iSize + aExifTag->Size() );
       
   267             LOGTEXT( _L( "ExifLib: CExifIfd::InsertTagL returning" ));
       
   268             return;
       
   269             }
       
   270         else
       
   271             {
       
   272             }
       
   273         }
       
   274 
       
   275     if ( index < 0 )
       
   276         {
       
   277         iTagArray.AppendL( aExifTag );
       
   278         }
       
   279     else
       
   280         {
       
   281         iTagArray.InsertL( index, aExifTag );
       
   282         }
       
   283     iSize = STATIC_CAST( TUint16, iSize + aExifTag->Size() );
       
   284     LOGTEXT( _L( "ExifLib: CExifIfd::InsertTagL returning" ));
       
   285     }
       
   286 
       
   287 // -----------------------------------------------------------------------------
       
   288 // CExifIfd::DeleteTag
       
   289 // Removes the specified tag from the IFD structure
       
   290 // -----------------------------------------------------------------------------
       
   291 //
       
   292 TInt CExifIfd::DeleteTag( TUint16 aTagId )
       
   293     {
       
   294     for ( TInt i = 0; i < iTagArray.Count(); ++i )
       
   295         {
       
   296         if ( iTagArray[i]->Id() == aTagId )
       
   297             {
       
   298             iSize = STATIC_CAST( TUint16, iSize - iTagArray[i]->Size() );
       
   299             delete iTagArray[i];
       
   300             iTagArray.Delete( i );
       
   301             return KErrNone;
       
   302             }
       
   303         }
       
   304     return KErrNotFound;
       
   305     }
       
   306 
       
   307 // -----------------------------------------------------------------------------
       
   308 // CExifIfd::GetTagL
       
   309 // Gets the unmodifiable specified tag instance from the IFD structure.
       
   310 // -----------------------------------------------------------------------------
       
   311 //
       
   312 const CExifTagImpl* CExifIfd::GetTagL( TUint16 aTagId ) const
       
   313     {
       
   314     if ( !IsAcceptableTagId( aTagId ) )
       
   315         {
       
   316         User::Leave( KErrNotSupported );
       
   317         }
       
   318     for ( TInt i = 0; i < iTagArray.Count(); ++i )
       
   319         {
       
   320         if ( iTagArray[i]->Id() == aTagId )
       
   321             {
       
   322             return iTagArray[i];
       
   323             }
       
   324         }
       
   325     User::Leave( KErrNotFound );
       
   326     return NULL;
       
   327     }
       
   328 
       
   329 // -----------------------------------------------------------------------------
       
   330 // CExifIfd::GetTagIdsL
       
   331 // Gets the IDs and amount of the tags existing in the IFD structure.
       
   332 // -----------------------------------------------------------------------------
       
   333 //
       
   334 TUint16* CExifIfd::GetTagIdsL( TInt& aNoTags ) const
       
   335     {
       
   336     if ( !iTagArray.Count() )
       
   337         {
       
   338         User::Leave( KErrNotFound );
       
   339         }
       
   340 
       
   341     TUint16* tagIds = STATIC_CAST( TUint16*, 
       
   342         User::AllocL( sizeof( TUint16 ) * iTagArray.Count() ) );
       
   343     for ( TInt i = 0; i < iTagArray.Count(); ++i )
       
   344         {
       
   345         tagIds[i] = iTagArray[i]->Id();
       
   346         }
       
   347     
       
   348     aNoTags = iTagArray.Count();
       
   349     return tagIds;
       
   350     }
       
   351 
       
   352 // -----------------------------------------------------------------------------
       
   353 // CExifIfd::IsAcceptableTagId
       
   354 // Checks if the given tag ID is one of the IDs that can be stored in the IFD 
       
   355 // structure.
       
   356 // -----------------------------------------------------------------------------
       
   357 //
       
   358 TBool CExifIfd::IsAcceptableTagId( TUint16 aTagId ) const
       
   359     {
       
   360     TInt noTags = 0;
       
   361     const TReferenceTag* tags = NULL;
       
   362     switch ( iIfdType )
       
   363         {
       
   364         case EIfd0:
       
   365             noTags = KNoIfd0Tags;
       
   366             tags = ifd0Tags;
       
   367             break;
       
   368         case EIfdExif:
       
   369             noTags = KNoIfdExifTags;
       
   370             tags = ifdExifTags;
       
   371             break;
       
   372         case EIfd1:
       
   373             noTags = KNoIfd1Tags;
       
   374             tags = ifd1Tags;
       
   375             break;
       
   376         case EIfdGps:
       
   377             noTags = KNoIfdGpsTags;
       
   378             tags = ifdGpsTags;
       
   379             break;
       
   380         case EIfdIntOp:
       
   381             noTags = KNoIfdIntOpTags;
       
   382             tags = ifdIntOpTags;
       
   383             break;
       
   384         default:
       
   385             return EFalse;
       
   386         }
       
   387 
       
   388     TInt k = 0;
       
   389     for ( k = 0; k < noTags; ++k )
       
   390         {
       
   391         if ( tags[k].iId == aTagId )
       
   392             {
       
   393             return ETrue;
       
   394             }
       
   395         }
       
   396     return EFalse;
       
   397     }
       
   398 
       
   399 
       
   400 // ============================ CLASS CExifIfd0 ================================
       
   401 // ============================ MEMBER FUNCTIONS ===============================
       
   402 
       
   403 // -----------------------------------------------------------------------------
       
   404 // CExifIfd0::CExifIfd0
       
   405 // C++ default constructor can NOT contain any code, that
       
   406 // might leave.
       
   407 // -----------------------------------------------------------------------------
       
   408 //
       
   409 CExifIfd0::CExifIfd0()
       
   410     {
       
   411     }
       
   412 
       
   413 // -----------------------------------------------------------------------------
       
   414 // CExifIfd0::NewL
       
   415 // Two-phased constructor.
       
   416 // -----------------------------------------------------------------------------
       
   417 //
       
   418 CExifIfd0* CExifIfd0::NewL()
       
   419     {
       
   420     CExifIfd0* self = new( ELeave ) CExifIfd0();
       
   421     CleanupStack::PushL( self );
       
   422     self->ConstructL();
       
   423     CleanupStack::Pop();
       
   424     return self;
       
   425     }
       
   426 
       
   427 // -----------------------------------------------------------------------------
       
   428 // CExifIfd0::ConstructL
       
   429 // Symbian 2nd phase constructor can leave.
       
   430 // -----------------------------------------------------------------------------
       
   431 //
       
   432 void CExifIfd0::ConstructL()
       
   433     {
       
   434     }
       
   435 
       
   436 // Destructor
       
   437 CExifIfd0::~CExifIfd0()
       
   438     {
       
   439     }
       
   440 
       
   441 // -----------------------------------------------------------------------------
       
   442 // CExifIfd0::IsValid
       
   443 // Checks if the IFD0 is in valid format, and contains all mandatory IFD0 tags.
       
   444 // -----------------------------------------------------------------------------
       
   445 //
       
   446 TBool CExifIfd0::IsValid() const
       
   447     {
       
   448     if ( !iTagArray.Count() )
       
   449         {
       
   450         return EFalse;
       
   451         }
       
   452     for ( TInt i = 0; i < KNoMandatoryIfd0Tags; ++i )
       
   453         {
       
   454         TBool found = EFalse;
       
   455         TInt j = 0;
       
   456         for ( j = 0; ( j < iTagArray.Count() ) && ( !found ); ++j )
       
   457             {
       
   458             if ( ifd0Tags[i].iId == iTagArray[j]->Id() )
       
   459                 {
       
   460                 found = ETrue;
       
   461                 }
       
   462             }
       
   463         if ( !found )
       
   464             {
       
   465             return EFalse;
       
   466             }
       
   467         }
       
   468     return ETrue;
       
   469     }
       
   470 
       
   471 
       
   472 // ============================ CLASS CExifIfdExif =============================
       
   473 // ============================ MEMBER FUNCTIONS ===============================
       
   474 
       
   475 // -----------------------------------------------------------------------------
       
   476 // CExifIfdExif::CExifIfdExif
       
   477 // C++ default constructor can NOT contain any code, that
       
   478 // might leave.
       
   479 // -----------------------------------------------------------------------------
       
   480 //
       
   481 CExifIfdExif::CExifIfdExif ( )
       
   482     {
       
   483     iIfdType = EIfdExif;
       
   484     }
       
   485 
       
   486 // -----------------------------------------------------------------------------
       
   487 // CExifIfdExif::NewL
       
   488 // Two-phased constructor.
       
   489 // -----------------------------------------------------------------------------
       
   490 //
       
   491 CExifIfdExif* CExifIfdExif::NewL()
       
   492     {
       
   493     CExifIfdExif* self = new( ELeave ) CExifIfdExif();
       
   494     CleanupStack::PushL( self );
       
   495     self->ConstructL();
       
   496     CleanupStack::Pop();
       
   497     return self;
       
   498     }
       
   499 
       
   500 // -----------------------------------------------------------------------------
       
   501 // CExifIfdExif::ConstructL
       
   502 // Symbian 2nd phase constructor can leave.
       
   503 // -----------------------------------------------------------------------------
       
   504 //
       
   505 void CExifIfdExif::ConstructL()
       
   506     {
       
   507     }
       
   508 
       
   509 // Destructor
       
   510 CExifIfdExif::~CExifIfdExif ( )
       
   511     {
       
   512     }
       
   513 
       
   514 // -----------------------------------------------------------------------------
       
   515 // CExifIfdExif::IsValid
       
   516 // Checks if the Exif IFD is in valid format, and contains all mandatory Exif 
       
   517 // IFD tags.
       
   518 // -----------------------------------------------------------------------------
       
   519 //
       
   520 TBool CExifIfdExif::IsValid() const
       
   521     {
       
   522     if ( !iTagArray.Count() )
       
   523         {
       
   524         return EFalse;
       
   525         }
       
   526     for ( TInt i = 0; i < KNoMandatoryIfdExifTags; ++i )
       
   527         {
       
   528         TBool found = EFalse;
       
   529         TInt j = 0;
       
   530         for ( j = 0; ( j < iTagArray.Count() ) && ( !found ); ++j )
       
   531             {
       
   532             if ( ifdExifTags[i].iId == iTagArray[j]->Id() )
       
   533                 {
       
   534                 found = ETrue;
       
   535                 }
       
   536             }
       
   537         if ( !found )
       
   538             {
       
   539             return EFalse;
       
   540             }
       
   541         }
       
   542     return ETrue;
       
   543     }
       
   544 
       
   545 
       
   546 // ============================ CLASS CExifIfd1 ================================
       
   547 // ============================ MEMBER FUNCTIONS ===============================
       
   548 
       
   549 // -----------------------------------------------------------------------------
       
   550 // CExifIfd1::CExifIfd1
       
   551 // C++ default constructor can NOT contain any code, that
       
   552 // might leave.
       
   553 // -----------------------------------------------------------------------------
       
   554 //
       
   555 CExifIfd1::CExifIfd1()
       
   556     {
       
   557     iIfdType = EIfd1;
       
   558     }
       
   559 
       
   560 // -----------------------------------------------------------------------------
       
   561 // CExifIfd1::NewL
       
   562 // Two-phased constructor.
       
   563 // -----------------------------------------------------------------------------
       
   564 //
       
   565 CExifIfd1* CExifIfd1::NewL()
       
   566     {
       
   567     CExifIfd1* self = new( ELeave ) CExifIfd1();
       
   568     CleanupStack::PushL( self );
       
   569     self->ConstructL();
       
   570     CleanupStack::Pop();
       
   571     return self;
       
   572     }
       
   573 
       
   574 // -----------------------------------------------------------------------------
       
   575 // CExifIfd1::ConstructL
       
   576 // Symbian 2nd phase constructor can leave.
       
   577 // -----------------------------------------------------------------------------
       
   578 //
       
   579 void CExifIfd1::ConstructL()
       
   580     {
       
   581     }
       
   582 
       
   583 // Destructor
       
   584 CExifIfd1::~CExifIfd1()
       
   585     {
       
   586     if ( iThumbnailBuffer )
       
   587         {
       
   588         delete iThumbnailBuffer;
       
   589         }
       
   590     }
       
   591 
       
   592 // -----------------------------------------------------------------------------
       
   593 // CExifIfd1::IsValid
       
   594 // Checks if the Exif IFD is in valid format, and contains all mandatory Exif 
       
   595 // IFD tags.
       
   596 // -----------------------------------------------------------------------------
       
   597 //
       
   598 TBool CExifIfd1::IsValid() const
       
   599     {
       
   600     if ( !iTagArray.Count() )
       
   601         {
       
   602         return EFalse;
       
   603         }
       
   604     for ( TInt i = 0; i < KNoMandatoryIfd1Tags; ++i )
       
   605         {
       
   606         TBool found = EFalse;
       
   607         TInt j = 0;
       
   608         for ( j = 0; ( j < iTagArray.Count() ) && ( !found ); ++j )
       
   609             {
       
   610             if ( ifd1Tags[i].iId == iTagArray[j]->Id() )
       
   611                 {
       
   612                 found = ETrue;
       
   613                 }
       
   614             }
       
   615         if ( !found )
       
   616             {
       
   617             return EFalse;
       
   618             }
       
   619         }
       
   620     if ( !iThumbnailBuffer )
       
   621         {
       
   622         return EFalse;
       
   623         }
       
   624     return ETrue;
       
   625     }
       
   626 
       
   627 // -----------------------------------------------------------------------------
       
   628 // CExifIfd1::WriteThumbnailL
       
   629 // Writes the Exif thumbnail image to the location defined by the given pointer 
       
   630 // and the offset.
       
   631 // -----------------------------------------------------------------------------
       
   632 //
       
   633 void CExifIfd1::WriteThumbnailL( TUint8*& aExifDataPtr, TUint& aPos ) const
       
   634     {
       
   635     if ( !iThumbnailBuffer )
       
   636         {
       
   637         User::Leave( KErrNotReady );
       
   638         }
       
   639     TPtr8 ptr( aExifDataPtr, iThumbnailBuffer->Length() );
       
   640     ptr.Copy( iThumbnailBuffer->Ptr(), iThumbnailBuffer->Length() );
       
   641     aExifDataPtr += iThumbnailBuffer->Length();
       
   642     aPos += iThumbnailBuffer->Length();
       
   643     }
       
   644 
       
   645 // -----------------------------------------------------------------------------
       
   646 // CExifIfd1::ThumbnailSize
       
   647 // Returns the size of the Exif thumbnail image in bytes.
       
   648 // -----------------------------------------------------------------------------
       
   649 //
       
   650 TUint16 CExifIfd1::ThumbnailSize() const
       
   651     {
       
   652     if ( !iThumbnailBuffer )
       
   653         {
       
   654         return 0;
       
   655         }
       
   656     return STATIC_CAST( TUint16, iThumbnailBuffer->Length() );
       
   657     }
       
   658 
       
   659 // -----------------------------------------------------------------------------
       
   660 // CExifIfd1::SetThumbnailData
       
   661 // Inserts/Updates the given Exif thumbnail image.
       
   662 // -----------------------------------------------------------------------------
       
   663 //
       
   664 TInt CExifIfd1::SetThumbnailData( TDesC8* aThumbnailData )
       
   665     {
       
   666     if ( !aThumbnailData )
       
   667         {
       
   668         return KErrGeneral;
       
   669         }
       
   670     if ( iThumbnailBuffer )
       
   671         {
       
   672         delete iThumbnailBuffer;
       
   673         }
       
   674     iThumbnailBuffer = aThumbnailData;
       
   675     return KErrNone;
       
   676     }
       
   677 
       
   678 // -----------------------------------------------------------------------------
       
   679 // CExifIfd1::GetThumbnailData
       
   680 // Gets the Exif thumbnail image.
       
   681 // -----------------------------------------------------------------------------
       
   682 //
       
   683 TInt CExifIfd1::GetThumbnailData( TDesC8*& aThumbnailData ) const
       
   684     {
       
   685     if ( !iThumbnailBuffer )
       
   686         {
       
   687         return KErrNotFound;
       
   688         }
       
   689     aThumbnailData = iThumbnailBuffer;
       
   690     return KErrNone;
       
   691     }
       
   692 
       
   693 // -----------------------------------------------------------------------------
       
   694 // CExifIfd1::RemoveThumbnailData
       
   695 // Removes the Exif thumbnail image.
       
   696 // -----------------------------------------------------------------------------
       
   697 //
       
   698 TInt CExifIfd1::RemoveThumbnailData()
       
   699     {
       
   700     if ( !iThumbnailBuffer )
       
   701         {
       
   702         return KErrNotFound;
       
   703         }
       
   704     delete iThumbnailBuffer;
       
   705     iThumbnailBuffer = 0;
       
   706     return KErrNone;
       
   707     }
       
   708 
       
   709 // -----------------------------------------------------------------------------
       
   710 // CExifIfd1::InsertTagL
       
   711 // Inserts/Replaces the given tag in the IFD structure.
       
   712 // -----------------------------------------------------------------------------
       
   713 //
       
   714 void CExifIfd1::InsertTagL( CExifTagImpl* aExifTag, TBool aCheckValidity )
       
   715     {
       
   716     LOGTEXT( _L( "ExifLib: CExifIfd1::InsertTagL entering" ));
       
   717     if ( !aExifTag )
       
   718         {
       
   719         LOGTEXT( _L( "ExifLib: CExifIfd1::InsertTagL Leaving KErrGeneral" ));
       
   720         User::Leave( KErrGeneral );
       
   721         }
       
   722     TUint16 tagId = aExifTag->Id();
       
   723     if ( tagId == KIdCompression )
       
   724         {
       
   725         if ( aExifTag->Data().Length() != 2 )
       
   726             {
       
   727             LOGTEXT2( _L( "ExifLib: CExifIfd1::InsertTagL Leaving KErrCorrupt, aExifTag->Data().Length()=0x%x" ), aExifTag->Data().Length());
       
   728             User::Leave( KErrCorrupt );
       
   729             }
       
   730         TUint16* ptr = REINTERPRET_CAST( TUint16*, CONST_CAST( TUint8*, 
       
   731             aExifTag->Data().Ptr() ) );
       
   732         if ( *ptr != 6 )
       
   733             {
       
   734             LOGTEXT2( _L( "ExifLib: CExifIfd1::InsertTagL Leaving KErrNotSupported, *ptr=0x%x" ), *ptr);
       
   735             User::Leave( KErrNotSupported );
       
   736             }
       
   737         }
       
   738     
       
   739     if ( aCheckValidity && ( !IsAcceptableTagId( tagId ) ) )
       
   740         {
       
   741         LOGTEXT2( _L( "ExifLib: CExifIfd1::InsertTagL Leaving KErrNotSupported, tagId=0x%x" ), tagId);
       
   742         User::Leave( KErrNotSupported );
       
   743         }
       
   744 
       
   745     TInt index = -1;
       
   746     for ( TInt i = 0; ( i <  iTagArray.Count() ) && ( index < 0 ); ++i )
       
   747         {
       
   748         if ( iTagArray[i]->Id() > tagId )
       
   749             {
       
   750             index = i;
       
   751             }
       
   752         else if ( iTagArray[i]->Id() == tagId )
       
   753             {
       
   754             iSize = STATIC_CAST( TUint16, iSize - iTagArray[i]->Size() );
       
   755             delete iTagArray[i];
       
   756             iTagArray[i] = aExifTag;
       
   757             iSize = STATIC_CAST( TUint16, iSize + aExifTag->Size() );
       
   758             LOGTEXT( _L( "ExifLib: CExifIfd1::InsertTagL returning" ));
       
   759             return;
       
   760             }
       
   761         else
       
   762             {
       
   763             }
       
   764         }
       
   765 
       
   766     if ( index < 0 )
       
   767         {
       
   768         iTagArray.AppendL( aExifTag );
       
   769         }
       
   770     else
       
   771         {
       
   772         iTagArray.InsertL( index, aExifTag );
       
   773         }
       
   774     iSize = STATIC_CAST( TUint16, iSize + aExifTag->Size() );
       
   775     LOGTEXT( _L( "ExifLib: CExifIfd1::InsertTagL returning" ));
       
   776     }
       
   777 
       
   778 
       
   779 // ============================ CLASS CExifIfdGps ==============================
       
   780 // ============================ MEMBER FUNCTIONS ===============================
       
   781 
       
   782 // -----------------------------------------------------------------------------
       
   783 // CExifIfdGps::CExifIfdGps
       
   784 // C++ default constructor can NOT contain any code, that
       
   785 // might leave.
       
   786 // -----------------------------------------------------------------------------
       
   787 //
       
   788 CExifIfdGps::CExifIfdGps()
       
   789     {
       
   790     iIfdType = EIfdGps;
       
   791     }
       
   792 
       
   793 // -----------------------------------------------------------------------------
       
   794 // CExifIfdGps::NewL
       
   795 // Two-phased constructor.
       
   796 // -----------------------------------------------------------------------------
       
   797 //
       
   798 CExifIfdGps* CExifIfdGps::NewL()
       
   799     {
       
   800     CExifIfdGps* self = new( ELeave ) CExifIfdGps();
       
   801     CleanupStack::PushL( self );
       
   802     self->ConstructL();
       
   803     CleanupStack::Pop();
       
   804     return self;
       
   805     }
       
   806 
       
   807 // -----------------------------------------------------------------------------
       
   808 // CExifIfdGps::ConstructL
       
   809 // Symbian 2nd phase constructor can leave.
       
   810 // -----------------------------------------------------------------------------
       
   811 //
       
   812 void CExifIfdGps::ConstructL()
       
   813     {
       
   814     }
       
   815 
       
   816 // Destructor
       
   817 CExifIfdGps::~CExifIfdGps()
       
   818     {
       
   819     }
       
   820 
       
   821 // -----------------------------------------------------------------------------
       
   822 // CExifIfdGps::IsValid
       
   823 // Checks if the Gps IFD is in valid format, and contains all Gps IFD mandatory 
       
   824 // tags.
       
   825 // -----------------------------------------------------------------------------
       
   826 //
       
   827 TBool CExifIfdGps::IsValid() const
       
   828     {
       
   829     if ( !iTagArray.Count() )
       
   830         {
       
   831         return EFalse;
       
   832         }
       
   833     for ( TInt i = 0; i < KNoMandatoryIfdGpsTags; ++i )
       
   834         {
       
   835         TBool found = EFalse;
       
   836         TInt j = 0;
       
   837         for ( j = 0; ( j < iTagArray.Count() ) && ( !found ); ++j )
       
   838             {
       
   839             if ( ifdGpsTags[i].iId == iTagArray[j]->Id() )
       
   840                 {
       
   841                 found = ETrue;
       
   842                 }
       
   843             }
       
   844         if ( !found )
       
   845             {
       
   846             return EFalse;
       
   847             }
       
   848         }
       
   849     return ETrue;
       
   850     }
       
   851 
       
   852 
       
   853 // ============================ CLASS CExifIfdIntOp ============================
       
   854 // ============================ MEMBER FUNCTIONS ===============================
       
   855 
       
   856 // -----------------------------------------------------------------------------
       
   857 // CExifIfdIntOp::CExifIfdIntOp
       
   858 // C++ default constructor can NOT contain any code, that
       
   859 // might leave.
       
   860 // -----------------------------------------------------------------------------
       
   861 //
       
   862 CExifIfdIntOp::CExifIfdIntOp()
       
   863     {
       
   864     iIfdType = EIfdIntOp;
       
   865     }
       
   866 
       
   867 // -----------------------------------------------------------------------------
       
   868 // CExifIfdIntOp::NewL
       
   869 // Two-phased constructor.
       
   870 // -----------------------------------------------------------------------------
       
   871 //
       
   872 CExifIfdIntOp* CExifIfdIntOp::NewL()
       
   873     {
       
   874     CExifIfdIntOp* self = new( ELeave ) CExifIfdIntOp();
       
   875     CleanupStack::PushL( self );
       
   876     self->ConstructL();
       
   877     CleanupStack::Pop();
       
   878     return self;
       
   879     }
       
   880 
       
   881 // -----------------------------------------------------------------------------
       
   882 // CExifIfdIntOp::ConstructL
       
   883 // Symbian 2nd phase constructor can leave.
       
   884 // -----------------------------------------------------------------------------
       
   885 //
       
   886 void CExifIfdIntOp::ConstructL()
       
   887     {
       
   888     }
       
   889 
       
   890 // Destructor
       
   891 CExifIfdIntOp::~CExifIfdIntOp()
       
   892     {
       
   893     }
       
   894 
       
   895 // -----------------------------------------------------------------------------
       
   896 // CExifIfdIntOp::IsValid
       
   897 // Checks if the Interoperability IFD is in valid format, and contains all IOP 
       
   898 // mandatory tags.
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 TBool CExifIfdIntOp::IsValid() const
       
   902     {
       
   903     /* KNoMandatoryIfdIntOpTags is 0, no need for this checking loop.
       
   904     if ( !iTagArray.Count() )
       
   905         {
       
   906         return EFalse;
       
   907         }
       
   908     for ( TUint i = 0; i < KNoMandatoryIfdIntOpTags; ++i )
       
   909         {
       
   910         TBool found = EFalse;
       
   911         TUint j = 0;
       
   912         for ( j = 0; ( j < iTagArray.Count() ) && ( !found ); ++j )
       
   913             {
       
   914             if ( ifdIntOpTags[i].iId == iTagArray[j]->Id() )
       
   915                 {
       
   916                 found = ETrue;
       
   917                 }
       
   918             }
       
   919         if ( !found )
       
   920             {
       
   921             return EFalse;
       
   922             }
       
   923         }
       
   924     */
       
   925     return ETrue;
       
   926     }