--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagingmodules/exiflib/src/ExifEndian.cpp Thu Dec 17 09:22:31 2009 +0200
@@ -0,0 +1,781 @@
+/*
+* 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: Exif data parser, that can parse both Little and Big endian
+* formats
+*
+*/
+
+
+// INCLUDE FILES
+#include "ExifEndian.h"
+#include "ExifCommon.h"
+
+// ============================ CLASS CExifEndianBase ==========================
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::CExifEndianBase
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CExifEndianBase::CExifEndianBase()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CExifEndianBase::ConstructL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::NewBaseL
+// Two-phased constructor. Instantiates and returns relevant derived class.
+// -----------------------------------------------------------------------------
+//
+CExifEndianBase* CExifEndianBase::NewBaseL(
+ const TUint8* aExifDataPtr,
+ TUint aDataLength,
+ TBool aIsExif )
+ {
+ //
+ // Parse header.
+ // Find SOI (FFD8 )
+ // ptr = SOI pos.
+ // Then check the following 10 bytes:
+ // APP1 Marker (FFE1) + APP1 Length (no check) + Identifier ("Exif"00) +
+ // Pad (00) (no check)
+
+ //TUint8* dataStartPtr = CONST_CAST( TUint8*, aExifData.Ptr() );
+ if ( !aExifDataPtr )
+ {
+ User::Leave( KErrGeneral );
+ }
+ TUint8* ptr = CONST_CAST( TUint8*, aExifDataPtr ) - 1;
+ TUint8 *pE = CONST_CAST( TUint8*, aExifDataPtr ) + aDataLength;
+
+ // Locate the SOI marker.
+ do
+ {
+ if ( ptr == pE )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+ while ( *++ptr != KMarkerStart );
+
+ if ( *( ptr + 1 ) != KSoiEnd )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ // ptr is now at SOI.
+
+ // If original is Exif, check whether it is Little- or Big-endian.
+ // Otherwise create Little-endian reader.
+ if ( aIsExif )
+ {
+ // Locate the APP1 marker
+ do
+ {
+ do
+ {
+ if ( ptr == pE )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+ while ( *++ptr != KMarkerStart );
+ }
+ while ( *( ptr + 1 ) != KApp1End );
+ // ptr is now at APP1
+ // Skip App1 length.
+ ptr += 4;
+
+ // Check the APP1 and Exif header.
+ if ( TExifCommon::Uint32L( ptr ) != KExifIdentifierRev )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ ptr += 4;
+
+ // Padding 0 after 8 bytes of data. No need to check, skip.
+ //if ( ( *ptr ) != 0)
+ // {
+ // User::Leave( KErrCorrupt );
+ // }
+ ptr += 2;
+
+ // Check if little- or big- endian, and create the reader.
+ if ( TExifCommon::Uint16L( ptr ) == KLittleEndian )
+ {
+ return CExifLittleEndian::NewL( aExifDataPtr, ptr, pE, aIsExif );
+ }
+ else if ( TExifCommon::Uint16L( ptr ) == KBigEndian )
+ {
+ return CExifBigEndian::NewL( aExifDataPtr, ptr, pE, aIsExif );
+ }
+ else // None of the formats match!!
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+ else
+ {
+ return CExifLittleEndian::NewL( aExifDataPtr, ptr, pE, aIsExif );
+ }
+
+ return NULL;
+ }
+
+// Destructor
+CExifEndianBase::~CExifEndianBase()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::CopyBufferL
+// Copies the data from the location, which starts and ends with the given
+// Jpeg Markers.
+// -----------------------------------------------------------------------------
+//
+void CExifEndianBase::CopyBufferL(
+ TUint16 aStartMarker,
+ TUint16 aEndMarker,
+ HBufC8*& aDestBuffer,
+ TBool aIncludeEnd )
+ {
+ TUint32 startOffset = 0;
+ if ( LocateJpegMarker( aStartMarker, startOffset ) )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ TUint32 endOffset = 0;
+ if ( LocateJpegMarker( aEndMarker, endOffset ) )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ TUint32 size = endOffset - startOffset;
+ if ( aIncludeEnd )
+ {
+ size += 2;
+ }
+ aDestBuffer = HBufC8::NewL( size );
+ CleanupStack::PushL( aDestBuffer );
+
+ iPosOffset = startOffset;
+
+ CopyBuffer( size, 1 , aDestBuffer );
+ CleanupStack::Pop();
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::ReadUint8
+// Gets the next 8-bit unsigned integer from the data.
+// -----------------------------------------------------------------------------
+//
+TInt CExifEndianBase::ReadUint8( TUint8& aInt8 )
+ {
+ if ( iPosOffset + 1 >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+ aInt8 = *( iDataStartPtr + iPosOffset );
+ ++iPosOffset;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::MoveTo
+// Moves to the specified offset.
+// -----------------------------------------------------------------------------
+//
+TInt CExifEndianBase::MoveTo( TUint aOffset )
+ {
+ if ( iExifStartOffset + aOffset >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+ iPosOffset = iExifStartOffset + aOffset;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::Skip
+// Moves the current position forward by the given number of bytes.
+// -----------------------------------------------------------------------------
+//
+TInt CExifEndianBase::Skip( TUint aNoBytes )
+ {
+ if ( iPosOffset + aNoBytes >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+ iPosOffset += aNoBytes;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::Locate8
+// Locates the offset of the next specified 8-bit unsigned integer
+// -----------------------------------------------------------------------------
+//
+TInt CExifEndianBase::Locate8( TUint8 aSearch, TUint32& aOffset )
+ {
+ TUint8 *pBuf = iDataStartPtr + iPosOffset;
+ TUint8 *pB = pBuf - 1;
+ TUint8* pE = iDataStartPtr + iExifEndOffset;
+ do
+ {
+ if ( pB == pE )
+ {
+ return KErrCorrupt;
+ }
+ }
+ while ( *++pB != aSearch );
+ aOffset = pB - iDataStartPtr;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::LocateJpegMarker
+// Locates the offset of the specified Jpeg Marker, which resides after the
+// given offset.
+// -----------------------------------------------------------------------------
+//
+TInt CExifEndianBase::LocateJpegMarker(
+ TUint16 aMarker,
+ TUint32& aOffset,
+ TUint32 aAfter,
+ TUint32 aBefore )
+ {
+ if ( aAfter < iPosOffset )
+ {
+ aAfter = iPosOffset;
+ }
+ TUint8* startPtr = iDataStartPtr + aAfter;
+ if ( !aBefore )
+ {
+ aBefore = iExifEndOffset;
+ }
+ TUint8* endPtr = iDataStartPtr + aBefore;
+ TUint8* pB = TExifCommon::LocateJpegMarkerPtr(
+ aMarker, startPtr, endPtr );
+ if ( !pB )
+ {
+ return KErrCorrupt;
+ }
+ aOffset = pB - iDataStartPtr;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::LocateJpegMarkerFromEnd
+// Locates the offset of the last specified Jpeg Marker.
+// -----------------------------------------------------------------------------
+//
+TInt CExifEndianBase::LocateJpegMarkerFromEnd(
+ TUint16 aMarker,
+ TUint32& aOffset,
+ TUint32 aAfter,
+ TUint32 aBefore )
+ {
+ if ( aAfter < iPosOffset)
+ {
+ aAfter = iPosOffset;
+ }
+ TUint8* startPtr = iDataStartPtr + aAfter;
+ if ( !aBefore )
+ {
+ aBefore = iExifEndOffset;
+ }
+ TUint8* endPtr = iDataStartPtr + aBefore;
+ TUint8* pB = TExifCommon::LocateJpegMarkerPtrFromEnd( aMarker,
+ startPtr, endPtr );
+ if ( !pB )
+ {
+ return KErrCorrupt;
+ }
+ aOffset = pB - iDataStartPtr;
+ return KErrNone;
+ }
+
+
+// ============================ CLASS CExifLittleEndian ========================
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CExifLittleEndian* CExifLittleEndian::NewL(
+ const TUint8* aDataStartPtr,
+ TUint8* aExifStartPtr,
+ TUint8* aExifEndPtr,
+ TBool aIsExif )
+ {
+ CExifLittleEndian* self = new( ELeave ) CExifLittleEndian();
+ CleanupStack::PushL( self );
+ self->ConstructL( CONST_CAST( TUint8*, aDataStartPtr ), aExifStartPtr,
+ aExifEndPtr, aIsExif );
+ CleanupStack::Pop();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::CExifLittleEndian
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CExifLittleEndian::CExifLittleEndian()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CExifLittleEndian::ConstructL(
+ TUint8* aDataStartPtr,
+ TUint8* aExifStartPtr,
+ TUint8* aExifEndPtr,
+ TBool aIsExif )
+ {
+ if ( !aDataStartPtr || !aExifStartPtr || !aExifEndPtr )
+ {
+ User::Leave( KErrGeneral );
+ }
+ iDataStartPtr = aDataStartPtr;
+ iExifEndOffset = aExifEndPtr - iDataStartPtr;
+ if ( aIsExif )
+ {
+ iExifStartOffset = aExifStartPtr - iDataStartPtr;
+ if ( TExifCommon::Uint16L( aExifStartPtr + 2 ) != KExifDummyRev )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ TUint32 ifdOffset = TExifCommon::Uint32L( aExifStartPtr + 4 );
+ iPosOffset = iExifStartOffset + ifdOffset; //Locate 0th IFD position
+ if ( iPosOffset >= iExifEndOffset )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+ else
+ {
+ iPosOffset = aExifStartPtr - iDataStartPtr;
+ }
+ }
+
+// Destructor
+CExifLittleEndian::~CExifLittleEndian()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::Locate16
+// Locates the offset of the next specified 16-bit unsigned integer.
+// -----------------------------------------------------------------------------
+//
+TInt CExifLittleEndian::Locate16( TUint16 aSearch, TUint32& aOffset )
+ {
+ TUint8* pB = iDataStartPtr + iPosOffset - 1;
+ TUint16 atHand = *pB;
+ TUint8* pE = iDataStartPtr + iExifEndOffset;
+ TInt error = KErrNone;
+ do
+ {
+ if ( pB >= pE )
+ {
+ return KErrCorrupt;
+ }
+ TRAP( error, atHand =TExifCommon::Uint16L( ++pB ) );
+ }
+ while ( ( atHand != aSearch ) && ( error == KErrNone ) );
+ if ( error )
+ {
+ return error;
+ }
+ aOffset = pB - iDataStartPtr;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::ReadUint16
+// Gets the next 16-bit unsigned integer from the data.
+// -----------------------------------------------------------------------------
+//
+TInt CExifLittleEndian::ReadUInt16( TUint16& aInt16 )
+ {
+ if ( iPosOffset + 2 >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ TRAPD( error, aInt16 = TExifCommon::Uint16L( iDataStartPtr + iPosOffset ) );
+
+ if ( error )
+ {
+ return error;
+ }
+
+ iPosOffset += 2;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::ReadUint32
+// Gets the next 32-bit unsigned integer from the data.
+// -----------------------------------------------------------------------------
+//
+TInt CExifLittleEndian::ReadUInt32( TUint32& aInt32 )
+ {
+ if ( iPosOffset + 4 >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ TRAPD( error, aInt32 = TExifCommon::Uint32L( iDataStartPtr + iPosOffset ) );
+ if ( error )
+ {
+ return error;
+ }
+
+ iPosOffset += 4;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::CopyBuffer
+// Copies the next specified amount of data to the given descriptor.
+// -----------------------------------------------------------------------------
+//
+TInt CExifLittleEndian::CopyBuffer(
+ TUint32 aCount,
+ TUint8 aWordSize,
+ HBufC8*& aBuffer )
+ {
+ if ( !aBuffer )
+ {
+ return KErrCorrupt;
+ }
+ TUint bufferSize = aCount * aWordSize;
+ if ( iPosOffset + bufferSize >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ aBuffer->Des().Copy( iDataStartPtr + iPosOffset, bufferSize );
+
+ iPosOffset += bufferSize;
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifLittleEndian::CopyBuffer
+// Copies the specified amount of data located in the given offset to the
+// given descriptor.
+// -----------------------------------------------------------------------------
+//
+TInt CExifLittleEndian::CopyBuffer(
+ TUint32 aOffset,
+ TUint32 aCount,
+ TUint8 aWordSize,
+ HBufC8*& aBuffer )
+ {
+ if ( !aBuffer )
+ {
+ return KErrCorrupt;
+ }
+ TUint bufferSize = aCount * aWordSize;
+ if ( ( aOffset + iExifStartOffset + bufferSize ) >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ TUint8* ptr = iDataStartPtr + iExifStartOffset + aOffset;
+ aBuffer->Des().Copy( ptr, bufferSize );
+
+ return KErrNone;
+ }
+
+
+// ============================ CLASS CExifBigEndian ===========================
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CExifBigEndian* CExifBigEndian::NewL(
+ const TUint8* aDataStartPtr,
+ TUint8* aExifStartPtr,
+ TUint8* aExifEndPtr,
+ TBool aIsExif )
+ {
+ CExifBigEndian* self = new( ELeave ) CExifBigEndian();
+ CleanupStack::PushL( self );
+ self->ConstructL( CONST_CAST( TUint8*, aDataStartPtr ), aExifStartPtr,
+ aExifEndPtr, aIsExif );
+ CleanupStack::Pop();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::CExifBigEndian
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CExifBigEndian::CExifBigEndian()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CExifBigEndian::ConstructL(
+ TUint8* aDataStartPtr,
+ TUint8* aExifStartPtr,
+ TUint8* aExifEndPtr,
+ TBool aIsExif )
+ {
+ if ( !aDataStartPtr || !aExifStartPtr || !aExifEndPtr )
+ {
+ User::Leave( KErrGeneral );
+ }
+ iDataStartPtr = aDataStartPtr;
+ iExifEndOffset = aExifEndPtr - iDataStartPtr;
+ if ( aIsExif )
+ {
+ iExifStartOffset = aExifStartPtr - iDataStartPtr;
+ if ( TExifCommon::Uint16L( aExifStartPtr + 2 ) != KExifDummy )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ TUint8* tmpPtr = aExifStartPtr + 4;
+ TUint32 ifdOffset = STATIC_CAST( TUint32, ( *tmpPtr << 24 )
+ + ( ( *( tmpPtr + 1 ) ) << 16 ) + ( ( *( tmpPtr + 2 ) ) << 8 )
+ + ( *( tmpPtr + 3 ) ) );
+ iPosOffset = ( iExifStartOffset + ifdOffset ); //Locate 0th IFD pos.
+ if ( iPosOffset >= iExifEndOffset )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+ else
+ {
+ iPosOffset = aExifStartPtr - iDataStartPtr;
+ }
+ }
+
+// Destructor
+CExifBigEndian::~CExifBigEndian()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::Locate16
+// Locates the offset of the next specified 16-bit unsigned integer.
+// -----------------------------------------------------------------------------
+//
+TInt CExifBigEndian::Locate16( TUint16 aSearch, TUint32& aOffset )
+ {
+ TUint8* pB = iDataStartPtr + iPosOffset;
+ TUint16 atHand = *pB;
+ TUint8* pE = iDataStartPtr + iExifEndOffset;
+ do
+ {
+ if ( pB >= pE )
+ {
+ return KErrCorrupt;
+ }
+ atHand = STATIC_CAST( TUint16, ( atHand << 8 ) + *++pB );
+ }
+ while ( atHand != aSearch );
+ aOffset = ( pB - 1 ) - iDataStartPtr;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::ReadUInt16
+// Gets the next 16-bit unsigned integer from the data.
+// -----------------------------------------------------------------------------
+//
+TInt CExifBigEndian::ReadUInt16( TUint16& aInt16 )
+ {
+ if ( iPosOffset + 2 >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ aInt16 = STATIC_CAST( TUint16, ( *( iDataStartPtr + iPosOffset ) << 8 )
+ + *( iDataStartPtr + iPosOffset + 1 ) );
+
+ iPosOffset += 2;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::ReadUInt32
+// Gets the next 32-bit unsigned integer from the data.
+// -----------------------------------------------------------------------------
+//
+TInt CExifBigEndian::ReadUInt32( TUint32& aInt32 )
+ {
+ if ( iPosOffset + 4 >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ aInt32 = STATIC_CAST( TUint32, ( *( iDataStartPtr + iPosOffset ) << 24 )
+ + ( *( iDataStartPtr + iPosOffset + 1 ) << 16 )
+ + ( *( iDataStartPtr + iPosOffset + 2 ) << 8 )
+ + *( iDataStartPtr + iPosOffset + 3 ) );
+
+ iPosOffset += 4;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::CopyBuffer
+// Copies the next specified amount of data to the given descriptor.
+// -----------------------------------------------------------------------------
+//
+TInt CExifBigEndian::CopyBuffer(
+ TUint32 aCount,
+ TUint8 aWordSize,
+ HBufC8*& aBuffer )
+ {
+ if ( !aBuffer )
+ {
+ return KErrCorrupt;
+ }
+ TInt bufferSize = aCount * aWordSize;
+ if ( iPosOffset + bufferSize >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ TUint8* posPtr = iDataStartPtr + iPosOffset;
+ if ( aWordSize == 1 )
+ {
+ aBuffer->Des().Copy( posPtr, bufferSize );
+ iPosOffset += bufferSize;
+ }
+ else if ( aWordSize == 2 )
+ {
+ TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
+ for( TUint i = 0; i < aCount; ++i)
+ {
+ destPtr[0] = posPtr[1];
+ destPtr[1] = *posPtr;
+ posPtr += 2;
+ iPosOffset += 2;
+ destPtr += 2;
+ }
+ }
+ else
+ {
+ TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
+ for( TInt i = 0; i < bufferSize / 4; ++i)
+ {
+ destPtr[0] = posPtr[3];
+ destPtr[1] = posPtr[2];
+ destPtr[2] = posPtr[1];
+ destPtr[3] = *posPtr;
+ posPtr += 4;
+ iPosOffset += 4;
+ destPtr += 4;
+ }
+ }
+ aBuffer->Des().SetLength( bufferSize );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifBigEndian::CopyBuffer
+// Copies the specified amount of data located in the given offset to the
+// given descriptor.
+// -----------------------------------------------------------------------------
+//
+TInt CExifBigEndian::CopyBuffer(
+ TUint32 aOffset,
+ TUint32 aCount,
+ TUint8 aWordSize,
+ HBufC8*& aBuffer )
+ {
+ if ( !aBuffer )
+ {
+ return KErrCorrupt;
+ }
+ TInt bufferSize = aCount * aWordSize;
+ if ( ( aOffset + iExifStartOffset + bufferSize ) >= iExifEndOffset )
+ {
+ return KErrCorrupt;
+ }
+
+ TUint8* ptr = iDataStartPtr + iExifStartOffset + aOffset;
+ if ( aWordSize == 1 )
+ {
+ aBuffer->Des().Copy( ptr, bufferSize );
+ }
+ else if ( aWordSize == 2 )
+ {
+ TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
+ for( TUint i = 0; i < aCount; ++i)
+ {
+ destPtr[0] = ptr[1];
+ destPtr[1] = *ptr;
+ destPtr += 2;
+ ptr += 2;
+ }
+ }
+ else
+ {
+ TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
+ for( TInt i = 0; i < bufferSize / 4; ++i)
+ {
+ destPtr[0] = ptr[3];
+ destPtr[1] = ptr[2];
+ destPtr[2] = ptr[1];
+ destPtr[3] = *ptr;
+ destPtr += 4;
+ ptr += 4;
+ }
+ }
+ aBuffer->Des().SetLength( bufferSize );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CExifEndianBase::CurrentPosOffset
+// Returns the current position of decoded data
+// -----------------------------------------------------------------------------
+//
+void CExifEndianBase::CurrentPosOffset( TUint32& aOffset )
+ {
+ aOffset = iPosOffset;
+ }