diff -r 000000000000 -r 469c91dae73b imagingmodules/exiflib/src/ExifCore.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagingmodules/exiflib/src/ExifCore.cpp Thu Dec 17 09:22:31 2009 +0200 @@ -0,0 +1,1631 @@ +/* +* Copyright (c) 2003, 2004 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: The core service class for handling Exif v2.2 File Format. +* +*/ + + +// INCLUDE FILES +#include "ExifIfd.h" +#include "ExifCore.h" +#include "ExifReadImpl.h" + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CExifCore::CExifCore +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CExifCore::CExifCore() + { + } + +// ----------------------------------------------------------------------------- +// CExifCore::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CExifCore::ConstructL() + { + CreateIfdL( EIfd0 ); + CreateIfdL( EIfdExif); + } + +// ----------------------------------------------------------------------------- +// CExifCore::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CExifCore* CExifCore::NewL() + { + CExifCore* self = new( ELeave ) CExifCore(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// Destructor +CExifCore::~CExifCore() + { + for ( TUint i = 0; i < KIfdNo; ++i ) + { + if ( iIfdArray[i] ) + { + delete iIfdArray[i]; + } + } + } + +// ----------------------------------------------------------------------------- +// CExifCore::InsertTagL +// Inserts the given tag into the specified IFD structure. +// ----------------------------------------------------------------------------- +// +void CExifCore::InsertTagL( TExifIfdType aIfdType, CExifTagImpl* aExifTag, TBool aCheckValidity ) + { + LOGTEXT3( _L( "ExifLib: CExifCore::InsertTagL() entering: aIfdType=0x%x, aCheckValidity=%d" ), aIfdType, aCheckValidity); + switch ( aIfdType ) + { + case EIfd0: + case EIfdExif: + case EIfd1: + case EIfdGps: + case EIfdIntOp: + if ( aCheckValidity && ( !TagIsValid( aExifTag->TagInfo(), aIfdType ) ) ) + { + LOGTEXT( _L( "ExifLib: CExifCore::InsertTagL() Leaving: KErrNotSupported" )); + User::Leave( KErrNotSupported ); + } + if ( !iIfdArray[aIfdType] ) + { + // Since a new IFD should be created, 6 bytes more than tag + // size is required. + // Check if it exceeds 64K bytes after insertion. + if ( App1Size() + aExifTag->Size() + 6 > KMaxApp1Size ) + { + LOGTEXT( _L( "ExifLib: CExifCore::InsertTagL() Leaving: KErrOverflow (>KMaxApp1Size)1" )); + User::Leave( KErrOverflow ); + } + CreateIfdL( aIfdType ); + TRAPD( error, iIfdArray[aIfdType]->InsertTagL( aExifTag, aCheckValidity ) ); + if ( error != KErrNone ) + { + delete( iIfdArray[aIfdType] ); + iIfdArray[aIfdType] = 0; + LOGTEXT2( _L( "ExifLib: CExifCore::InsertTagL() Leaving: error=%d" ), error ); + User::Leave( error ); + } + } + else + { + // Check if it exceeds 64K bytes after insertion. + if ( !( TagExists( aExifTag->Id(), aIfdType ) ) && + ( App1Size() + aExifTag->Size() > KMaxApp1Size ) ) + { + LOGTEXT( _L( "ExifLib: CExifCore::InsertTagL() Leaving: KErrOverflow (>KMaxApp1Size)2" )); + User::Leave( KErrOverflow ); + } + iIfdArray[aIfdType]->InsertTagL( aExifTag, aCheckValidity ); + } + break; + default: + { + LOGTEXT( _L( "ExifLib: CExifCore::InsertTagL() Leaving: KErrArgument" )); + User::Leave( KErrArgument ); + } + } + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetTagDataL +// Sets the given 8-bit integer to the data of tag specified by the given tag ID +// ----------------------------------------------------------------------------- +// +void CExifCore::SetTagDataL( TUint16 aTagId, TInt8 aTagData ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagUndefined; + // Total tag data size = 1 bytes. + TUint32 tagCount = 1; + TExifIfdType ifdType = EIfdExif; + HBufC8* buffer = HBufC8::NewL( 1 ); + CleanupStack::PushL( buffer ); + buffer->Des().SetLength( 1 ); + switch ( aTagId ) + { + case KIdFileSource: + break; + default: + { + LOGTEXT2( _L( "ExifLib: CExifCore::SetTagDataL() Leave( KErrNotSupported ) aTagId=0x%x" ), aTagId); + User::Leave( KErrNotSupported ); + } + } + *REINTERPRET_CAST( TInt8*, CONST_CAST( TUint8*, buffer->Ptr() ) ) + = aTagData; + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( ifdType, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetTagDataL +// Sets the given 16-bit unsigned integer to the data of a tag specified by the +// given tag ID. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetTagDataL( TUint16 aTagId, TUint16 aTagData ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagShort; + // Total tag data size = 2 bytes. + // Since tag data type is 2-byte type, tagCount = 1. + TUint32 tagCount = 1; + TExifIfdType ifdType = EIfdExif; + HBufC8* buffer = HBufC8::NewL( 2 ); + buffer->Des().SetLength( 2 ); + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdCompression: + case KIdOrientation: + case KIdResolutionUnit: + case KIdYCbCrPositioning: + ifdType = EIfd0; + break; + case KIdFlash: + case KIdColorSpace: + case KIdExposureMode: + case KIdWhiteBalance: + case KIdSceneCaptureType: + case KIdExposureProgram: + case KIdMeteringMode: + case KIdLightSource: + case KIdContrast: + case KIdSaturation: + case KIdSharpness: + case KIdCustomRendered: + case KIdGainControl: + break; + default: + { + LOGTEXT2( _L( "ExifLib: CExifCore::SetTagDataL() Leave( KErrNotSupported ) 16 aTagId=0x%x" ), aTagId); + User::Leave( KErrNotSupported ); + } + } + TExifCommon::SetUint16( CONST_CAST( TUint8*, buffer->Ptr() ), aTagData ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( ifdType, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetTagDataL +// Sets the given 32-bit integer to the data of tag specified by given tag ID +// ----------------------------------------------------------------------------- +// +void CExifCore::SetTagDataL( TUint16 aTagId, TUint32 aTagData ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagLong; + + // Total tag data size = 4 bytes. + // If the tag data type is one of 4-byte types, tagCount = 1. + // If the tag data type is one of 1-byte types, tagCount = 4. + TUint32 tagCount = 1; + TExifIfdType ifdType = EIfdExif; + HBufC8* buffer = HBufC8::NewL(4 ); + buffer->Des().SetLength(4 ); + + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdExifIfdPointer: + case KIdGpsIfdPointer: + ifdType = EIfd0; + break; + case KIdIntOpIfdPointer: + case KIdPixelXDimension: + case KIdPixelYDimension: + break; + case KIdComponentsConfiguration: + case KIdExifVersion: + case KIdFlashPixVersion: + tagType = CExifTag::ETagUndefined; + tagCount = 4; + break; + case KIdGpsVersion: + tagType = CExifTag::ETagByte; + tagCount = 4; + ifdType = EIfdGps; + break; + default: + { + LOGTEXT2( _L( "ExifLib: CExifCore::SetTagDataL() Leave( KErrNotSupported ) 32 aTagId=0x%x" ), aTagId); + User::Leave( KErrNotSupported ); + } + } + TExifCommon::SetUint32( CONST_CAST( TUint8*, buffer->Ptr() ), aTagData ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( ifdType, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetTagDataL +// Sets the given data buffer to the data of a tag specified by the given tag ID +// ----------------------------------------------------------------------------- +// +void CExifCore::SetTagDataL( TUint16 aTagId, const TDesC8& aTagData ) + { + if ( !aTagData.Length() ) + { + User::Leave( KErrArgument ); + } + CExifTag::TExifTagDataType tagType = CExifTag::ETagAscii; + TUint32 tagCount = aTagData.Length(); + TExifIfdType ifdType = EIfd0; + switch ( aTagId ) + { + case KIdImageDescription: + case KIdMake: + case KIdModel: + case KIdSoftware: + case KIdCopyright: + break; + case KIdTransferFunction: + tagType = CExifTag::ETagShort; + tagCount /= 2; + break; + case KIdDateTime: + break; + case KIdIsoSpeedRatings: + tagType = CExifTag::ETagShort; + tagCount /= 2; + ifdType = EIfdExif; + break; + case KIdDateTimeOriginal: + case KIdDateTimeDigitized: + case KIdRelatedSoundFile: + ifdType = EIfdExif; + break; + case KIdMakerNote: + case KIdUserComment: + tagType = CExifTag::ETagUndefined; + ifdType = EIfdExif; + break; + default: + { + LOGTEXT2( _L( "ExifLib: CExifCore::SetTagDataL() Leave( KErrNotSupported ) C8 aTagId=0x%x" ), aTagId); + User::Leave( KErrNotSupported ); + } + } + // Check if ASCII string terminates with NULL character. + // If not add NULL. + HBufC8* buffer = NULL; + if ( ( tagType == CExifTag::ETagAscii ) && + ( aTagData.Ptr()[aTagData.Length() - 1] ) ) + { + ++tagCount; + buffer = HBufC8::NewL( aTagData.Length() + 1 ); + buffer->Des().Copy( aTagData ); + *( CONST_CAST( TUint8*, buffer->Des().Ptr() ) + + aTagData.Length() ) = NULL; + buffer->Des().SetLength( aTagData.Length() + 1 ); + } + else + { + buffer = aTagData.AllocL(); + } + CleanupStack::PushL( buffer ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop(); + CleanupStack::PushL( tag ); + InsertTagL( ifdType, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetTagDataL +// Sets the given 64-bit (2 x 32-bit ) unsigned integers to the data of a tag +// specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetTagDataL( + TUint16 aTagId, + TUint32 aNumerator, + TUint32 aDenominator ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagRational; + + // Total tag data size = 8 bytes. + // Since tag data type is 8-byte type, tagCount = 1. + TUint32 tagCount = 1; + TExifIfdType ifdType = EIfd0; + HBufC8* buffer = HBufC8::NewL( 8 ); + buffer->Des().SetLength( 8 ); + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdXResolution: + case KIdYResolution: + break; + case KIdExposureTime: + case KIdApertureValue: + case KIdDigitalZoomRatio: + ifdType = EIfdExif; + break; + default: + User::Leave( KErrNotSupported ); + } + TExifCommon::SetUint32( CONST_CAST( TUint8*, buffer->Ptr() ), aNumerator ); + TExifCommon::SetUint32( + CONST_CAST( TUint8*, buffer->Ptr() + 4 ), aDenominator ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( ifdType, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetTagDataL +// Sets the given 64-bit (2 x 32-bit ) integers to the data of a tag specified +// by the given tag ID. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetTagDataL( + TUint16 aTagId, + TInt32 aNumerator, + TInt32 aDenominator ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagSrational; + // Total tag data size = 8 bytes. + // Since tag data type is 8-byte type, tagCount = 1. + TUint32 tagCount = 1; + TExifIfdType ifdType = EIfdExif; + HBufC8* buffer = HBufC8::NewL( 8 ); + buffer->Des().SetLength( 8 ); + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdExposureBiasValue: + case KIdShutterSpeedValue: + case KIdBrightnessValue: + break; + default: + User::Leave( KErrNotSupported ); + } + TExifCommon::SetUint32( CONST_CAST( TUint8*, buffer->Ptr() ), aNumerator ); + TExifCommon::SetUint32( + CONST_CAST( TUint8*, buffer->Ptr() + 4 ), aDenominator ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( ifdType, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetThumbnailTagDataL +// Sets the given 16-bit unsigned integer to the data of a thumbnail (IFD1) tag +// specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetThumbnailTagDataL( TUint16 aTagId, TUint16 aTagData ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagShort; + TUint32 tagCount = 1; + HBufC8* buffer = HBufC8::NewL( 2 ); + buffer->Des().SetLength( 2 ); + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdCompression: + case KIdResolutionUnit: + break; + default: + User::Leave( KErrNotSupported ); + } + TExifCommon::SetUint16( CONST_CAST( TUint8*, buffer->Ptr() ), aTagData ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( EIfd1, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetThumbnailTagDataL +// Sets the given 32-bit unsigned integer to the data of a thumbnail (IFD1) tag +// specified by the given tag ID, +// ----------------------------------------------------------------------------- +// +void CExifCore::SetThumbnailTagDataL( TUint16 aTagId, TUint32 aTagData ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagLong; + TUint32 tagCount = 1; + HBufC8* buffer = HBufC8::NewL( 4 ); + buffer->Des().SetLength( 4 ); + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdJpegInterchangeFormat: + case KIdJpegInterchangeFormatLength: + break; + default: + User::Leave( KErrNotSupported ); + } + TExifCommon::SetUint32( CONST_CAST( TUint8*, buffer->Ptr() ), aTagData ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( EIfd1, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetThumbnailTagDataL +// Sets the given 64-bit (2 x 32-bit ) unsigned integers to the data of a +// thumbnail (IFD1) tag specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetThumbnailTagDataL( + TUint16 aTagId, + TUint32 aNumerator, + TUint32 aDenominator ) + { + CExifTag::TExifTagDataType tagType = CExifTag::ETagRational; + TUint32 tagCount = 1; + HBufC8* buffer = HBufC8::NewL( 8 ); + buffer->Des().SetLength( 8 ); + CleanupStack::PushL( buffer ); + switch ( aTagId ) + { + case KIdXResolution: + case KIdYResolution: + break; + default: + User::Leave( KErrNotSupported ); + } + TExifCommon::SetUint32( CONST_CAST( TUint8*, buffer->Ptr() ), aNumerator ); + TExifCommon::SetUint32( + CONST_CAST( TUint8*, buffer->Ptr() + 4 ), aDenominator ); + CExifTagImpl* tag = CExifTagImpl::NewL( aTagId, tagType, tagCount, buffer, ETrue ); + CleanupStack::Pop( buffer ); + CleanupStack::PushL( tag ); + InsertTagL( EIfd1, tag, ETrue ); + CleanupStack::Pop(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagData +// Gets the 8-bit integer data of a tag specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetTagData( TUint16 aTagId, TInt8& aTagData ) const + { + TExifIfdType ifdType = EIfdExif; + switch ( aTagId ) + { + case KIdFileSource: + break; + default: + return KErrNotSupported; + } + const CExifTagImpl* tag = NULL; + TRAPD( error, tag = GetTagL( ifdType, aTagId ) ); + if ( ( error ) || ( !tag ) ) + { + return KErrNotFound; + } + TPtrC8 tagData = tag->Data(); + aTagData = *REINTERPRET_CAST( TInt8*, CONST_CAST( TUint8*, tagData.Ptr() ) ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagData +// Gets the 16-bit unsigned integer data of a tag specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetTagData( TUint16 aTagId, TUint16& aTagData ) const + { + TExifIfdType ifdType = EIfdExif; + switch ( aTagId ) + { + case KIdFlash: + case KIdColorSpace: + case KIdExposureMode: + case KIdWhiteBalance: + case KIdSceneCaptureType: + case KIdExposureProgram: + case KIdMeteringMode: + case KIdLightSource: + case KIdContrast: + case KIdSaturation: + case KIdSharpness: + case KIdCustomRendered: + case KIdGainControl: + break; + case KIdOrientation: + case KIdResolutionUnit: + case KIdYCbCrPositioning: + ifdType = EIfd0; + break; + default: + return KErrNotSupported; + } + const CExifTagImpl* tag = NULL; + TRAPD( error, tag = GetTagL( ifdType, aTagId ) ); + if ( ( error ) || ( !tag ) ) + { + return KErrNotFound; + } + TPtrC8 tagData = tag->Data(); + TRAP( error, aTagData = TExifCommon::Uint16L( + CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagData +// Gets the 32-bit unsigned integer data of a tag specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetTagData( TUint16 aTagId, TUint32& aTagData ) const + { + TExifIfdType ifdType = EIfdExif; + switch ( aTagId ) + { + case KIdComponentsConfiguration: + case KIdPixelXDimension: + case KIdPixelYDimension: + case KIdExifVersion: + case KIdFlashPixVersion: + case KIdIntOpIfdPointer: + break; + case KIdGpsVersion: + ifdType = EIfdGps; + break; + case KIdExifIfdPointer: + case KIdGpsIfdPointer: + ifdType = EIfd0; + break; + default: + return KErrNotSupported; + } + CExifTagImpl* tag = NULL; + TRAPD( error, tag = + CONST_CAST( CExifTagImpl*, GetTagL( ifdType, aTagId ) ) ); + if ( ( error ) || ( !tag ) ) + { + return KErrNotFound; + } + TPtrC8 tagData = tag->Data(); + if ( tagData.Length() == 2) + { + TRAP( error, aTagData = STATIC_CAST( TUint32, + TExifCommon::Uint16L( CONST_CAST( TUint8*, tagData.Ptr() ) ) ) ); + } + else + { + TRAP( error, aTagData = TExifCommon::Uint32L( + CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + } + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagDataL +// Gets the data buffer of a tag specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +HBufC8* CExifCore::GetTagDataL( TUint16 aTagId ) const + { + TExifIfdType ifdType = EIfd0; + switch ( aTagId ) + { + case KIdImageDescription: + case KIdMake: + case KIdModel: + case KIdTransferFunction: + case KIdDateTime: + case KIdSoftware: + case KIdCopyright: + break; + case KIdIsoSpeedRatings: + case KIdDateTimeOriginal: + case KIdDateTimeDigitized: + case KIdMakerNote: + case KIdUserComment: + case KIdRelatedSoundFile: + ifdType = EIfdExif; + break; + default: + User::Leave( KErrNotSupported ); + } + const CExifTagImpl* tag = GetTagL( ifdType, aTagId ); + + return tag->Data().AllocL(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagData +// Gets the 64-bit (2 x 32-bit) unsigned integer data of a tag specified by the +// given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetTagData( + TUint16 aTagId, + TUint32& aNumerator, + TUint32& aDenominator ) const + { + TExifIfdType ifdType = EIfd0; + switch ( aTagId ) + { + case KIdXResolution: + case KIdYResolution: + break; + case KIdExposureTime: + case KIdApertureValue: + case KIdDigitalZoomRatio: + ifdType = EIfdExif; + break; + default: + return KErrNotSupported; + } + const CExifTagImpl* tag = NULL; + TRAPD( error, tag = GetTagL( ifdType, aTagId ) ); + if ( ( error ) || ( !tag ) ) + { + return KErrNotFound; + } + + TPtrC8 tagData = tag->Data(); + TRAP( error, aNumerator = TExifCommon::Uint32L( + CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + if ( error ) + { + return error; + } + TRAP( error, aDenominator = TExifCommon::Uint32L( + CONST_CAST( TUint8*, tagData.Ptr() + 4 ) ) ); + + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagData +// Gets the 64-bit (2 x 32-bit) integer data of tag specified by the given tag +// ID +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetTagData( + TUint16 aTagId, + TInt32& aNumerator, + TInt32& aDenominator ) const + { + TExifIfdType ifdType = EIfdExif; + switch ( aTagId ) + { + case KIdExposureBiasValue: + case KIdShutterSpeedValue: + case KIdBrightnessValue: + break; + default: + return KErrNotSupported; + } + const CExifTagImpl* tag = NULL; + TRAPD( error, tag = GetTagL( ifdType, aTagId ) ); + if ( ( error ) || ( !tag ) ) + { + return KErrNotFound; + } + + TPtrC8 tagData = tag->Data(); + TRAP( error, aNumerator = TExifCommon::Int32L( + CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + if ( error ) + { + return error; + } + TRAP( error, aDenominator = TExifCommon::Int32L( + CONST_CAST( TUint8*, tagData.Ptr() + 4 ) )); + + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetThumbnailTagData +// Gets the 16-bit unsigned integer data of a thumbnail (IFD1) tag specified by +// the given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetThumbnailTagData( TUint16 aTagId, TUint16& aTagData ) const + { + LOGTEXT( _L( "ExifLib: CExifCore::GetThumbnailTagData TUint16 entering" )); + TExifIfdType ifdType = EIfd1; + switch ( aTagId ) + { + case KIdResolutionUnit: + case KIdCompression: + break; + default: + LOGTEXT( _L( "ExifLib: CExifCore::GetThumbnailTagData returning: KErrNotSupported" )); + return KErrNotSupported; + } + const CExifTagImpl* tag = NULL; + TRAPD( error, tag = GetTagL( ifdType, aTagId ) ); + if ( ( error ) || ( !tag ) ) + { + LOGTEXT( _L( "ExifLib: CExifCore::GetThumbnailTagData returning: KErrNotFound" )); + return KErrNotFound; + } + TPtrC8 tagData = tag->Data(); + TRAP( error, aTagData = TExifCommon::Uint16L( + CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + LOGTEXT2( _L( "ExifLib: CExifCore::GetThumbnailTagData returning: error=%d" ), error); + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetThumbnailTagData +// Gets the 32-bit unsigned integer data of a thumbnail (IFD1) tag specified by +// the given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetThumbnailTagData( TUint16 aTagId, TUint32& aTagData ) const + { + LOGTEXT( _L( "ExifLib: CExifCore::GetThumbnailTagData TUint32 entering" )); + TExifIfdType ifdType = EIfd1; + switch ( aTagId ) + { + case KIdJpegInterchangeFormat: + case KIdJpegInterchangeFormatLength: + break; + default: + LOGTEXT( _L( "ExifLib: CExifCore::GetThumbnailTagData returning: KErrNotSupported" )); + return KErrNotSupported; + } + CExifTagImpl* tag = NULL; + TRAPD( error, tag = CONST_CAST( CExifTagImpl*, GetTagL( ifdType, aTagId ) ) ); + if ( ( error ) || ( !tag ) ) + { + LOGTEXT( _L( "ExifLib: CExifCore::GetThumbnailTagData returning: KErrNotFound" )); + return KErrNotFound; + } + TPtrC8 tagData = tag->Data(); + TRAP( error, aTagData = TExifCommon::Uint32L( + CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + LOGTEXT2( _L( "ExifLib: CExifCore::GetThumbnailTagData returning: error=%d" ), error); + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetThumbnailTagData +// Gets the 64-bit (2 x 32-bit) unsigned integer data of a thumbnail (IFD1) tag +// specified by the given tag ID. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetThumbnailTagData( + TUint16 aTagId, + TUint32& aNumerator, + TUint32& aDenominator ) const + { + TExifIfdType ifdType = EIfd1; + switch ( aTagId ) + { + case KIdXResolution: + case KIdYResolution: + break; + default: + return KErrNotSupported; + } + const CExifTagImpl* tag = NULL; + TRAPD( error, tag = GetTagL( ifdType, aTagId ) ); + if ( ( error ) || ( !tag ) ) + { + return KErrNotFound; + } + + TPtrC8 tagData = tag->Data(); + TRAP( error, aNumerator = + TExifCommon::Uint32L( CONST_CAST( TUint8*, tagData.Ptr() ) ) ); + if ( error ) + { + return error; + } + TRAP( error, aDenominator = + TExifCommon::Uint32L( CONST_CAST( TUint8*, tagData.Ptr() + 4 ) ) ); + + return error; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagL +// Gets the tag instance having the given tag ID from the specified IFD +// structure +// ----------------------------------------------------------------------------- +// +const CExifTagImpl* CExifCore::GetTagL( + TExifIfdType aIfdType, TUint16 aTagId ) const + { + switch ( aIfdType ) + { + case EIfd0: + case EIfdExif: + case EIfd1: + case EIfdGps: + case EIfdIntOp: + if ( !iIfdArray[aIfdType] ) + { + User::Leave( KErrNotFound ); + } + return iIfdArray[aIfdType]->GetTagL( aTagId ); + default: + User::Leave( KErrArgument ); + } + return 0; + } + +// ----------------------------------------------------------------------------- +// CExifCore::DeleteTag +// Removes the tag instance having the given tag ID from the specified IFD +// structure +// ----------------------------------------------------------------------------- +// +TInt CExifCore::DeleteTag( TExifIfdType aIfdType, TUint16 aTagId ) + { + switch ( aIfdType ) + { + case EIfd0: + case EIfdExif: + case EIfd1: + case EIfdGps: + case EIfdIntOp: + { + if ( !iIfdArray[aIfdType] ) + { + return KErrNotFound; + } + TInt error = iIfdArray[aIfdType]->DeleteTag( aTagId ); + if ( error ) + { + return error; + } + if ( iIfdArray[aIfdType]->Size() ) + { + return KErrNone; + } + return DeleteIfd( aIfdType ); + } + default: + return KErrArgument; + } + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetTagIdsL +// Gets the tag IDs and the number of tags in the specified IFD structure. +// ----------------------------------------------------------------------------- +// +TUint16* CExifCore::GetTagIdsL( TExifIfdType aIfdType, TInt& aNoTags ) const + { + switch ( aIfdType ) + { + case EIfd0: + case EIfdExif: + case EIfd1: + case EIfdGps: + case EIfdIntOp: + if ( !iIfdArray[aIfdType] ) + { + User::Leave( KErrNotFound ); + } + return iIfdArray[aIfdType]->GetTagIdsL( aNoTags ); + default: + User::Leave( KErrArgument ); + } + return 0; + } + +// ----------------------------------------------------------------------------- +// CExifCore::iExifCore->CreateIfdL +// Instantiates the specified IFD structure. +// ----------------------------------------------------------------------------- +// +void CExifCore::CreateIfdL( TExifIfdType aIfdType ) + { + if ( App1Size() > ( KMaxApp1Size - 6 ) ) + { + User::Leave( KErrOverflow ); + } + switch ( aIfdType ) + { + case EIfd0: + case EIfdExif: + case EIfd1: + case EIfdGps: + case EIfdIntOp: + iIfdArray[aIfdType] = CExifIfd::NewBaseL( aIfdType ); + break; + default: + User::Leave( KErrArgument ); + } + } + +// ----------------------------------------------------------------------------- +// CExifCore::DeleteIfd +// Removes the specified IFD structure and all its tags. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::DeleteIfd( TExifIfdType aIfdType ) + { + switch ( aIfdType ) + { + case EIfd0: + break; + case EIfdExif: + break; + case EIfd1: + iIfdArray[EIfd0]->SetNextIfdOffset( 0 ); + break; + case EIfdGps: + iIfdArray[EIfd0]->DeleteTag( KIdGpsIfdPointer ); + break; + case EIfdIntOp: + iIfdArray[EIfdExif]->DeleteTag( KIdIntOpIfdPointer ); + break; + default: + return KErrArgument; + } + if ( iIfdArray[aIfdType] ) + { + delete ( iIfdArray[aIfdType] ); + iIfdArray[aIfdType] = 0; + return KErrNone; + } + else + { + return KErrNotFound; + } + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetIfdTypesL +// Gets the IFD types and number of IFDs in the file format. +// ----------------------------------------------------------------------------- +// +TExifIfdType* CExifCore::GetIfdTypesL( TInt& aNoIfd ) const + { + TInt noIfd = 0; + TUint i = 0; + for ( i = 0; i < KIfdNo; ++i ) + { + if ( iIfdArray[i] ) + { + ++noIfd; + } + } + if ( !noIfd ) + { + User::Leave( KErrNotFound ); + } + + TExifIfdType* ifdTypes = STATIC_CAST( TExifIfdType*, + User::AllocL( sizeof( TExifIfdType ) * noIfd ) ); + aNoIfd = noIfd; + noIfd = 0; + for ( i=EIfd0; i<=EIfdIntOp; ++i ) + { + if ( iIfdArray[i] ) + { + ifdTypes[noIfd] = STATIC_CAST( TExifIfdType, i ); + ++noIfd; + } + } + return ifdTypes; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetThumbnailL +// Gets the Exif thumbnail image data from the IFD1 structure. +// ----------------------------------------------------------------------------- +// +HBufC8* CExifCore::GetThumbnailL() const + { + if ( !iIfdArray[EIfd1] ) + { + User::Leave( KErrNotFound ); + } + + TDesC8* thumbnailData = NULL; + User::LeaveIfError( ( STATIC_CAST( CExifIfd1*, iIfdArray[EIfd1] ) )-> + GetThumbnailData( thumbnailData ) ); + + // Next check needed when option ENoTagChecking is used + if ( !thumbnailData ) + { + User::Leave( KErrNotFound ); + } + + return thumbnailData->AllocL(); + } + +// ----------------------------------------------------------------------------- +// CExifCore::InsertThumbnailL +// Inserts/Updates the given Exif thumbnail image data in the IFD1 structure. +// ----------------------------------------------------------------------------- +// +void CExifCore::InsertThumbnailL( TDesC8* aThumbnailData ) + { + if ( STATIC_CAST( TUint, App1Size() + aThumbnailData->Length() ) > + KMaxApp1Size ) + { + User::Leave( KErrOverflow ); + } + + TUint8* jpgStartPtr = CONST_CAST( TUint8*, aThumbnailData->Ptr() ); + TUint8* jpgEndPtr = jpgStartPtr + aThumbnailData->Length(); + + jpgStartPtr = TExifCommon::LocateJpegMarkerPtr( + KSoi, jpgStartPtr, jpgEndPtr ); + if( !jpgStartPtr ) + { + User::Leave( KErrCorrupt ); + } + + jpgStartPtr = TExifCommon::LocateJpegMarkerPtr( + KSof0, jpgStartPtr, jpgEndPtr ); + if( !jpgStartPtr ) + { + User::Leave( KErrCorrupt ); + } + + jpgStartPtr = TExifCommon::LocateJpegMarkerPtr( + KEoi, jpgStartPtr, jpgEndPtr ); + if( !jpgStartPtr ) + { + User::Leave( KErrCorrupt ); + } + + if ( !iIfdArray[EIfd1] ) + { + CreateIfdL( EIfd1 ); + } + User::LeaveIfError( ( STATIC_CAST( CExifIfd1*, iIfdArray[EIfd1] ) )-> + SetThumbnailData( aThumbnailData ) ); + } + +// ----------------------------------------------------------------------------- +// CExifCore::RemoveThumbnail +// Removes the Exif thumbnail image data from the IFD1 structure. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::RemoveThumbnail() + { + if ( !iIfdArray[EIfd1] ) + { + return KErrNotFound; + } + return + ( STATIC_CAST( CExifIfd1*, iIfdArray[EIfd1] ) )->RemoveThumbnailData(); + } + + +// ----------------------------------------------------------------------------- +// CExifCore::WriteExifDataL +// Writes the Exif data to the given descriptor starting from the specified +// position/offset. +// ----------------------------------------------------------------------------- +// +void CExifCore::WriteExifDataL( HBufC8*& aExifData, TUint& aPos ) + { + // Ensure byte alignment + if ( ( aExifData->Length() - aPos ) % 2 > 0 ) + { + User::Leave( KErrGeneral ); + } + TUint16* exifDataPtr = REINTERPRET_CAST( TUint16*, + CONST_CAST( TUint8*, aExifData->Ptr() ) + aPos ); + WriteExifHeaderL( exifDataPtr, aPos ); + WriteIfdL( exifDataPtr, EIfd0, aPos ); + WriteIfdL( exifDataPtr, EIfdExif, aPos ); + WriteIfdL( exifDataPtr, EIfdGps, aPos ); + WriteIfdL( exifDataPtr, EIfdIntOp, aPos ); + WriteIfdL( exifDataPtr, EIfd1, aPos ); + } + +// ----------------------------------------------------------------------------- +// CExifCore::WriteJpegHeaderL +// Writes the Jpeg header to the given descriptor starting from the specified +// position/offset. +// ----------------------------------------------------------------------------- +// +void CExifCore::WriteJpegHeaderL( HBufC8*& aExifData, TUint& aPos ) + { + if ( ( aExifData->Length() - aPos ) % 2 > 0 ) + { + User::Leave( KErrGeneral ); + } + TUint16* exifDataPtr = REINTERPRET_CAST( TUint16*, + CONST_CAST( TUint8*, aExifData->Ptr() ) + aPos ); + *exifDataPtr = KSoiRev; + aPos+=2; + } + +// ----------------------------------------------------------------------------- +// CExifCore::Finalize +// Finalizes the Exif data to ensure the validity, updates the internal offsets. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::Finalize() + { + TInt error = 0; + TUint32 ifdOffset = FindIfdOffset( EIfdExif ); + TRAP( error, SetTagDataL( KIdExifIfdPointer, ifdOffset ) ); + if ( error ) + { + return error; + } + + ifdOffset = FindIfdOffset( EIfdGps ); + if ( ifdOffset ) + { + TRAP( error, SetTagDataL( KIdGpsIfdPointer, ifdOffset ) ); + if ( error ) + { + return error; + } + } + else + { + DeleteTag( EIfd0, KIdGpsIfdPointer ); + } + + ifdOffset = FindIfdOffset( EIfdIntOp ); + if ( ifdOffset ) + { + TRAP( error, SetTagDataL( KIdIntOpIfdPointer, ifdOffset ) ); + if ( error ) + { + return error; + } + } + else + { + DeleteTag( EIfdExif, KIdIntOpIfdPointer ); + } + + if ( iIfdArray[EIfd1] ) + { + if ( !STATIC_CAST( CExifIfd1*, iIfdArray[EIfd1] )->ThumbnailSize() ) + { + DeleteIfd( EIfd1 ); + iIfdArray[EIfd0]->SetNextIfdOffset( 0 ); + } + else + { + ifdOffset = FindIfdOffset( EIfd1 ); + iIfdArray[EIfd0]->SetNextIfdOffset( ifdOffset ); + TRAP( error, SetThumbnailTagDataL( KIdJpegInterchangeFormat, + STATIC_CAST( TUint32, ifdOffset + iIfdArray[EIfd1]->Size() ) ) ); + if ( error ) + { + return error; + } + TRAP( error, SetThumbnailTagDataL( KIdJpegInterchangeFormatLength, + STATIC_CAST( TUint32, STATIC_CAST( CExifIfd1*, + iIfdArray[EIfd1] )->ThumbnailSize() ) ) ); + if ( error ) + { + return error; + } + TRAP( error, SetThumbnailTagDataL( KIdCompression, KCompressed ) ); + if ( error ) + { + return error; + } + } + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CExifCore::TotalSize +// Returns the total size of the Exif file format in bytes. +// ----------------------------------------------------------------------------- +// +TUint CExifCore::TotalSize() const + { + return ( App1Size() + 4 + JpegSize() ); + } + +// ----------------------------------------------------------------------------- +// CExifCore::JpegSize +// Returns the size of the Jpeg image in the Exif file format, excluding SOI +// and APP markers in bytes. +// ----------------------------------------------------------------------------- +// +TUint CExifCore::JpegSize() const + { + return iJpgEndOffset - iJpgStartOffset; + } + +// ----------------------------------------------------------------------------- +// CExifCore::App1Size +// Returns the size of the APP1 marker, which includes the Exif-specific data +// in bytes +// ----------------------------------------------------------------------------- +// +TUint16 CExifCore::App1Size() const + { + TUint16 app1Size = 0; + if ( iIfdArray[EIfd0] ) + { + app1Size = STATIC_CAST( TUint16, app1Size + iIfdArray[EIfd0]->Size() ); + } + if ( iIfdArray[EIfdExif] ) + { + app1Size = + STATIC_CAST( TUint16, app1Size + iIfdArray[EIfdExif]->Size() ); + } + if ( iIfdArray[EIfd1] ) + { + app1Size = STATIC_CAST( TUint16, app1Size + iIfdArray[EIfd1]->Size() ); + app1Size = STATIC_CAST( TUint16, app1Size + ( STATIC_CAST( CExifIfd1*, + iIfdArray[EIfd1] )->ThumbnailSize() ) ); + } + if ( iIfdArray[EIfdGps] ) + { + app1Size = + STATIC_CAST( TUint16, app1Size + iIfdArray[EIfdGps]->Size() ); + } + if ( iIfdArray[EIfdIntOp] ) + { + app1Size = + STATIC_CAST( TUint16, app1Size + iIfdArray[EIfdIntOp]->Size() ); + } + return STATIC_CAST( TUint16, app1Size + 16 ); + } + +// ----------------------------------------------------------------------------- +// CExifCore::IsValid +// Checks if the Exif data is in valid Exif v2.2 format and contains all +// mandatory information. +// ----------------------------------------------------------------------------- +// +TBool CExifCore::IsValid() const + { + if ( (!iIfdArray[EIfd0] ) || (!iIfdArray[EIfdExif] ) ) + { + return EFalse; + } + + if ( !iIfdArray[EIfd0]->IsValid() ) + { + return EFalse; + } + + if ( !iIfdArray[EIfdExif]->IsValid() ) + { + return EFalse; + } + + if ( iIfdArray[EIfd1] ) + { + if ( !iIfdArray[EIfd1]->IsValid() ) + { + return EFalse; + } + } + if ( iIfdArray[EIfdGps] ) + { + if ( !iIfdArray[EIfdGps]->IsValid() ) + { + return EFalse; + } + TRAPD( error, GetTagL( EIfd0, KIdGpsIfdPointer ) ); + if ( error ) + { + return EFalse; + } + } + + if ( iIfdArray[EIfdIntOp] ) + { + if ( !iIfdArray[EIfdIntOp]->IsValid() ) + { + return EFalse; + } + TRAPD( error, GetTagL( EIfdExif, KIdIntOpIfdPointer ) ); + if ( error ) + { + return EFalse; + } + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CExifCore::TagIsValid +// Checks if the specified tag information conforms to the Full Validity +// characteristics (Data count is correct, data type matches tag ID and data +// value falls into the predefined range). +// ----------------------------------------------------------------------------- +// +TBool CExifCore::TagIsValid( TExifTagInfo aTagInfo, TExifIfdType aIfdType ) const + { + LOGTEXT3( _L( "ExifLib: CExifCore::TagIsValid() entering: aIfdType=0x%x, aTagInfo.iId=0x%x" ), aIfdType, aTagInfo.iId ); + TInt noTags = 0; + const TReferenceTag* tags = NULL; + switch ( aIfdType ) + { + case EIfd0: + noTags = KNoIfd0Tags; + tags = ifd0Tags; + break; + case EIfdExif: + noTags = KNoIfdExifTags; + tags = ifdExifTags; + break; + case EIfd1: + noTags = KNoIfd1Tags; + tags = ifd1Tags; + break; + case EIfdGps: + noTags = KNoIfdGpsTags; + tags = ifdGpsTags; + break; + case EIfdIntOp: + noTags = KNoIfdIntOpTags; + tags = ifdIntOpTags; + break; + default: + return EFalse; + } + + TInt k = 0; + TBool found = EFalse; + for ( k = 0; ( k < noTags ) && ( !found ); ++k ) + { + if ( tags[k].iId == aTagInfo.iId ) + { + found = ETrue; + } + } + + if ( !found ) + { + LOGTEXT( _L( "ExifLib: CExifCore::TagIsValid() returning EFalse (tag not found)" )); + return EFalse; + } + // k locates the item next to the found item. Make it locate the found. + --k; + + if ( tags[k].iDataType != TReferenceTag::ETagLongOrShort ) + { + if ( tags[k].iDataType != aTagInfo.iDataType ) + { + LOGTEXT2( _L( "ExifLib: CExifCore::TagIsValid() returning EFalse 1 aTagInfo.iDataType=0x%x" ), aTagInfo.iDataType ); + return EFalse; + } + } + else if ( ( aTagInfo.iDataType != CExifTag::ETagShort ) && + ( aTagInfo.iDataType != CExifTag::ETagLong ) ) + { + LOGTEXT2( _L( "ExifLib: CExifCore::TagIsValid() returning EFalse 2 aTagInfo.iDataType=0x%x" ), aTagInfo.iDataType ); + return EFalse; + } + else + { + // Nothing to check for this case! + } + + if ( tags[k].iDataCount != KAny ) + { + if ( tags[k].iDataCount != aTagInfo.iDataCount ) + { + LOGTEXT2( _L( "ExifLib: CExifCore::TagIsValid() returning EFalse aTagInfo.iDataCount=0x%x" ), aTagInfo.iDataCount ); + return EFalse; + } + } + + LOGTEXT( _L( "ExifLib: CExifCore::TagIsValid() returning ETrue" )); + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CExifCore::IfdExists +// Checks if the specified IFD structure exists in the Exif data. +// ----------------------------------------------------------------------------- +// +TBool CExifCore::IfdExists( TExifIfdType aIfdType ) const + { + if ( iIfdArray[aIfdType] ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CExifCore::TagExists +// Checks if the tag having the given tag ID exists in the specified IFD +// structure +// ----------------------------------------------------------------------------- +// +TBool CExifCore::TagExists( TUint16 aTagId, TExifIfdType aIfdType ) const + { + if ( iIfdArray[aIfdType] ) + { + return iIfdArray[aIfdType]->TagExists( aTagId ); + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetJpgOffsets +// Sets the given Jpeg data start and end offsets. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetJpgOffsets( TUint32 aJpgStartOffset, TUint32 aJpgEndOffset ) + { + iJpgStartOffset = aJpgStartOffset; + iJpgEndOffset = aJpgEndOffset; + } + +// ----------------------------------------------------------------------------- +// CExifCore::GetJpegData +// Gets the pure Jpeg image data excluding the SOI and APP1 markers. +// ----------------------------------------------------------------------------- +// +TInt CExifCore::GetJpegData( TPtr8 aJpgPointer ) const + { + if ( !iJpgStartOffset ) + { + return KErrGeneral; + } + + TUint8* jpgStartPtr = CONST_CAST( TUint8*, iDataStartPtr + iJpgStartOffset ); + if ( *jpgStartPtr != KMarkerStart ) + { + return KErrGeneral; + } + aJpgPointer.Copy( jpgStartPtr, JpegSize() ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CExifCore::SetDataStartPtr +// Sets the Exif data start pointer. +// ----------------------------------------------------------------------------- +// +void CExifCore::SetDataStartPtr( const TUint8* aPtr ) + { + iDataStartPtr = aPtr; + } + +// ----------------------------------------------------------------------------- +// CExifCore::WriteExifHeaderL +// Writes the Exif header to the location, which is defined by the given pointer +// and the offset. +// ----------------------------------------------------------------------------- +// +void CExifCore::WriteExifHeaderL( TUint16*& aExifDataPtr, TUint& aPos ) + { + if ( !aExifDataPtr ) + { + User::Leave( KErrGeneral ); + } + *aExifDataPtr++ = KApp1Rev; + TUint16 app1Size = App1Size(); + *REINTERPRET_CAST( TUint8*, aExifDataPtr ) = STATIC_CAST( TUint8, + app1Size >> 8 ); + *( REINTERPRET_CAST( TUint8*, aExifDataPtr ) + 1 ) = STATIC_CAST( + TUint8, app1Size ); + ++aExifDataPtr; + TExifCommon::SetUint32( REINTERPRET_CAST( TUint8*, aExifDataPtr ), + KExifIdentifierRev ); + aExifDataPtr+=2; + *aExifDataPtr++ = KExifPad; + *aExifDataPtr++ = KLittleEndian; + *aExifDataPtr++ = KExifDummyRev; + TExifCommon::SetUint32( REINTERPRET_CAST( TUint8*, aExifDataPtr ), + KHeaderOffset ); + aExifDataPtr+=2; + aPos = 20; + } + +// ----------------------------------------------------------------------------- +// CExifCore::WriteIfdl +// Writes the specified IFD data to the location, which is defined by the given +// pointer and the offset. +// ----------------------------------------------------------------------------- +// +void CExifCore::WriteIfdL( + TUint16*& aExifDataPtr, + TExifIfdType aIfdType, + TUint& aPos ) + { + if ( !aExifDataPtr ) + { + User::Leave( KErrGeneral ); + } + if ( iIfdArray[aIfdType] ) + { + iIfdArray[aIfdType]->WriteTagsL( aExifDataPtr, aPos ); + if ( aIfdType == EIfd1 ) + { + (STATIC_CAST( CExifIfd1*, iIfdArray[aIfdType] ) )->WriteThumbnailL( + REINTERPRET_CAST( TUint8*&, aExifDataPtr ), aPos ); + } + } + } + +// ----------------------------------------------------------------------------- +// CExifCore::FindIfdOffset +// Returns the offset of the specified IFD structure in the Exif data. +// ----------------------------------------------------------------------------- +// +TUint32 CExifCore::FindIfdOffset( TExifIfdType aIfdType ) const + { + if ( !iIfdArray[aIfdType] ) + { + return 0; + } + TUint32 offset = 8; + switch ( aIfdType ) + { + case EIfd0: + break; + case EIfdExif: + offset += ( iIfdArray[EIfd0]->Size() ); + break; + case EIfd1: + offset += ( iIfdArray[EIfd0]->Size() + iIfdArray[EIfdExif]->Size() ); + if ( iIfdArray[EIfdGps] ) + { + offset += iIfdArray[EIfdGps]->Size(); + } + if ( iIfdArray[EIfdIntOp] ) + { + offset += iIfdArray[EIfdIntOp]->Size(); + } + break; + case EIfdGps: + offset += ( iIfdArray[EIfd0]->Size() + iIfdArray[EIfdExif]->Size() ); + break; + case EIfdIntOp: + offset += ( iIfdArray[EIfd0]->Size() + iIfdArray[EIfdExif]->Size() ); + if ( iIfdArray[EIfdGps] ) + { + offset += iIfdArray[EIfdGps]->Size(); + } + break; + default: + return 0; + } + return offset; + } +