harvester/common/src/harvesterexifutil.cpp
changeset 0 c53acadfccc6
child 6 646a02f170b9
equal deleted inserted replaced
-1:000000000000 0:c53acadfccc6
       
     1 /*
       
     2 * Copyright (c) 2007-2009 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-utilities for harvester
       
    15 *
       
    16 */
       
    17 
       
    18 #include "harvesterexifutil.h"
       
    19 
       
    20 #include "mdsutils.h"
       
    21 #include "mdeobjectdef.h"
       
    22 #include "mdeconstants.h"
       
    23 #include "mdeproperty.h"
       
    24 #include "tz.h"
       
    25 #include <ExifModify.h>
       
    26 
       
    27 
       
    28 
       
    29 using namespace MdeConstants;
       
    30 
       
    31 const TUint16 KIdColorSpace = 0xA001;
       
    32 const TUint16 KIdResolutionUnit = 0x0128;
       
    33 const TUint16 KIdYbCrPositioning = 0x0213;
       
    34 const TUint16 KIdImageDescription = 0x010E;
       
    35 const TUint16 KIdCopyright = 0x8298;
       
    36 const TUint16 KIdUserComment = 0x9286;
       
    37 const TUint16 KIdDateTime = 0x0132;
       
    38 const TUint16 KIdDateTimeOriginal = 0x9003;
       
    39 const TUint16 KIdDateTimeDigitized = 0x9004;
       
    40 const TUint16 KIdDateTimeModified = 0x132;
       
    41 const TUint16 KIdFNumber = 0x829D;
       
    42 const TUint16 KIdMake = 0x010F;
       
    43 const TUint16 KIdModel = 0x0110;
       
    44 const TUint16 KIdFocalLength = 0x920A;
       
    45 const TUint16 KIdFocalLengthIn35mm = 0xA405;
       
    46 const TUint16 KIdSamplesPerPixel = 0x0115;
       
    47 const TUint16 KIdISOSpeedRatings = 0x8827;
       
    48 const TUint16 KIdComponentsConfig = 0x9101;
       
    49 const TUint16 KIdArtist = 0x013B;
       
    50 const TUint16 KIdPixelXDimension = 0xA002;
       
    51 const TUint16 KIdPixelYDimension = 0xA003;
       
    52 const TUint16 KIdRelatedSoundFile = 0xA004;
       
    53 const TUint16 KIdFocalPlaneResolutionUnit = 0xA210;
       
    54 const TUint16 KIdFocalPlaneXResolution = 0xA20E;
       
    55 const TUint16 KIdFocalPlaneYResolution = 0xA20F;
       
    56 
       
    57 const TUint16 KIdExposureTime = 0x829A;
       
    58 const TUint16 KIdApertureValue = 0x9202;
       
    59 const TUint16 KIdExposureBias = 0x9204;
       
    60 const TUint16 KIdMeteringMode = 0x9207;
       
    61 const TUint16 KIdShutterSpeed = 0x9201;
       
    62 const TUint16 KIdXResolution = 0x011A;
       
    63 const TUint16 KIdYResolution = 0x011B;
       
    64 const TUint16 KIdWhiteBalance = 0xA403;
       
    65 const TUint16 KIdExposureProgram = 0x8822;
       
    66 const TUint16 KIdFlash = 0x9209;
       
    67 const TUint16 KIdOrientation = 0x112;
       
    68 
       
    69 const TUint16 KIdGpsLatitudeRef = 0x1;
       
    70 const TUint16 KIdGpsLatitude = 0x2;
       
    71 const TUint16 KIdGpsLongitudeRef = 0x3;
       
    72 const TUint16 KIdGpsLongitude = 0x4;
       
    73 const TUint16 KIdGpsAltitudeRef = 0x5;
       
    74 const TUint16 KIdGpsAltitude = 0x6;
       
    75 const TUint16 KIdGpsMeasureMode = 0xA;
       
    76 const TUint16 KIdGpsDop = 0xB;
       
    77 const TUint16 KIdGpsMapDatum = 0x12;
       
    78 
       
    79 _LIT( KExifDateTimeFormat, "%F%Y:%M:%D %H:%T:%S\0" );
       
    80 const TInt KDateBufferSize = 20;
       
    81 const TInt KCoordinateBufferSize = 24;
       
    82 
       
    83 // This is needed for exif description field
       
    84 _LIT8( KAsciiCodeDesignation,     "\x41\x53\x43\x49\x49\x00\x00\x00");
       
    85 _LIT8( KJisCodeDesignation,     "\x4A\x49\x53\x00\x00\x00\x00\x00");
       
    86 _LIT8( KUnicodeCodeDesignation, "\x55\x4E\x49\x43\x4F\x44\x45\x00");
       
    87 _LIT8( KUnknownCodeDesignation, "\x00\x00\x00\x00\x00\x00\x00\x00");
       
    88 
       
    89 _LIT8( KNorth, "N\0" );
       
    90 _LIT8( KSouth, "S\0" );
       
    91 _LIT8( KEast, "E\0" );
       
    92 _LIT8( KWest, "W\0" );
       
    93 _LIT8( KMeasureMode2, "2\0" );
       
    94 _LIT8( KMeasureMode3, "3\0" );
       
    95 _LIT8( KMapDatum, "WGS-84\0");
       
    96 
       
    97 CHarvesterExifUtil::CHarvesterExifUtil() :
       
    98     iSession( NULL ), iDefaultNamespace( NULL )
       
    99 {
       
   100 }
       
   101 
       
   102 
       
   103 CHarvesterExifUtil::~CHarvesterExifUtil()
       
   104 {
       
   105 }
       
   106 
       
   107 EXPORT_C CHarvesterExifUtil* CHarvesterExifUtil::NewLC()
       
   108 {
       
   109 	CHarvesterExifUtil* self = new (ELeave)CHarvesterExifUtil();
       
   110 	CleanupStack::PushL(self);
       
   111 	self->ConstructL();
       
   112 	return self;
       
   113 }
       
   114 
       
   115 EXPORT_C CHarvesterExifUtil* CHarvesterExifUtil::NewL()
       
   116 {
       
   117 	CHarvesterExifUtil* self=CHarvesterExifUtil::NewLC();
       
   118 	CleanupStack::Pop( self ); // self;
       
   119 	return self;
       
   120 }
       
   121 
       
   122 void CHarvesterExifUtil::ConstructL()
       
   123 {
       
   124 
       
   125 }
       
   126 
       
   127 EXPORT_C void CHarvesterExifUtil::SetSession( CMdESession* aSession )
       
   128 	{
       
   129 	iSession = aSession;
       
   130 	if ( !iDefaultNamespace && aSession )
       
   131 		{
       
   132     	TRAP_IGNORE( iDefaultNamespace = &iSession->GetDefaultNamespaceDefL() );
       
   133 		}
       
   134 	}
       
   135 
       
   136 
       
   137 EXPORT_C TBool CHarvesterExifUtil::IsValidExifData(TPtr8 aPtr)
       
   138 	{
       
   139 	WRITELOG( "CHarvesterExifUtil::IsValidExifData start" );
       
   140 	
       
   141 	CExifRead* reader = NULL;
       
   142 	
       
   143 	TRAPD(err, reader = CExifRead::NewL(aPtr, CExifRead::ENoJpeg | CExifRead::ENoTagChecking));
       
   144 	if (err != KErrNone || !reader )
       
   145 		{
       
   146 		WRITELOG1( "CHarvesterExifUtil::IsValidExifData - error code: %d", err );
       
   147 	
       
   148 		return EFalse;
       
   149 		}
       
   150 	
       
   151 	delete reader;
       
   152 	
       
   153 	WRITELOG( "CHarvesterExifUtil::IsValidExifData end" );	
       
   154 	
       
   155 	return ETrue;
       
   156 	}
       
   157 
       
   158 void CHarvesterExifUtil::StripNulls( HBufC& aString )
       
   159 	{
       
   160 	_LIT( KNull, "\0" );
       
   161 	_LIT( KSpace, " " );
       
   162 	
       
   163 	TInt pos( 0 );
       
   164     while( (pos = aString.Find( KNull ) ) != KErrNotFound )
       
   165     	{
       
   166     	aString.Des().Replace( pos, 1, KSpace );
       
   167     	}
       
   168     aString.Des().TrimAll();
       
   169 	}
       
   170 
       
   171 HBufC16* CHarvesterExifUtil::ReadExifTagL( const CExifRead& aReader, TExifIfdType aIFD, TUint16 aTagID )
       
   172 	{
       
   173 	HBufC16* destination = NULL;
       
   174     if( aReader.TagExists( aTagID, aIFD ) )
       
   175     	{
       
   176         const CExifTag* tag = aReader.GetTagL( aIFD, aTagID );
       
   177     	destination = CnvUtfConverter::ConvertToUnicodeFromUtf8L( tag->Data() );
       
   178     	StripNulls( *destination );    	
       
   179     	}	
       
   180     return destination;
       
   181 	}
       
   182 
       
   183 EXPORT_C TInt CHarvesterExifUtil::ReadExifDataL( CHarvestData& aHd, CFileData& aFileData )
       
   184     {
       
   185     WRITELOG( "CHarvesterExifUtil::ReadExifDataL()" );
       
   186 
       
   187     CExifRead* reader = CExifRead::NewL(
       
   188     		aFileData.iImageData->Des(), CExifRead::ENoJpeg | CExifRead::ENoTagChecking);
       
   189     CleanupStack::PushL(reader);
       
   190     
       
   191     // Getting description
       
   192     aHd.iDescription16 = ReadExifTagL( *reader, EIfd0, KIdImageDescription );
       
   193 
       
   194     // Getting UserComment
       
   195     ReadUserCommentL( aHd, reader ); 
       
   196           
       
   197     // Getting copyright
       
   198     aHd.iCopyright16 = ReadExifTagL( *reader, EIfd0, KIdCopyright );
       
   199     
       
   200     // Artist
       
   201     aHd.iArtist = ReadExifTagL( *reader, EIfd0, KIdArtist );
       
   202     
       
   203     // Getting whitebalance
       
   204     aHd.iStoreWhiteBalance = reader->GetWhiteBalance( aHd.iWhiteBalance ) == KErrNone;
       
   205  
       
   206     // Getting aHd.iFlash    
       
   207     aHd.iStoreFlash = reader->GetFlash( aHd.iFlash ) == KErrNone;
       
   208     
       
   209     // Getting exposure
       
   210     aHd.iStoreExposureProgram = reader->GetExposureProgram( aHd.iExposureProgram ) == KErrNone;
       
   211                 
       
   212     // Getting width
       
   213     if ( reader->TagExists( KIdPixelXDimension, EIfdExif ) )
       
   214         {
       
   215         // PixelXDimension tag should be found in EXIF according to the standard.
       
   216         reader->GetPixelXDimension(aHd.iImageWidthExif);
       
   217         }
       
   218     
       
   219     // Getting height
       
   220     if ( reader->TagExists( KIdPixelYDimension, EIfdExif ) )
       
   221         {
       
   222         // PixelYDimension tag should be found in EXIF according to the standard.
       
   223         reader->GetPixelYDimension(aHd.iImageHeightExif);
       
   224         }
       
   225     
       
   226     // Getting aFileData.iModified date
       
   227     if ( reader->TagExists(KIdDateTime, EIfd0) )
       
   228         {
       
   229         WRITELOG( "CHarvesterExifUtil::ReadExifDataL() - getting last aFileData.iModified date (exif)" );
       
   230         aHd.iDateModified8 = reader->GetDateTimeL();
       
   231         }
       
   232     
       
   233     // Getting original date
       
   234     if ( reader->TagExists(KIdDateTimeOriginal, EIfdExif) )
       
   235         {
       
   236         WRITELOG( "CHarvesterExifUtil::ReadExifDataL() - getting original date (exif)" );
       
   237         aHd.iDateOriginal8 = reader->GetDateTimeOriginalL();
       
   238         }
       
   239         
       
   240     // Getting date & time digitized
       
   241     if ( reader->TagExists(KIdDateTimeDigitized, EIfdExif) )
       
   242         {
       
   243         WRITELOG( "CHarvesterExifUtil::ReadExifDataL() - getting digitized date (exif)" );
       
   244         aHd.iDateDigitized8 = reader->GetDateTimeDigitizedL();
       
   245         }            
       
   246     
       
   247     //Getting camera maker
       
   248     aHd.iMake = ReadExifTagL( *reader, EIfd0, KIdMake );
       
   249     
       
   250     //Getting camera aHd.iModel
       
   251     aHd.iModel = ReadExifTagL( *reader, EIfd0, KIdModel );
       
   252     
       
   253     //Getting aHd.iOrientation
       
   254     aHd.iStoreOrientation = reader->GetOrientation( aHd.iOrientation ) == KErrNone;
       
   255     
       
   256     //Getting X Resolution
       
   257     ReadXResolutionL( aHd, reader ); 
       
   258     
       
   259     //Getting Y Resolution
       
   260     ReadXResolutionL( aHd, reader ); 
       
   261     
       
   262     //Getting resolution unit (mandatory tag)
       
   263     reader->GetResolutionUnit( aHd.iResolutionUnit );
       
   264     
       
   265     //Getting YCbCr Positioning
       
   266     aHd.iStoreYCbCrPositioning = reader->GetYCbCrPositioning( aHd.iYCbCrPositioning ) == KErrNone;
       
   267         
       
   268     //Getting exposure bias value
       
   269     ReadExposureBiasL( aHd, reader ); 
       
   270     
       
   271     //Getting exposure time
       
   272     ReadExposureTimeL( aHd, reader ); 
       
   273         
       
   274     //Getting FNumber
       
   275     ReadFNumberL( aHd, reader );
       
   276     
       
   277     //Getting Exif version
       
   278     aHd.iStoreExifVersion = reader->GetExifVersion( aHd.iExifVersion ) == KErrNone;           
       
   279         
       
   280     //Getting FlashPix version
       
   281     aHd.iStoreFlashPixVersion = reader->GetFlashPixVersion( aHd.iFlashPixVersion ) == KErrNone;
       
   282     
       
   283     // Shutter speed
       
   284     ReadShutterSpeedL( aHd, reader );
       
   285         
       
   286     //Getting aHd.iAperture
       
   287     ReadApertureValueL( aHd, reader );
       
   288     
       
   289     //Getting focal length
       
   290     ReadFocalLengthL( aHd, reader );
       
   291     
       
   292     // Getting focal length in 35 mm
       
   293     ReadFocalLength35mmL( aHd, reader );
       
   294         
       
   295     aHd.iStoreColourSpace = reader->GetColorSpace( aHd.iColourSpace ) == KErrNone;
       
   296     
       
   297     aHd.iStoreThumbCompression = reader->GetThumbnailCompression( aHd.iThumbCompression ) == KErrNone;
       
   298     
       
   299 	TUint32 numerator = 0;
       
   300     TUint32 denominator = 0;
       
   301 	
       
   302     //Getting thumbnail X resolution    
       
   303     TInt error = reader->GetThumbnailXResolution( numerator, denominator );
       
   304     if ( error == KErrNone )
       
   305         {
       
   306         aHd.iStoreThumbXResolution = ETrue;
       
   307         aHd.iThumbXResolution = 0.0f;
       
   308         if ( denominator > 0)
       
   309             {
       
   310             aHd.iThumbXResolution = numerator / denominator;
       
   311             }
       
   312         }
       
   313     
       
   314     //Getting thumbnail Y resolution
       
   315     error = reader->GetThumbnailYResolution( numerator, denominator );
       
   316     if ( error == KErrNone )
       
   317         {
       
   318         aHd.iStoreThumbYResolution = ETrue;
       
   319         aHd.iThumbYResolution = 0.0f;
       
   320         if ( denominator > 0 )
       
   321             {
       
   322             aHd.iThumbYResolution = numerator / denominator;
       
   323             }
       
   324         }
       
   325         
       
   326     aHd.iStoreThumbResolutionUnit =
       
   327     	reader->GetThumbnailResolutionUnit( aHd.iThumbResolutionUnit ) == KErrNone;
       
   328        
       
   329     // Bits per sample and Samples per pixel not recorded in JPEG Exif.
       
   330     if ( reader->TagExists( KIdSamplesPerPixel, EIfd0 ) )
       
   331         {
       
   332         const CExifTag* tag = reader->GetTagL( EIfd0, KIdSamplesPerPixel );
       
   333         TPtrC8 tagData = tag->Data();
       
   334         
       
   335         aHd.iSamplesPerPixel = MdsUtils::ToUInt16L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
   336         aHd.iStoreSamplesPerPixel = ETrue;
       
   337         
       
   338         WRITELOG1( "CHarvesterExifUtil::ReadExifDataL() - samples per pixel: %d", aHd.iSamplesPerPixel );
       
   339         }
       
   340     
       
   341     //Getting ISO speed rating.
       
   342     if ( reader->TagExists(KIdISOSpeedRatings, EIfdExif) )
       
   343         {
       
   344         HBufC8* iso8 = reader->GetIsoSpeedRatingsL();
       
   345         
       
   346         if ( iso8 )
       
   347             {
       
   348             aHd.iStoreIsoSpeedRating = ETrue;
       
   349             aHd.iIsoSpeedRating = iso8->Des()[0];
       
   350             delete iso8;
       
   351             iso8 = NULL;
       
   352             }    
       
   353         }
       
   354     
       
   355     //Getting components configuration
       
   356     if ( reader->TagExists( KIdComponentsConfig, EIfdExif ) )
       
   357         {
       
   358         const CExifTag* tag = reader->GetTagL(
       
   359         		EIfdExif, KIdComponentsConfig );
       
   360         TPtrC8 tagData = tag->Data();
       
   361         
       
   362         aHd.iComponentsConfiguration = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
   363         aHd.iStoreComponentsConfig = ETrue;
       
   364         }
       
   365     
       
   366     // Getting thumbnail compression
       
   367     aHd.iStoreThumbCompression =
       
   368     	reader->GetThumbnailCompression( aHd.iThumbCompression ) == KErrNone;
       
   369         
       
   370     // Getting metering mode
       
   371     aHd.iStoreMeteringMode = reader->GetMeteringMode( aHd.iMeteringMode ) ==KErrNone;
       
   372     
       
   373     // Getting related soundfile
       
   374     aHd.iRelatedSoundFile = ReadExifTagL( *reader, EIfdExif, KIdRelatedSoundFile );
       
   375         
       
   376     // Getting focal plane resolution unit
       
   377     if ( reader->TagExists(KIdFocalPlaneResolutionUnit, EIfdExif) )
       
   378         {
       
   379         const CExifTag* tag = reader->GetTagL(
       
   380         		EIfdExif, KIdFocalPlaneResolutionUnit );
       
   381         TPtrC8 tagData = tag->Data();
       
   382         
       
   383         aHd.iFocalPlaneResolutionUnit = MdsUtils::ToUInt16L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
   384         aHd.iStoreFocalPlaneResolutionUnit = ETrue;
       
   385         }
       
   386     
       
   387     // Getting focal plane X resolution
       
   388     ReadFocalXPlaneResolutionL( aHd, reader );
       
   389 
       
   390         
       
   391     // Getting focal plane Y resolution
       
   392     ReadFocalYPlaneResolutionL( aHd, reader );
       
   393 
       
   394     // Get GPS tags
       
   395     TBool latitudeExists = EFalse;
       
   396     
       
   397     // latitude
       
   398     ReadGPSLatitudeL( aHd, reader, latitudeExists );
       
   399 
       
   400     // longitude
       
   401     ReadGPSLongitudeL( aHd, reader, latitudeExists );
       
   402     
       
   403     // altitude
       
   404     ReadGPSAltitudeL( aHd, reader );
       
   405         
       
   406     CleanupStack::PopAndDestroy( reader );
       
   407     return KErrNone;
       
   408     }
       
   409 
       
   410 // ---------------------------------------------------------------------------
       
   411 // Time converting
       
   412 // ---------------------------------------------------------------------------
       
   413 //
       
   414 EXPORT_C TTime CHarvesterExifUtil::ConvertExifDateTimeToSymbianTimeL(
       
   415 		const TDesC8& aDateTime )
       
   416     {
       
   417     WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL()" );
       
   418     
       
   419     TDateTime datetime( 0, EJanuary, 0, 0, 0, 0, 0 );
       
   420     TBuf<4> text;
       
   421     
       
   422     // Year
       
   423     TPtrC8 textPart = aDateTime.Left(4);
       
   424     TLex8 lex( textPart );
       
   425     TInt number = 0;
       
   426     TInt error = lex.Val( number );
       
   427     if ( error != KErrNone )
       
   428         {
       
   429         WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL() - couldn't get year" );
       
   430         User::Leave( error );
       
   431         }
       
   432     datetime.SetYear( number );
       
   433     
       
   434     // Month
       
   435     TPtrC8 textPart2 = aDateTime.Mid( 5,2 );
       
   436     lex.Assign( textPart2 );
       
   437     error = lex.Val( number );
       
   438     if ( error != KErrNone )
       
   439         {
       
   440         WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL() - couldn't get month" );
       
   441         User::Leave( error );
       
   442         }        
       
   443     number--;
       
   444     TMonth month = (TMonth) number;
       
   445     datetime.SetMonth( month );
       
   446     
       
   447     // Day
       
   448     TPtrC8 textPart3 = aDateTime.Mid( 8,2 );
       
   449     lex.Assign( textPart3 );
       
   450     error = lex.Val( number );
       
   451     if ( error != KErrNone )
       
   452         {
       
   453         WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL() - couldn't get date" );
       
   454         User::Leave( error );
       
   455         }
       
   456     datetime.SetDay( number - 1 );
       
   457     
       
   458     // Hours
       
   459     TPtrC8 textPart4 = aDateTime.Mid( 11,2 );
       
   460     lex.Assign( textPart4 );
       
   461     error = lex.Val( number );
       
   462     if ( error != KErrNone )
       
   463         {
       
   464         WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL() - couldn't get hours" );
       
   465         User::Leave( error );
       
   466         }    
       
   467     datetime.SetHour( number );
       
   468     
       
   469     // Minutes
       
   470     TPtrC8 textPart5 = aDateTime.Mid( 14,2 );
       
   471     lex.Assign( textPart5 );
       
   472     error = lex.Val( number );
       
   473     if ( error != KErrNone )
       
   474         {
       
   475         WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL() - couldn't get minutes" );
       
   476         User::Leave( error );
       
   477         }
       
   478     datetime.SetMinute( number );
       
   479     
       
   480     // Seconds
       
   481     TPtrC8 textPart6 = aDateTime.Mid( 17,2 );
       
   482     lex.Assign( textPart6 );
       
   483     error = lex.Val( number );
       
   484     if ( error != KErrNone )
       
   485         {
       
   486         WRITELOG( "CHarvesterImagePluginAO::ConvertExifDateTimeToSymbianTimeL() - couldn't get seconds" );
       
   487         User::Leave( error );
       
   488         }
       
   489     datetime.SetSecond( number );
       
   490     
       
   491     TTime time( datetime );
       
   492 
       
   493     return time;
       
   494     }
       
   495 
       
   496 void CHarvesterExifUtil::AddPropertyL( CMdEObjectDef& aObjectDef, CMdEObject& aMdeObject,
       
   497 		const TDesC& aProperty, TUint16 aValue )
       
   498 	{
       
   499 	CMdEPropertyDef& propDef = aObjectDef.GetPropertyDefL( aProperty );    
       
   500 	CMdEProperty* mdeProp = NULL;
       
   501 	
       
   502 	aMdeObject.Property( propDef, mdeProp, 0 );
       
   503     if ( !mdeProp )
       
   504         {
       
   505         aMdeObject.AddUint16PropertyL( propDef, aValue );
       
   506         }	
       
   507 	}
       
   508 
       
   509 void CHarvesterExifUtil::AddPropertyL( CMdEObjectDef& aObjectDef, CMdEObject& aMdeObject,
       
   510 		   const TDesC& aProperty, TUint32 aValue )
       
   511 {
       
   512 	CMdEPropertyDef& propDef = aObjectDef.GetPropertyDefL( aProperty );    
       
   513 	CMdEProperty* mdeProp = NULL;
       
   514 	
       
   515 	aMdeObject.Property( propDef, mdeProp, 0 );
       
   516 	if ( !mdeProp )
       
   517 		{
       
   518 		aMdeObject.AddUint32PropertyL( propDef, aValue );
       
   519 		}	
       
   520 }
       
   521 
       
   522 void CHarvesterExifUtil::SetExifDefaultsL( CMdEObject& aMdeObject, CExifModify& aExifModify )
       
   523 	{
       
   524     const TUint32 KPixPerResolution = 72;
       
   525     const TUint32 KPixPerResDenm = 1;
       
   526     const TUint16 KResUnitInch = 2;
       
   527     const TUint16 KYCbCrPositioning = 1;
       
   528     const TUint8  KCompConf1st = 1;
       
   529     const TUint8  KCompConf2nd = 2;
       
   530     const TUint8  KCompConf3rd = 3;
       
   531     const TUint8  KCompConf4rd = 0;
       
   532     const TUint16 KColorSpaceRGB = 1;
       
   533 
       
   534     CMdEObjectDef& imageDef = iDefaultNamespace->GetObjectDefL( Image::KImageObject );
       
   535     
       
   536     aExifModify.SetXResolutionL( KPixPerResolution, KPixPerResDenm );
       
   537     aExifModify.SetYResolutionL( KPixPerResolution, KPixPerResDenm );
       
   538 
       
   539     AddPropertyL( imageDef, aMdeObject, MediaObject::KResolutionUnitProperty,
       
   540     		      KResUnitInch );
       
   541     aExifModify.SetResolutionUnitL( KResUnitInch );
       
   542 
       
   543     AddPropertyL( imageDef, aMdeObject, Image::KYCbCrPositioningProperty,
       
   544     		      KYCbCrPositioning );
       
   545     aExifModify.SetYCbCrPositioningL( KYCbCrPositioning );
       
   546 
       
   547     TUint32 compUint32( 0 );
       
   548     TUint8* components = (TUint8*) &compUint32;
       
   549     *(components + 3) = KCompConf4rd;
       
   550     *(components + 2) = KCompConf3rd;
       
   551     *(components + 1) = KCompConf2nd;
       
   552           *components = KCompConf1st;
       
   553     
       
   554     AddPropertyL( imageDef, aMdeObject, Image::KComponentsConfigurationProperty,
       
   555     		      compUint32 );
       
   556     aExifModify.SetComponentsConfigurationL( KCompConf1st, KCompConf2nd,
       
   557     										 KCompConf3rd, KCompConf4rd );
       
   558 
       
   559     AddPropertyL( imageDef, aMdeObject, Image::KColourSpaceProperty, KColorSpaceRGB );
       
   560     aExifModify.SetColorSpaceL( KColorSpaceRGB );
       
   561 	}
       
   562 
       
   563 HBufC8* CHarvesterExifUtil::GetPropertyValueLC( const CMdEPropertyDef& aPropDef,
       
   564 		const CMdEProperty& aProperty )
       
   565 	{
       
   566 	switch( aPropDef.PropertyType() )
       
   567 		{
       
   568 		case EPropertyReal32:
       
   569 			{
       
   570 			TUint32 denominator = 1; 
       
   571 			if( aPropDef.Name().CompareF( Image::KExposureTimeProperty ) == 0 )
       
   572 				{
       
   573 				denominator = 1000000;
       
   574 				}
       
   575 			else if( aPropDef.Name().CompareF( Image::KApertureValueProperty ) == 0 )
       
   576 				{
       
   577 				denominator = 100;
       
   578 				}
       
   579 			else if( aPropDef.Name().CompareF( Image::KExposureBiasValueProperty ) == 0 )
       
   580 				{
       
   581 				denominator = 100;
       
   582 				}
       
   583 			else if( aPropDef.Name().CompareF( Image::KShutterSpeedValueProperty ) == 0 )
       
   584 				{
       
   585 				denominator = 1000;
       
   586 				}
       
   587 			else if( aPropDef.Name().CompareF( Image::KFNumberProperty ) == 0 )
       
   588 				{
       
   589 				denominator = 10;
       
   590 				}			
       
   591 			TUint32 value = TUint32( aProperty.Real32ValueL() * (TReal32)denominator );
       
   592 
       
   593 			HBufC8* buf8 = HBufC8::NewLC( 2 * sizeof(TUint32) );
       
   594 			TPtr8 ptr = buf8->Des();
       
   595 			ptr.Append( (TUint8*)&value, sizeof(TUint32) );
       
   596 			ptr.Append( (TUint8*)&denominator, sizeof(TUint32) );
       
   597 			
       
   598 			return buf8;
       
   599 			}
       
   600 		case EPropertyTime:
       
   601 			{
       
   602 	        TTime time = aProperty.TimeValueL();
       
   603 	        if( aPropDef.Name().CompareF( Image::KDateTimeProperty ) == 0 )
       
   604 	        	{
       
   605 	        	RTz timezone;
       
   606 	        	CleanupClosePushL( timezone );
       
   607 	        	User::LeaveIfError( timezone.Connect() );
       
   608 	        	timezone.ConvertToLocalTime( time );
       
   609 	        	CleanupStack::PopAndDestroy( &timezone );
       
   610 	        	}
       
   611 	        HBufC* buf = HBufC::NewLC( KDateBufferSize );
       
   612 	        TPtr ptr = buf->Des();
       
   613 	        time.FormatL( ptr, KExifDateTimeFormat );
       
   614 	        HBufC8* buf8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( ptr );
       
   615 	        CleanupStack::PopAndDestroy( buf );
       
   616 	        CleanupStack::PushL( buf8 );
       
   617 	        return buf8;
       
   618 			}
       
   619 		case EPropertyText:
       
   620 			{
       
   621 			TPtrC text = aProperty.TextValueL();
       
   622 			if( aPropDef.Name().CompareF( MediaObject::KCommentProperty ) == 0 )
       
   623 				{
       
   624 		        const TUint16 bufLength = KUnicodeCodeDesignation.iTypeLength + text.Size();
       
   625 		        HBufC8* commentBuf = HBufC8::NewLC( bufLength );
       
   626 		        TPtr8 commentPtr = commentBuf->Des();
       
   627 		        commentPtr.Append( KUnicodeCodeDesignation );
       
   628 		        commentPtr.Append( (TUint8*)text.Ptr(), text.Size() );
       
   629 		        return commentBuf;
       
   630 				}
       
   631 			HBufC8* buf = CnvUtfConverter::ConvertFromUnicodeToUtf8L( text );
       
   632 			CleanupStack::PushL( buf );
       
   633 	        return buf;
       
   634 			}
       
   635 		case EPropertyUint16:
       
   636 			{
       
   637         	TUint16 value = aProperty.Uint16ValueL();
       
   638         	HBufC8* buf = HBufC8::NewLC( sizeof(value) );
       
   639         	TPtr8 ptr = buf->Des();
       
   640         	ptr.Copy( (TUint8*)(&value), sizeof(value) );
       
   641 			return buf;
       
   642 			}
       
   643 		default:
       
   644 			User::Leave( KErrGeneral );
       
   645 		}
       
   646 	    return NULL;
       
   647 	}
       
   648 
       
   649 CExifTag::TExifTagDataType CHarvesterExifUtil::ExifTagDataType( TUint16 aTagID, const CMdEPropertyDef& aPropDef )
       
   650 	{
       
   651 	if( aTagID == KIdUserComment )
       
   652 		{
       
   653 		return CExifTag::ETagUndefined;   		
       
   654 		}
       
   655 	if( aTagID == KIdShutterSpeed || aTagID == KIdExposureBias )
       
   656 		{
       
   657 		return CExifTag::ETagSrational;
       
   658 		}
       
   659 	switch( aPropDef.PropertyType() )
       
   660 		{
       
   661 		case EPropertyBool:
       
   662 		case EPropertyInt8:
       
   663 		case EPropertyUint8:
       
   664 			return CExifTag::ETagByte;
       
   665 		case EPropertyInt16:
       
   666 		case EPropertyUint16:
       
   667 			return CExifTag::ETagShort;
       
   668 		case EPropertyUint32:
       
   669 			return CExifTag::ETagLong;
       
   670 		case EPropertyInt32:
       
   671 			return CExifTag::ETagSlong;
       
   672 		case EPropertyReal32:
       
   673 			return CExifTag::ETagRational;
       
   674 		case EPropertyTime:
       
   675 			return CExifTag::ETagAscii;
       
   676 		case EPropertyText:
       
   677 			return CExifTag::ETagAscii;
       
   678 		default:
       
   679 			return CExifTag::ETagUndefined;
       
   680 		}
       
   681 	}
       
   682 
       
   683 TBool CHarvesterExifUtil::CompareTag( TPtrC8 aMdeData, const CExifTag* aTag )
       
   684 	{
       
   685 	if( aTag->TagInfo().iDataType == CExifTag::ETagRational )
       
   686 		{
       
   687 		TUint32 denominator;
       
   688 		TUint32 value;
       
   689         TPtrC8 ptr( aTag->Data() );
       
   690         memcpy( &value, ptr.Ptr(), sizeof(value) );
       
   691         memcpy( &denominator, ptr.Ptr()+sizeof(value), sizeof(denominator) );
       
   692 
       
   693     	TReal32 tagValue = 0.0f;
       
   694     	if ( denominator != 0 )
       
   695     		{
       
   696     		tagValue = (TReal32)value / (TReal32)denominator;
       
   697     		}
       
   698         ptr.Set( aMdeData );
       
   699         memcpy( &value, ptr.Ptr(), sizeof(value) );
       
   700         memcpy( &denominator, ptr.Ptr()+sizeof(value), sizeof(denominator) );
       
   701 
       
   702     	TReal32 mdeValue = 0.0f;
       
   703     	if ( denominator != 0 )
       
   704     		{
       
   705     		mdeValue = (TReal32)value / (TReal32)denominator;
       
   706     		}
       
   707     	return Abs( tagValue - mdeValue ) > 0.01f;
       
   708 		}
       
   709 	else
       
   710 		{
       
   711 		return aMdeData.CompareF( aTag->Data() ) != 0; 
       
   712 		}
       
   713 	}
       
   714 
       
   715 TBool CHarvesterExifUtil::ModifyExifTagL( CMdEObject& aMdeObject, CExifModify& aExifModify,
       
   716 		const TDesC& aProperty, TExifIfdType aIFD, TUint16 aTagID, TBool aRemove )
       
   717 	{
       
   718 	CMdEObjectDef& imageDef = iDefaultNamespace->GetObjectDefL( Image::KImageObject );
       
   719 	CMdEPropertyDef& propDef = imageDef.GetPropertyDefL( aProperty );    
       
   720 	CMdEProperty* mdeProp = NULL;
       
   721 	TBool exifChanged = EFalse;
       
   722 	
       
   723 	aMdeObject.Property( propDef, mdeProp, 0 );
       
   724 	TBool tagExists = EFalse;
       
   725 	if( aRemove )
       
   726 		{
       
   727 		tagExists = aExifModify.Reader()->TagExists( aTagID, aIFD );
       
   728 		}
       
   729 	if ( mdeProp )
       
   730         {
       
   731         HBufC8* mdedata = GetPropertyValueLC( propDef, *mdeProp );
       
   732         TPtrC8 ptr = mdedata->Des();
       
   733         TBool change = EFalse;
       
   734         const CExifTag* tag = NULL;
       
   735         TRAP_IGNORE( tag = aExifModify.Reader()->GetTagL( aIFD, aTagID ) );
       
   736         if( !tag ) //create new exif tag
       
   737         	{
       
   738         	change = ETrue;
       
   739         	}
       
   740         else if( CompareTag( ptr, tag ) )
       
   741             {
       
   742             change = ETrue;
       
   743             }
       
   744         if( change )
       
   745         	{
       
   746         	CExifTag::TExifTagDataType type = ExifTagDataType( aTagID, propDef );
       
   747         	TInt len = 1;
       
   748         	if( type == CExifTag::ETagUndefined || type == CExifTag::ETagAscii  )
       
   749         		{
       
   750         		len = ptr.Length();
       
   751         		}
       
   752         	TExifTagInfo info( aTagID, type, len  );
       
   753             aExifModify.SetTagL( aIFD, info, ptr );
       
   754             exifChanged = ETrue;        	
       
   755         	}
       
   756         CleanupStack::PopAndDestroy( mdedata );
       
   757         }
       
   758 	else if( tagExists ) // remove from exif
       
   759         {
       
   760         aExifModify.DeleteTag( aIFD, aTagID );
       
   761         exifChanged = ETrue;
       
   762         }
       
   763     return exifChanged;
       
   764 	}
       
   765 
       
   766 // ---------------------------------------------------------------------------
       
   767 // ComposeExifData
       
   768 // ---------------------------------------------------------------------------
       
   769 //
       
   770 EXPORT_C TInt CHarvesterExifUtil::ComposeExifDataL( CMdEObject& aMdeObject, TPtr8 aImagePtr, HBufC8*& aModified )
       
   771 	{
       
   772 
       
   773 	if ( !iSession )
       
   774 		{
       
   775 		User::Leave( KErrSessionClosed );
       
   776 		}
       
   777 	
       
   778     WRITELOG1( "CHarvesterExifUtil::ComposeExifData() - Compose Start Object ID: %d", aMdeObject.Id() );
       
   779     TBool exifChanged = EFalse;
       
   780 
       
   781     // 2. try to init EXIF data from image file's data
       
   782     CExifModify* modifyExif = NULL;
       
   783     TInt exifError = KErrNone;
       
   784     TRAP( exifError, modifyExif = CExifModify::NewL( aImagePtr, 
       
   785     		CExifModify::EModify, CExifModify::ENoJpegParsing ) );
       
   786 
       
   787     // 3. Is this image format supported?
       
   788     if ( exifError == KErrNotSupported )
       
   789         {
       
   790         WRITELOG( "CHarvesterExifUtil::ComposeExifData() - Image format not supported (!jpeg)" );
       
   791         User::Leave( exifError );
       
   792         }
       
   793 
       
   794     // 4. if image does not contain EXIF data try to create it
       
   795     if ( exifError != KErrNone )
       
   796         {
       
   797         WRITELOG( "CHarvesterExifUtil::ComposeExifData() - Image doesn't contain EXIF data" );
       
   798         modifyExif = CExifModify::NewL( aImagePtr, 
       
   799         		CExifModify::ECreate, CExifModify::ENoJpegParsing );
       
   800         SetExifDefaultsL( aMdeObject, *modifyExif );
       
   801         exifChanged = ETrue;
       
   802         }
       
   803     CleanupStack::PushL( modifyExif );
       
   804     const CExifRead* readExif = modifyExif->Reader();
       
   805     CMdEObjectDef& imageDef = iDefaultNamespace->GetObjectDefL( Image::KImageObject );
       
   806     
       
   807     // Set pixel X dimension tag (mandatory)
       
   808     TBool changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   809     		MediaObject::KWidthProperty, EIfdExif, KIdPixelXDimension);
       
   810     exifChanged = (exifChanged | changed);
       
   811 
       
   812     // Set pixel Y dimension tag (mandatory)
       
   813     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   814     		MediaObject::KHeightProperty, EIfdExif, KIdPixelYDimension);
       
   815     exifChanged = (exifChanged | changed);
       
   816 
       
   817     // Set white balance tag (recommended)
       
   818     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   819     		Image::KWhiteBalanceProperty, EIfdExif, KIdWhiteBalance, ETrue );
       
   820     exifChanged = (exifChanged | changed);
       
   821     
       
   822     // Set flash tag (recommended)
       
   823     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   824     		Image::KFlashProperty, EIfdExif, KIdFlash, ETrue );
       
   825     exifChanged = (exifChanged | changed);
       
   826     
       
   827     // Set exposure program tag (optional)
       
   828     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   829     		Image::KExposureProgramProperty, EIfdExif, KIdExposureProgram, ETrue );
       
   830     exifChanged = (exifChanged | changed);
       
   831 
       
   832     // Set description tag (recommended)
       
   833     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   834     		MediaObject::KDescriptionProperty, EIfd0, KIdImageDescription, ETrue );
       
   835     exifChanged = (exifChanged | changed);
       
   836     
       
   837     // Set user comment tag (optional)
       
   838     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   839     		MediaObject::KCommentProperty, EIfdExif, KIdUserComment, ETrue );
       
   840     exifChanged = (exifChanged | changed);
       
   841     
       
   842     // Set copyright tag (optional)
       
   843     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   844     		MediaObject::KCopyrightProperty, EIfd0, KIdCopyright, ETrue );
       
   845     exifChanged = (exifChanged | changed);
       
   846 
       
   847     // Set DateTimeOriginal tag (optional)
       
   848     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   849     		Image::KDateTimeOriginalProperty, EIfdExif, KIdDateTimeOriginal, ETrue );
       
   850     exifChanged = (exifChanged | changed);
       
   851     
       
   852     // Set DateTimeDigitized tag (optional)
       
   853     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   854     		Image::KDateTimeDigitizedProperty, EIfdExif, KIdDateTimeDigitized, ETrue );
       
   855     exifChanged = (exifChanged | changed);
       
   856     
       
   857     // Set DateTime (_image_ modified) tag (recommended)
       
   858     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   859     		Image::KDateTimeProperty, EIfd0, KIdDateTimeModified, ETrue );
       
   860     exifChanged = (exifChanged | changed);
       
   861     
       
   862     // Set maker tag (optional)
       
   863     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   864     		Image::KMakeProperty, EIfd1, KIdMake, ETrue );
       
   865     exifChanged = (exifChanged | changed);
       
   866     
       
   867     // Set model tag (optional)
       
   868     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   869     		Image::KModelProperty, EIfd1, KIdModel, ETrue );
       
   870     exifChanged = (exifChanged | changed);
       
   871     
       
   872     // Set orientation tag (recommended)
       
   873     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   874     		Image::KOrientationProperty, EIfd0, KIdOrientation , ETrue );
       
   875     exifChanged = (exifChanged | changed);
       
   876 
       
   877     // Set YCbCrPositioning tag (mandatory)
       
   878     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   879     		Image::KYCbCrPositioningProperty, EIfd1, KIdYbCrPositioning, EFalse );
       
   880     exifChanged = (exifChanged | changed);
       
   881     
       
   882     // Set resolution unit tag (mandatory)
       
   883     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   884     		MediaObject::KResolutionUnitProperty, EIfd1, KIdResolutionUnit, EFalse );
       
   885     exifChanged = (exifChanged | changed);
       
   886     
       
   887     // Set ISO speed tag (optional)
       
   888     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   889     		Image::KISOSpeedRatingsProperty, EIfdExif, KIdISOSpeedRatings, ETrue );
       
   890     exifChanged = (exifChanged | changed);
       
   891 
       
   892     // Set related soundfile tag (optional)
       
   893     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   894     		Image::KRelatedSoundFileProperty, EIfdExif, KIdRelatedSoundFile, ETrue );
       
   895     exifChanged = (exifChanged | changed);    
       
   896     
       
   897     // Set exposure time tag (recommended)
       
   898     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   899     		Image::KExposureTimeProperty, EIfdExif, KIdExposureTime, ETrue );
       
   900     exifChanged = (exifChanged | changed);   
       
   901         
       
   902     // Set aperture value tag (optional)
       
   903     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   904     		Image::KApertureValueProperty, EIfdExif, KIdApertureValue, ETrue );
       
   905     exifChanged = (exifChanged | changed);  
       
   906     
       
   907     // Set colour space tag (mandatory)
       
   908     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   909 		Image::KColourSpaceProperty, EIfdExif, KIdColorSpace , EFalse );
       
   910     exifChanged = (exifChanged | changed);
       
   911         
       
   912     // Set exposure bias tag (optional)
       
   913     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   914     		Image::KExposureBiasValueProperty, EIfdExif, KIdExposureBias, ETrue );
       
   915     exifChanged = (exifChanged | changed);
       
   916     
       
   917     // Set metering mode tag (optional)
       
   918     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   919     		Image::KMeteringModeProperty, EIfdExif, KIdMeteringMode, ETrue );
       
   920     exifChanged = (exifChanged | changed);
       
   921 
       
   922     // Set shutter speed tag (optional)
       
   923     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   924     		Image::KShutterSpeedValueProperty, EIfdExif, KIdShutterSpeed, ETrue );
       
   925     exifChanged = (exifChanged | changed);
       
   926 
       
   927     // Set X resolution tag (mandatory)
       
   928     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   929     		Image::KXResolutionProperty, EIfd0, KIdXResolution, EFalse );
       
   930     exifChanged = (exifChanged | changed); 
       
   931 
       
   932     // Set Y resolution tag (mandatory)
       
   933     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   934     		Image::KYResolutionProperty, EIfd0, KIdYResolution, EFalse );
       
   935     exifChanged = (exifChanged | changed); 
       
   936     
       
   937     // Set F number tag (optional)
       
   938     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   939     		Image::KFNumberProperty, EIfdExif, KIdFNumber, ETrue );
       
   940     exifChanged = (exifChanged | changed);     
       
   941     
       
   942     // Set focal length tag (optional)
       
   943     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   944     		Image::KFocalLengthProperty, EIfdExif, KIdFocalLength, ETrue );
       
   945     exifChanged = (exifChanged | changed);  
       
   946     
       
   947     // Set focal length in 35 mm film tag (optional)
       
   948     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   949     		Image::KFocalLengthIn35mmFilmProperty, EIfdExif, KIdFocalLengthIn35mm, ETrue );
       
   950     exifChanged = (exifChanged | changed);   
       
   951 
       
   952     // Set focal plane resolution unit (optional)
       
   953     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   954     		Image::KFocalPlaneResolutionUnitProperty, EIfdExif, KIdFocalPlaneResolutionUnit, ETrue );
       
   955     exifChanged = (exifChanged | changed);   
       
   956 
       
   957     // Set focal plane X resolution (optional)
       
   958     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   959     		Image::KFocalPlaneXResolutionProperty, EIfdExif, KIdFocalPlaneXResolution, ETrue );
       
   960     exifChanged = (exifChanged | changed);
       
   961     
       
   962     // Set focal plane Y resolution (optional)
       
   963     changed = ModifyExifTagL( aMdeObject, *modifyExif,
       
   964     		Image::KFocalPlaneYResolutionProperty, EIfdExif, KIdFocalPlaneYResolution, ETrue );
       
   965     exifChanged = (exifChanged | changed);
       
   966     
       
   967     TUint16 uint16Value( 0 );
       
   968     TUint32 uint32Value( 0 );
       
   969     
       
   970     // Set components configuration tag (mandatory)
       
   971     const CMdEPropertyDef& componentsDef = imageDef.GetPropertyDefL(
       
   972      		Image::KComponentsConfigurationProperty );
       
   973         {
       
   974         CMdEProperty* componentsProp = NULL;
       
   975         aMdeObject.Property( componentsDef, componentsProp, 0 );
       
   976 
       
   977         if ( componentsProp )
       
   978             {
       
   979             TUint32 componentsValue = componentsProp->Uint32ValueL();
       
   980             TUint8* components = (TUint8*) &componentsValue;
       
   981             const TUint8 KComponent4th = *(components + 3);
       
   982             const TUint8 KComponent3rd = *(components + 2);
       
   983             const TUint8 KComponent2nd = *(components + 1);
       
   984             const TUint8 KComponent1st = *components;
       
   985             
       
   986             TUint8 exifComponent4th( 0 );
       
   987             TUint8 exifComponent3rd( 0 );
       
   988             TUint8 exifComponent2nd( 0 );
       
   989             TUint8 exifComponent1st( 0 );
       
   990             
       
   991             exifError = readExif->GetComponentsConfiguration(
       
   992               	exifComponent1st, exifComponent2nd, exifComponent3rd, exifComponent4th );
       
   993             if ( exifError != KErrNone || 
       
   994                  exifComponent1st != KComponent1st || exifComponent2nd != KComponent2nd ||
       
   995                  exifComponent3rd != KComponent3rd || exifComponent4th != KComponent4th )
       
   996                 {
       
   997                 modifyExif->SetComponentsConfigurationL(
       
   998                 		KComponent1st, KComponent2nd, KComponent3rd, KComponent4th );
       
   999                 exifChanged = ETrue;
       
  1000                 }
       
  1001             }
       
  1002         }        
       
  1003         
       
  1004 	// Set thumbnail X resolution tag (mandatory)
       
  1005     const CMdEPropertyDef& thumbXDef = imageDef.GetPropertyDefL(
       
  1006         Image::KThumbXResolutionProperty );
       
  1007         {
       
  1008         CMdEProperty* thumbXProp = NULL;
       
  1009         aMdeObject.Property( thumbXDef, thumbXProp, 0 );
       
  1010 
       
  1011         if ( thumbXProp )
       
  1012             {
       
  1013             const TUint32 thumbX = thumbXProp->Uint32ValueL();
       
  1014 
       
  1015             TUint32 exifDenominator = 0;
       
  1016             exifError = readExif->GetThumbnailXResolution( uint32Value, exifDenominator );
       
  1017             TUint32 exifThumbXResol = 0;
       
  1018             if ( exifDenominator > 0 )
       
  1019                 {
       
  1020                 exifThumbXResol = uint32Value / exifDenominator;
       
  1021                 }
       
  1022 
       
  1023             if ( exifError != KErrNone || exifThumbXResol != thumbX )
       
  1024                 {
       
  1025                 const TUint32 KDenominator = 1;
       
  1026                 modifyExif->SetThumbnailXResolutionL( thumbX, KDenominator );
       
  1027                 exifChanged = ETrue;
       
  1028                 }
       
  1029             }
       
  1030         }
       
  1031 
       
  1032 	// Set thumbnail Y resolution tag (mandatory)
       
  1033     const CMdEPropertyDef& thumbYDef = imageDef.GetPropertyDefL(
       
  1034       		Image::KThumbYResolutionProperty );
       
  1035         {
       
  1036         CMdEProperty* thumbYProp = NULL;
       
  1037         aMdeObject.Property( thumbYDef, thumbYProp, 0 );
       
  1038 
       
  1039         if ( thumbYProp )
       
  1040             {
       
  1041             TUint32 thumbY = TUint32( thumbYProp->Uint32ValueL() );
       
  1042             TUint32 exifDenominator = 0;
       
  1043             exifError = readExif->GetThumbnailYResolution( uint32Value, exifDenominator );
       
  1044             TUint32 exifThumbYResol = 0;
       
  1045             if ( exifDenominator > 0 )
       
  1046                 {
       
  1047                 exifThumbYResol = uint32Value / exifDenominator;
       
  1048                 }
       
  1049             
       
  1050             if ( exifError != KErrNone || exifThumbYResol != thumbY )
       
  1051                 {
       
  1052                 const TUint32 KDenominator = 1;
       
  1053                 modifyExif->SetThumbnailYResolutionL( thumbY, KDenominator );
       
  1054                 exifChanged = ETrue;
       
  1055                 }
       
  1056             }
       
  1057         }
       
  1058 
       
  1059 	// Set thumbnail resolution unit tag (mandatory)
       
  1060     const CMdEPropertyDef& thumbResolutionUnitDef = imageDef.GetPropertyDefL(
       
  1061         	Image::KThumbResolutionUnitProperty );
       
  1062         {
       
  1063         CMdEProperty* thumbResolutionUnitProp = NULL;            
       
  1064         aMdeObject.Property( thumbResolutionUnitDef, thumbResolutionUnitProp, 0 );
       
  1065 
       
  1066         if ( thumbResolutionUnitProp )
       
  1067             {
       
  1068             exifError = readExif->GetThumbnailResolutionUnit( uint16Value );
       
  1069             const TUint16 thumbnailResolutionUnitValue =
       
  1070              	thumbResolutionUnitProp->Uint16ValueL();
       
  1071             if ( exifError != KErrNone || uint16Value != thumbnailResolutionUnitValue )
       
  1072                 {
       
  1073                 modifyExif->SetThumbnailResolutionUnitL( thumbnailResolutionUnitValue );
       
  1074                 exifChanged = ETrue;
       
  1075                 }
       
  1076             }
       
  1077         }
       
  1078         
       
  1079     if ( exifChanged )
       
  1080         {
       
  1081         WRITELOG( "CHarvesterExifUtil::ComposeExifData() - write exif to buffer" );
       
  1082         aModified = modifyExif->WriteDataL( aImagePtr );
       
  1083         }
       
  1084     CleanupStack::PopAndDestroy( modifyExif );
       
  1085 
       
  1086     WRITELOG1( "CHarvesterExifUtil::ComposeExifData() - Compose End Object ID: %d", aMdeObject.Id() );
       
  1087 
       
  1088 	return KErrNone;
       
  1089 	}
       
  1090 
       
  1091 // ---------------------------------------------------------------------------
       
  1092 // ComposeLocation
       
  1093 // ---------------------------------------------------------------------------
       
  1094 //
       
  1095 EXPORT_C void CHarvesterExifUtil::ComposeLocationL( CMdEObject* aLocation, TPtr8 aImagePtr, HBufC8*& aModified )
       
  1096     {
       
  1097     CMdEProperty* latitudeProperty = NULL;
       
  1098     CMdEProperty* longitudeProperty = NULL;
       
  1099     CMdEProperty* altitudeProperty = NULL;
       
  1100     CMdEProperty* qualityProperty = NULL;
       
  1101     
       
  1102     CMdEObjectDef& locationDef = iDefaultNamespace->GetObjectDefL( Location::KLocationObject );
       
  1103 
       
  1104     aLocation->Property( locationDef.GetPropertyDefL(
       
  1105     		Location::KLatitudeProperty ), latitudeProperty, 0 );
       
  1106     aLocation->Property( locationDef.GetPropertyDefL(
       
  1107     		Location::KLongitudeProperty ), longitudeProperty, 0 );
       
  1108     aLocation->Property( locationDef.GetPropertyDefL(
       
  1109     		Location::KAltitudeProperty ), altitudeProperty, 0 );
       
  1110     aLocation->Property( locationDef.GetPropertyDefL(
       
  1111     		Location::KQualityProperty ), qualityProperty, 0 );
       
  1112 
       
  1113     CExifModify* exifWriter = CExifModify::NewL( aImagePtr, 
       
  1114     		CExifModify::EModify, CExifModify::ENoJpegParsing );
       
  1115     CleanupStack::PushL( exifWriter );
       
  1116     const CExifRead* exifReader = exifWriter->Reader();
       
  1117 
       
  1118     TBool exifChanged = EFalse;
       
  1119     TBool changed = EFalse;
       
  1120     const TReal KAngleSecond = 1.0 / 3600.0;
       
  1121     TInt exifError( 0 );
       
  1122     // location data (all fields are optional)
       
  1123     // latitude
       
  1124     const CExifTag* exifLatitudeRefTag = NULL;
       
  1125     TRAP( exifError, exifLatitudeRefTag = exifReader->GetTagL( EIfdGps, KIdGpsLatitudeRef ) );
       
  1126     if ( latitudeProperty )
       
  1127         {
       
  1128         TBuf8<2> south( KSouth );
       
  1129         TBuf8<2> north( KNorth );
       
  1130         TReal64 latitude = latitudeProperty->Real64ValueL();
       
  1131 
       
  1132         TReal64 exifLatitude( 0.0 );
       
  1133         TBuf8<2> exifLatitudeRef;
       
  1134         if ( exifError == KErrNone )
       
  1135             {
       
  1136             TPtrC8 exifLatitudeRefBuf( exifLatitudeRefTag->Data() );
       
  1137             exifLatitudeRef.Append( exifLatitudeRefBuf.Ptr(), 2 );
       
  1138 
       
  1139             if ( latitude < 0 )
       
  1140                 {
       
  1141                 if ( south.Compare(exifLatitudeRef) )
       
  1142                     {
       
  1143                     changed = ETrue;
       
  1144                     }
       
  1145                 }
       
  1146             else
       
  1147                 {
       
  1148                 if ( north.Compare(exifLatitudeRef) )
       
  1149                     {
       
  1150                     changed = ETrue;
       
  1151                     }
       
  1152                 }
       
  1153 
       
  1154             if ( !changed )
       
  1155                 {
       
  1156                 TBuf8<KCoordinateBufferSize> exifLatitudeBuf;
       
  1157                 const CExifTag* exifLatitudeTag = NULL;
       
  1158                 TRAPD( err, exifLatitudeTag = exifReader->GetTagL( EIfdGps, KIdGpsLatitude ) );
       
  1159                 if ( err == KErrNone )
       
  1160                     {
       
  1161                     TPtrC8 exifLatitudeTagBuf( exifLatitudeTag->Data() );
       
  1162                     exifLatitudeBuf.Append( exifLatitudeTagBuf.Ptr(), KCoordinateBufferSize );
       
  1163                     MdsUtils::ConvertFromDegreesToDecimalL( exifLatitudeBuf, exifLatitude );
       
  1164                     }
       
  1165                 else
       
  1166                     {
       
  1167                     exifError = err;
       
  1168                     }
       
  1169                 }
       
  1170             }
       
  1171 
       
  1172         if ( exifError != KErrNone || changed || Abs(exifLatitude - latitude) > KAngleSecond )
       
  1173             {
       
  1174             // latitude ref (N/S)
       
  1175             if ( latitude < 0 )
       
  1176                 {
       
  1177                 exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1178                 		KIdGpsLatitudeRef, CExifTag::ETagAscii, 2 ), south );
       
  1179                 latitude = -latitude;
       
  1180                 }
       
  1181             else
       
  1182                 {
       
  1183                 exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1184                 		KIdGpsLatitudeRef, CExifTag::ETagAscii, 2 ), north );
       
  1185                 }
       
  1186 
       
  1187             TBuf8<KCoordinateBufferSize> latitudeBuf;
       
  1188             MdsUtils::ConvertFromDecimalToDegreesL( latitude, latitudeBuf );
       
  1189             exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1190             		KIdGpsLatitude, CExifTag::ETagRational, 3 ), latitudeBuf );
       
  1191             exifChanged = ETrue;
       
  1192             }
       
  1193         }
       
  1194     else if ( exifError == KErrNone )
       
  1195         {
       
  1196         exifWriter->DeleteTag( EIfdGps, KIdGpsLatitudeRef );
       
  1197         exifWriter->DeleteTag( EIfdGps, KIdGpsLatitude );
       
  1198         exifChanged = ETrue;
       
  1199         }
       
  1200 
       
  1201     changed = EFalse;
       
  1202     
       
  1203     // longitude
       
  1204     const CExifTag* exifLongitudeRefTag = NULL;
       
  1205     TRAP( exifError, exifLongitudeRefTag = exifReader->GetTagL(
       
  1206     		EIfdGps, KIdGpsLongitudeRef ) );
       
  1207     if ( longitudeProperty )
       
  1208         {
       
  1209         TBuf8<2> west( KWest );
       
  1210         TBuf8<2> east( KEast );        
       
  1211         TReal64 longitude = longitudeProperty->Real64ValueL();
       
  1212         
       
  1213         TReal64 exifLongitude( 0.0 );
       
  1214         TBuf8<2> exifLongitudeRef;
       
  1215         if ( exifError == KErrNone )
       
  1216             {
       
  1217             TPtrC8 exifLongitudeRefBuf( exifLongitudeRefTag->Data() );
       
  1218             exifLongitudeRef.Append( exifLongitudeRefBuf.Ptr(), 2 );
       
  1219 
       
  1220             if ( longitude < 0 )
       
  1221                 {
       
  1222                 if ( west.Compare(exifLongitudeRef) )
       
  1223                     {
       
  1224                     changed = ETrue;
       
  1225                     }
       
  1226                 }
       
  1227             else
       
  1228                 {
       
  1229                 if ( east.Compare(exifLongitudeRef) )
       
  1230                     {
       
  1231                     changed = ETrue;
       
  1232                     }
       
  1233                 }
       
  1234 
       
  1235             if ( !changed )
       
  1236                 {
       
  1237                 TBuf8<KCoordinateBufferSize> exifLongitudeBuf;
       
  1238                 const CExifTag* exifLongitudeTag = NULL;
       
  1239                 TRAPD( err, exifLongitudeTag = exifReader->GetTagL( EIfdGps, KIdGpsLongitude ) );
       
  1240                 if ( err == KErrNone )
       
  1241                     {
       
  1242                     TPtrC8 exifLongitudeTagBuf( exifLongitudeTag->Data() );
       
  1243                     exifLongitudeBuf.Append( exifLongitudeTagBuf.Ptr(), KCoordinateBufferSize );
       
  1244                     MdsUtils::ConvertFromDegreesToDecimalL( exifLongitudeBuf, exifLongitude );
       
  1245                     if ( exifLongitudeRef.Compare( KWest ) == 0 )
       
  1246                         {
       
  1247                         exifLongitude = -exifLongitude;
       
  1248                         }
       
  1249                     }
       
  1250                 else
       
  1251                     {
       
  1252                     exifError = err;
       
  1253                     }
       
  1254                 }
       
  1255             }
       
  1256 
       
  1257         if ( exifError != KErrNone || changed || Abs(exifLongitude - longitude) > KAngleSecond )
       
  1258             {
       
  1259             // longitude ref (E/W)
       
  1260             if ( longitude < 0 )
       
  1261                 {
       
  1262                 exifWriter->SetTagL( EIfdGps,
       
  1263                 		TExifTagInfo( KIdGpsLongitudeRef, CExifTag::ETagAscii, 2 ), west );
       
  1264                 longitude = -longitude;
       
  1265                 }
       
  1266             else
       
  1267                 {
       
  1268                 exifWriter->SetTagL( EIfdGps,
       
  1269                 		TExifTagInfo( KIdGpsLongitudeRef, CExifTag::ETagAscii, 2 ), east );
       
  1270                 }
       
  1271             
       
  1272             TBuf8<KCoordinateBufferSize> longitudeBuf;
       
  1273             MdsUtils::ConvertFromDecimalToDegreesL( longitude, longitudeBuf );
       
  1274             exifWriter->SetTagL( EIfdGps,
       
  1275             		TExifTagInfo( KIdGpsLongitude, CExifTag::ETagRational, 3 ), longitudeBuf );
       
  1276             exifChanged = ETrue;
       
  1277             }
       
  1278         }
       
  1279     else if ( exifError == KErrNone )
       
  1280         {
       
  1281         exifWriter->DeleteTag( EIfdGps, KIdGpsLongitudeRef );
       
  1282         exifWriter->DeleteTag( EIfdGps, KIdGpsLongitude  );
       
  1283         exifChanged = ETrue;
       
  1284         }
       
  1285 
       
  1286     changed = EFalse;
       
  1287     
       
  1288     // altitude
       
  1289     const CExifTag* exifAltitudeRefTag = NULL;
       
  1290     TRAP( exifError, exifAltitudeRefTag = exifReader->GetTagL( EIfdGps, KIdGpsAltitudeRef ) );
       
  1291     if ( altitudeProperty )
       
  1292         {
       
  1293         TReal64 altitude = altitudeProperty->Real64ValueL();
       
  1294 
       
  1295         TBuf8<8> altitudeBuf;
       
  1296         const TInt32 KAltDenominator = 100;
       
  1297         altitude *= KAltDenominator;
       
  1298 
       
  1299         TUint8 altitudeRef = 0;
       
  1300         TBuf8<1> altRefBuf;
       
  1301         
       
  1302         if ( altitude < 0 )
       
  1303             {
       
  1304             altitudeRef = 1;
       
  1305             altitude = -altitude;
       
  1306             }        	
       
  1307         
       
  1308         altRefBuf.Append( &altitudeRef, 1 );
       
  1309 
       
  1310         TInt32 exifAltitudeValue( 0 );
       
  1311         TInt32 exifAltDenominator( 0 );
       
  1312         TReal64 exifAltitude = 0.0f;
       
  1313         TBuf8<1> exifAltitudeRef;
       
  1314         if ( exifError == KErrNone )
       
  1315             {
       
  1316             TPtrC8 exifAltitudeRefBuf( exifAltitudeRefTag->Data() );
       
  1317             exifAltitudeRef.Append( exifAltitudeRefBuf.Ptr(), 1 );
       
  1318             const CExifTag* exifAltitudeTag = NULL;
       
  1319             TRAPD( err, exifAltitudeTag = exifReader->GetTagL( EIfdGps, KIdGpsAltitude ) );
       
  1320             if ( err == KErrNone )
       
  1321                 {
       
  1322                 TPtrC8 exifAltitudeTagBuf( exifAltitudeTag->Data() );
       
  1323                 memcpy( &exifAltitudeValue, exifAltitudeTagBuf.Ptr(),
       
  1324                 		sizeof(exifAltitudeValue) );
       
  1325                 memcpy( &exifAltDenominator,
       
  1326                 		exifAltitudeTagBuf.Ptr()+sizeof(exifAltitudeValue),
       
  1327                 		sizeof(exifAltDenominator) );
       
  1328                 }
       
  1329             else
       
  1330                 {
       
  1331                 exifError = err;
       
  1332                 }
       
  1333             exifAltitude = (TReal64)exifAltitudeValue;
       
  1334             }
       
  1335 
       
  1336         if ( exifError != KErrNone || exifAltitudeRef.Compare(altRefBuf) ||
       
  1337         		Abs(altitude - exifAltitude) > KAngleSecond )
       
  1338             {
       
  1339             exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1340             		KIdGpsAltitudeRef, CExifTag::ETagByte, 1 ), altRefBuf );
       
  1341 
       
  1342             TInt32 tmpAlt = (TInt32) altitude;
       
  1343             altitudeBuf.Append( (TUint8*) &tmpAlt, 4 );
       
  1344             altitudeBuf.Append( (TUint8*) &KAltDenominator, 4 );
       
  1345             exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1346             		KIdGpsAltitude, CExifTag::ETagRational, 1 ), altitudeBuf );
       
  1347             exifChanged = ETrue;
       
  1348 
       
  1349             changed = EFalse;            
       
  1350             }
       
  1351         // measure mode
       
  1352         const CExifTag* exifMeasureModeTag = NULL;
       
  1353         TRAPD( err, exifMeasureModeTag = exifReader->GetTagL( EIfdGps, KIdGpsMeasureMode ) );
       
  1354         if ( err == KErrNone )
       
  1355         	{
       
  1356         	
       
  1357         	TBuf8<2> exifMeasureMode;
       
  1358             TPtrC8 exifMeasureModeBuf( exifMeasureModeTag->Data() );
       
  1359             exifMeasureMode.Append( exifMeasureModeBuf.Ptr(), 2 );
       
  1360         	
       
  1361             if (altitude == 0)
       
  1362             	{
       
  1363             	if (exifMeasureMode.Compare(KMeasureMode3))
       
  1364             		{
       
  1365             		changed = ETrue;
       
  1366             		}
       
  1367             	}
       
  1368             else
       
  1369             	{
       
  1370             	if (exifMeasureMode.Compare(KMeasureMode2))
       
  1371             		{
       
  1372             		changed = ETrue;
       
  1373             		}
       
  1374             	}
       
  1375         	}
       
  1376         else
       
  1377             {
       
  1378             exifError = err;
       
  1379             }
       
  1380         
       
  1381         if (err != KErrNone || changed)
       
  1382         	{
       
  1383         	if (altitude == 0)
       
  1384             	{
       
  1385             	exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1386             		KIdGpsMeasureMode, CExifTag::ETagAscii, 2 ), KMeasureMode2 );
       
  1387             	}
       
  1388         	else
       
  1389         		{
       
  1390         		exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1391                 		KIdGpsMeasureMode, CExifTag::ETagAscii, 2 ), KMeasureMode3 );
       
  1392         		}
       
  1393         	}
       
  1394         }
       
  1395     else if ( exifError == KErrNone )
       
  1396         {
       
  1397         exifWriter->DeleteTag( EIfdGps, KIdGpsAltitudeRef  );
       
  1398         exifWriter->DeleteTag( EIfdGps, KIdGpsAltitude  );
       
  1399         exifWriter->DeleteTag( EIfdGps, KIdGpsMeasureMode  );
       
  1400         exifChanged = ETrue;
       
  1401         } 
       
  1402     
       
  1403     changed = EFalse;
       
  1404     
       
  1405     // quality, DOP value
       
  1406     const CExifTag* exifQualityTag = NULL;
       
  1407     TRAPD( err, exifQualityTag = exifReader->GetTagL( EIfdGps, KIdGpsDop ) );
       
  1408     if (qualityProperty)
       
  1409     	{
       
  1410         CMdEReal32Property* qualityReal = static_cast<CMdEReal32Property*>(qualityProperty);
       
  1411         TReal32 quality = qualityReal->Value();
       
  1412         const TInt32 KQualityDenominator = 10;
       
  1413         TBuf8<8> qualityBuf;
       
  1414         TInt32 exifQualityValue( 0 );
       
  1415         TInt32 exifQualityDenominator( 0 );  
       
  1416         TReal32 exifQuality (0.0f);
       
  1417         quality = quality * KQualityDenominator;
       
  1418         
       
  1419 	    if ( err == KErrNone )
       
  1420 	        {
       
  1421                 TPtrC8 exifQualityTagBuf( exifQualityTag->Data() );
       
  1422                 memcpy( &exifQualityValue, exifQualityTagBuf.Ptr(),
       
  1423                 		sizeof(exifQualityValue) );
       
  1424                 memcpy( &exifQualityDenominator,
       
  1425                 		exifQualityTagBuf.Ptr()+sizeof(exifQualityValue),
       
  1426                 		sizeof(exifQualityDenominator) );
       
  1427 	        }
       
  1428         else
       
  1429             {
       
  1430             exifError = err;
       
  1431             }
       
  1432 	    
       
  1433 	    if (exifQualityDenominator > 0)
       
  1434 	    	{
       
  1435 	    	exifQuality = (TReal32)exifQualityValue;
       
  1436 	    	}
       
  1437 	    
       
  1438 	    if (exifError != KErrNone || Abs(quality - exifQuality) > 0.1f)
       
  1439 	    	{
       
  1440 	    	
       
  1441 	    	TInt32 tmpQuality = (TInt32) quality;
       
  1442 	    	qualityBuf.Append( (TUint8*) &tmpQuality, 4 );
       
  1443 	    	qualityBuf.Append( (TUint8*) &KQualityDenominator, 4 );
       
  1444             exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1445             		KIdGpsDop, CExifTag::ETagRational, 1 ), qualityBuf );
       
  1446             exifChanged = ETrue;	    	
       
  1447 	    	}	    
       
  1448     	}
       
  1449     
       
  1450     const CExifTag* exifDatumTag = NULL;
       
  1451     TRAP( err, exifDatumTag = exifReader->GetTagL( EIfdGps, KIdGpsMapDatum ) );
       
  1452     TBuf8<7> mapdatum( KMapDatum );
       
  1453 
       
  1454     
       
  1455     if ( err == KErrNone )
       
  1456         {        
       
  1457         if (exifDatumTag->Data().Compare(mapdatum))
       
  1458     		{
       
  1459     		changed = ETrue;
       
  1460     		}        	
       
  1461         }
       
  1462     else
       
  1463         {
       
  1464         exifError = err;
       
  1465         }
       
  1466     
       
  1467     if (exifError != KErrNone || changed)
       
  1468     	{        		
       
  1469 		exifWriter->SetTagL( EIfdGps, TExifTagInfo(
       
  1470 			KIdGpsMapDatum, CExifTag::ETagAscii, 7 ), mapdatum );
       
  1471     	}
       
  1472     
       
  1473     // write the EXIF data to the image
       
  1474     if ( exifChanged )
       
  1475         {
       
  1476         aModified = exifWriter->WriteDataL( aImagePtr );
       
  1477         }
       
  1478     CleanupStack::PopAndDestroy( exifWriter );
       
  1479     }
       
  1480 
       
  1481 void CHarvesterExifUtil::ReadUserCommentL( CHarvestData& aHd, CExifRead* aReader )
       
  1482     {
       
  1483     // Getting UserComment
       
  1484     if ( aReader->TagExists(KIdUserComment, EIfdExif ) )
       
  1485         {
       
  1486         TUint16 KMaxCommentLength = 256;
       
  1487         
       
  1488         HBufC8* comment = aReader->GetUserCommentL();
       
  1489         CleanupStack::PushL( comment );
       
  1490         if( comment->Length() >= 8 )
       
  1491             {
       
  1492             TBuf8<8> commentFormat = comment->Mid( 0,8 );
       
  1493             
       
  1494             TUint16 commentLength = comment->Length();
       
  1495             
       
  1496             TPtrC8 userPtr = comment->Mid( 8, commentLength > KMaxCommentLength ?
       
  1497                     KMaxCommentLength - 8 : commentLength - 8 );
       
  1498             
       
  1499             if ( commentFormat.Compare(KUnicodeCodeDesignation) == 0 )
       
  1500                 {
       
  1501                 WRITELOG( "CHarvesterExifUtil::ReadUserCommentL() - comment, Unicode encoding" );
       
  1502                 aHd.iComment16 = HBufC::NewL( userPtr.Length() );
       
  1503                 TPtr ptr = aHd.iComment16->Des();
       
  1504                 TPtrC16 ptr16( (TUint16*)(userPtr.Ptr()), (userPtr.Size()/2) );
       
  1505                 ptr.Copy( ptr16 );
       
  1506                 }
       
  1507             else if ( commentFormat.Compare(KAsciiCodeDesignation) == 0 ||
       
  1508                       commentFormat.Compare(KUnknownCodeDesignation) == 0 ||
       
  1509                       commentFormat.Compare(KJisCodeDesignation) == 0 )
       
  1510                 {
       
  1511                 aHd.iComment16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L( userPtr ); 
       
  1512                 }
       
  1513             else
       
  1514                 {
       
  1515                 WRITELOG( "CHarvesterExifUtil::ReadUserCommentL() - unknown comment encoding" );    
       
  1516                 }
       
  1517             if( aHd.iComment16 )
       
  1518                 {
       
  1519                 StripNulls( *(aHd.iComment16) );
       
  1520                 }
       
  1521             }
       
  1522         CleanupStack::PopAndDestroy( comment );
       
  1523         comment = NULL;
       
  1524         }
       
  1525     }
       
  1526 
       
  1527 void CHarvesterExifUtil::ReadXResolutionL( CHarvestData& aHd, CExifRead* aReader )
       
  1528     {
       
  1529     //Getting X Resolution
       
  1530     TUint32 numerator = 0;
       
  1531     TUint32 denominator = 0;
       
  1532     const TInt error = aReader->GetXResolution( numerator, denominator );
       
  1533     if ( error == KErrNone )
       
  1534         {
       
  1535         aHd.iStoreXResolution = ETrue;
       
  1536         aHd.iXResolution = 0.0f;
       
  1537         if ( denominator > 0 )
       
  1538             {
       
  1539             aHd.iXResolution = (TReal32) numerator / (TReal32) denominator;
       
  1540             }
       
  1541         }
       
  1542     }
       
  1543 
       
  1544 void CHarvesterExifUtil::ReadYResolutionL( CHarvestData& aHd, CExifRead* aReader )
       
  1545     {
       
  1546     //Getting Y Resolution
       
  1547     TUint32 numerator = 0;
       
  1548     TUint32 denominator = 0;
       
  1549     const TInt error = aReader->GetYResolution( numerator, denominator );
       
  1550     if ( error == KErrNone )
       
  1551         {
       
  1552         aHd.iStoreYResolution = ETrue;
       
  1553         aHd.iYResolution = 0.0f;
       
  1554         if ( denominator > 0 )
       
  1555             {
       
  1556             aHd.iYResolution = (TReal32) numerator / (TReal32) denominator;
       
  1557             }
       
  1558         }
       
  1559     }
       
  1560 
       
  1561 void CHarvesterExifUtil::ReadExposureBiasL( CHarvestData& aHd, CExifRead* aReader )
       
  1562     {
       
  1563     // Getting exposure bias
       
  1564     TInt32 num( 0 );
       
  1565     TInt32 deno( 0 );
       
  1566     const TInt error = aReader->GetExposureBiasValue( num, deno );
       
  1567     if ( error == KErrNone )
       
  1568         {
       
  1569         aHd.iStoreExposureBias = ETrue;
       
  1570         aHd.iExposureBias = 0.0f;
       
  1571         if ( deno != 0 )
       
  1572             {
       
  1573             aHd.iExposureBias = (TReal32) num / (TReal32) deno;    
       
  1574             }
       
  1575         }
       
  1576     }
       
  1577 
       
  1578 void CHarvesterExifUtil::ReadExposureTimeL( CHarvestData& aHd, CExifRead* aReader )
       
  1579     {
       
  1580     // Getting exposure time
       
  1581     TUint32 numerator = 0;
       
  1582     TUint32 denominator = 0;
       
  1583     const TInt error = aReader->GetExposureTime( numerator, denominator );
       
  1584     if ( error == KErrNone )
       
  1585         {
       
  1586         aHd.iStoreExposureTime = ETrue;
       
  1587         aHd.iExposureTime = 0.0f;
       
  1588         if ( denominator > 0 )
       
  1589             {
       
  1590             aHd.iExposureTime = (TReal32) numerator / (TReal32) denominator;
       
  1591             }
       
  1592         }
       
  1593     }
       
  1594 
       
  1595 void CHarvesterExifUtil::ReadFNumberL( CHarvestData& aHd, CExifRead* aReader )
       
  1596     {
       
  1597     //Getting FNumber
       
  1598     if ( aReader->TagExists(KIdFNumber, EIfdExif) )
       
  1599         {
       
  1600         const CExifTag* tag = aReader->GetTagL( EIfdExif, KIdFNumber );
       
  1601         TPtrC8 tagData = tag->Data();
       
  1602         
       
  1603         TUint32 numerator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
  1604         TUint32 denominator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() + 4 ) );
       
  1605         if ( denominator == 0 )
       
  1606             {
       
  1607             denominator = 1;
       
  1608             }
       
  1609         
       
  1610         aHd.iFNumber = (TReal32) numerator / (TReal32) denominator;
       
  1611         aHd.iStoreFNumber = ETrue;
       
  1612         WRITELOG1( "CHarvesterExifUtil::ReadFNumberL() - fnumber %f", aHd.iFNumber );
       
  1613         }
       
  1614     }
       
  1615 
       
  1616 void CHarvesterExifUtil::ReadShutterSpeedL( CHarvestData& aHd, CExifRead* aReader )
       
  1617     {
       
  1618     //Getting shutter speed value
       
  1619     TInt32 num( 0 );
       
  1620     TInt32 deno( 0 );
       
  1621     const TInt error = aReader->GetShutterSpeedValue( num, deno );
       
  1622     if ( error == KErrNone )
       
  1623         {
       
  1624         aHd.iStoreShutterSpeed = ETrue;
       
  1625         aHd.iShutterSpeed = 0.0f;
       
  1626         if ( deno != 0 )
       
  1627             {
       
  1628             aHd.iShutterSpeed = (TReal32) num / (TReal32) deno;
       
  1629             }
       
  1630         
       
  1631         WRITELOG1( "CHarvesterExifUtil::ReadExifDataL() - shutter speed %f", aHd.iShutterSpeed );
       
  1632         }
       
  1633     }
       
  1634 
       
  1635 void CHarvesterExifUtil::ReadApertureValueL( CHarvestData& aHd, CExifRead* aReader )
       
  1636     {
       
  1637     //Getting aHd.iAperture
       
  1638     TUint32 numerator = 0;
       
  1639     TUint32 denominator = 0;
       
  1640     const TInt error = aReader->GetApertureValue( numerator, denominator );
       
  1641     if ( error == KErrNone )
       
  1642         {
       
  1643         aHd.iStoreAperture = ETrue;
       
  1644         aHd.iAperture = 0.0f;
       
  1645         if ( denominator > 0 )
       
  1646             {
       
  1647             aHd.iAperture = (TReal32) numerator / (TReal32) denominator;
       
  1648             }
       
  1649       
       
  1650         WRITELOG1( "CHarvesterExifUtil::ReadExifDataL() - aHd.iAperture %f", aHd.iAperture );
       
  1651         }
       
  1652     }
       
  1653 
       
  1654 void CHarvesterExifUtil::ReadFocalLengthL( CHarvestData& aHd, CExifRead* aReader )
       
  1655     {
       
  1656     //Getting focal length
       
  1657     TUint32 numerator = 0;
       
  1658     TUint32 denominator = 0;
       
  1659     if ( aReader->TagExists(KIdFocalLength, EIfdExif) )
       
  1660         {                
       
  1661         const CExifTag* tag = aReader->GetTagL( EIfdExif, KIdFocalLength );
       
  1662         TPtrC8 tagData = tag->Data();
       
  1663         
       
  1664         numerator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
  1665         denominator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() + 4 ) );
       
  1666         
       
  1667         if ( denominator == 0 )
       
  1668             {
       
  1669             denominator = 1;
       
  1670             }
       
  1671         
       
  1672         aHd.iFocalLength = (TReal32) numerator / (TReal32) denominator;
       
  1673         aHd.iStoreFocalLength = ETrue;
       
  1674         
       
  1675         WRITELOG1( "CHarvesterExifUtil::ReadExifDataL() - focal length %f", aHd.iFocalLength );
       
  1676         }
       
  1677     }
       
  1678 
       
  1679 void CHarvesterExifUtil::ReadFocalLength35mmL( CHarvestData& aHd, CExifRead* aReader )
       
  1680     {
       
  1681     // Getting focal length in 35 mm
       
  1682     if ( aReader->TagExists(KIdFocalLengthIn35mm, EIfdExif) )
       
  1683         {
       
  1684         const CExifTag* tag = aReader->GetTagL( EIfdExif, KIdFocalLengthIn35mm );
       
  1685         TPtrC8 tagData = tag->Data();
       
  1686         
       
  1687         aHd.iFocalLengthIn35mm = MdsUtils::ToUInt16L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
  1688         
       
  1689         aHd.iStoreFocalLengthIn35 = ETrue;
       
  1690         
       
  1691         WRITELOG1( "CHarvesterExifUtil::ReadExifDataL() - focal length in 35 mm: %f", aHd.iFocalLengthIn35mm );
       
  1692         }
       
  1693     }
       
  1694 
       
  1695 void CHarvesterExifUtil::ReadFocalXPlaneResolutionL( CHarvestData& aHd, CExifRead* aReader )
       
  1696     {
       
  1697     // Getting focal plane X resolution
       
  1698     if ( aReader->TagExists(KIdFocalPlaneXResolution, EIfdExif) )
       
  1699         {
       
  1700         const CExifTag* tag = aReader->GetTagL(
       
  1701                 EIfdExif, KIdFocalPlaneXResolution );
       
  1702         TPtrC8 tagData = tag->Data();
       
  1703         
       
  1704         TUint32 numerator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
  1705         TUint32 denominator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() + 4 ) );
       
  1706         if ( denominator == 0 )
       
  1707             {
       
  1708             denominator = 1;
       
  1709             }
       
  1710         
       
  1711         aHd.iFocalPlaneXResolution = (TReal32) numerator / (TReal32) denominator;
       
  1712         aHd.iStoreFocalPlaneXResolution = ETrue;
       
  1713         }
       
  1714     }
       
  1715 
       
  1716 void CHarvesterExifUtil::ReadFocalYPlaneResolutionL( CHarvestData& aHd, CExifRead* aReader )
       
  1717     {
       
  1718     // Getting focal plane Y resolution
       
  1719     if ( aReader->TagExists(KIdFocalPlaneYResolution, EIfdExif) )
       
  1720         {
       
  1721         const CExifTag* tag = aReader->GetTagL(
       
  1722                 EIfdExif, KIdFocalPlaneYResolution );
       
  1723         TPtrC8 tagData = tag->Data();
       
  1724         
       
  1725         TUint32 numerator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() ) );
       
  1726         TUint32 denominator = MdsUtils::ToUInt32L( CONST_CAST( TUint8*, tagData.Ptr() + 4 ) );
       
  1727         if ( denominator == 0 )
       
  1728             {
       
  1729             denominator = 1;
       
  1730             }
       
  1731         
       
  1732         aHd.iFocalPlaneYResolution = (TReal32) numerator / (TReal32) denominator;
       
  1733         aHd.iStoreFocalPlaneYResolution = ETrue;
       
  1734         }
       
  1735     }
       
  1736 
       
  1737 void CHarvesterExifUtil::ReadGPSLatitudeL( CHarvestData& aHd, 
       
  1738                                                                        CExifRead* aReader, 
       
  1739                                                                        TBool& aLatitude )
       
  1740     {
       
  1741     const TInt KCoordinateBufferSize = 24;
       
  1742     
       
  1743     WRITELOG( "CHarvesterExifUtil::ReadGPSLatitudeL() - trying to read GPS Latitude" );
       
  1744     
       
  1745     // Getting GPS latitude   
       
  1746     if ( aReader->TagExists(KIdGpsLatitudeRef, EIfdGps) &&
       
  1747             aReader->TagExists(KIdGpsLatitude, EIfdGps) )
       
  1748         {
       
  1749         WRITELOG( "CHarvesterExifUtil::ReadGPSLatitudeL() - GPS Latitude found" );
       
  1750         
       
  1751         TReal64 latitude = 0.0;
       
  1752         const CExifTag* refTag = aReader->GetTagL(
       
  1753                 EIfdGps, KIdGpsLatitudeRef );
       
  1754         TBuf8<2> latitudeRef = refTag->Data();
       
  1755         const CExifTag* latitudeTag = aReader->GetTagL(
       
  1756                 EIfdGps, KIdGpsLatitude );
       
  1757         TBuf8<KCoordinateBufferSize> latitudeBuf = latitudeTag->Data();
       
  1758         MdsUtils::ConvertFromDegreesToDecimalL( latitudeBuf, latitude );
       
  1759         if ( latitudeRef == KSouth )
       
  1760             {
       
  1761             latitude = -latitude;
       
  1762             }
       
  1763         aHd.iGpsLatitude = latitude;
       
  1764         aLatitude = ETrue;
       
  1765         }
       
  1766     
       
  1767     WRITELOG( "CHarvesterExifUtil::ReadGPSLatitudeL() - trying to read GPS Latitude - end" );
       
  1768     }
       
  1769 
       
  1770 void CHarvesterExifUtil::ReadGPSLongitudeL( CHarvestData& aHd, 
       
  1771                                                                           CExifRead* aReader, 
       
  1772                                                                           TBool& aLatitude )
       
  1773     {
       
  1774     const TInt KCoordinateBufferSize = 24;
       
  1775     
       
  1776     WRITELOG( "CHarvesterExifUtil::ReadGPSLongitudeL() - trying to read GPS Longitude" );
       
  1777     
       
  1778     // Getting GPS longitude
       
  1779     if ( aReader->TagExists(KIdGpsLongitudeRef, EIfdGps) &&
       
  1780             aReader->TagExists(KIdGpsLongitude, EIfdGps) )
       
  1781         {
       
  1782         WRITELOG( "CHarvesterExifUtil::ReadGPSLatitudeL() - GPS Longitude found" );
       
  1783     
       
  1784         TReal64 longitude = 0.0;
       
  1785         const CExifTag* refTag = aReader->GetTagL(
       
  1786                 EIfdGps, KIdGpsLongitudeRef );
       
  1787         TBuf8<2> longitudeRef = refTag->Data();
       
  1788         const CExifTag* longitudeTag = aReader->GetTagL(
       
  1789                 EIfdGps, KIdGpsLongitude );
       
  1790         TBuf8<KCoordinateBufferSize> longitudeBuf = longitudeTag->Data();
       
  1791         MdsUtils::ConvertFromDegreesToDecimalL( longitudeBuf, longitude );
       
  1792         if ( longitudeRef == KWest )
       
  1793             {
       
  1794             longitude = -longitude;
       
  1795             }
       
  1796         aHd.iGpsLongitude = longitude;
       
  1797         if ( aLatitude )
       
  1798             {
       
  1799             aHd.iStoreGpsLatitudeAndLongitude = ETrue;
       
  1800             }
       
  1801         }
       
  1802     
       
  1803     WRITELOG( "CHarvesterExifUtil::ReadGPSLongitudeL() - trying to read GPS Longitude - end" );
       
  1804     }
       
  1805 
       
  1806 void CHarvesterExifUtil::ReadGPSAltitudeL( CHarvestData& aHd, CExifRead* aReader )
       
  1807     {
       
  1808     const TInt KAltitudeBufferSize = 8;
       
  1809     
       
  1810     WRITELOG( "CHarvesterExifUtil::ReadGPSLongitudeL() - trying to read GPS Altitude" );
       
  1811     
       
  1812     // Getting GPS altitude
       
  1813     if ( aReader->TagExists(KIdGpsAltitudeRef, EIfdGps) &&
       
  1814             aReader->TagExists(KIdGpsAltitude, EIfdGps) )
       
  1815         {
       
  1816         WRITELOG( "CHarvesterExifUtil::ReadGPSLatitudeL() - GPS Altitude found" );
       
  1817     
       
  1818         const CExifTag* refTag = aReader->GetTagL(
       
  1819                 EIfdGps, KIdGpsAltitudeRef );
       
  1820         TBuf8<1> altitudeRef = refTag->Data();
       
  1821         const CExifTag* altitudeTag = aReader->GetTagL(
       
  1822                 EIfdGps, KIdGpsAltitude );
       
  1823         TBuf8<KAltitudeBufferSize> altitudeBuf = altitudeTag->Data();
       
  1824         TInt32 altitude = MdsUtils::ToUInt32L(
       
  1825                 CONST_CAST( TUint8*, altitudeBuf.Left(4).Ptr() ) );
       
  1826         TInt32 denominator =  MdsUtils::ToUInt32L(
       
  1827                 CONST_CAST( TUint8*, altitudeBuf.Right(4).Ptr() ) );
       
  1828         TInt8 ref = *((TUint8*) altitudeRef.Ptr());
       
  1829 
       
  1830         if ( ref == 1 )
       
  1831             {
       
  1832             altitude = -altitude;
       
  1833             }
       
  1834 
       
  1835         aHd.iGpsAltitude = 0.0f;
       
  1836         if ( denominator != 0 )
       
  1837             {
       
  1838             aHd.iGpsAltitude = (TReal64)altitude / (TReal64)denominator;
       
  1839             }
       
  1840 
       
  1841         aHd.iStoreGpsAltitude = ETrue;
       
  1842         }
       
  1843     
       
  1844     WRITELOG( "CHarvesterExifUtil::ReadGPSLongitudeL() - trying to read GPS Altitude - end" );
       
  1845     }
       
  1846 
       
  1847 // End of file