harvester/harvesterplugins/ImagePlugin/src/harvesterimageplugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Mar 2010 09:38:01 +0200
changeset 20 6dfc5f825351
parent 1 acef663c1218
child 21 50bf9db68373
permissions -rw-r--r--
Revision: 201007 Kit: 201011

/*
* 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;
    
    iMimeTypeMappings.Close();
    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 );
        
    TInt errorCode( KErrNone );
    TRAPD( error, errorCode = GatherDataL( mdeObject, *fileData, *harvestData ) );
    if ( error == KErrNone && (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 ) );
            mdeObject.SetPlaceholder( EFalse );
            }
        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 if( error != KErrNone)
        {
        WRITELOG1( "CHarvesterImagePlugin::HarvestL() - other error: %d", error );
        TInt convertedError = KErrNone;
        MdsUtils::ConvertTrapError( error, convertedError );
        aHD->SetErrorCode( convertedError );
        WRITELOG1( "CHarvesterImagePlugin::HarvestL() - returning: %d", convertedError );
        }
    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 );
	}

// ---------------------------------------------------------------------------
// CHarvesterImagePlugin::GetMimeType (from CHarvesterPlugin)
// ---------------------------------------------------------------------------
//    
void CHarvesterImagePlugin::GetMimeType( const TDesC& aUri, TDes& aMimeType )
    {
    aMimeType.Zero();
    
    TPtrC ext;
    if( !MdsUtils::GetExt( aUri, ext ) )
        {
        return;
        }

    TMimeTypeMapping<TImageMetadataHandling> finder(ext);
    TLinearOrder< TMimeTypeMapping<TImageMetadataHandling> > cmp(
            TMimeTypeMapping<TImageMetadataHandling>::CompareFunction);

    const TInt pos = iMimeTypeMappings.FindInOrder( finder, cmp );

    if ( pos == KErrNotFound )
        {
        return;
        }

    aMimeType = iMimeTypeMappings[pos].iMimeType;
    }

// ---------------------------------------------------------------------------
// 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." );

        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 );
            iDecoder->Reset();
            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 );
					iDecoder->Reset();
					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" );
            	iDecoder->Reset();
            	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;
        
        iDecoder->Reset();
        }

    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);

	const 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;
    
    if( ! mdeObject.Placeholder() )
    	{
        // Object - Creation date
	    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
	    CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iLastModifiedDatePropertyDef, &aFileData.iModified, aIsAdd );
	    
	    // Object - Size
	    CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iSizePropertyDef, &aFileData.iFileSize, aIsAdd );
	    
	    // Item Type
	    CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iItemTypePropertyDef, &aFileData.iMime16, aIsAdd );
    	}

    if( aFileData.iJpeg )
    	{
    	// Time offset
    	TInt16 timeOffsetMinutes = timeOffsetSeconds.Int() / 60;
    	CMdeObjectWrapper::HandleObjectPropertyL(mdeObject, *iPropDefs->iTimeOffsetPropertyDef, &timeOffsetMinutes, 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;
    }