harvester/harvesterplugins/ImagePlugin/src/harvesterimageplugin.cpp
changeset 0 c53acadfccc6
child 1 acef663c1218
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harvester/harvesterplugins/ImagePlugin/src/harvesterimageplugin.cpp	Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,954 @@
+/*
+* Copyright (c) 2006-2009 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:  Harvester image plugin
+*
+*/
+
+
+#include <e32base.h>
+#include <e32math.h>
+#include <locationdatatype.h>
+#include <harvesterdata.h>
+
+#include "harvesterlog.h"
+#include "mdsutils.h"
+#include "harvesterexifutil.h"
+#include "harvesterimageplugin.h"
+#include "mdeobjectwrapper.h"
+
+using namespace MdeConstants;
+
+// image mime types
+_LIT( KJpegMime, "image/jpeg" );
+_LIT( KJpeg2000Mime, "image/jp2" );
+_LIT( KJpeg2000_2Mime, "image/jpx" );
+_LIT( KTiffMime, "image/tiff" );
+_LIT( KMsmMime, "application/x-msmetafile" );
+_LIT( KGifMime, "image/gif" );
+_LIT( KXbmpMime, "image/x-bmp" );
+_LIT( KBmpMime, "image/bmp" );
+_LIT( KPngMime, "image/png" );
+_LIT( KMbmMime, "image/x-epoc-mbm" );
+_LIT( KOtaMime, "image/vnd.nokia.ota-bitmap" );
+_LIT( KXotaMime, "image/x-ota-bitmap" );
+_LIT( KWbmpMime, "image/vnd.wap.wbmp" );
+_LIT( KWmfMime, "image/x-wmf" );
+_LIT( KOtbMime, "image/vnd.nokia.ota-bitmap" );
+
+_LIT( KExtJpg, "JPG" );
+_LIT( KExtJpeg, "JPEG" );
+_LIT( KExtJp2, "JP2" );
+_LIT( KExtJ2k, "J2K" ); 
+_LIT( KExtJpx, "JPX" ); 
+_LIT( KExtJpf, "JPF" );
+_LIT( KExtMbm, "MBM" ); 
+_LIT( KExtPng, "PNG" );
+_LIT( KExtGif, "GIF" );
+_LIT( KExtBmp, "BMP" );
+_LIT( KExtTif, "TIF" );
+_LIT( KExtTiff, "TIFF" );
+_LIT( KExtOta, "OTA" );
+_LIT( KExtWbmp, "WBMP" );
+_LIT( KExtWmf, "WMF" ); 
+_LIT( KExtOtb, "OTB" ); 
+
+#ifdef MDS_MULTIPLE_STAGE_IMAGE_PROCESSING
+const TUid KBGPSUid = { 0x0ADC2480 };
+#endif
+
+CHarvesterImagePluginPropertyDefs::CHarvesterImagePluginPropertyDefs() : CBase()
+	{
+	}
+
+void CHarvesterImagePluginPropertyDefs::ConstructL(CMdEObjectDef& aObjectDef)
+	{
+	CMdENamespaceDef& nsDef = aObjectDef.NamespaceDef();
+
+	// Image property definitions
+	CMdEObjectDef& objectDef = nsDef.GetObjectDefL( Object::KBaseObject );
+	iCreationDatePropertyDef = &objectDef.GetPropertyDefL( Object::KCreationDateProperty );
+	iLastModifiedDatePropertyDef = &objectDef.GetPropertyDefL( Object::KLastModifiedDateProperty );
+	iSizePropertyDef = &objectDef.GetPropertyDefL( Object::KSizeProperty );
+	iTimeOffsetPropertyDef = &objectDef.GetPropertyDefL( Object::KTimeOffsetProperty );
+	iItemTypePropertyDef = &objectDef.GetPropertyDefL( Object::KItemTypeProperty );
+
+	// Media property definitions
+	CMdEObjectDef& mediaDef = nsDef.GetObjectDefL( MediaObject::KMediaObject );
+	iWidthPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KWidthProperty );
+	iHeightPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KHeightProperty );
+	iDescriptionPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KDescriptionProperty );
+	iCommentPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KCommentProperty );
+	iReleaseDatePropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KReleaseDateProperty );
+	iCopyrightPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KCopyrightProperty );
+	iCaptureDatePropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KCaptureDateProperty );
+	iResolutionUnitPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KResolutionUnitProperty );
+	iArtistPropertyDef = &mediaDef.GetPropertyDefL( MediaObject::KArtistProperty );
+
+	// Image property definitions
+	CMdEObjectDef& imageDef = nsDef.GetObjectDefL( Image::KImageObject );
+	iPixelYDimensionPropertyDef = &imageDef.GetPropertyDefL( Image::KPixelYDimensionProperty );
+	iPixelXDimensionPropertyDef = &imageDef.GetPropertyDefL( Image::KPixelXDimensionProperty );
+	iBitsPerSamplePropertyDef = &imageDef.GetPropertyDefL( Image::KBitsPerSampleProperty );
+	iFrameCountPropertyDef = &imageDef.GetPropertyDefL( Image::KFrameCountProperty );
+	iDateTimeOriginalPropertyDef = &imageDef.GetPropertyDefL( Image::KDateTimeOriginalProperty );
+	iDateTimeDigitizedPropertyDef = &imageDef.GetPropertyDefL( Image::KDateTimeDigitizedProperty );
+	iDateTimePropertyDef = &imageDef.GetPropertyDefL( Image::KDateTimeProperty );
+	iWhiteBalancePropertyDef = &imageDef.GetPropertyDefL( Image::KWhiteBalanceProperty );
+	iFlashPropertyDef = &imageDef.GetPropertyDefL( Image::KFlashProperty );
+	iExposureProgramPropertyDef = &imageDef.GetPropertyDefL( Image::KExposureProgramProperty );
+	iMakePropertyDef = &imageDef.GetPropertyDefL( Image::KMakeProperty );
+	iModelPropertyDef = &imageDef.GetPropertyDefL( Image::KModelProperty );
+	iOrientationPropertyDef = &imageDef.GetPropertyDefL( Image::KOrientationProperty );
+	iXResolutionPropertyDef = &imageDef.GetPropertyDefL( Image::KXResolutionProperty );
+	iYResolutionPropertyDef = &imageDef.GetPropertyDefL( Image::KYResolutionProperty );
+	iYCbCrPositioningPropertyDef = &imageDef.GetPropertyDefL( Image::KYCbCrPositioningProperty );
+	iExposureTimePropertyDef = &imageDef.GetPropertyDefL( Image::KExposureTimeProperty );
+	iFNumberPropertyDef = &imageDef.GetPropertyDefL( Image::KFNumberProperty );
+	iExifVersionPropertyDef = &imageDef.GetPropertyDefL( Image::KExifVersionProperty );
+	iShutterSpeedValuePropertyDef = &imageDef.GetPropertyDefL( Image::KShutterSpeedValueProperty );
+	iApertureValuePropertyDef = &imageDef.GetPropertyDefL( Image::KApertureValueProperty );
+	iFocalLengthPropertyDef = &imageDef.GetPropertyDefL( Image::KFocalLengthProperty );
+	iFlashPixVersionPropertyDef = &imageDef.GetPropertyDefL( Image::KFlashPixVersionProperty );
+	iColourSpacePropertyDef = &imageDef.GetPropertyDefL( Image::KColourSpaceProperty );
+	iISOSpeedRatingsPropertyDef = &imageDef.GetPropertyDefL( Image::KISOSpeedRatingsProperty );
+	iComponentsConfigurationPropertyDef = &imageDef.GetPropertyDefL( Image::KComponentsConfigurationProperty );
+	iExposureBiasValuePropertyDef = &imageDef.GetPropertyDefL( Image::KExposureBiasValueProperty );
+	iSamplesPerPixelPropertyDef = &imageDef.GetPropertyDefL( Image::KSamplesPerPixelProperty );
+	iThumbCompressionPropertyDef = &imageDef.GetPropertyDefL( Image::KThumbCompressionProperty );
+	iThumbXResolutionPropertyDef = &imageDef.GetPropertyDefL( Image::KThumbXResolutionProperty );
+	iThumbYResolutionPropertyDef = &imageDef.GetPropertyDefL( Image::KThumbYResolutionProperty );
+	iThumbResolutionUnitPropertyDef = &imageDef.GetPropertyDefL( Image::KThumbResolutionUnitProperty );
+	iFocalLengthIn35mmFilmPropertyDef = &imageDef.GetPropertyDefL( Image::KFocalLengthIn35mmFilmProperty );
+	iMeteringModePropertyDef = &imageDef.GetPropertyDefL( Image::KMeteringModeProperty );
+	iRelatedSoundFilePropertyDef = &imageDef.GetPropertyDefL( Image::KRelatedSoundFileProperty );
+	iFocalPlaneResolutionUnitPropertyDef = &imageDef.GetPropertyDefL( Image::KFocalPlaneResolutionUnitProperty );
+	iFocalPlaneXResolutionPropertyDef = &imageDef.GetPropertyDefL( Image::KFocalPlaneXResolutionProperty );
+	iFocalPlaneYResolutionPropertyDef = &imageDef.GetPropertyDefL( Image::KFocalPlaneYResolutionProperty );
+	iDraftPropertyDef = &imageDef.GetPropertyDefL( Image::KDraftProperty );
+	}
+
+CHarvesterImagePluginPropertyDefs* CHarvesterImagePluginPropertyDefs::NewL(CMdEObjectDef& aObjectDef)
+	{
+	CHarvesterImagePluginPropertyDefs* self = 
+		new (ELeave) CHarvesterImagePluginPropertyDefs();
+	CleanupStack::PushL( self );
+	self->ConstructL( aObjectDef );
+	CleanupStack::Pop( self );
+	return self;
+	}
+
+/**
+* Default constructor
+*/
+CHarvesterImagePlugin::CHarvesterImagePlugin() : CHarvesterPlugin(),
+    iExifUtil( NULL ), iDecoder( NULL ), iPropDefs( NULL )
+	{
+	}
+
+/**
+* Construction
+* @return Harvester image plugin
+*/
+CHarvesterImagePlugin* CHarvesterImagePlugin::NewL()
+	{
+	WRITELOG( "CHarvesterImagePlugin::NewL()" );
+	CHarvesterImagePlugin* self = new (ELeave) CHarvesterImagePlugin();
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	
+	return self;
+	}
+
+/**
+* Destruction
+*/
+CHarvesterImagePlugin::~CHarvesterImagePlugin()
+	{
+	WRITELOG( "CHarvesterImagePlugin::~CHarvesterImagePlugin()" );
+	
+	if (iDecoder)
+		{
+		iDecoder->Reset();
+	    delete iDecoder;
+		}   
+    
+    if (iExifUtil)
+		{
+		delete iExifUtil;
+		}
+   	
+    delete iPropDefs;
+    
+    iFbs.Disconnect();
+	}
+
+/**
+* 2nd phase constructor
+*/
+void CHarvesterImagePlugin::ConstructL()
+	{
+	WRITELOG( "CHarvesterImagePlugin::ConstructL()" );
+	iDecoder = CBufferedImageDecoder::NewL( iFs );
+	iExifUtil = CHarvesterExifUtil::NewL();
+    User::LeaveIfError( iFbs.Connect() );
+
+    TLinearOrder< TMimeTypeMapping<TImageMetadataHandling> > cmp(
+    		TMimeTypeMapping<TImageMetadataHandling>::CompareFunction);
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtJpg(), KJpegMime(), EJpegHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtJpeg(), KJpegMime(), EJpegHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtGif(), KGifMime(), EGifHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtBmp(), KBmpMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtJpf(), KJpeg2000_2Mime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtJpx(), KJpeg2000_2Mime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtJp2(), KJpeg2000Mime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtJ2k(), KJpeg2000Mime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtMbm(), KMbmMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtOta(), KOtaMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtPng(), KPngMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtTif(), KTiffMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtTiff(), KTiffMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtWbmp(), KWbmpMime(), EOtherHandling ), cmp ) );
+
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+    		KExtWmf(), KWmfMime(), EOtherHandling ), cmp ) );
+    
+    User::LeaveIfError( iMimeTypeMappings.InsertInOrder( TMimeTypeMapping<TImageMetadataHandling>(
+            KExtOtb(), KOtbMime(), EOtherHandling ), cmp ) );
+	}
+
+void CHarvesterImagePlugin::HarvestL( CHarvesterData* aHD )
+	{
+	WRITELOG( "CHarvesterImagePlugin::HarvestL()" );
+    CMdEObject& mdeObject = aHD->MdeObject();
+
+    CFileData* fileData = CFileData::NewL();
+    CleanupStack::PushL( fileData );
+    CHarvestData* harvestData = CHarvestData::NewL();
+    CleanupStack::PushL( harvestData );
+        
+    const TInt errorCode = GatherDataL( mdeObject, *fileData, *harvestData );
+    if ( errorCode == KErrNone || errorCode == KErrCompletion ) // ok, something got harvested
+        {
+        if ( mdeObject.Id() == 0 || mdeObject.Placeholder() ) // is a new object or placeholder
+            {
+            TRAP_IGNORE( HandleObjectPropertiesL( *harvestData, *fileData, *aHD, ETrue ) );
+            }
+        else   // not a new object
+            {
+            TRAP_IGNORE( HandleObjectPropertiesL( *harvestData, *fileData, *aHD, EFalse ) );
+            }
+        
+        if( harvestData->iStoreGpsLatitudeAndLongitude ||
+        	harvestData->iStoreGpsAltitude )
+        	{
+        	TLocationData* locData = new (ELeave) TLocationData();
+
+        	if( harvestData->iStoreGpsAltitude )
+        		{
+        		locData->iPosition.SetCoordinate( 
+        				harvestData->iGpsLatitude, harvestData->iGpsLongitude, 
+        				harvestData->iGpsAltitude);
+        		}
+        	else
+        		{
+        		locData->iPosition.SetCoordinate( 
+        				harvestData->iGpsLatitude, harvestData->iGpsLongitude);
+        		}
+
+        	// remove unnessesary values
+        	locData->iNetworkInfo.iAreaKnown = EFalse;
+        	
+        	TRealX nanX;
+        	nanX.SetNaN();
+        	nanX.GetTReal( locData->iQuality );
+        	
+        	aHD->SetLocationData( locData );
+        	}
+        }
+    else
+        {
+        WRITELOG1( "CHarvesterImagePlugin::HarvestL() - other error: %d", errorCode );
+        TInt convertedError = KErrNone;
+        MdsUtils::ConvertTrapError( errorCode, convertedError );
+        aHD->SetErrorCode( convertedError );
+        WRITELOG1( "CHarvesterImagePlugin::HarvestL() - returning: %d", convertedError );
+        }
+
+    // Delete image data.
+    CleanupStack::PopAndDestroy( 2, fileData );
+	}
+
+// ---------------------------------------------------------------------------
+// GatherData
+// ---------------------------------------------------------------------------
+//    
+TInt CHarvesterImagePlugin::GatherDataL( CMdEObject& aMetadataObject,
+    CFileData& aFileData, CHarvestData& aHarvestData )
+    {
+#ifdef _DEBUG
+    TTime dStart, dStop;
+    dStart.UniversalTime();
+    dStop.UniversalTime();
+    WRITELOG1( "CHarvesterImagePlugin::GatherData() start %d us", (TInt)dStop.MicroSecondsFrom(dStart).Int64() );
+#endif
+    
+    WRITELOG( "CHarvesterImagePlugin::GatherData()" );
+
+    TBool dataExtracted( aMetadataObject.Id() == 0 || aMetadataObject.Placeholder() );
+    aFileData.iImageDef = &aMetadataObject.Def();
+    
+    if( dataExtracted )
+        {
+        CMdEProperty* prop = NULL;
+        CMdEObjectDef& objectDef = *aFileData.iImageDef;
+        
+        if( !iPropDefs )
+        	{
+        	iPropDefs = CHarvesterImagePluginPropertyDefs::NewL( objectDef );
+        	}
+        
+        aMetadataObject.Property( *iPropDefs->iSizePropertyDef, prop );
+        if( prop )
+            {
+            aFileData.iFileSize  = prop->Uint32ValueL();
+            }
+        else
+            {
+            dataExtracted = EFalse;
+            }
+
+        aMetadataObject.Property( *iPropDefs->iLastModifiedDatePropertyDef, prop );
+        if( prop )
+            {
+            aFileData.iModified  = prop->TimeValueL();
+            }
+        else
+            {
+            dataExtracted = EFalse;
+            }
+        }
+
+    const TDesC& uri = aMetadataObject.Uri();
+    
+    if( !dataExtracted )
+        {
+        TEntry entry;
+        const TInt errorcode = iFs.Entry( uri, entry );
+        
+        if ( errorcode != KErrNone )
+            {
+            return errorcode; // metadata cannot be gathered!
+            }
+        
+        aFileData.iModified = entry.iModified;
+        aFileData.iFileSize = (TUint)entry.iSize;
+        }
+
+    TPtrC imageFile = uri;
+
+    aFileData.iUri = &imageFile;
+    aFileData.iFrameCount = 1;
+
+    TRAPD( readError, DataFromImageFileL( aFileData ) );
+
+    if ( readError != KErrNone )
+        {
+        WRITELOG1( "CHarvesterImagePlugin::GatherData() - error reading image data, error: %d", readError );
+        return KErrCompletion; // metadata item still can be created, thus KErrCompletion
+        }
+
+    TInt err = KErrNone;
+    if ( aFileData.iExifSupported )
+        {
+        TRAP( err, iExifUtil->ReadExifDataL( aHarvestData, aFileData ) );
+        }
+    if( !aFileData.iExifSupported || err != KErrNone )
+        {
+        // Exif couldn't be found. Open the image with ICL decoder instead.
+        WRITELOG( "CHarvesterImagePlugin::GatherData() - Exif could not be read. Using ICL." );
+
+        iDecoder->Reset();
+
+        TPtr8 imageDataPtr = aFileData.iImageData->Des();
+        TRAP( err, iDecoder->OpenL(imageDataPtr, aFileData.iMime8,
+                CImageDecoder::TOptions( CImageDecoder::EPreferFastDecode | CImageDecoder::EOptionIgnoreExifMetaData ) ) );
+        WRITELOG( "CHarvesterImagePlugin::GatherData() - Image decoder has opened the file." );
+
+        if ( err != KErrNone )
+            {
+            WRITELOG1( "CHarvesterImagePlugin::GatherData() - ERROR: Decoder could not open image data! Code %d", err );
+            return KErrCompletion; // metadata item still can be created, thus KErrCompletion
+            }
+
+        if ( !iDecoder->ValidDecoder() )
+        	{
+        	// read all remaining data from file
+        	TInt64 additionalDataSize = aFileData.iFileSize - aFileData.iImageDataSize;
+        	if( additionalDataSize < 0 )
+        	    {
+        	    additionalDataSize = 0;
+        	    }
+ 
+            HBufC8* additionalData = HBufC8::NewLC( additionalDataSize );
+			if ( additionalData )
+				{
+				TPtr8 addPtr = additionalData->Des();
+				TInt readStatus = iFs.ReadFileSection(
+						*aFileData.iUri, aFileData.iImageDataSize, addPtr, additionalDataSize );
+				if ( readStatus != KErrNone )
+					{
+					CleanupStack::PopAndDestroy( additionalData );
+					return KErrCompletion;
+					}
+				
+				// append all remaining data to image decoder
+				TRAP( err, iDecoder->AppendDataL( addPtr ) );
+				if ( err == KErrNone )
+					{
+					TRAP( err, iDecoder->ContinueOpenL() );
+					}
+				CleanupStack::PopAndDestroy( additionalData );
+				}
+
+            if ( err || !iDecoder->ValidDecoder() )
+            	{
+            	WRITELOG( "CHarvesterImagePlugin::GatherData() - ERROR: no valid decoder" );
+            	return KErrCompletion; // metadata item still can be created, thus KErrCompletion
+            	}
+            }
+
+        // Get image width, frame count, height and bits per pixel from image decoder.
+        const TFrameInfo info = iDecoder->FrameInfo( 0 );
+        const TSize imageSize = info.iOverallSizeInPixels;
+        const TInt framecount = iDecoder->FrameCount();
+        aFileData.iFrameCount = framecount;
+        aFileData.iImageWidth = imageSize.iWidth;
+        aFileData.iImageHeight = imageSize.iHeight;
+        aFileData.iBitsPerPixel = info.iBitsPerPixel;
+        }
+
+    WRITELOG( "CHarvesterImagePlugin::GatherData() - end" );
+
+#ifdef _DEBUG
+    dStop.UniversalTime();
+    WRITELOG1( "CHarvesterImagePlugin::GatherData() end %d us", (TInt)dStop.MicroSecondsFrom(dStart).Int64() );
+#endif   
+
+    return KErrNone;
+    }
+
+///---------------------------------------------------------------------------
+/// DataFromImageFile
+///---------------------------------------------------------------------------
+void CHarvesterImagePlugin::DataFromImageFileL( CFileData& aFileData )
+    {
+    WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL()" );
+    
+    TPtrC ext;
+    if( !MdsUtils::GetExt( *aFileData.iUri, ext ) )
+    	{
+    	User::Leave( KErrNotSupported );
+    	}
+
+	TMimeTypeMapping<TImageMetadataHandling> finder(ext);
+	TLinearOrder< TMimeTypeMapping<TImageMetadataHandling> > cmp(
+			TMimeTypeMapping<TImageMetadataHandling>::CompareFunction);
+
+	TInt pos = iMimeTypeMappings.FindInOrder( finder, cmp );
+
+	TImageMetadataHandling handler( EOtherHandling ); 
+
+	if ( pos != KErrNotFound )
+		{
+		handler = iMimeTypeMappings[pos].iHandler;
+		}
+
+    switch( handler )
+    	{
+    	case EJpegHandling:
+			{
+			aFileData.iJpeg = ETrue;
+			const TInt K64Kb = 65536;
+			aFileData.iImageDataSize = K64Kb;
+			WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL() - read first 64Kb from JPEG" );
+			break;
+			}
+    	case EGifHandling:
+    		{
+    		aFileData.iJpeg = EFalse;
+    		aFileData.iImageDataSize = aFileData.iFileSize;
+			WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL() - read whole GIF file" );
+    		break;
+    		}
+    	default:
+    		{
+    		aFileData.iJpeg = EFalse;
+			const TInt K4Kb = 4096;
+			aFileData.iImageDataSize = K4Kb; 
+			WRITELOG1( "CHarvesterImagePlugin::DataFromImageFileL() - read first %d bytes from image", aFileData.iImageDataSize );
+    		}
+    	}	
+
+    aFileData.iImageData = HBufC8::NewL( aFileData.iImageDataSize );
+    TPtr8 myImagePtr = aFileData.iImageData->Des();
+
+    const TInt readStatus = iFs.ReadFileSection(
+    		*aFileData.iUri, 0, myImagePtr, aFileData.iImageDataSize );
+    if ( readStatus != KErrNone )
+        {
+        WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL() - ERROR: file could not be read!" );
+        User::Leave( readStatus );
+        }
+
+    // extension was in mapping list, so use that 
+	if ( pos != KErrNotFound )
+		{
+		aFileData.iMime8.Copy( iMimeTypeMappings[pos].iMimeType );
+		aFileData.iMime16.Copy( aFileData.iMime8 );
+		}
+	// otherwise try to recognize using image decoder
+    else
+        {
+        CImageDecoder::GetMimeTypeDataL( myImagePtr, aFileData.iMime8 );
+        aFileData.iMime16.Copy( aFileData.iMime8 );
+
+        // Check if MIME type is supported
+        User::LeaveIfError( CheckIfMimeSupported( aFileData.iMime16 ) );
+        }
+
+    // If is jpeg get EXIF data
+    if ( aFileData.iJpeg )
+        {
+        if( iExifUtil->IsValidExifData(myImagePtr) )
+            {
+            WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL() - exif data found!" );
+            aFileData.iExifSupported = ETrue;
+            }
+        else
+            {
+            WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL() - no exif data!" );
+            aFileData.iImageDataSize = aFileData.iFileSize;
+            aFileData.iExifSupported = EFalse;
+            }
+        }
+    
+    WRITELOG( "CHarvesterImagePlugin::DataFromImageFileL() - reading IMAGE file done!" );
+    }
+
+// ---------------------------------------------------------------------------
+// HandleNewObjectL
+// ---------------------------------------------------------------------------
+//    
+void CHarvesterImagePlugin::HandleObjectPropertiesL(
+		CHarvestData& aHd,
+		CFileData& aFileData,
+		CHarvesterData& aHarvesterData,
+		TBool aIsAdd )
+    {
+    WRITELOG( "CHarvesterImagePlugin::HandleObjectPropertiesL() - New MdE object" );
+    
+    CMdEObject& mdeObject = aHarvesterData.MdeObject();
+    
+    if( !iPropDefs )
+    	{
+    	iPropDefs = CHarvesterImagePluginPropertyDefs::NewL( mdeObject.Def() );
+    	}
+
+    TTimeIntervalSeconds timeOffsetSeconds = User::UTCOffset();
+
+    TTime localModifiedDate = aFileData.iModified + timeOffsetSeconds;
+    
+    // Object - Creation date
+    if( ! mdeObject.Placeholder() )
+    	{
+	    if ( aFileData.iExifSupported && aHd.iDateOriginal8 )
+	        {
+	        TTime originalTime = iExifUtil->ConvertExifDateTimeToSymbianTimeL(
+	        		aHd.iDateOriginal8->Des() );
+	        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCreationDatePropertyDef, &originalTime, aIsAdd );
+	        }
+	    else if ( aIsAdd )
+	        {
+	        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCreationDatePropertyDef, &localModifiedDate, aIsAdd );
+	        }
+    	}
+
+    // Object - last aFileData.iModified date
+    if( ! mdeObject.Placeholder() )
+    	{
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iLastModifiedDatePropertyDef, &aFileData.iModified, aIsAdd );
+    	}
+
+    if( aFileData.iJpeg )
+    	{
+    	// Time offset
+    	TInt16 timeOffsetMinutes = timeOffsetSeconds.Int() / 60;
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iTimeOffsetPropertyDef, &timeOffsetMinutes, aIsAdd );
+    	}
+
+    // Object - Size
+    if( ! mdeObject.Placeholder() )
+    	{
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iSizePropertyDef, &aFileData.iFileSize, aIsAdd );
+    	}
+    
+    // Item Type
+	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iItemTypePropertyDef, &aFileData.iMime16, aIsAdd );
+    
+    // MediaObject - Width
+    if ( aFileData.iExifSupported )
+        {
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iWidthPropertyDef, &aHd.iImageWidthExif, aIsAdd );
+
+        // If pixelXDimension tag is found, save its value to both Width and PixelXDimension in DB.
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iPixelXDimensionPropertyDef, &aHd.iImageWidthExif, aIsAdd );
+        }
+    else if (aFileData.iImageWidth != 0)
+        {
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iWidthPropertyDef, &aFileData.iImageWidth, aIsAdd );
+        }
+    
+    // MediaObject - Height
+    if ( aFileData.iExifSupported )
+        {
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iHeightPropertyDef, &aHd.iImageHeightExif, aIsAdd );
+        
+        // If pixelYDimension tag is found, save its value to both Height and PixelYDimension in DB.
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iPixelYDimensionPropertyDef, &aHd.iImageHeightExif, aIsAdd );
+        }
+    else if (aFileData.iImageHeight != 0)
+        {
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iHeightPropertyDef, &aFileData.iImageHeight, aIsAdd );
+        } 
+
+#ifdef MDS_MULTIPLE_STAGE_IMAGE_PROCESSING
+    TBool draftVal = ETrue;
+    if( aIsAdd )
+        {
+        if( aHarvesterData.Origin() != MdeConstants::Object::ECamera )
+            {
+            draftVal = EFalse;
+            }
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iDraftPropertyDef, &draftVal, aIsAdd );
+        }
+    else
+        {
+        if( aHarvesterData.ClientId() == KBGPSUid )
+            {
+            draftVal = EFalse;
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iDraftPropertyDef, &draftVal, aIsAdd );
+            }
+        }
+#endif
+    
+    // Image - Bits per Sample
+    if (aFileData.iBitsPerPixel != 0)
+        {
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iBitsPerSamplePropertyDef, &aFileData.iBitsPerPixel, aIsAdd );
+        }
+
+    // Image - Framecount
+    CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFrameCountPropertyDef, &aFileData.iFrameCount, aIsAdd );
+
+    // If is jpeg write EXIF data
+    if ( aFileData.iExifSupported )
+        {
+       	// MediaObject - Description
+       	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iDescriptionPropertyDef, aHd.iDescription16, aIsAdd );
+
+        // MediaObject - Comment (user comment)
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCommentPropertyDef, aHd.iComment16, aIsAdd );
+        
+        // MediaObject - Release date
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iReleaseDatePropertyDef, &localModifiedDate, aIsAdd );
+
+        // MediaObject - Copyright
+    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCopyrightPropertyDef, aHd.iCopyright16, aIsAdd );
+        
+        // Data & time original
+        if ( aHd.iDateOriginal8 )
+            {
+            TTime originalTime = iExifUtil->ConvertExifDateTimeToSymbianTimeL( aHd.iDateOriginal8->Des() );
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iDateTimeOriginalPropertyDef, &originalTime, aIsAdd );
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCaptureDatePropertyDef, &originalTime, aIsAdd );
+            if( originalTime.Int64() == 0 )
+                {
+                CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCreationDatePropertyDef, &localModifiedDate, EFalse );
+                }
+            else
+                {
+                CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iCreationDatePropertyDef, &originalTime, EFalse );
+                }
+            }
+        
+        // Date & time digitized
+        if ( aHd.iDateDigitized8 )
+            {
+            TTime digitizedTime = iExifUtil->ConvertExifDateTimeToSymbianTimeL( aHd.iDateDigitized8->Des() );
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iDateTimeDigitizedPropertyDef, &digitizedTime, aIsAdd );
+            }
+
+        // Date & time aFileData.iModified (DateTime tag)
+        if ( aHd.iDateModified8 )
+            {
+            TTime modifiedTime = iExifUtil->ConvertExifDateTimeToSymbianTimeL(
+            		aHd.iDateModified8->Des() );
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iDateTimePropertyDef, &modifiedTime, aIsAdd );
+            }
+        
+        // Artist    
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iArtistPropertyDef, aHd.iArtist, aIsAdd );
+
+        // Image - White balance
+        if ( aHd.iStoreWhiteBalance )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iWhiteBalancePropertyDef, &aHd.iWhiteBalance, aIsAdd );
+            }
+         
+        // Image - Flash
+        if ( aHd.iStoreFlash )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFlashPropertyDef, &aHd.iFlash, aIsAdd );
+            }
+        
+        // Image - Exposure program                
+        if ( aHd.iStoreExposureProgram )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iExposureProgramPropertyDef, &aHd.iExposureProgram, aIsAdd );
+            }     
+         
+         // Make string            
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iMakePropertyDef, aHd.iMake, aIsAdd );
+            
+        // Model string
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iModelPropertyDef, aHd.iModel, aIsAdd );
+                    
+        // Orientation
+        if ( aHd.iStoreOrientation )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iOrientationPropertyDef, &aHd.iOrientation, aIsAdd );
+            }
+            
+        // X resolution    
+        if ( aHd.iStoreXResolution )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iXResolutionPropertyDef, &aHd.iXResolution, aIsAdd );
+            }
+            
+        // Y resolution    
+        if ( aHd.iStoreYResolution )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iYResolutionPropertyDef, &aHd.iYResolution, aIsAdd );
+            }
+            
+        // Resolution unit
+        CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iResolutionUnitPropertyDef, &aHd.iResolutionUnit, aIsAdd );
+        
+        // YCbCrPositioning
+        if ( aHd.iStoreYCbCrPositioning )    
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iYCbCrPositioningPropertyDef, &aHd.iYCbCrPositioning, aIsAdd );
+            }
+        
+        // Exposure time                
+        if ( aHd.iStoreExposureTime )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iExposureTimePropertyDef, &aHd.iExposureTime, aIsAdd );
+            }
+            
+        // F number
+        if ( aHd.iStoreFNumber )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFNumberPropertyDef, &aHd.iFNumber, aIsAdd );
+            }
+            
+        // EXIF version                
+        if ( aHd.iStoreExifVersion )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iExifVersionPropertyDef, &aHd.iExifVersion, aIsAdd );
+            }
+        
+        //     Shutter speed
+        if ( aHd.iStoreShutterSpeed )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iShutterSpeedValuePropertyDef, &aHd.iShutterSpeed, aIsAdd );
+            }
+            
+        // Aperture    
+        if ( aHd.iStoreAperture )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iApertureValuePropertyDef, &aHd.iAperture, aIsAdd );
+            }
+        
+        // Focal length        
+        if ( aHd.iStoreFocalLength )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFocalLengthPropertyDef, &aHd.iFocalLength, aIsAdd );
+            }
+            
+        // FlashPix version    
+        if ( aHd.iStoreFlashPixVersion )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFlashPixVersionPropertyDef, &aHd.iFlashPixVersion, aIsAdd );
+            }
+            
+        // Colour space            
+        if ( aHd.iStoreColourSpace )    
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iColourSpacePropertyDef, &aHd.iColourSpace, aIsAdd );
+            }
+            
+        // ISO speed rating            
+        if ( aHd.iStoreIsoSpeedRating )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iISOSpeedRatingsPropertyDef, &aHd.iIsoSpeedRating, aIsAdd );
+            }
+        
+        // Components configuration    
+        if ( aHd.iStoreComponentsConfig )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iComponentsConfigurationPropertyDef, &aHd.iComponentsConfiguration, aIsAdd );
+            }
+        
+        // Exposure bias value        
+        if ( aHd.iStoreExposureBias )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iExposureBiasValuePropertyDef, &aHd.iExposureBias, aIsAdd );
+            }
+            
+        // Samples per pixel    
+        if ( aHd.iStoreSamplesPerPixel )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iSamplesPerPixelPropertyDef, &aHd.iSamplesPerPixel, aIsAdd );
+            }
+            
+        // Thumbnail compression                
+        if ( aHd.iStoreThumbCompression )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iThumbCompressionPropertyDef, &aHd.iThumbCompression, aIsAdd );
+            }
+            
+        // Thumbnail X resolution    
+        if ( aHd.iStoreThumbXResolution )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iThumbXResolutionPropertyDef, &aHd.iThumbXResolution, aIsAdd );
+            }
+            
+        // Thumbnail Y resolution            
+        if ( aHd.iStoreThumbYResolution )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iThumbYResolutionPropertyDef, &aHd.iThumbYResolution, aIsAdd );
+            }
+            
+        // Thumbnail resolution unit    
+        if ( aHd.iStoreThumbResolutionUnit )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iThumbResolutionUnitPropertyDef, &aHd.iThumbResolutionUnit, aIsAdd );
+            }
+        
+        // Focal length in 35 mm    
+        if ( aHd.iStoreFocalLengthIn35 )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFocalLengthIn35mmFilmPropertyDef, &aHd.iFocalLengthIn35mm, aIsAdd );
+            }
+            
+        // Metering mode                
+        if ( aHd.iStoreMeteringMode )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iMeteringModePropertyDef, &aHd.iMeteringMode, aIsAdd );
+            }
+            
+        // Related soundfile            
+        if ( aHd.iRelatedSoundFile && aHd.iRelatedSoundFile->Length() > 0 )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iRelatedSoundFilePropertyDef, aHd.iRelatedSoundFile, aIsAdd );
+            }
+        
+        // Focal plane resolution unit
+        if ( aHd.iStoreFocalPlaneResolutionUnit )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFocalPlaneResolutionUnitPropertyDef, &aHd.iFocalPlaneResolutionUnit, aIsAdd );
+            }
+            
+        // Focal plane X resolution
+        if ( aHd.iStoreFocalPlaneXResolution )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFocalPlaneXResolutionPropertyDef, &aHd.iFocalPlaneXResolution, aIsAdd );
+            }
+            
+        // Focal plane Y resolution
+        if ( aHd.iStoreFocalPlaneYResolution )
+            {
+            CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iFocalPlaneYResolutionPropertyDef, &aHd.iFocalPlaneYResolution, aIsAdd );
+            }
+        WRITELOG( "CHarvesterImagePlugin::HandleObjectPropertiesL() - All EXIF tags added." );
+        }
+    }
+
+//---------------------------------------------------------------------------
+// CheckIfMimeSupported
+//---------------------------------------------------------------------------
+//
+TInt CHarvesterImagePlugin::CheckIfMimeSupported(const TDesC& aMimeBuf)
+    {
+    if ( MdsUtils::Compare(KJpegMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KJpeg2000Mime, aMimeBuf) == 0
+            || MdsUtils::Compare(KJpeg2000_2Mime, aMimeBuf) == 0
+            || MdsUtils::Compare(KPngMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KGifMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KBmpMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KMsmMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KXbmpMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KWbmpMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KMbmMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KTiffMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KOtaMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KXotaMime, aMimeBuf) == 0
+            || MdsUtils::Compare(KWmfMime, aMimeBuf) == 0 )
+
+    	{
+        return KErrNone;
+        }
+    
+    return KErrNotSupported;
+    }