imaging/imagingfws/src/ImageClientApi.cpp
changeset 0 5752a19fdefe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imaging/imagingfws/src/ImageClientApi.cpp	Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,5056 @@
+// Copyright (c) 2001-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:
+//
+
+#include <ecom/ecom.h>
+#include <bitdev.h>
+#include <bautils.h>
+#include <barsc.h>
+#include <caf/caf.h>
+using namespace ContentAccess;
+
+#include "ImageConversion.h"
+#include "ImageClientMain.h"
+#include "ImageResolverAPI.h"
+#include "ImageUtils.h"
+#include "ImageConvResolvrUtils.h"
+#include "ImageRelay.h"
+#include "icl/ImageConstruct.h"
+#include "icl/ImagePlugin.h"
+#include "ImageConversion.inl"
+#include "ImageCodecBody.h"
+#include "EnDecoderUtils.h"
+#include "icl/imageconversionextension.h"
+#include "fwextconstants.h"
+
+const TInt KMaxMimeLength = 256;
+const TInt KMinimumHeaderLength = 2;
+
+
+//
+// CImageTypeDescription
+//
+
+/**
+Constructs a new image type description entry.
+
+A leave occurs if there is insufficient memory available.
+
+@param  aDescription
+        A description of the plugin decoder/encoder.
+@param  aImageType
+        The plugin decoder/encoder type UID.
+@param  aSubType
+        The plugin decoder/encoder sub-type UID.
+
+@return A pointer to the new image type description entry.
+*/
+CImageTypeDescription* CImageTypeDescription::NewL(const TDesC& aDescription, const TUid aImageType, const TUid aSubType)
+	{
+	CImageTypeDescription* self = CImageTypeDescription::NewLC(aDescription, aImageType, aSubType);
+	CleanupStack::Pop();
+	return self;
+	}
+
+/**
+Constructs a new image type description entry. The new object created on the clean-up stack.
+
+A leave occurs if there is insufficient memory available.
+
+@param  aDescription
+        A description of the plugin decoder/encoder.
+@param  aImageType
+        The plugin decoder/encoder type UID.
+@param  aSubType
+        The plugin decoder/encoder sub-type UID.
+
+@return A pointer to the new image type description entry.
+*/
+CImageTypeDescription* CImageTypeDescription::NewLC(const TDesC& aDescription, const TUid aImageType, const TUid aSubType)
+	{
+	CImageTypeDescription* self = new(ELeave) CImageTypeDescription(aImageType, aSubType);
+	CleanupStack::PushL(self);
+	self->ConstructL(aDescription);
+	return self;
+	}
+
+
+/** 
+Default constructor. 
+@param aImageType 
+           The plugin decoder/encoder type UID. 
+@param aSubType 
+           The plugin decoder/encoder sub-type UID 
+*/ 
+
+CImageTypeDescription::CImageTypeDescription(const TUid aImageType, const TUid aSubType)
+	: iImageType(aImageType), iSubType(aSubType)
+	{
+	}
+
+/** 
+Second phase constructor. 
+@param aDescription 
+           A description of the plugin decoder/encoder. 
+*/ 
+
+void CImageTypeDescription::ConstructL(const TDesC& aDescription)
+	{
+	iDescription = aDescription.AllocL();
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CImageTypeDescription::~CImageTypeDescription()
+	{
+	delete iDescription;
+	}
+
+/**
+Returns the image description info.
+
+@return  A reference to the descriptor containing the description.
+*/
+EXPORT_C const TDesC& CImageTypeDescription::Description() const
+	{
+	return *iDescription;
+	}
+
+/**
+Returns the image type info.
+
+@return The image type info as a TUid object.
+*/
+EXPORT_C TUid CImageTypeDescription::ImageType() const
+	{
+	return iImageType;
+	}
+
+/**
+Returns the image sub-type information.
+
+@return The image sub-type information as a TUid object.
+*/
+EXPORT_C TUid CImageTypeDescription::SubType() const
+	{
+	return iSubType;
+	}
+
+//
+// CFileExtensionMIMEType
+//
+
+/**
+Constructs a new file extension/MIME type entry.
+
+A leave occurs if there is insufficient memory available.
+
+@param  aExtn
+        The file extension.
+@param  aMIMEType
+        The associated MIME type.
+@param  aDisplayName The display name of the implementation 
+@param  aImageType The plugin decoder/encoder type UID. 
+@param  aImageSubType The plugin decoder/encoder sub-type UID. 
+@param  aImplementationUid The unique ID of the implementation. 
+@return A pointer to the new file extension/MIME type entry.
+*/
+CFileExtensionMIMEType* CFileExtensionMIMEType::NewL(const TDesC8& aExtn, const TDesC8& aMIMEType, const TDesC& aDisplayName, TUid aImageType, TUid aImageSubType, TUid aImplementationUid)
+	{
+	CFileExtensionMIMEType* self = CFileExtensionMIMEType::NewLC(aExtn, aMIMEType, aDisplayName, aImageType, aImageSubType, aImplementationUid);
+	CleanupStack::Pop();
+	return self;
+	}
+
+/**
+Constructs a new file extension/MIME type entry. The new object is left on the clean-up stack.
+
+A leave occurs if there is insufficient memory available.
+
+@param  aExtn
+        The file extension.
+@param  aMIMEType 
+        The associated MIME type.
+@param  aDisplayName The display name of the implementation 
+@param  aImageType The plugin decoder/encoder type UID. 
+@param  aImageSubType The plugin decoder/encoder sub-type UID. 
+@param  aImplementationUid The unique ID of the implementation. 
+@return A pointer to the new file extension/MIME type entry.
+*/
+EXPORT_C CFileExtensionMIMEType* CFileExtensionMIMEType::NewLC(const TDesC8& aExtn, const TDesC8& aMIMEType, const TDesC& aDisplayName, TUid aImageType, TUid aImageSubType, TUid aImplementationUid)
+	{
+	CFileExtensionMIMEType* self = new(ELeave) CFileExtensionMIMEType;
+	CleanupStack::PushL(self);
+	self->ConstructL(aExtn, aMIMEType, aDisplayName, aImageType, aImageSubType, aImplementationUid);
+	return self;
+	}
+/**
+Default constructor. 
+*/
+CFileExtensionMIMEType::CFileExtensionMIMEType()
+	{
+	}
+
+/**
+Second phase constructor. 
+@param aExtn The file extension 
+@param aMIMEType The associated MIME type. 
+@param aDisplayName The display name of the implementation 
+@param aImageType The plugin decoder/encoder type UID. 
+@param aImageSubType The plugin decoder/encoder sub-type UID. 
+@param aImplementationUid The unique ID of the implementation. 
+*/
+void CFileExtensionMIMEType::ConstructL(const TDesC8& aExtn, const TDesC8& aMIMEType, const TDesC& aDisplayName, TUid aImageType, TUid aImageSubType, TUid aImplementationUid)
+	{
+	iFileExtension = HBufC::NewL(aExtn.Length());
+	iFileExtension->Des().Copy(aExtn); // Create a 16 bit copy of the 8 bit original
+	ASSERT(iFileExtension->Length() == aExtn.Length());
+	iMIMEType = aMIMEType.AllocL();
+	ASSERT(iMIMEType->Length() == aMIMEType.Length());
+	iDisplayName = aDisplayName.AllocL();
+	iImageTypeUid = aImageType;
+	iImageSubTypeUid = aImageSubType;
+	iImplementationUid = aImplementationUid;
+	}
+
+/**
+Destructor.
+
+Frees all resources owned by the object prior to its destruction.
+*/
+EXPORT_C CFileExtensionMIMEType::~CFileExtensionMIMEType()
+	{
+	delete iFileExtension;
+	delete iMIMEType;
+	delete iDisplayName;
+	}
+
+/**
+Returns the image file extension info.
+
+@return A reference to the descriptor containing the file extension.
+*/
+EXPORT_C const TDesC& CFileExtensionMIMEType::FileExtension() const
+	{
+	return *iFileExtension;
+	}
+
+/**
+Returns the image MIME type info.
+
+@return A reference to the descriptor containing the MIME type.
+*/
+EXPORT_C const TDesC8& CFileExtensionMIMEType::MIMEType() const
+	{
+	return *iMIMEType;
+	}
+
+/**
+Returns the human-readable plugin description.
+
+@return A reference to the display descriptor.
+*/
+EXPORT_C const TDesC& CFileExtensionMIMEType::DisplayName() const
+	{
+	return *iDisplayName;
+	}
+
+/**
+Returns the image type associated with the plugin.
+
+@return The image type associated with the plugin
+*/
+EXPORT_C TUid CFileExtensionMIMEType::ImageType() const
+	{
+	return iImageTypeUid;
+	}
+
+/**
+Returns the image sub-type associated with the plugin.
+
+@return The image sub-type associated with the plugin.
+*/
+EXPORT_C TUid CFileExtensionMIMEType::ImageSubType() const
+	{
+	return iImageSubTypeUid;
+	}
+
+/**
+Returns the implementation UID of the plugin.
+
+@return	The implementation UID of the plugin.
+*/
+EXPORT_C TUid CFileExtensionMIMEType::ImplementationUid() const
+	{
+	return iImplementationUid;
+	}
+
+//
+// CImplementationInformationType
+//
+
+/**
+Constructs a new implementation information object.
+
+@return A pointer to the new implementation information object.
+*/
+
+CImplementationInformationType* CImplementationInformationType::NewL()
+	{
+	CImplementationInformationType* self = CImplementationInformationType::NewLC();
+	CleanupStack::Pop();
+	return self;
+	}
+
+// CImplementationInformationType transfer ownership of iDisplyName, iDataType and iOpaqueData
+
+/**
+Sets the contents of the CImplementationInformationType object.
+
+Use this variant of SetDataL() if the plugin is installed on a drive other than the default, which is zero.
+
+@param  aImplementationUid
+        The unique ID of the implementation.
+@param  aVersion
+        The version number of the implementation.
+@param  aDisplayName
+        The display name of the implementation.
+@param  aDataType
+        The data type supported by the implementation.
+@param  aOpaqueData
+        Additional data for this implementation. This data is not used by the ECom framework.
+@param  aDrive
+        The drive on which the plugin is installed.
+*/
+void CImplementationInformationType::SetDataL(TUid aImplementationUid, TInt aVersion, const TDesC& aDisplayName, const TDesC8& aDataType, const TDesC8& aOpaqueData, TDriveUnit aDrive)
+	{
+	iImplementationUid = aImplementationUid;
+	iVersion = aVersion;
+
+	delete iDisplayName; iDisplayName = NULL;
+	iDisplayName = aDisplayName.AllocL();
+
+	delete iDataType; iDataType = NULL;
+	iDataType = aDataType.AllocL();
+
+	delete iOpaqueData; iOpaqueData = NULL;
+	iOpaqueData = aOpaqueData.AllocL();
+
+	iDrive = aDrive;
+	}
+
+/**
+Default constructor.
+
+This member is internal and not intended for use.
+*/
+CImplementationInformationType::CImplementationInformationType()
+	{
+	}
+
+/**
+Constructs a new implementation information object. The new object is left on the clean-up stack.
+
+@return A pointer to the new implementation information object.
+*/
+CImplementationInformationType* CImplementationInformationType::NewLC()
+	{
+	CImplementationInformationType* self = new(ELeave) CImplementationInformationType;
+	CleanupStack::PushL(self);
+	return self;
+	}
+
+/**
+Destructor.
+
+Frees all resources owned by the object prior to its destruction.
+*/
+EXPORT_C CImplementationInformationType::~CImplementationInformationType()
+	{
+	delete iDisplayName;
+	delete iDataType;
+	delete iOpaqueData;
+	}
+
+
+/**
+Returns the implementation UID.
+
+@return The implementation UID as a TUid object.
+*/
+EXPORT_C TUid CImplementationInformationType::ImplementationUid() const
+	{
+	return iImplementationUid;
+	}
+
+/**
+Returns the version number of the implementation.
+
+@return The version number of the implementation.
+*/
+EXPORT_C TInt CImplementationInformationType::Version() const
+	{
+	return iVersion;
+	}
+
+/**
+Returns the display name of the implementation.
+
+@return A reference to the display name of the implementation.
+*/
+EXPORT_C const TDesC& CImplementationInformationType::DisplayName() const
+	{
+	return *iDisplayName;
+	}
+
+/**
+Returns the data type supported by the implementation.
+
+@return A reference to the descriptor containing the data type.
+*/
+EXPORT_C const TDesC8& CImplementationInformationType::DataType() const
+	{
+	return *iDataType;
+	}
+
+/**
+Returns the opaque binary data for the implementation.
+
+@return A reference to the descriptor containing the data.
+*/
+EXPORT_C const TDesC8& CImplementationInformationType::OpaqueData() const
+	{
+	return *iOpaqueData;
+	}
+
+/**
+Returns the drive location information for the implementation.
+
+@return The drive location information as a TDriveUnit object.
+*/
+EXPORT_C TDriveUnit CImplementationInformationType::Drive()
+	{
+	return iDrive;
+	}
+
+/**
+Function to sort an array of CFileExtensionMIMEType in ascending
+order of file extesion and MIME type.
+
+@param  aItem1
+        The first element.
+@param  aItem2
+        The second element.
+
+@return	An indication of the element swapping order.
+*/
+TInt ImageEnDecoderUtils::SortAsending(const CFileExtensionMIMEType& aItem1, const CFileExtensionMIMEType& aItem2)
+	{
+	TInt result = aItem1.FileExtension().Compare(aItem2.FileExtension());
+	if(result==0)
+		result = aItem1.MIMEType().Compare(aItem2.MIMEType());
+	return result;
+	}
+
+// Used by the 4 decoder and encoder functions that return arrays of Uids and plugin descriptions
+void ImageEnDecoderUtils::DoGetImageTypesL(TUid aInterfaceUid, RImageTypeDescriptionArray& aImageTypeArray, TUid aBaseType)
+	{
+	RImplInfoPtrArray pluginArray; // Array to return matching plugins in
+	CleanupResetAndDestroyPushL(pluginArray);
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	TEComResolverParams resolverParams; // Parameters on which to match
+
+	customMatchData->SetMatchType(EListImageTypes);
+	customMatchData->SetBaseType(aBaseType);
+	customMatchData->SetSubType(KNullUid);
+	customMatchData->SetImplementationType(KNullUid);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(aInterfaceUid, resolverParams, KImageConvertResolverUid, pluginArray);
+	if (pluginArray.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+
+	// Transfer data to our array
+	for (TInt index = 0; index < pluginArray.Count(); index++)
+		{
+		COpaqueDataParse* parser = NULL;
+		TRAPD(error, parser = COpaqueDataParse::NewL(pluginArray[index]->OpaqueData()));
+		if (error!=KErrNone)
+			{
+			if (error==KErrNotSupported)
+				{
+				// means that the resource entry was not valid
+				continue;
+				}
+			else
+				User::Leave(error);
+			}
+
+		CleanupStack::PushL(parser);
+		CImageTypeDescription* imageTypeDescription = CImageTypeDescription::NewLC(pluginArray[index]->DisplayName(), parser->ImageTypeUid(), parser->ImageSubTypeUid());
+
+		TBool mustAppend = ETrue;
+		for(TInt i=0; i< aImageTypeArray.Count(); i++)
+			{
+			if(	aImageTypeArray[i]->ImageType().iUid == imageTypeDescription->ImageType().iUid &&
+				aImageTypeArray[i]->SubType().iUid == imageTypeDescription->SubType().iUid &&
+				(aImageTypeArray[i]->Description().Compare(imageTypeDescription->Description())) == 0)
+				{
+				// If here - image type implementation with same description is already in array.
+				mustAppend = EFalse;
+				CleanupStack::PopAndDestroy(imageTypeDescription); 
+				break;
+				}
+			}
+		if(mustAppend)
+			{
+			//A new image type implementation, add it to array.
+			User::LeaveIfError(aImageTypeArray.Append(imageTypeDescription));		
+			CleanupStack::Pop(imageTypeDescription); 
+			}
+		CleanupStack::PopAndDestroy(parser);
+		}
+	CleanupStack::PopAndDestroy(&pluginArray); 
+	}
+
+// Used by both the decoder and encoder functions that return arrays of file extensions and MIME types.
+// This function creates an array of each valid file extension along with the associated "primary"
+// (ie. first) MIME type plus the "secondary" MIME type(s).
+void ImageEnDecoderUtils::DoGetFileTypesL(TUid aInterfaceUid, RFileExtensionMIMETypeArray& aFileTypeArray)
+	{
+	RImplInfoPtrArray pluginArray; // Array to return matching plugins in
+	CleanupResetAndDestroyPushL(pluginArray);
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	TEComResolverParams resolverParams; // Parameters on which to match
+
+	customMatchData->SetMatchType(EListFileTypes);
+
+	HBufC8* package = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(aInterfaceUid, resolverParams, KImageConvertResolverUid, pluginArray);
+	if (pluginArray.Count() == 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+
+	// Transfer data to our array
+	for (TInt index = 0; index < pluginArray.Count(); index++)
+		{
+		CImplementationInformation* implInfo = pluginArray[index];
+		COpaqueDataParse* parser = NULL;
+		TRAPD(error, parser = COpaqueDataParse::NewL(implInfo->OpaqueData()));
+		if (error != KErrNone)
+			{
+			if (error==KErrNotSupported)
+				{
+				// means that the resource entry was not valid
+				continue;
+				}
+			else
+				{
+				User::Leave(error);
+				}				
+			}
+
+		CleanupStack::PushL(parser);
+  		if (parser->OnlyUidsAvail() || parser->IsSubCodec()) // ignore simple descriptions
+			{
+			CleanupStack::PopAndDestroy(); // parser
+			continue;
+			}
+		parser->EnsureMIMETypesReadL();
+
+		// Return all the MIME types specified in the resource file, not just the primary
+		// one by filling the file type array with elements created multiplicatively
+		// for each extension and each MIME type.
+
+		// use a blank MIME type if none provided by the plugin
+		const TBool blankMIMEType = (parser->MIMETypesCount() == 0);
+		const TInt numMIMETypes = blankMIMEType ? 1 : parser->MIMETypesCount();
+
+		//use a blank extension if not provided by plugin
+		const TBool blankExtn = (parser->ExtnsCount() == 0);
+		const TInt numExtns = blankExtn ? 1 : parser->ExtnsCount();
+
+		TLinearOrder<CFileExtensionMIMEType> sortFunction(SortAsending);
+		for (TInt index2 = 0; index2 < numExtns; index2++)
+			{
+			const TDesC8& extn = blankExtn ? KNullDesC8() : parser->Extn(index2);
+			for (TInt index3 = 0; index3 < numMIMETypes; index3++)
+				{
+				const TDesC8& MIMEType = blankMIMEType ? KNullDesC8() : parser->MIMEType(index3);
+				CFileExtensionMIMEType* fileExtensionMIMEType = CFileExtensionMIMEType::NewLC(  extn, MIMEType,
+																								implInfo->DisplayName(),
+																								parser->ImageTypeUid(),
+																								parser->ImageSubTypeUid(),
+																								implInfo->ImplementationUid());
+				//InsertInOrder will return KErrAlreadyExists if an entry already exists that
+				//has the same MIME type and file extension.  Thus, aFileTypeArray may not
+				//contain all implementation UIDs that are present. 
+				//We assume the resolver CImageConversionResolver::ListAllL() return highest version number first
+				//if calls succeed ownership is transferred
+				TInt error = aFileTypeArray.InsertInOrder(fileExtensionMIMEType, sortFunction);
+				if (error != KErrNone)
+					{
+					CleanupStack::PopAndDestroy(fileExtensionMIMEType);
+					if (error != KErrAlreadyExists)
+						{
+						User::Leave(error);
+						}
+					}
+				else
+					{
+					CleanupStack::Pop(fileExtensionMIMEType);				
+					}
+				}
+			}
+		CleanupStack::PopAndDestroy(parser);
+		}
+	CleanupStack::PopAndDestroy(&pluginArray); 
+	}
+
+// Used by the decoder and encoder functions to obtain the implementation information a specific codec
+void ImageEnDecoderUtils::DoGetImplementationInformationL(const TUid aInterfaceUid, CImplementationInformationType& aImplementationInformation, const TUid aImplementationUid)
+	{
+	RImplInfoPtrArray pluginArray; // Array to return matching plugins in
+	CleanupResetAndDestroyPushL(pluginArray);
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	TEComResolverParams resolverParams; // Parameters on which to match
+
+	customMatchData->SetMatchType(EMatchUids);
+	customMatchData->SetImplementationType(aImplementationUid);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(aInterfaceUid, resolverParams, KImageConvertResolverUid, pluginArray);
+	if (pluginArray.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+	
+	// Transfer data (if more than one is found take first)
+	CImplementationInformation* impInfo = pluginArray[0];
+	aImplementationInformation.SetDataL(impInfo->ImplementationUid(),
+										impInfo->Version(),
+										impInfo->DisplayName(),
+										impInfo->DataType(),
+										impInfo->OpaqueData(),
+										impInfo->Drive()
+										);
+
+	CleanupStack::PopAndDestroy(); // pluginArray
+	}
+
+// Used by the decoder and encoder functions to obtain the implementation properties of a specific codec
+// Since this function can be called by both CImageEncoder and CImageDecoder functions we must
+// use the generic TUint data type for the aOptions parameter rather than TOptions.
+void ImageEnDecoderUtils::DoGetPluginPropertiesL(const TUid aInterfaceUid, const TUid aImplementationUid, RUidDataArray& aPropertiesArray, const TUint aOptions)
+	{
+	RImplInfoPtrArray pluginArray; // Array to return matching plugins in
+	CleanupResetAndDestroyPushL(pluginArray);
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	TEComResolverParams resolverParams; // Parameters on which to match
+
+	customMatchData->SetMatchType(EMatchUids);
+	customMatchData->SetImplementationType(aImplementationUid);
+	customMatchData->SetOptions(CImageDecoder::TOptions(aOptions));
+	customMatchData->SetExtensionOptions(aOptions);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(aInterfaceUid, resolverParams, KImageConvertResolverUid, pluginArray);
+	if (pluginArray.Count() == 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+	
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+	
+	// Transfer data to our array
+	COpaqueDataParse* parser = NULL;
+	TRAPD(error, parser = COpaqueDataParse::NewL((pluginArray[0])->OpaqueData()));
+	if (error != KErrNone)
+		{
+		User::Leave(error);
+		}
+
+	CleanupStack::PushL(parser);
+	parser->EnsureBinaryPropertiesReadL();
+	parser->GetBinaryPropertiesArrayL(aPropertiesArray);
+	
+	CleanupStack::PopAndDestroy(2); // parser, &pluginArray
+	}
+
+// Used by the decoder and encoder functions to obtain the implementations (array of uids) that have the required properties and UIDs
+void ImageEnDecoderUtils::DoGetInterfaceImplementationsL(const TUid aInterfaceUid, const RUidDataArray& aRequiredUids, RUidDataArray& aImplArray)
+	{
+	RImplInfoPtrArray pluginArray; // Array to return matching plugins in
+	CleanupResetAndDestroyPushL(pluginArray);
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	TEComResolverParams resolverParams; // Parameters on which to match
+
+	customMatchData->SetMatchType(EMatchReqUids);
+	customMatchData->SetMatchReqUidsL(aRequiredUids);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(aInterfaceUid, resolverParams, KImageConvertResolverUid, pluginArray);
+	if (pluginArray.Count() == 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+	
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+	
+	// Transfer data to our array
+	aImplArray.Reset();
+	for (TInt index = 0; index < pluginArray.Count(); index++)
+		{
+		User::LeaveIfError(aImplArray.Append((pluginArray[index])->ImplementationUid()));
+		}
+	
+	CleanupStack::PopAndDestroy(&pluginArray);
+	}
+
+/**
+Static factory function for creating instances of CFrameImageData.
+The managed list of image data is created/destroyed internally.
+
+@return A pointer to a fully constructed CFrameImageData.
+*/
+EXPORT_C CFrameImageData* CFrameImageData::NewL()
+	{
+	CImageDataArray* newImageData = new(ELeave) CImageDataArray;
+	CleanupStack::PushL(newImageData);
+
+	CFrameImageData* newFrameImageData = new(ELeave) CFrameImageData(*newImageData, ETrue);
+	CleanupStack::Pop(); // newImageData
+
+	return newFrameImageData;
+	}
+
+/**
+Static factory function for creating instances of CFrameImageData.
+
+The managed list of image data is created internally. If a data owner is specified then the responsibility
+for destroying the managed list is that of the owner. If no owner is specified the managed list is
+destroyed internally.
+
+@param  aImageData
+        A reference to an externally created CImageDataArray.
+@param  aImageDataOwner
+        If set to true, responsibility for deleting CImageDataArray
+        is passed to the CFrameImageData object.
+
+@return A pointer to a fully constructed CFrameImageData.
+*/
+EXPORT_C CFrameImageData* CFrameImageData::NewL(CImageDataArray& aImageData, TBool aImageDataOwner)
+	{
+	CFrameImageData* newFrameImageData = new(ELeave) CFrameImageData(aImageData, aImageDataOwner);
+	return newFrameImageData;
+	}
+
+CFrameImageData::CFrameImageData(CImageDataArray& aImageData, TBool aImageDataOwner)
+	: iImageData(aImageData),
+	iImageDataOwner(aImageDataOwner)
+	{
+	}
+
+/**
+Destructor for this class.
+
+If ownership of the image data was transfered, it is now destroyed.
+*/
+EXPORT_C CFrameImageData::~CFrameImageData()
+	{
+	if (iImageDataOwner)
+		delete &iImageData;
+
+	iFrameData.ResetAndDestroy();
+	}
+
+/**
+Intended for future proofing - will panic if called.
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CFrameImageData::Reserved_1()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called.
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CFrameImageData::Reserved_2()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called.
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CFrameImageData::Reserved_3()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called.
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CFrameImageData::Reserved_4()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@see     CFrameImageData::ImageDataCount().
+
+Inserts a pointer to an image data block into the internally held list in front
+of the item at position aPos.
+
+@param  aEntry
+        The image data block pointer to be inserted.
+@param  aPos
+        The position at which to insert the pointer into the internal list.
+        Must not be less than 0 or greater than the value returned by
+        CFrameImageData::ImageDataCount().
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+*/
+EXPORT_C TInt CFrameImageData::InsertImageData(const TImageDataBlock* aEntry, TInt aPos)
+	{
+	ASSERT(aEntry != NULL);
+	return iImageData.InsertImageData(aEntry, aPos);
+	}
+
+/**
+Adds a pointer to an image data block to the end of the internally held list.
+
+@param  aEntry
+        The image data block pointer to be inserted.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+*/
+EXPORT_C TInt CFrameImageData::AppendImageData(const TImageDataBlock* aEntry)
+	{
+	ASSERT(aEntry != NULL);
+	return iImageData.AppendImageData(aEntry);
+	}
+
+/**
+Removes a pointer to an image data block at position aIndex from the
+internally held list.
+
+@param  aIndex
+        The index into the list. Must not be less than 0 or greater
+        than the value returned by CFrameImageData::ImageDataCount().
+
+@see    CFrameImageData::ImageDataCount().
+*/
+EXPORT_C void CFrameImageData::RemoveImageData(TInt aIndex)
+	{
+	iImageData.RemoveImageData(aIndex);
+	}
+
+/**
+Inserts a pointer to a frame data block into the internally held list in front
+of the item at position aPos.
+
+@param  aEntry
+        The frame data block pointer to be inserted.
+@param  aPos
+        The position at which to insert the pointer into the internal list. Must not be
+		less than 0 or greater than the value returned by CFrameImageData::FrameDataCount().
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+
+@see    CFrameImageData::FrameDataCount()
+*/
+EXPORT_C TInt CFrameImageData::InsertFrameData(const TFrameDataBlock* aEntry, TInt aPos)
+	{
+	ASSERT(aEntry != NULL);
+	return iFrameData.Insert(aEntry, aPos);
+	}
+
+/**
+Adds a pointer to a frame data block to the end of the internally held list.
+
+@param  aEntry
+        The frame data block pointer to be inserted.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+*/
+EXPORT_C TInt CFrameImageData::AppendFrameData(const TFrameDataBlock* aEntry)
+	{
+	ASSERT(aEntry != NULL);
+	return iFrameData.Append(aEntry);
+	}
+
+/**
+Removes a pointer to a frame data block at position aIndex from the
+internally held list.
+
+@param  aIndex
+        Position of the pointer to delete. Must not be less than 0 or greater
+        than the value returned by CFrameImageData::ImageDataCount().
+
+@see    CFrameImageData::FrameDataCount().
+*/
+EXPORT_C void CFrameImageData::RemoveFrameData(TInt aIndex)
+	{
+	iFrameData.Remove(aIndex);
+	}
+
+/**
+Creates a full copy of the objects data.
+Ownership is transferred to the caller.
+
+@return  A pointer to the new copy of the frame data.
+*/
+EXPORT_C CFrameImageData* CFrameImageData::AllocL() const
+	{
+	// Make copies of the TImageDataBlock arrays.
+	CImageDataArray* newImageData = new (ELeave) CImageDataArray;
+	CleanupStack::PushL(newImageData);
+
+	CFrameImageData* newFrameData = new (ELeave) CFrameImageData(*newImageData, ETrue);
+	CleanupStack::Pop(newImageData);
+	CleanupStack::PushL(newFrameData);
+
+	// Copy the contents.
+	TInt index;
+	TInt count = ImageDataCount();
+	for (index = 0 ; index<count ; index++)
+		{
+		const TImageDataBlock* imageData = GetImageData(index);
+		TImageDataBlock* tmpImageData = imageData->DuplicateL(*newFrameData);
+		CleanupDeletePushL(tmpImageData);
+
+		User::LeaveIfError(newFrameData->AppendImageData(tmpImageData));
+		CleanupStack::Pop(); // tmpImageData
+		}
+
+	count = FrameDataCount();
+	for (index = 0 ; index<count ; index++)
+		{
+		const TFrameDataBlock* frameData = GetFrameData(index);
+		TFrameDataBlock* tmpFrameData = frameData->DuplicateL(*newFrameData);
+		CleanupDeletePushL(tmpFrameData);
+
+		User::LeaveIfError(newFrameData->AppendFrameData(tmpFrameData));
+		CleanupStack::Pop(); // tmpFrameData
+		}
+
+	CleanupStack::Pop(newFrameData); // newFrameData
+	return newFrameData;
+	}
+
+/**
+Returns the image data block at the given position from the
+internally held list.
+
+@param  aIndex
+        The position of the image data block to retrieve. Must be in the range 0 to ImageDataCount().
+
+@return A pointer to the image data block.
+*/
+EXPORT_C const TImageDataBlock* CFrameImageData::GetImageData(TInt aIndex) const
+	{
+	return iImageData.GetImageData(aIndex);
+	}
+
+/**
+Returns the image data block at the given position from the
+internally held list.
+
+@param  aIndex
+        The position of the image data block to retrieve. Must be in the range 0 to ImageDataCount().
+
+@return A pointer to the image data block.
+*/
+EXPORT_C TImageDataBlock* CFrameImageData::GetImageData(TInt aIndex)
+	{
+	return iImageData.GetImageData(aIndex);
+	}
+
+/**
+Const version.
+
+Returns the frame data block at the given position from the
+internally held list.
+
+@param  aIndex
+        The position of the frame data block to retrieve. Must be in the range 0 to FrameDataCount().
+
+@return A pointer to the image data block.
+*/
+EXPORT_C const TFrameDataBlock* CFrameImageData::GetFrameData(TInt aIndex) const
+	{
+	return iFrameData[aIndex];
+	}
+
+/**
+Non const version.
+
+Returns the frame data block at the given position from the
+internally held list.
+
+@param  aIndex
+        The position of the frame data block to retrieve. Must be in the range 0 to FrameDataCount().
+
+@return A pointer to the image data block.
+*/
+EXPORT_C TFrameDataBlock* CFrameImageData::GetFrameData(TInt aIndex)
+	{
+	return iFrameData[aIndex];
+	}
+
+/**
+Returns the number of image data blocks in the internally held list.
+
+@return The number of image data blocks.
+*/
+EXPORT_C TInt CFrameImageData::ImageDataCount() const
+	{
+	return iImageData.ImageDataCount();
+	}
+
+/**
+Returns the number of frame data blocks in the internally held list.
+
+@return The number of image data blocks.
+*/
+EXPORT_C TInt CFrameImageData::FrameDataCount() const
+	{
+	return iFrameData.Count();
+	}
+
+/**
+Stores the supplied image data in a newly allocated entry in the image buffer array.
+
+@param  aImageBuffer
+        The HBufC8 pointer to take ownership of.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+*/
+EXPORT_C TInt CFrameImageData::AppendImageBuffer(const HBufC8* aImageBuffer)
+	{
+	return iImageData.AppendImageBuffer(aImageBuffer);
+	}
+
+// Codec virtual fns.
+
+// CImageReadCodec
+
+/**
+Default constructor.
+*/
+EXPORT_C CImageReadCodec::CImageReadCodec()
+	{
+	}
+
+/**
+Second phase constructor.
+*/
+EXPORT_C void CImageReadCodec::ConstructL()
+	{
+	// NO-OP - reserved in case we need to do Cheshire Cat at a later state. Should always be called.
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CImageReadCodec::~CImageReadCodec()
+	{
+	}
+
+/**
+Used to initialise the frame header data structures. 
+
+The default version of this function does nothing. It should be implemented by
+the codec to at least update the appropriate processing state of the current
+frame using its TFrameInfo structure.
+
+@param  aFrameInfo
+        A reference to a TFrameInfo object which will contain the current frame's header info
+@param  aFrameData
+        A reference to a TFrameInfo object which will contain the current frame's header data
+*/
+EXPORT_C void CImageReadCodec::InitFrameHeader(TFrameInfo& /*aFrameInfo*/, CFrameImageData& /*aFrameData*/)
+	{
+	}
+
+/**
+Processes the header for one frame.
+
+The default version of this function and simply returns EFrameComplete.  It
+should be implemented by the codec to at least update the appropriate
+processing state of the current frame using its TFrameInfo structure.
+
+@param  aData
+        A reference to a TBufPtr8 that contains the frame data.
+@return The completion status of this frame's processing
+*/
+EXPORT_C TFrameState CImageReadCodec::ProcessFrameHeaderL(TBufPtr8& /*aData*/)
+	{
+	return EFrameComplete;
+	}
+
+/**
+Processes/displays converted image data.
+
+This function is called on frame completion and on underflow. The default version of this function
+does nothing. It should be implemented by the codec if required. 
+
+If it is called on underflow for example, it can enable display of a partially decoded image. In such
+cases this function could display all the image data up to the point of the underflow.
+*/
+EXPORT_C void CImageReadCodec::Complete()
+	{
+	}
+
+/**
+Returns a new position and number of bytes to read for the data stream.
+
+The default version of this function does nothing.
+It should be implemented by the codec, if required.
+
+@param  aPosition
+        A reference to the returned new position.
+@param  aLength
+        A reference to the number of bytes to read.
+*/
+EXPORT_C void CImageReadCodec::GetNewDataPosition(TInt& /*aPosition*/, TInt& /*aLength*/)
+	{
+	}
+
+/**
+@internalComponent
+
+Sets the current frame number.
+Called by the framework before InitFrameHeader() and InitFrameL()
+
+@param  aFrameNumber
+        The current frame number
+*/
+void CImageReadCodec::SetCurrentFrame(TInt aFrameNumber)
+	{
+	iCurrentFrame = aFrameNumber;
+	}
+
+/**
+Return the current frame number
+
+@return	The current frame number
+*/
+EXPORT_C TInt CImageReadCodec::CurrentFrame() const
+	{
+	return iCurrentFrame;
+	}
+
+/**
+Calculates reduction factor based on the input parameters.
+The default Implementation is given here. It should be implemented by the Codecs, If required.
+
+@param  aOriginalSize
+        A reference to the original size of an image.
+@param  aReducedSize
+        A reference to the new size of an image.
+@return The reduction factor.
+*/
+
+EXPORT_C TInt CImageReadCodec::ReductionFactor(const TSize& aOriginalSize,const TSize& aReducedSize) const
+   {
+   if( (aReducedSize.iWidth<=0) || (aReducedSize.iHeight<=0))
+      {
+      return 0;
+      }
+   TInt reductionFactor = 0;
+   TInt roundup=0;
+   while( ((aOriginalSize.iWidth+roundup)>>reductionFactor) > aReducedSize.iWidth || 
+         ((aOriginalSize.iHeight+roundup)>>reductionFactor) > aReducedSize.iHeight)
+      {
+      reductionFactor++;
+      roundup=(1<<reductionFactor)-1;
+      }
+   return reductionFactor;
+   }
+
+/**
+Calculates reduced size of the decoded bitmap based on the input parameters and updates aReducedSize with this value.
+The default Implementation is given here. It should be implemented by the Codecs, If required.
+
+@param  aOriginalSize
+        A reference to the original size of an image.
+@param  aReducedFactor
+        The reduction factor to be applied
+@param  aReducedSize
+        A reference to the new size of an image.
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        KErrArgument
+*/
+
+EXPORT_C TInt CImageReadCodec::ReducedSize(const TSize& aOriginalSize,TInt aReductionFactor, TSize& aReducedSize) const
+   {
+   aReducedSize = aOriginalSize;
+   if (aReductionFactor<0)
+   	   {
+   	   return KErrArgument;
+   	   }
+   TInt roundup = aReductionFactor>0? (1<<aReductionFactor)-1: 0;
+   aReducedSize.SetSize(((aOriginalSize.iWidth+roundup)>>aReductionFactor),
+               ((aOriginalSize.iHeight+roundup)>>aReductionFactor) );
+   return KErrNone;            
+   }
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageReadCodec::ReservedVirtual1()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageReadCodec::ReservedVirtual2()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageReadCodec::ReservedVirtual3()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageReadCodec::ReservedVirtual4()
+	{
+	Panic(EReservedCall);
+	}
+
+// CImageProcessorReadCodec
+
+/**
+Default constructor.
+*/
+EXPORT_C CImageProcessorReadCodec::CImageProcessorReadCodec()
+	{
+	}
+
+/**
+Second phase constructor.
+*/
+EXPORT_C void CImageProcessorReadCodec::ConstructL()
+	{
+	CImageReadCodec::ConstructL();
+
+	iBody = CImageProcessorReadCodecBody::NewL();
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CImageProcessorReadCodec::~CImageProcessorReadCodec()
+	{
+	delete iBody;
+	}
+
+/**
+Returns a pointer to the codec's CImageProcessor.
+
+@return	A pointer to the codec's CImageProcessor derived object.
+*/
+EXPORT_C CImageProcessor* CImageProcessorReadCodec::ImageProcessor() const
+	{
+	return iBody->ImageProcessor();
+	}
+
+/**
+Sets the codec's CImageProcessor.
+
+Ownership is transferred.
+
+@param  aImageProc
+        A pointer to a full constructed CImageProcessor derived object.
+*/
+EXPORT_C void CImageProcessorReadCodec::SetImageProcessor(CImageProcessor *aImageProc)
+	{
+	iBody->SetImageProcessor(aImageProc);
+	}
+
+/**
+Returns the current position within the bitmap (const version).
+
+@return	A reference to a TPoint object specifying the location.
+*/
+EXPORT_C const TPoint& CImageProcessorReadCodec::Pos() const
+	{
+	return iBody->Pos();
+	}
+
+/**
+Returns the current position within the bitmap (non const version).
+
+@return	A reference to a TPoint object specifying the location.
+*/
+EXPORT_C TPoint& CImageProcessorReadCodec::Pos()
+	{
+	return iBody->Pos();
+	}
+
+/**
+Sets the current position within the bitmap.
+
+@param  aPos
+        A reference to a TPoint object specifying the location.
+*/
+EXPORT_C void CImageProcessorReadCodec::SetPos(const TPoint& aPos)
+	{
+	iBody->SetPos(aPos);
+	}
+
+// CImageMaskProcessorReadCodec
+
+/**
+Default constructor.
+*/
+EXPORT_C CImageMaskProcessorReadCodec::CImageMaskProcessorReadCodec()
+	{
+	}
+
+/**
+Second phase constructor.
+*/
+EXPORT_C void CImageMaskProcessorReadCodec::ConstructL()
+	{
+	CImageProcessorReadCodec::ConstructL();
+
+	iBody = CImageMaskProcessorReadCodecBody::NewL();
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CImageMaskProcessorReadCodec::~CImageMaskProcessorReadCodec()
+	{
+	delete iBody;
+	}
+
+/**
+Returns a pointer to the codec's CImageProcessor used when decoding
+the image mask.
+
+@return	A pointer to the codec's CImageProcessor derived object.
+*/
+EXPORT_C CImageProcessor* CImageMaskProcessorReadCodec::MaskProcessor() const
+	{
+	return iBody->MaskProcessor();
+	}
+
+/**
+Replaces a codec's existing CImageProcessor with a new fully constructed instance of the same
+object. 
+
+Ownership of the new instance is transferred.
+
+@param  aMaskProc
+        A pointer to a full constructed CImageProcessor derived object.
+*/
+EXPORT_C void CImageMaskProcessorReadCodec::SetMaskProcessor(CImageProcessor *aMaskProc)
+	{
+	iBody->SetMaskProcessor(aMaskProc);
+	}
+
+/**
+Constructor for this class.
+*/
+EXPORT_C CImageProcessorReadCodecExtension::CImageProcessorReadCodecExtension()
+	{
+	}
+
+EXPORT_C void CImageProcessorReadCodecExtension::ConstructL()
+	{
+	CImageProcessorReadCodec::ConstructL();
+	}
+
+/**
+Destructor for this class.
+*/
+EXPORT_C CImageProcessorReadCodecExtension::~CImageProcessorReadCodecExtension()
+	{
+	}
+
+EXPORT_C TInt CImageProcessorReadCodecExtension::ScalingCoefficient(const TSize& aOriginalSize, const TSize& aDesiredSize) const
+	{
+	TInt reductionFactor = ReductionFactor(aOriginalSize, aDesiredSize);
+	return -(reductionFactor+1);
+	}
+
+EXPORT_C TInt CImageProcessorReadCodecExtension::GetReducedSize(const TSize& aOriginalSize, TInt aScalingCoeff, TSize& aReducedSize) const
+	{
+	return ReducedSize(aOriginalSize, -(aScalingCoeff+1), aReducedSize);
+	}
+
+EXPORT_C CImageMaskProcessorReadCodecExtension::CImageMaskProcessorReadCodecExtension()
+	{
+	}
+
+EXPORT_C void CImageMaskProcessorReadCodecExtension::ConstructL()
+	{
+	CImageMaskProcessorReadCodec::ConstructL();
+	}
+
+EXPORT_C CImageMaskProcessorReadCodecExtension::~CImageMaskProcessorReadCodecExtension()
+	{
+	}
+
+EXPORT_C TInt CImageMaskProcessorReadCodecExtension::ScalingCoefficient(const TSize& aOriginalSize, const TSize& aDesiredSize) const
+	{
+	TInt reductionFactor = ReductionFactor(aOriginalSize, aDesiredSize);
+	return -(reductionFactor+1);
+	}
+
+EXPORT_C TInt CImageMaskProcessorReadCodecExtension::GetReducedSize(const TSize& aOriginalSize, TInt aScalingCoeff, TSize& aReducedSize) const
+	{
+	return ReducedSize(aOriginalSize, -(aScalingCoeff+1), aReducedSize);
+	}
+
+// CImageWriteCodec
+
+/**
+Default constructor.
+*/
+EXPORT_C CImageWriteCodec::CImageWriteCodec()
+	{
+	}
+
+/**
+Second phase constructor.
+*/
+EXPORT_C void CImageWriteCodec::ConstructL()
+	{
+	// NO-OP - reserved in case we need to do Cheshire Cat at a later state. Should always be called.
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CImageWriteCodec::~CImageWriteCodec()
+	{
+	}
+
+/**
+Performs initial processing of image data from an internally held buffer.
+
+Used to initialise the frame header. The default version of this function does nothing.
+It should be implemented by the codec, if required.
+
+@param  aDst
+        The destination buffer.
+@param  aSource
+        The source internally held buffer.
+*/
+EXPORT_C void CImageWriteCodec::InitFrameL(TBufPtr8& /*aDst*/, const CFbsBitmap& /*aSource*/)
+	{
+	}
+
+/**
+Returns the codec's source bitmap.
+
+@return	A pointer to the codec's source bitmap.
+*/
+EXPORT_C const CFbsBitmap* CImageWriteCodec::Source() const
+	{
+	return iSource;
+	}
+
+/**
+Sets the codec's source bitmap.
+
+Use this function if you need to process more than one internally held buffer. This 
+will be necessary if, for example, you need to add a bitmap mask to the destination buffer. 
+
+@param  aSource
+        A pointer to the codec's source bitmap.
+*/
+EXPORT_C void CImageWriteCodec::SetSource(const CFbsBitmap* aSource)
+	{
+	iSource = aSource;
+	}
+
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageWriteCodec::ReservedVirtual1()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageWriteCodec::ReservedVirtual2()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageWriteCodec::ReservedVirtual3()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageWriteCodec::ReservedVirtual4()
+	{
+	Panic(EReservedCall);
+	}
+
+// CFrameInfoStrings fns.
+
+CFrameInfoStrings::CFrameInfoStrings()
+	{
+	}
+
+/**
+Static factory function for creating instances of CFrameInfoStrings.
+Leaves the newly allocated object on the cleanup stack.
+
+@return A pointer to a fully constructed CFrameInfoStrings.
+*/
+EXPORT_C CFrameInfoStrings* CFrameInfoStrings::NewLC()
+	{
+	CFrameInfoStrings* result = new (ELeave) CFrameInfoStrings;
+	CleanupStack::PushL(result);
+	result->ConstructL();
+	return result;
+	}
+
+/**
+Static factory function for creating instances of CFrameInfoStrings.
+
+@return A pointer to a fully constructed CFrameInfoStrings.
+*/
+EXPORT_C CFrameInfoStrings* CFrameInfoStrings::NewL()
+	{
+	CFrameInfoStrings* result = NewLC();
+	CleanupStack::Pop(result);
+	return result;
+	}
+
+/**
+Destructor.
+
+Frees all resources owned by the object prior to its destruction.
+*/
+EXPORT_C CFrameInfoStrings::~CFrameInfoStrings()
+	{
+	delete iFrameInfoStrings;
+	}
+
+void CFrameInfoStrings::ConstructL()
+	{
+	iFrameInfoStrings = new (ELeave) CDesC16ArrayFlat(6);
+	}
+
+void CFrameInfoStrings::SetStringL(TInt aIndex, const TDesC& aString)
+	{
+	// ensure we have enough to just append to - as standard case
+	const TInt minRequired = aIndex;
+	while (iFrameInfoStrings->Count() < minRequired)
+		iFrameInfoStrings->AppendL(KNullDesC);
+
+	if (iFrameInfoStrings->Count()==minRequired)
+		iFrameInfoStrings->AppendL(aString);
+	else
+		{
+		// delete the original and insert
+		iFrameInfoStrings->Delete(aIndex);
+		iFrameInfoStrings->InsertL(aIndex, aString);
+		}
+
+	ASSERT(String(aIndex)==aString);
+	}
+
+/**
+Returns the string at position aIndex in the string table.
+The index runs from 0 to CFrameInfoStrings::Count() - 1.
+
+@param  aIndex
+        The position of the string to retrieve.
+
+@return	A pointer to the string at the given index.
+*/
+EXPORT_C const TPtrC CFrameInfoStrings::String(TInt aIndex) const
+	{
+	ASSERT(aIndex < iFrameInfoStrings->Count());
+	return (*iFrameInfoStrings)[aIndex];
+	}
+
+/**
+Returns the number of strings in the string table.
+
+@return	Returns the number of entries in the string table.
+*/
+EXPORT_C TInt CFrameInfoStrings::Count() const
+	{
+	return iFrameInfoStrings->Count();
+	}
+
+/**
+Returns a pointer to the 'decoder' entry string from this object.
+
+@return	A read-only pointer to the returned string.
+*/
+EXPORT_C const TPtrC CFrameInfoStrings::Decoder() const
+	{
+	return String(EDecoder);
+	}
+
+/**
+Adds the supplied string to this object as the 'decoder' entry.
+
+@param  aString
+        A descriptor containing the string to add.
+*/
+EXPORT_C void CFrameInfoStrings::SetDecoderL(const TDesC& aString)
+	{
+	SetStringL(EDecoder, aString);
+	}
+
+/**
+Retruns a pointer to the 'format' entry string from this object.
+
+@return	A pointer to the returned read-only string.
+*/
+EXPORT_C const TPtrC CFrameInfoStrings::Format() const
+	{
+	return String(EFormat);
+	}
+
+/**
+Adds the supplied string to this object as the 'format' entry.
+
+@param  aString
+        A descriptor containing the string to add.
+*/
+EXPORT_C void CFrameInfoStrings::SetFormatL(const TDesC& aString)
+	{
+	SetStringL(EFormat, aString);
+	}
+
+/**
+Returns a pointer to the 'dimensions' entry string from this object.
+
+@return	A pointer to the returned read-only string.
+*/
+EXPORT_C const TPtrC CFrameInfoStrings::Dimensions() const
+	{
+	return String(EDimensions);
+	}
+
+/**
+Adds the supplied string to this object as the 'dimensions' entry.
+
+@param  aString
+        A descriptor containing the string to add.
+*/
+EXPORT_C void CFrameInfoStrings::SetDimensionsL(const TDesC& aString)
+	{
+	SetStringL(EDimensions, aString);
+	}
+
+/**
+Returns a pointer to the 'depth' entry string from this object.
+
+@return	A pointer to the returned read-only string.
+*/
+EXPORT_C const TPtrC CFrameInfoStrings::Depth() const
+	{
+	return String(EDepth);
+	}
+
+/**
+Adds the supplied string to this object as the 'depth' entry.
+
+@param  aString
+        A descriptor containing the string to add.
+*/
+EXPORT_C void CFrameInfoStrings::SetDepthL(const TDesC& aString)
+	{
+	SetStringL(EDepth, aString);
+	}
+
+/**
+Returns a pointer to the 'details' entry string from this object.
+
+@return	A pointer to the returned read-only string.
+*/
+EXPORT_C const TPtrC CFrameInfoStrings::Details() const
+	{ 
+	return String(EDetails);
+	}
+
+/**
+Adds the supplied string to this object as the 'details' entry.
+
+@param  aString
+        A descriptor containing the string to add.
+*/
+EXPORT_C void CFrameInfoStrings::SetDetailsL(const TDesC& aString)
+	{
+	SetStringL(EDetails, aString);
+	}
+
+/**
+Get a list of the basic image types that can be decoded, based on the
+currently available decoder plugins.
+
+@param  aImageTypeArray
+        An empty array, into which this function will put a list of
+        entries. Each entry will consist of the "display string" from
+        the registry entry for a plugin that has been found and that is
+        a decoder for a basic image type, accompanied by the Uids for
+        that image type. Since we asked for basic types the second Uid,
+        for the image sub-type, will always be zero.
+
+        Ownership of the array is passed to the caller so, before the
+        array goes out of scope in the client, the caller must call
+        ResetAndDestroy() on it to free the entries.
+*/
+EXPORT_C void CImageDecoder::GetImageTypesL(RImageTypeDescriptionArray& aImageTypeArray)
+	{
+	ImageEnDecoderUtils::DoGetImageTypesL(KImageDecoderInterfaceUid, aImageTypeArray);
+	}
+
+/**
+For a given basic image type, get a list of the sub image types that can
+be decoded, based on the currently available decoder plugins.
+
+@param  aImageType
+        The basic image type for which you want a list of sub-types.
+@param  aSubTypeArray
+        An empty array, into which this function will put a list of
+        entries. Each entry will consist of the "display string" from
+        the registry entry for a plugin that has been found and that is
+        a decoder for a sub-type of the given basic image type,
+        accompanied by the Uids for the sub type. The first Uid, for
+        the basic type, will always correspond to aImageType.
+
+        Ownership of the array is passed to the caller so, before the
+        array goes out of scope in the client, the caller must call
+        ResetAndDestroy() on it to free the entries.
+*/
+EXPORT_C void CImageDecoder::GetImageSubTypesL(const TUid aImageType, RImageTypeDescriptionArray& aSubTypeArray)
+	{
+	ImageEnDecoderUtils::DoGetImageTypesL(KImageDecoderInterfaceUid, aSubTypeArray, aImageType);
+	}
+
+/**
+Get a list of the file extensions that can be decoded and their corresponding
+MIME types, based on the currently available decoder plugins.
+
+@param  aFileTypeArray
+        An empty array, into which this function will put a list of
+        entries. Each entry will consist of a file extension string for
+        which a decoder plugin has been found, accompanied by the
+        primary MIME type and then any secondary MIME types
+        (if present).
+        
+        Ownership of the array is passed to the caller so, before the
+        array goes out of scope in the client, the caller must call
+        ResetAndDestroy() on it to free the entries.
+*/
+EXPORT_C void CImageDecoder::GetFileTypesL(RFileExtensionMIMETypeArray& aFileTypeArray)
+	{
+	ImageEnDecoderUtils::DoGetFileTypesL(KImageDecoderInterfaceUid, aFileTypeArray);
+	}
+
+/**
+Get the primary MIME type of the decoder that will be used to
+decode a file.
+Some file types (like OTA or WBPM), which do not have unique 
+pattern in their header may not be recognised, in case when 
+the source file name doesn't have extension or, extension is 
+not common to that file type. Such files are not supported by this API.
+
+@param  aFs
+        A reference to a file server session to use.
+@param  aFileName
+        The name of the file for which a MIME type has to be determined
+@param	aMimeType
+        An empty descriptor in which the MIME type assosiated with the file
+        will be returned. Ownership is passed to the caller.
+*/
+EXPORT_C void CImageDecoder::GetMimeTypeFileL(RFs& /*aFs*/, const TDesC& aFileName, TDes8& aMimeType)
+	{
+	CContent* content = CContent::NewLC(aFileName, EContentShareReadWrite);
+	CData* data = content->OpenContentL(EPeek);
+	
+	CleanupStack::PushL(data);
+	TBool mimeTypeKnown = data->GetMimeTypeL(aMimeType);
+
+	if (!mimeTypeKnown)
+		{
+		TBuf8<KImageHeaderSize> imageHeader;
+		User::LeaveIfError(data->Read(imageHeader, KImageHeaderSize));
+
+		if (imageHeader.Length() < KImageHeaderSize) // There is not enough data in the file
+			{ // Get out - clean up and leave
+			User::Leave(KErrUnderflow);
+			}
+
+		DoGetMimeTypeL(aFileName, imageHeader, aMimeType);
+		}
+	CleanupStack::PopAndDestroy(2, content); // content, data
+	}
+
+/**
+Get the primary MIME type of the decoder that will be used to
+decode a descriptor.
+Some file types (like OTA or WBPM), which do not have unique 
+pattern in their header may not be recognised.
+Such files are not supported by this API
+
+@param  aImageData
+        A descriptor containing the image data for which a MIME
+        type has to be determined.
+@param  aMimeType
+        An empty descriptor in which the MIME type assosiated with the file
+        will be returned. Ownership is passed to the caller.
+*/
+EXPORT_C void CImageDecoder::GetMimeTypeDataL(const TDesC8& aImageData, TDes8& aMimeType)
+	{
+	TBuf8<KImageHeaderSize> imageHeader;
+
+	if (aImageData.Length() < KImageHeaderSize) // There is not enough data in this source
+		{ // Get out - clean up and leave
+		User::Leave(KErrUnderflow);
+		}
+
+	imageHeader = aImageData.Left(KImageHeaderSize);
+
+	DoGetMimeTypeL(KNullDesC, imageHeader, aMimeType);
+	}
+
+/**
+Gets the implementation information for a specific decoder plugin
+
+Ownership of the implementation information is passed to the caller.
+
+@param	aImplementationUid
+        The decoder implementation UID for which to retrieve implementation information
+@return	A pointer to the implementation information.
+*/
+EXPORT_C CImplementationInformationType* CImageDecoder::GetImplementationInformationL(TUid aImplementationUid)
+	{
+	CImplementationInformationType* implementationInformation;
+	implementationInformation = CImplementationInformationType::NewLC();
+	ImageEnDecoderUtils::DoGetImplementationInformationL(KImageDecoderInterfaceUid, *implementationInformation, aImplementationUid);
+	CleanupStack::Pop(implementationInformation);
+	return implementationInformation;
+	}
+
+/**
+Gets a list of the properties of a specific decoder plugin.
+
+@publishedAll
+@released
+@param	aImplementationUid
+        The decoder implementation UID for which the plugin properties need to be retrieved.
+@param	aPropertiesArray
+		The array of plugin properties owned by the specified decoder.
+		The caller has the ownership of the array.
+*/
+EXPORT_C void CImageDecoder::GetPluginPropertiesL(const TUid aImplementationUid, RUidDataArray& aPropertiesArray)
+	{
+	ImageEnDecoderUtils::DoGetPluginPropertiesL(KImageDecoderInterfaceUid, aImplementationUid, aPropertiesArray);
+	}
+
+/**
+@publishedAll
+@released
+
+Gets a list of decoder implementations UIDs which have a set of specific capabilities defined by UIDs.
+
+@param	aRequiredUids
+        The array containing the required UIDs (properties, image type, image sub-type or class UIDs).
+@param	aImplArray
+		The array containing the implementation UIDs of the available decoder plugins with the required UIDs.
+		The caller has the ownership of the array.
+*/
+EXPORT_C void CImageDecoder::GetInterfaceImplementationsL(const RUidDataArray& aRequiredUids, RUidDataArray& aImplArray)
+	{
+	ImageEnDecoderUtils::DoGetInterfaceImplementationsL(KImageDecoderInterfaceUid, aRequiredUids, aImplArray);
+	}
+
+/**
+@publishedAll
+@released
+
+Gets a list of decoder implementations UIDs which have a set of specific capabilities defined by UIDs.
+
+@param	aRequiredUids
+        The array containing the required UIDs (properties, image type, image sub-type or class UIDs).
+@param	aLength
+		The length of aRequiredUids (number of required UIDs).
+@param	aImplArray
+		The array containing the implementation UIDs of the available decoder plugins with the required UIDs.
+		The caller has the ownership of the array.
+*/	
+EXPORT_C void CImageDecoder::GetInterfaceImplementationsL(const TUid* aRequiredUids, const TInt aLength, RUidDataArray& aImplArray)
+	{
+	RUidDataArray requiredUids;
+	CleanupClosePushL(requiredUids);
+	for(TInt index = 0 ; index < aLength ; index++)
+		{
+		User::LeaveIfError(requiredUids.Append(aRequiredUids[index]));
+		}
+	ImageEnDecoderUtils::DoGetInterfaceImplementationsL(KImageDecoderInterfaceUid, requiredUids, aImplArray);	
+	CleanupStack::PopAndDestroy(1); //requiredUids
+	}
+	
+/**
+Create a list of decoders that support the specified MIME type.
+
+@param  aDecoderList
+        A list of decoders that support the given MIME type.
+@param  aMIMEType
+        The MIME type to decode.
+@param	aOptions
+		Extension options which must be supported by the plugin.
+*/
+void CImageDecoder::MimeTypeGetDecoderListL(RImplInfoPtrArray& aDecoderList, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	if (aMIMEType.Length() == 0)
+		{ // Get out, empty MIME type string
+		User::Leave(KErrArgument);
+		}
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	customMatchData->SetMatchType(EMatchMIMEType);
+	customMatchData->SetMatchStringL(aMIMEType);
+	customMatchData->SetOptions(aOptions);
+	customMatchData->SetExtensionOptions(aOptions);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+
+	TEComResolverParams resolverParams; // Parameters on which to match
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(KImageDecoderInterfaceUid, resolverParams, KImageConvertResolverUid, aDecoderList);
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+	}
+
+
+/**
+Create a list of decoders that support the specified image type.
+
+@param  aDecoderList
+        A list of decoders that support the specified image type.
+@param  aImageHeader
+        The header of the image file.
+@param  aImageType
+        The image base type.
+@param  aImageSubType
+        The image sub type.
+@param  aDecoderUid
+        The implementation UID for a specific codec or a decoder/encoder class UID.
+@param	aOptions
+		Extension options which must be supported by the plugin.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+*/
+void CImageDecoder::ImageTypeGetDecoderListL(RImplInfoPtrArray& aDecoderList, const TDesC8& aImageHeader, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid, const TOptions aOptions)
+	{
+	if (aDecoderUid != KNullUid)
+		{
+		RImplInfoPtrArray list;
+		CleanupResetAndDestroyPushL(list);
+		
+		REComSession::ListImplementationsL(KImageDecoderInterfaceUid, list);
+		
+		for (TInt i = 0; i < list.Count(); i++)
+			{
+			if (list[i]->ImplementationUid() == aDecoderUid)
+				{
+				User::LeaveIfError(aDecoderList.Append(list[i]));
+				}
+			else
+				{
+				delete list[i];
+				}
+			list[i] = NULL;
+			}
+		
+		CleanupStack::PopAndDestroy(&list);
+		if (aDecoderList.Count() > 0)
+			{
+			return;
+			}
+		}
+		
+	TBuf8<KImageHeaderSize> imageHeader;
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+
+	if ((aImageType != KNullUid) || (aDecoderUid != KNullUid))
+		{ // We have a specific image type we are trying to convert
+		customMatchData->SetMatchType(EMatchUids);
+		customMatchData->SetBaseType(aImageType);
+		customMatchData->SetSubType(aImageSubType);
+		customMatchData->SetImplementationType(aDecoderUid);
+		}
+	else
+		{
+		if (aImageHeader.Length() < KMinimumHeaderLength) // There is not enough data in the header
+			{ // Get out - clean up and leave
+			User::Leave(KErrUnderflow);
+			}
+		imageHeader = aImageHeader.Left(KImageHeaderSize);
+		customMatchData->SetMatchType(EMatchString);
+		customMatchData->SetMatchStringL(imageHeader);
+		}
+
+	customMatchData->SetOptions(aOptions);
+	customMatchData->SetExtensionOptions(aOptions);
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+
+	TEComResolverParams resolverParams; // Parameters on which to match
+	resolverParams.SetDataType(packageDes);
+
+	#if defined(__ICL_PROFILING)
+	// intended for use with TProfImage only
+	RDebug::ProfileStart(2);
+	TRAPD(err,REComSession::ListImplementationsL(KImageDecoderInterfaceUid, resolverParams, KImageConvertResolverUid, aDecoderList));
+	RDebug::ProfileEnd(2);
+	User::LeaveIfError(err);
+	#else
+	REComSession::ListImplementationsL(KImageDecoderInterfaceUid, resolverParams, KImageConvertResolverUid, aDecoderList);
+	#endif  // defined(__ICL_PROFILING)
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+	}
+
+/**
+@internalComponent
+
+Creates a list of decoders that support the specified file extension.
+
+@param  aDecoderList
+        A list of decoders that support the given file extension.
+@param  aFileName
+        The file name from which the file extension will be taken.
+@param	aOptions
+		Extension options which must be supported by the plugin.
+*/
+void CImageDecoder::SuffixTypeGetDecoderListL(RImplInfoPtrArray& aDecoderList, const TDesC& aFileName, const TOptions aOptions)
+	{
+	TParse fileName;
+	fileName.Set(aFileName,NULL,NULL);
+
+	//No file extension
+	if (!fileName.ExtPresent())
+		User::Leave(KErrNotFound);
+
+	//Get the suffix
+	TPtrC suffix(fileName.Ext());
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	customMatchData->SetMatchType(EMatchFileSuffix);
+	customMatchData->SetFileSuffixL(suffix);
+	customMatchData->SetOptions(aOptions);
+	customMatchData->SetExtensionOptions(aOptions);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+
+	TEComResolverParams resolverParams; // Parameters on which to match
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(KImageDecoderInterfaceUid, resolverParams, KImageConvertResolverUid, aDecoderList);
+
+	CleanupStack::PopAndDestroy(2,customMatchData); // package, customMatchData
+	}
+
+/**
+@internalTechnology
+
+Scans a sorted list of decoders for the first one that can decode the image.
+
+@param  aDecoderList
+        A list of decoders that support the image format.
+@param  aFs
+        A file server session for the decoder to use.
+@param  aSourceFilename
+        The filename of the file to decode.
+@param  aOptions
+        The options to use during decoding.
+
+@return A pointer to the decoder.
+*/
+
+CImageDecoder* CImageDecoder::FileFindDecoderNewL(const RImplInfoPtrArray& aDecoderList, RFs& aFs, const TDesC& aSourceFilename, const TOptions aOptions, const TDesC& aUniqueId)
+	{
+	TInt noOfDecoders = aDecoderList.Count();
+
+	if (noOfDecoders == 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	CImageDecoder* decoder = NULL;
+	TInt decoderNo = 0;
+	TInt error = KErrNone;
+
+	do
+		{
+		const CImplementationInformation& decoderInfo = *(aDecoderList[decoderNo++]);
+
+		TRAP(error,decoder=FileDecoderNewL(decoderInfo, aFs, aSourceFilename, aOptions, aUniqueId));
+
+		if (error != KErrCorrupt && error != KErrNotSupported && error != KErrNotFound)
+			break;
+		}
+	while(decoderNo < noOfDecoders);
+
+	if(error!=KErrNone)
+		{
+		ASSERT(decoder==NULL);
+		if (error == KErrCorrupt || error == KErrNotSupported)
+			error = KErrNotFound;
+		User::Leave(error);
+		}
+
+	return decoder;
+	}
+	
+/**
+@internalTechnology
+
+Create a construct that can create a decoder and call
+functions to initialise the decoder with the image data.
+
+@param  aDecoderInfo
+        Implementation information for the decoder to be created.
+@param  aFs
+        A file server session for the decoder to use.
+@param  aSourceFilename
+        The filename of the file to decode.
+@param  aOptions
+        Options the decoder must use.
+
+@return	A pointer to the decoder.
+*/
+
+CImageDecoder* CImageDecoder::FileDecoderNewL(const CImplementationInformation& aDecoderInfo, RFs& aFs, const TDesC& aSourceFilename, const TOptions aOptions, const TDesC& aUniqueId)
+	{
+	CImageDecodeConstruct* construct = NULL;
+	construct = NewDecodeConstructL(aDecoderInfo, aOptions);
+	ASSERT(construct!= NULL);
+
+	CImageDecoder* decoder = NewL(construct, aOptions); // note NewL takes ownership of construct - don't push on stack
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+
+	decoder->iRelay->SetUniqueIdL(aUniqueId);
+
+	decoder->iRelay->SetFileL(aFs, aSourceFilename, aOptions);
+	decoder->iRelay->HandleNewlyOpenedImageL();
+
+	CleanupStack::Pop(decoder);
+	return decoder;
+	}
+
+/**
+@internalTechnology
+@released
+Scan a sorted list of decoders for the first one that can decode the image.
+
+@param  aDecoderList
+        A list of decoders that support the image format.
+@param  aFs
+        A file server session for the decoder to use.
+@param  aSourceData
+        The data to decode.
+@param  aOptions
+        Options to use during decoding.
+
+@return A pointer to the decoder.
+ */
+CImageDecoder* CImageDecoder::DataFindDecoderNewL(const RImplInfoPtrArray& aDecoderList, RFs& aFs, const TDesC8& aSourceData, const TOptions aOptions)
+	{
+	TInt noOfDecoders = aDecoderList.Count();
+
+	if(noOfDecoders == 0)
+		User::Leave(KErrNotFound);
+
+	CImageDecoder* decoder = NULL;
+	TInt decoderNo = 0;
+	TInt error = KErrNone;
+	do
+		{
+		const CImplementationInformation& decoderInfo = *(aDecoderList[decoderNo++]);
+		TRAP(error,decoder=DataDecoderNewL(decoderInfo, aFs, aSourceData, aOptions));
+		if (error != KErrCorrupt && error != KErrNotSupported && error != KErrNotFound)
+			break;
+		}
+	while(decoderNo < noOfDecoders);
+
+	if(error!=KErrNone)
+		{
+		ASSERT(decoder==NULL);
+		if (error == KErrCorrupt || error == KErrNotSupported)
+			error = KErrNotFound;
+		User::Leave(error);
+		}
+
+	return decoder;
+	}
+
+/**
+@internalTechnology
+@released
+Create a construct that can create a decoder and call
+functions to initialise the decoder with the image data.
+
+@param  aDecoderInfo
+        Implementation information for the decoder to be created.
+@param  aFs
+        A file server session for the decoder to use.
+@param  aSourceData
+        The data to decode.
+@param  aOptions
+        Options the decoder must use.
+
+@return	A pointer to the decoder.
+*/
+CImageDecoder* CImageDecoder::DataDecoderNewL(const CImplementationInformation& aDecoderInfo, RFs& aFs, const TDesC8& aSourceData, const TOptions aOptions)
+	{
+	CImageDecodeConstruct* construct = NULL;
+	construct = NewDecodeConstructL(aDecoderInfo, aOptions);
+	ASSERT(construct!= NULL);
+
+	CImageDecoder* decoder = NewL(construct, aOptions); // note NewL takes ownership of construct - don't push on stack
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+
+	decoder->iRelay->SetDataL(aFs, aSourceData, aOptions);
+	decoder->iRelay->HandleNewlyOpenedImageL();
+
+	CleanupStack::Pop(decoder);
+	return decoder;
+	}
+
+/**
+@internalTechnology
+
+Create a construct object for the specified decoder.
+
+@param  aDecoderInfo
+        Implementation information for the decoder to be created.
+@param	aOptions
+		Extension options which must be supported by the plugin.
+@return	A construct object that can create the decoder.
+*/
+CImageDecodeConstruct* CImageDecoder::NewDecodeConstructL(const CImplementationInformation& aDecoderInfo, const TOptions aOptions)
+	{
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	COpaqueDataParse* parse = COpaqueDataParse::NewLC(aDecoderInfo.OpaqueData());
+
+	customMatchData->SetMatchType(EMatchUids);
+	customMatchData->SetBaseType(parse->ImageTypeUid());
+	customMatchData->SetSubType(parse->ImageSubTypeUid());
+	customMatchData->SetImplementationType(aDecoderInfo.ImplementationUid());
+
+	CleanupStack::PopAndDestroy(parse);
+
+	customMatchData->SetOptions(aOptions);
+	customMatchData->SetExtensionOptions(aOptions);
+	HBufC8* package = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+
+	TEComResolverParams resolverParams;
+	resolverParams.SetDataType(packageDes);
+
+	CImageDecodeConstruct* construct = NULL;
+#if defined(__ICL_PROFILING)
+	// intended for use with TProfImage only
+	RDebug::ProfileStart(3);
+	TRAPD(err, construct = STATIC_CAST(CImageDecodeConstruct*,
+			REComSession::CreateImplementationL(KImageDecoderInterfaceUid,
+			_FOFF(CImageDecodeConstruct, iDtorIDKey),
+			resolverParams,
+			KImageConvertResolverUid)));
+	RDebug::ProfileEnd(3);
+	User::LeaveIfError(err);
+#else
+	construct = STATIC_CAST(CImageDecodeConstruct*,
+			REComSession::CreateImplementationL(KImageDecoderInterfaceUid,
+			_FOFF(CImageDecodeConstruct, iDtorIDKey),
+			resolverParams,
+			KImageConvertResolverUid));
+#endif  // defined(__ICL_PROFILING)
+
+	ASSERT(construct!=NULL);
+
+	CleanupStack::PopAndDestroy(2, customMatchData); //package, customMatchData
+
+	return construct;
+	}
+
+/**
+@internalTechnology
+
+Get the MIME type for a given match string.
+
+@param  aFileName
+        The file name of the image file.
+@param  aMatchString
+        An image header of an image file.
+@param  aMimeType
+        The primary MIME type returned.
+*/
+void CImageDecoder::DoGetMimeTypeL(const TDesC& aFileName, const TDesC8& aMatchString, TDes8& aMimeType)
+	{
+	// Get a list of decoders that will decode the image.
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+	CImageDecoder::ImageTypeGetDecoderListL(decoderList, aMatchString, KNullUid, KNullUid, KNullUid);
+
+	// Try to match by file extension.
+	// aFileName will be KNullDesC when called from GetMimeTypeDataL()
+	if(aFileName!=KNullDesC && decoderList.Count() == 0)
+		CImageDecoder::SuffixTypeGetDecoderListL(decoderList, aFileName);
+
+	if(decoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+    TInt decoderNo = 0;
+
+#if defined (__GET_MIME_TYPE_THOROUGH)
+	RFs fs;
+	CleanupClosePushL(fs);
+    User::LeaveIfError(fs.Connect());
+	TInt noOfDecoders = decoderList.Count();
+
+    CImageDecoder* decoder = NULL;
+    TInt error = KErrNotFound;
+	while(decoderNo < noOfDecoders)
+		{
+		const CImplementationInformation& decoderInfo = *(decoderList[decoderNo]);
+        TRAP(error,decoder=DataDecoderNewL(decoderInfo, fs, aMatchString, EOptionAllowZeroFrameOpen));
+  		// if decoder didn't match, then it should return KErrCorrupt,
+		// but we also accept KErrNotSupported & KErrNotFound
+		if (error != KErrCorrupt && error != KErrNotSupported && error != KErrNotFound)
+			break;
+		decoderNo++;
+		}
+
+	if (error!=KErrNone)
+		{
+		ASSERT(decoder==NULL);
+		if (error == KErrCorrupt || error == KErrNotSupported)
+			error = KErrNotFound;
+		User::Leave(error);
+		}
+    delete decoder;
+	CleanupStack::PopAndDestroy(&fs); 
+#endif  // defined (__GET_MIME_TYPE_THOROUGH)
+
+	//Use the highest rated decoder.
+	CImageDecodeConstruct* construct = NewDecodeConstructL(*decoderList[decoderNo]);
+	CleanupStack::PopAndDestroy(&decoderList);
+	if (construct == NULL)
+		{ // We didn't get a match - leave
+		User::Leave(KErrNotFound); 
+		}
+	CleanupStack::PushL(construct);
+
+	// Determine the primary Mime type of the decoder	
+	CImplementationInformationType* implementationInformation = NULL;
+	implementationInformation = GetImplementationInformationL(construct->ImplementationUid());
+	CleanupStack::PushL(implementationInformation);
+
+	TPtrC8 opaqueDataPtr = implementationInformation->OpaqueData();
+	COpaqueDataParse* parse = COpaqueDataParse::NewLC(opaqueDataPtr);
+
+	if(parse->OnlyUidsAvail())
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	parse->EnsureMIMETypesReadL();
+
+	aMimeType = parse->MIMEType(0);
+
+	CleanupStack::PopAndDestroy(3); // parse, ImplementationInformation, decoderPtr
+	}
+
+/**
+Create a decoder for the image in the named file. The client supplies a
+MIME type which will be used to try and select an appropriate plugin
+decoder. If it finds a decoder it creates it and then goes on to use that
+decoder to scan the beginning of the image file.
+
+If any file related errors are encountered opening the specified file, this 
+function leaves with an appropriate file related leave code.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceFilename
+        The name of the file to be decoded.
+@param  aMIMEType
+        The MIME type of the image in the file.
+@param	aOptions
+        Decoder options to use.
+
+@return	Returns a pointer to the newly created decoder.
+
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        Either the specific plugin decoder for this file hasn't been found, or the file itself is missing.
+
+@see    TOptions
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFs& aFs, const TDesC& aSourceFilename, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	return CImageDecoder::FileNewImplL(aFs, aSourceFilename, aMIMEType, KDefaultContentObject, EPeek, aOptions);
+	}
+
+/**
+Create a decoder for the image in the named file. The client supplies a
+MIME type which will be used to try and select an appropriate plugin
+decoder. If it finds a decoder it creates it and then goes on to use that
+decoder to scan the beginning of the image file.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceFilename
+        The name of the file to be decoded.
+@param  aMIMEType
+        The MIME type of the image in the file.
+@param  aIntent
+        The DRM Intent for image conversion.
+@param  aOptions
+        The decoder options to use.
+
+@return A pointer to the newly created decoder.
+
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        Either the specific plugin decoder for this file hasn't been found, or the file itself is missing.
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFs& aFs, const TDesC& aSourceFilename, const TDesC8& aMIMEType, TIntent aIntent, const TOptions aOptions)
+	{
+	return CImageDecoder::FileNewImplL(aFs, aSourceFilename, aMIMEType, KDefaultContentObject, aIntent, aOptions);
+	}
+
+/**
+Create a decoder for the image in the named file. The client supplies a
+MIME type which will be used to try and select an appropriate plugin
+decoder. If it finds a decoder it creates it and then goes on to use that
+decoder to scan the beginning of the image file.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSource
+        An interface between filename based and file handle.
+@param  aMIMEType
+        The MIME type of the image in the file.
+@param  aOptions
+        The decoder options to use. Specifying one of more extension options (for example EOptionExtCrop) can be used to cause the 
+		to cause a plugin to load which supports the image type and supports the requested extensions.
+
+@return A pointer to the newly created decoder.
+
+@leave  KErrNotSupported
+        A matching decoder could not be found for the MIME type.
+@leave	KErrNotFound
+		Either the specific plugin decoder for this source image hasn't been found, or the source image itself is missing, or
+		a plugin with the requested extensions cannot be found.
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFs& aFs, const TMMSource& aSource, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	if (aSource.SourceType()==KUidMMFileHandleSource)
+		{
+		const TMMFileHandleSource& source = static_cast<const TMMFileHandleSource&>(aSource);
+		return CImageDecoder::FileNewImplL(source.Handle(), aMIMEType, source.UniqueId(), source.Intent(), aOptions);
+		}
+	else if (aSource.SourceType()==KUidMMFileSource)
+		{
+		const TMMFileSource& source = static_cast<const TMMFileSource&>(aSource);
+		return CImageDecoder::FileNewImplL(aFs, source.Name(), aMIMEType, source.UniqueId(), source.Intent(), aOptions);
+		}
+	else
+		{
+		// unknown source type
+		User::Leave(KErrNotSupported);
+		return NULL;
+		}
+	}
+
+/**
+Create a decoder for the image in the named source.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSource
+        An interface between filename based and file handle.
+@param  aOptions
+        The decoder options to use. Specifying one of more extension options (for example EOptionExtCrop) can be used to cause the 
+		to cause a plugin to load which supports the image type and supports the requested extensions.
+@param  aImageType
+        The image type of the image in the file.
+@param  aImageSubType
+        The image sub-type of the image in the file.
+@param  aDecoderUid
+        The implementation UID for a specific codec or a decoder/encoder class UID.        
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+@return A pointer to the newly created decoder.
+
+@leave  KErrNotSupported
+        A matching decoder could not be found for the MIME type.
+@leave  KErrNotFound
+        Either the specific plugin decoder for this source image hasn't been found, or the source image itself is missing.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFs& aFs, const TMMSource& aSource, 
+                                                const TOptions aOptions, const TUid aImageType, 
+                                                const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	if (aSource.SourceType()==KUidMMFileHandleSource)
+		{
+		const TMMFileHandleSource& source = static_cast<const TMMFileHandleSource&>(aSource);
+		return CImageDecoder::FileNewImplL(source.Handle(), source.UniqueId(), source.Intent(), aOptions, aImageType, aImageSubType, aDecoderUid);
+		}
+	else if (aSource.SourceType()==KUidMMFileSource)
+		{
+		const TMMFileSource& source = static_cast<const TMMFileSource&>(aSource);
+		return CImageDecoder::FileNewImplL(aFs, source.Name(), source.UniqueId(), source.Intent(), aOptions, aImageType, aImageSubType, aDecoderUid);
+		}
+	else
+		{
+		// unknown source type
+		User::Leave(KErrNotSupported);
+		return NULL;
+		}
+	}
+
+/**
+
+Sets the properties for the Image decoder.
+
+@param  aProperty
+        The property to set.
+@param  aValue
+        The value of the property.
+               
+@return KErrNone if successful, otherwise one of the system-wide errors.
+*/
+EXPORT_C TInt CImageDecoder::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
+	{
+	ASSERT(ValidProperties());
+	return iRelay->SetAgentProperty(aProperty, aValue);
+	}
+
+/**
+@internalTechnology
+
+Creates a decoder for the image in the named file. The client supplies a
+MIME type which will be used to try and select an appropriate plugin
+decoder. If it finds a decoder it creates it and then goes on to use that
+decoder to scan the beginning of the image file.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceFilename
+        The name of the file to be decoded.
+@param  aMIMEType
+        The MIME type of the image in the file.
+@param  aUniqueId
+        The object to open for reading. If the UniqueId is set to KNullDesC the entire file will be opened for reading with no transformation.
+@param  aIntent
+        The DRM Intent for image conversion.
+@param  aOptions
+        The decoder options to use.
+
+@return	A pointer to the newly created decoder.
+
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        Either the specific plugin decoder for this file hasn't been found, or the file itself is missing.
+*/
+
+CImageDecoder* CImageDecoder::FileNewImplL(RFs& aFs, const TDesC& aSourceFilename, const TDesC8& aMIMEType, const TDesC& aUniqueId, TIntent aIntent, const TOptions aOptions)
+	{
+	CContent* content = NULL;
+	content = GetContentLC(aSourceFilename);
+	CData* data = content->OpenContentL(aIntent, aUniqueId); // check file presence, evaluate (not execute) intent
+	CleanupStack::PopAndDestroy(content);
+
+	delete data; // close file
+	
+
+	//Get a sorted list of decoders that will decode the image
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+	CImageDecoder::MimeTypeGetDecoderListL(decoderList, aMIMEType, aOptions);
+
+	CImageDecoder* decoder = NULL;
+	decoder = CImageDecoder::FileFindDecoderNewL(decoderList, aFs, aSourceFilename, aOptions, aUniqueId);
+
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+	decoder->iRelay->SetIntent(aIntent);
+
+	CleanupStack::Pop(decoder);
+	CleanupStack::PopAndDestroy(&decoderList);
+	return decoder;
+	}
+
+/**
+Create a decoder for the image in the source buffer. The client supplies a
+MIME type which will be used to try and select an appropriate plugin
+decoder. If a decoder is found it is created and then used to scan
+the beginning of the image file.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceData
+        The buffer containing the image to be decoded. Note that the framework 
+        doesn't take a copy of the actual data, therefore both the descriptor
+        object and the data must persist during decoding.
+@param  aMIMEType
+        The MIME type of the image in the file(used to determine the plugin
+		to create).
+@param  aOptions
+        The decoder options to use. Specifying one of more extension options (for example EOptionExtCrop) can be used to cause the 
+		to cause a plugin to load which supports the image type and supports the requested extensions.
+
+@return	Returns a pointer to the newly created decoder.
+
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        No appropriate plugin decoder for this image has been found.
+
+@see    TOptions
+*/
+EXPORT_C CImageDecoder* CImageDecoder::DataNewL(RFs& aFs, const TDesC8& aSourceData, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	//Get a list of decoders that will decode the image
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+	CImageDecoder::MimeTypeGetDecoderListL(decoderList, aMIMEType, aOptions);
+
+	CImageDecoder* decoder = NULL;
+	decoder = CImageDecoder::DataFindDecoderNewL(decoderList, aFs, aSourceData, aOptions);
+	ASSERT(decoder!=NULL);
+
+	CleanupStack::PopAndDestroy(&decoderList);
+	return decoder;
+	}
+
+/**
+Create a decoder for the image in the named file. 
+
+If the client supplies an image type (and sub-type, if applicable) or decoder 
+UID, these will be used to try and select an appropriate plugin decoder. If 
+not, then the selection will be done by matching the image header in the file. 
+If it finds a decoder, it will be created and then used to scan the beginning 
+of the image file.
+
+Note: Every image format has two IDs, known as the type and the sub-type (although 
+generally the sub-type is KNullUid). To retrieve a list of supported types and 
+sub-types that can be decoded, use the static functions GetImageTypesL() and 
+GetImageSubTypesL().
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceFilename
+        The name of the file to be decoded.
+@param	aOptions
+        Decoder options to use.
+@param  aImageType
+        The image type of the image in the file (optional, defaults to KNullUid).
+@param  aImageSubType
+        The image sub-type of the image in the file (optional, defaults to KNullUid).
+@param  aDecoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+@return	Returns a pointer to the newly created decoder.
+
+@leave  KErrUnderflow
+        Not enough data in file to identify which plugin decoder to use.
+@leave  KErrNotFound
+        Either the appropriate plugin decoder for this file hasn't been found, or the file itself is missing.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+
+@see    TOptions
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFs& aFs, const TDesC& aSourceFilename, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	return CImageDecoder::FileNewImplL(aFs, aSourceFilename, KDefaultContentObject, EPeek, aOptions, aImageType, aImageSubType, aDecoderUid);
+	}
+
+/**
+Creates a decoder for the image in the named file. If the client supplies an
+image type (and sub-type, if applicable) or decoder UID, these will be used
+to try and select an appropriate plugin decoder. If not, then the selection
+will be done by matching the image header in the file. If it finds a decoder
+it creates it and then goes on to use that decoder to scan the beginning of
+the image file.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceFilename
+        The name of the file to be decoded.
+@param  aIntent
+        The DRM Intent for image conversion.
+@param  aOptions
+        The decoder options to use. See TOptions.
+@param  aImageType
+        The image type of the image in the file (optional, defaults to KNullUid).
+@param  aImageSubType
+        The image sub-type of the image in the file (optional, defaults to KNullUid).
+@param  aDecoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return	A pointer to the newly created decoder.
+
+@leave  KErrUnderflow
+        Not enough data in file to identify which plugin decoder to use.
+@leave  KErrNotFound
+        Either the appropriate plugin decoder for this file hasn't been found, or the file itself is missing.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+
+@see     TOptions
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFs& aFs, const TDesC& aSourceFilename, TIntent aIntent, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	return CImageDecoder::FileNewImplL(aFs, aSourceFilename, KDefaultContentObject, aIntent, aOptions, aImageType, aImageSubType, aDecoderUid);
+	}
+
+/**
+@internalTechnology
+
+Creates a decoder for the image in the named file. If the client supplies an
+image type (and sub-type, if applicable) or decoder UID, these will be used
+to try and select an appropriate plugin decoder. If not, then the selection
+will be done by matching the image header in the file. If it finds a decoder
+it creates it and then goes on to use that decoder to scan the beginning of
+the image file.
+
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceFilename
+        The name of the file to be decoded.
+@param  aUniqueId
+        The object to open for reading. If the UniqueId is set to KNullDesC the entire file will be opened for reading with no transformation.
+@param  aIntent
+        The DRM Intent for image conversion
+@param  aOptions
+        The decoder options to use. See TOptions.
+@param  aImageType
+        The image type of the image in the file (optional, defaults to KNullUid).
+@param  aImageSubType
+        The image sub-type of the image in the file (optional, defaults to KNullUid).
+@param  aDecoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return A pointer to the newly created decoder.
+
+@leave  KErrUnderflow
+        Not enough data in file to identify which plugin decoder to use.
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        Either the appropriate plugin decoder for this file hasn't been found, or the file itself is missing.
+@panic  ImageConversion 19
+        No base type given for sub-type.
+
+@see    TOptions
+ */
+
+CImageDecoder* CImageDecoder::FileNewImplL(RFs& aFs, const TDesC& aSourceFilename, const TDesC& aUniqueId, const TIntent aIntent, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	if ((aImageType == KNullUid) && (aImageSubType != KNullUid))
+		{ // Get out, no base type given for sub-type
+		Panic(EIllegalImageSubType); 
+		}
+
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+
+	CContent* content = NULL;
+	content = GetContentLC(aSourceFilename);
+	CData* data = content->OpenContentL(aIntent, aUniqueId);
+	CleanupStack::PopAndDestroy(content);
+
+	CleanupStack::PushL(data);
+
+	if (aImageType == KNullUid && aDecoderUid == KNullUid)
+		{ 
+		TBuf8<KMaxMimeLength> mimeType;
+		if (data->GetMimeTypeL(mimeType))
+			{
+			// try to find a controller based on MIME type
+			CImageDecoder::MimeTypeGetDecoderListL(decoderList, mimeType, aOptions);
+			}
+		if (decoderList.Count()==0)
+			{
+			// read header data
+			TBuf8<KImageHeaderSize> imageHeader;
+			User::LeaveIfError(data->Read(imageHeader, KImageHeaderSize));
+			CImageDecoder::ImageTypeGetDecoderListL(decoderList, imageHeader, aImageType, aImageSubType, aDecoderUid, aOptions);
+			}
+		}
+	else
+		{
+		TBuf8<KImageHeaderSize> imageHeader;
+		User::LeaveIfError(data->Read(imageHeader, KImageHeaderSize));
+		CImageDecoder::ImageTypeGetDecoderListL(decoderList, imageHeader, aImageType, aImageSubType, aDecoderUid, aOptions);
+		}
+	
+	CleanupStack::PopAndDestroy(1, data); //data
+
+	//Try to match by file extension only
+	//1) If no plugin was found and 
+	//2) No specific decoder or format was specified
+	const TBool formatSpecified = (aImageType!=KNullUid || aImageSubType!=KNullUid || aDecoderUid!=KNullUid);
+	if(decoderList.Count()==0 && !formatSpecified)
+		{
+		CImageDecoder::SuffixTypeGetDecoderListL(decoderList, aSourceFilename, aOptions);
+		}
+
+	CImageDecoder* decoder = NULL;
+	decoder = CImageDecoder::FileFindDecoderNewL(decoderList, aFs, aSourceFilename, aOptions, aUniqueId);
+
+
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+	decoder->iRelay->SetIntent(aIntent);
+
+	CleanupStack::Pop(decoder);
+	CleanupStack::PopAndDestroy(&decoderList);
+	return decoder;
+	}
+
+
+/**
+Creates a decoder for the image in the source buffer. 
+
+If the client supplies an image type (and sub-type, if applicable) or decoder UID, 
+these will be used to try and select an appropriate plugin decoder. If not, then 
+the selection will be done by matching the image header from the buffer. If it
+finds a decoder, it is created and then used to scan the beginning of the image
+buffer.
+
+@param  aFs
+        A reference to a file server session for the decoder to use.
+@param  aSourceData
+        The buffer containing the image to be decoded. Note that the framework 
+        doesn't take a copy of the actual data, therefore both the descriptor
+        object and the data must persist during decoding.
+@param  aOptions
+        Decoder options to use.
+@param  aImageType
+        The image type of the image in the file (optional, defaults to KNullUid).
+@param  aImageSubType
+        The image sub-type of the image in the file (optional, defaults to KNullUid).
+@param	aDecoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return	Returns a pointer to the newly created decoder.
+
+@leave  KErrUnderflow
+        Not enough data in descriptor to identify which plugin decoder to use.
+@leave  KErrNotFound
+        No appropriate plugin decoder for this image has been found.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+
+@see    TOptions
+*/
+EXPORT_C CImageDecoder* CImageDecoder::DataNewL(RFs& aFs, const TDesC8& aSourceData, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	if ((aImageType == KNullUid) && (aImageSubType != KNullUid))
+		{ // Get out, no base type given for sub-type
+		Panic(EIllegalImageSubType); 
+		}
+
+	//Get a list of decoders that will decode the image
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+	CImageDecoder::ImageTypeGetDecoderListL(decoderList, aSourceData, aImageType, aImageSubType, aDecoderUid, aOptions);
+
+	CImageDecoder* decoder = NULL;
+	decoder = CImageDecoder::DataFindDecoderNewL(decoderList, aFs, aSourceData, aOptions);
+	ASSERT(decoder!=NULL);
+
+	CleanupStack::PopAndDestroy(&decoderList);
+	return decoder;
+
+
+	}
+
+/**
+@internalTechnology
+
+Called internally to create a CImageDecoder and associated iRelay body
+
+This member is internal and not intended for use.
+*/
+CImageDecoder* CImageDecoder::NewL(CImageDecodeConstruct* aConstruct, TOptions aOptions)
+	{
+	CleanupStack::PushL(aConstruct); // we take ownership of this until can pass to relay
+	CImageDecoder* self = aConstruct->NewDecoderL(); // typically will callback to CImageDecoder::NewL()
+	CleanupStack::PushL(self);
+	TBool alwaysThread = (aOptions & EOptionAlwaysThread)!=EFalse;
+	self->iRelay = MImageDecoderRelay::NewL(aConstruct, alwaysThread);
+	CleanupStack::Pop(2); // self and construct
+	self->iRelay->TransferConstructOwnership();
+	return self;
+	}
+
+/**
+@internalTechnology
+
+Actual factory function for CImageDecoder - ie. it creates the object
+Called back plugin - to allow plugin to override if required
+
+This member is internal and not intended for use.
+*/
+CImageDecoder* CImageDecoder::NewL()
+	{
+	CImageDecoder* self = new (ELeave) CImageDecoder;
+	return self;
+	}
+
+/**
+Constructor for this class.
+@internalTechnology
+*/
+EXPORT_C CImageDecoder::CImageDecoder()
+	{
+	}
+
+/**
+Destructor for this class.
+
+If using a local file session, it closes it.
+It also informs ECom that has finished with the decoder instance.
+
+Frees all resources owned by the object prior to its destruction.
+*/
+EXPORT_C CImageDecoder::~CImageDecoder()
+	{
+	Cancel();
+
+	delete iRelay;
+	}
+
+/**
+Start decoding an image frame asynchronously.
+
+@pre
+The destination bitmap aDestination, must be created before the call to
+Convert() is made. aDestination must be large enough to contain the frame and
+be set to the required display mode. FrameInfo() can be used to obtain
+the size and display mode of the frame.
+
+When the conversion is complete, successfully or otherwise, the status is 
+returned in aRequestStatus. 
+
+If the operations completes with KErrUnderflow, then there is insufficient 
+information in the descriptor. In this situation, ContinueConvert() should be 
+called repeatedly until the descriptor has accumulated enough information 
+for ContinueConvert() to complete with KErrNone.It is the responsibility of the 
+caller to ensure that the original data source used to create this decoder object 
+gets enough information. If there is no data available then a caller can ignore 
+this error code and use partially decoded image.
+
+@param  aRequestStatus
+        Request status. On completion contains an error code.
+        KErrNone if frame was decoded successfully,
+        KErrUnderflow if the frame was partially decoded
+        otherwise another of the system-wide error codes.
+@param  aDestination
+        A bitmap that will contain the decoded frame.
+@param	aFrameNumber
+        The frame in a multi-frame image to decode (optional, defaults to zero).
+
+@note
+As most codec plugins support downscaling the image but not upscaling, the standard behaviour (i.e. no requested
+transformations) for codecs begins with the size of the destination bitmap passed to CImageDecoder::Convert being
+inspected, and:
+
+- 1. If the destination size matches the frame size of the image then the image is decoded full size into the destination
+bitmap.
+- 2. If the destination size is larger than the frame size of the image then the image is decoded full size into the
+destination bitmap with no upscaling. The image origin is aligned with the top left corner of the bitmap and any area
+in the bitmap to the bottom and right of image is left in its initialised state.
+- 3. If the destination size is smaller than the frame size of the image then a reduction factor is calculated and the
+image is scaled down (1/2, 1/4, 1/8 size) whilst maintaining the aspect ratio of the image. The size is the next
+smallest size that will fit in the destination bitmap. The use case for this is when the client wants to pass in the
+screen size of device and have the image scaled to fill as much of the screen as possible.
+However, if the extension interfaces (clipping, scale, operation) are used then the additional behaviour below applies.
+- 4. If the extension interfaces for clipping rectangle and/or operation are applied, but not scaling, then the size of
+the destination bitmap for an unscaled image can be obtained via CImageDecoder::GetDestinationSize.
+Lets call that SizeA. The same rules apply as given in 1, 2, 3 above resulting in a down-scaled destination if the
+destination bitmap is smaller than SizeA.
+- 5. If the extension interface for scaling is called via one of the two TImageConvScaler::SetScalingL(.. functions then
+it is required that the destination size is obtained through CImageDecoder::GetDestinationSize and that a destination
+bitmap of that size is passed to CImageDecoder::Convert. Failure to do this will cause the decoder to fail with KErrArgument.
+This rule holds if clipping and/or operation is applied as well as scaling.
+*/
+EXPORT_C void CImageDecoder::Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, TInt aFrameNumber)
+	{
+	ASSERT(ValidProperties());
+	iRelay->Convert(aRequestStatus, aDestination, aFrameNumber);
+	}
+
+/**
+Set the source image type, this can be any value from TImageType. It can leave with a system wide
+error. Typical leaves are documented below.
+   
+@param 	aImageType
+		An image type from TImageType to denote source image that the decoder should use.
+@leave  KErrNotFound
+		If the image for the type specified is not found.
+@leave  KErrCorrupt
+		For a corrupt image. In the case of failing to change the source image from a valid 
+		EImageTypeMain image to a corrupt EImageTypeThumbnail, the decoder resets the image 
+		type back to the valid EImageTypeMain.
+*/
+EXPORT_C void CImageDecoder::SetImageTypeL(TInt aImageType)
+	{
+	ASSERT(ValidProperties());
+	iRelay->SetImageTypeL(aImageType);
+	}
+
+
+/**
+Start decoding an image frame and mask asynchronously.
+
+@pre
+The destination bitmap aDestination, must be created before the call to
+Convert() is made. aDestination must be large enough to contain the frame and
+be set to the required display mode. FrameInfo() can be used to obtain
+the size and display mode of the frame. The destination mask aDestinationMask
+must be created before the call to Convert() is made and must be large enough for
+the mask. The display mode must be EGray2 or EGray256 and must be EGray256 if the
+image contains alpha-blending information. This information can be obtained from
+the iFlags property of TFrameInfo obtained from a FrameInfo() call.
+
+When the conversion is complete, successfully or otherwise, the status is 
+returned in aRequestStatus.
+
+If the operations completes with KErrUnderflow, then there is insufficient 
+information in the descriptor. In this situation, ContinueConvert() should be 
+called repeatedly until the descriptor has accumulated enough information 
+for ContinueConvert() to complete with KErrNone.It is the responsibility of the 
+caller to ensure that the original data source used to create this decoder object 
+gets enough information. If there is no data available then a caller can ignore 
+this error code and use partially decoded image.
+
+@param  aRequestStatus
+        Request status. On completion contains an error code.
+        KErrNone if frame was decoded successfully,
+        KErrUnderflow if the frame was partially decoded
+        otherwise another of the system-wide error codes.
+@param  aDestination
+        A bitmap that will contain the decoded frame.
+@param  aDestinationMask
+        A bitmap that will contain the decoded frame mask.
+@param  aFrameNumber
+        The frame in multi-frame image to decode (optional, defaults to zero).
+
+@see    TFrameInfo
+*/
+EXPORT_C void CImageDecoder::Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, CFbsBitmap& aDestinationMask, TInt aFrameNumber)
+	{
+	ASSERT(ValidProperties());
+	iRelay->Convert(aRequestStatus, aDestination, aDestinationMask, aFrameNumber);
+	}
+
+/**
+Continue decoding a frame and/or mask after new image data was added to
+the source file or descriptor and a previous call to Convert() or
+ContinueConvert() returned KErrUnderflow.
+
+@param  aRequestStatus
+        Request status. On completion contains an error code.
+        KErrNone if frame was decoded successfully,
+        KErrUnderflow if the frame was partially decoded
+        otherwise another of the system-wide error codes.
+*/
+EXPORT_C void CImageDecoder::ContinueConvert(TRequestStatus* aRequestStatus)
+	{
+	ASSERT(ValidProperties());
+	iRelay->ContinueConvert(aRequestStatus);
+	}
+
+/**
+Return the number of frames in the image being decoded. 
+
+This function can be called immediately after the call to create the decoder, 
+thus enabling the caller to know how many frames need to be converted. Client 
+may have to call IsImageHeaderProcessingComplete() & ContinueProcessingHeaders() 
+to ensure all all data is available.
+
+@return The number of frames in the source image.
+*/
+EXPORT_C TInt CImageDecoder::FrameCount() const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->FrameCount();
+	}
+
+/**
+Return the status of the image.
+
+If the image is incomplete EFalse will be returned. The client should continue
+to supply more data and call ContinueProcessingHeaders() until ETrue is returned.
+
+Panic categories:  Many CImageDecoder functions are dependent upon this function
+returning ETrue before they can successfully be called.  If the client calls one
+of these dependent functions, then that function call may panic with either the 
+'ImageConversion' panic category or a decoder plugin specific panic category,
+for example: 'BMPConvertPlugin', 'GIFConvertPlugin', 'ICOConvertPlugin',
+'JPEGConvertPlugin', 'MBMConvertPlugin', 'OTAConvertPlugin', 'PNGConvertPlugin',
+'TIFFConvertPlugin', 'WBMPConvertPlugin', 'WMFConvertPlugin'.
+
+
+@return Image status.
+*/
+EXPORT_C TBool CImageDecoder::IsImageHeaderProcessingComplete() const
+	{
+	return iRelay->IsImageHeaderProcessingComplete();
+	}
+
+/**
+Continue processing image headers after new image data was added to
+the source file or descriptor.
+
+@see IsImageHeaderProcessingComplete()
+*/
+EXPORT_C void CImageDecoder::ContinueProcessingHeaderL()
+	{
+	ASSERT(ValidProperties());
+	iRelay->ContinueProcessingHeaderL();
+	}
+
+/**
+Cancels any conversions currently in progress (Cancel is synchronous).
+*/
+EXPORT_C void CImageDecoder::Cancel()
+	{
+	if(ValidProperties())
+		iRelay->Cancel();
+	}
+
+/**
+Return the frame info for a specified frame of the image. 
+
+This function can be called immediately after the call to create 
+the decoder, thus enabling the caller to know about each frame in 
+advance of converting it.
+
+The returned information contains details of the size of the image,
+the dimensions of the frame, its colour depth and so on. More advanced 
+information may be available for the image using FrameData().
+
+Use FrameCount() to determine how many frames are contained in the image 
+before using this function.
+
+@param  aFrameNumber
+        The frame number.
+
+@return The returned information for the specified frame.
+
+@panic  ImageConversion 10
+        Frame number outside the range 0 to FrameCount()-1.
+        See CImageDecoder::FrameCount().
+
+@see	CImageDecoder::FrameCount()
+*/
+EXPORT_C const TFrameInfo& CImageDecoder::FrameInfo(TInt aFrameNumber) const
+	{
+	// Return the frame info for a particular frame
+	ASSERT(ValidProperties());
+	return iRelay->FrameInfo(aFrameNumber);
+	}
+
+/**
+Returns additional plugin specific information on a specified frame.
+
+The plugin specific information usually covers advanced image features such 
+as image quality, advanced colour settings and so on.
+
+Use FrameCount() to determine how many frames are contained in the 
+image before using this function.
+
+@param  aFrameNumber
+        The frame number.
+
+@return The data for the specified frame.
+
+@panic  ImageConversion 10
+        Frame number outside the range 0 to FrameCount()-1.
+        See CImageDecoder::FrameCount().
+
+@see	CImageDecoder::FrameCount()
+*/
+EXPORT_C const CFrameImageData& CImageDecoder::FrameData(TInt aFrameNumber) const
+	{
+	// Return the frame image data for a particular frame.
+	ASSERT(ValidProperties());
+	return iRelay->FrameData(aFrameNumber);
+	}
+
+/**
+Return the number of comments attached to the image (as opposed to
+a particular frame).
+
+For further informantion on panic categories, please see the note in
+CImageDecoder::IsImageHeaderProcessingComplete().
+
+@panic  ImageConversion 13 Header processing has not completed.
+		See CImageDecoder::IsImageHeaderProcessingComplete().
+
+@see	IsImageHeaderProcessingComplete()
+
+@return The number of comments attached to the image.
+*/
+EXPORT_C TInt CImageDecoder::NumberOfImageComments() const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->Plugin()->NumberOfImageComments();
+	}
+
+/**
+Return a particular comment attached to the image.
+
+Ownership of the returned buffer is transferred to the caller. Use NumberOfImageComments() 
+to determine how many (if any) comments are contained within the image.
+
+For further informantion on panic categories, please see the note in
+CImageDecoder::IsImageHeaderProcessingComplete().
+
+@param  aCommentNumber	The comment number.
+
+@panic 	ImageConversion 12 Comments are not supported.
+		See CImageDecoder::NumberOfImageComments().
+
+@panic  ImageConversion 13 Header processing has not completed.
+		See CImageDecoder::IsImageHeaderProcessingComplete().
+
+@panic 	ImageConversion 14 aCommentNumber is not valid.
+		See CImageDecoder::NumberOfImageComments().
+
+@see	IsImageHeaderProcessingComplete()
+@see	NumberOfImageComments()
+
+@return A buffer containing the comment.
+*/
+EXPORT_C HBufC* CImageDecoder::ImageCommentL(TInt aCommentNumber) const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->Plugin()->ImageCommentL(aCommentNumber);
+	}
+
+/**
+Return the number of comments attached to a given frame of the image
+(as opposed to the whole image).
+
+Use FrameCount() to retrieve the number of frames in the image to ensure 
+that a valid aFrameNumber is used.
+
+For further informantion on panic categories, please see the note in
+CImageDecoder::IsImageHeaderProcessingComplete().
+
+@param	aFrameNumber The frame number.
+
+@panic 	ImageConversion 10 aFrameNumber is not valid.
+		See CImageDecoder::FrameCount().
+
+@panic  ImageConversion 13 Header processing has not completed.
+		See CImageDecoder::IsImageHeaderProcessingComplete().
+
+@see	IsImageHeaderProcessingComplete()
+@see	FrameCount()
+
+@return	The number of comments attached to a given frame of the image.
+*/
+EXPORT_C TInt CImageDecoder::NumberOfFrameComments(TInt aFrameNumber) const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->Plugin()->NumberOfFrameComments(aFrameNumber);
+	}
+
+/**
+Return a particular comment attached to a given frame of the image.
+
+The desired order of calling methods should be FrameCount(),NumberOfFrameComments() and then FrameCommentL().
+
+Use FrameCount() to retrieve the number of frames in the image to ensure that a valid aFrameNumber is used.
+
+Use NumberOfFrameComments() to retrieve the number of comments attached to a given frame
+of the image (as opposed to the whole image),to ensure that a valid aCommentNumber is used.
+
+Ownership of the returned buffer is transferred to the caller.
+
+For further informantion on panic categories, please see the note in
+CImageDecoder::IsImageHeaderProcessingComplete().
+
+@param  aFrameNumber	The frame number within the image from which to retrieve the specified comment.
+
+@param  aCommentNumber	The comment number to retrieve from the specified frame.
+
+@panic 	ImageConversion 10 aFrameNumber is not valid.
+		See CImageDecoder::FrameCount().
+
+@panic  ImageConversion 13 Header processing has not completed.
+		See CImageDecoder::IsImageHeaderProcessingComplete().
+		
+@panic	ImageConversion 14 aCommentNumber is not valid.
+		See CImageDecoder::NumberOfFrameComments().
+
+@see	IsImageHeaderProcessingComplete()
+@see	FrameCount()
+@see	NumberOfFrameComments()
+
+@return A buffer containing the specified comment.
+*/
+EXPORT_C HBufC* CImageDecoder::FrameCommentL(TInt aFrameNumber, TInt aCommentNumber) const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->Plugin()->FrameCommentL(aFrameNumber, aCommentNumber);
+	}
+
+/**
+Return the formatted frame information strings for a specific frame
+and leave it on the cleanup stack.
+
+Ownership is transferred to the caller.
+
+@param  aFrameNumber
+        The frame number from which to retrieve the formatted information string.
+
+@return The formatted frame information strings.
+*/
+EXPORT_C CFrameInfoStrings* CImageDecoder::FrameInfoStringsLC(TInt aFrameNumber)
+	{
+	ASSERT(ValidProperties());
+	return iRelay->FrameInfoStringsLC(aFrameNumber);
+	}
+
+/**
+Return the formatted frame information strings for a specific frame.
+Ownership is transferred to the caller.
+
+@param  aFrameNumber
+        The frame number from which to retrieve the formatted information string.
+
+@return The formatted frame information strings.
+*/
+EXPORT_C CFrameInfoStrings* CImageDecoder::FrameInfoStringsL(TInt aFrameNumber)
+	{
+	CFrameInfoStrings* frameInfoStrings = FrameInfoStringsLC(aFrameNumber);
+	CleanupStack::Pop();
+
+	return frameInfoStrings;
+	}
+
+/**
+Return the implementation UID of the decoder being used to decode the image.
+
+@return	The implementation UID of the decoder.
+*/
+EXPORT_C TUid CImageDecoder::ImplementationUid() const
+	{
+	return iRelay->ImplementationUid();
+	}
+
+/**
+Retrieves the image type and sub-type for a given frame of the image that
+has just been decoded.
+
+For further informantion on panic categories, please see the note in
+CImageDecoder::IsImageHeaderProcessingComplete().
+
+@param  aFrameNumber
+        The frame number for which type information should be retreived.
+@param  aImageType
+        On return contains the image type UID for the specified frame.
+@param  aImageSubType
+        On return contains the image sub-type UID if there is one (or KNullUid if 
+		there is not).
+
+@panic 	ImageConversion 10 aFrameNumber is not valid.
+		See CImageDecoder::FrameCount().
+
+@see	IsImageHeaderProcessingComplete()
+@see	FrameCount()
+*/
+EXPORT_C void CImageDecoder::ImageType(TInt aFrameNumber, TUid& aImageType, TUid& aImageSubType) const
+	{
+	ASSERT(ValidProperties());
+	iRelay->Plugin()->ImageType(aFrameNumber, aImageType, aImageSubType);	
+	}
+
+/**
+Calls CImageDecoderPlugin::HandleCustomSyncL(aParam) that executes user defined plugin 
+specific functions. Subsequent behaviour depends on the CImageDecoderPlugin class.
+
+This function is part of the support for extended codecs for use within classes 
+derived from CImageDecoder.
+
+Note: This function is intended for use by plugin writers only.
+
+@param  aParam
+        Interpretation dependent on plugin.
+        
+@see    CImageDecoderPlugin::HandleCustomSyncL()
+*/
+
+EXPORT_C void CImageDecoder::CustomSyncL(TInt aParam)
+	{
+	ASSERT(ValidProperties());
+	iRelay->CustomSyncL(aParam);
+	}
+
+/**
+Sets up background convert cycle, bypassing Convert().
+A call to this will result in a call to the associated CImageDecoderPlugin::InitCustomAsyncL(aParam),
+which if successful will start background processing. This function uses the same mechanism as Convert(),
+and therefore cannot be used concurrently. Cancel() etc work as expected.
+
+Note: This function is intended for use by plugin writers only.
+
+@param  aRequestStatus
+        Request status. On completion contains an error code.
+        KErrNone if the bitmap was successfully decoded,
+        otherwise another of the system-wide error codes.
+@param  aParam
+        Interpretation dependent on plugin.
+*/
+EXPORT_C void CImageDecoder::CustomAsync(TRequestStatus* aRequestStatus, TInt aParam)
+	{
+	ASSERT(ValidProperties());
+	iRelay->CustomAsync(aRequestStatus, aParam);
+	}
+
+/**
+Returns associated CImageDecoderPlugin.
+
+Allows the extended CImageDecoder object to talk to its CImageDecoderPlugin equivalent.
+
+Note: This function is intendend for use by plugin writers only.
+
+@return A pointer to the related CImageDecoderPlugin instance.
+*/
+EXPORT_C CImageDecoderPlugin* CImageDecoder::Plugin() const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->Plugin();	
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageDecoder::ReservedVirtual1()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageDecoder::ReservedVirtual2()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageDecoder::ReservedVirtual3()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will panic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageDecoder::ReservedVirtual4()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Function to calculate the reduction factor based on the input parameters.
+
+@param  aOriginalSize
+        A reference to the original size of an image.
+@param  aReducedSize
+        A reference to the new size of an image.
+@return The reduction factor.
+*/
+
+EXPORT_C TInt CImageDecoder::ReductionFactor(const TSize& aOriginalSize, const TSize& aReducedSize) const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->ReductionFactor(aOriginalSize, aReducedSize);	
+	}
+
+/**
+Calculates reduced size of the decoded bitmap based on the input parameters and updates aReducedSize with this value.
+
+@param  aOriginalSize
+        A reference to the original size of an image.
+@param  aReductionFactor
+        The Reduction Factor to be applied
+@param  aReducedSize
+        A reference to the new size of the image.
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        KErrArgument.
+*/
+	
+EXPORT_C TInt CImageDecoder::ReducedSize(const TSize& aOriginalSize, TInt aReductionFactor, TSize& aReducedSize) const	
+	{
+	ASSERT(ValidProperties());
+	return iRelay->ReducedSize(aOriginalSize, aReductionFactor, aReducedSize);	
+	}
+
+
+/**
+Set the decoder worker thread priority
+
+@param  aPriority
+		a new value for worker thread priority
+@return KErrNotSupported 
+		the decoder object doesn't use a worker thread.
+		Other system-wide error codes.
+@see	TThreadPriority
+*/
+EXPORT_C TInt CImageDecoder::SetDecoderThreadPriority(TThreadPriority aPriority)
+	{
+	return iRelay->SetDecoderThreadPriority( aPriority );
+	}
+
+
+/* IMAGE ENCODER */
+
+/**
+Returns a list of the basic image types that can be encoded, based on the
+currently available encoder plugins.
+
+The returned array contains entries for the supported image types. Each entry
+consists of the "display string" as well as the UID for that image type. Since 
+this function only returns basic image type UID's, the second UID which represents 
+the sub-type will always be zero.
+
+Ownership of the array is passed to the caller so, before the array goes out of 
+scope in the client, the caller must call the array's ResetAndDestroy() method to free 
+any entries.
+
+@param  aImageTypeArray
+        An empty array, into which this function will put a list of supported image types.
+*/
+EXPORT_C void CImageEncoder::GetImageTypesL(RImageTypeDescriptionArray& aImageTypeArray)
+	{
+	ImageEnDecoderUtils::DoGetImageTypesL(KImageEncoderInterfaceUid, aImageTypeArray);
+	}
+
+/**
+@publishedAll
+@released
+
+Gets a list of the properties of a specific encoder plugin.
+
+@param	aImplementationUid
+        The encoder implementation UID for which the plugin properties need to be retrieved.
+@param	aPropertiesArray
+		The array of plugin properties owned by the specified encoder.
+		The caller has the ownership of the array.
+*/
+EXPORT_C void CImageEncoder::GetPluginPropertiesL(const TUid aImplementationUid, RUidDataArray& aPropertiesArray)
+	{
+	ImageEnDecoderUtils::DoGetPluginPropertiesL(KImageEncoderInterfaceUid, aImplementationUid, aPropertiesArray);
+	}
+
+/**
+@publishedAll
+@released
+
+Gets a list of encoder implementations UIDs that have some specific uids (properties, image type, image sub-type or class uids).
+
+@param	aRequiredUids
+        The array containing the UIDs of the required uids (properties, image type, image sub-type or class uids).
+@param	aImplArray
+		The array containing the implementation UIDs of the available encoder plugins with the required UIDs.
+		The caller has the ownership of the array.
+*/
+EXPORT_C void CImageEncoder::GetInterfaceImplementationsL(const RUidDataArray& aRequiredUids, RUidDataArray& aImplArray)
+	{
+	ImageEnDecoderUtils::DoGetInterfaceImplementationsL(KImageEncoderInterfaceUid, aRequiredUids, aImplArray);
+	}
+
+/**
+@publishedAll
+@released
+
+Gets a list of encoder implementations UIDs that have some specific required uids (properties, image type, image sub-type or class uids).
+
+@param	aRequiredUids
+        The array containing the UIDs of the required uids (properties, image type, image sub-type or class uids).
+@param	aLength
+		The length of aRequiredUids (number of required uids).
+@param	aImplArray
+		The array containing the implementation UIDs of the available encoder plugins with the required UIDs.
+		The caller has the ownership of the array.
+*/	
+EXPORT_C void CImageEncoder::GetInterfaceImplementationsL(const TUid* aRequiredUids, const TInt aLength, RUidDataArray& aImplArray)
+	{
+	RUidDataArray requiredUids;
+	CleanupClosePushL(requiredUids);
+	for(TInt index = 0 ; index < aLength ; index++)
+		{
+		User::LeaveIfError(requiredUids.Append(aRequiredUids[index]));
+		}
+	ImageEnDecoderUtils::DoGetInterfaceImplementationsL(KImageEncoderInterfaceUid, requiredUids, aImplArray);
+	CleanupStack::PopAndDestroy(1); //requiredUids
+	}
+
+/**
+For a given basic image type, returns a list of the image sub-types that can
+be encoded, based on the currently available encoder plugins.
+
+Each entry in the returned array consists of the "display string" for
+the plugin as well as the UID for the sub-type. The first UID represents
+the basic type and is always set to aImageType.
+
+Ownership of the array is passed to the caller, so before the
+array goes out of scope in the client, the caller must call
+the array's ResetAndDestroy() method to free any entries.
+
+@param  aImageType
+        The basic image type for which a list of sub-types should be returned.
+@param  aSubTypeArray
+        An empty array, into which this function will put a list of of supported
+        image sub-types.
+*/
+EXPORT_C void CImageEncoder::GetImageSubTypesL(const TUid aImageType, RImageTypeDescriptionArray& aSubTypeArray)
+	{
+	ImageEnDecoderUtils::DoGetImageTypesL(KImageEncoderInterfaceUid, aSubTypeArray, aImageType);
+	}
+
+/**
+Get a list of the file extensions that can be encoded and their corresponding
+MIME types, based on the currently available encoder plugins.
+
+@param  aFileTypeArray
+        An empty array, into which this function will put a list of
+        entries. Each entry will consist of a file extension string for
+        which an encoder plugin has been found, accompanied by the
+        primary MIME type and then any secondary MIME types
+        (if present).
+        
+		Ownership of the array is passed to the caller, so before the
+		array goes out of scope in the client, the caller must call
+		the array's ResetAndDestroy() method to free any entries.
+*/
+EXPORT_C void CImageEncoder::GetFileTypesL(RFileExtensionMIMETypeArray& aFileTypeArray)
+	{
+	ImageEnDecoderUtils::DoGetFileTypesL(KImageEncoderInterfaceUid, aFileTypeArray);
+	}
+
+
+/**
+Creates an encoder based on a specified MIME type and write output to a named file.
+
+The client supplies a MIME type which will be used to try and select an appropriate
+plugin encoder. If an appropriate encoder is found, it is created.
+
+If any file related errors are encountered opening the specified file, this
+function leaves with an appropriate file related leave code.
+
+@param  aFs
+        A reference to a file server session for the encoder to use.
+@param  aDestinationFilename
+        The name of the file into which to put the encoded image.
+@param  aMIMEType
+        The MIME type to use for the encoding.
+@param  aOptions
+        The encoder options to use.
+
+@return Returns a pointer to the newly created encoder.
+
+@see    TOptions
+*/
+EXPORT_C CImageEncoder* CImageEncoder::FileNewL(RFs& aFs, const TDesC& aDestinationFilename, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	//Get a sorted list of encoders
+	RImplInfoPtrArray encoderList;
+	CleanupResetAndDestroyPushL(encoderList);
+	CImageEncoder::MimeTypeGetEncoderListL(encoderList, aMIMEType, aOptions);
+
+	if(encoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	//Use the highest rated encoder.
+	CImageEncodeConstruct* construct = NewEncodeConstructL(*encoderList[0], aOptions);
+	CleanupStack::PopAndDestroy(&encoderList);
+
+	CImageEncoder* encoderPtr = NewL(construct, aOptions); // NewL takes ownership of construct - no need to push on stack
+	CleanupStack::PushL(encoderPtr);
+	encoderPtr->iRelay->SetFileL(aFs, aDestinationFilename, aOptions);
+	CleanupStack::Pop(encoderPtr); 
+
+	return encoderPtr;
+	}
+
+/**
+Creates a plugin encoder for a specified MIME type and writes output to a descriptor.
+
+The client supplies a MIME type which will be used to try and select an appropriate
+plugin encoder. If an appropriate encoder is found, it creates it.
+
+@param  aDestinationData
+        The buffer pointer into which to put the encoded image. This must be
+        a NULL pointer. Memory will be allocated internally and ownership of
+        the data passed to the caller.
+@param  aMIMEType
+        The MIME type to use for the encoding.
+@param  aOptions
+        Encoder options to use.
+
+@return	A pointer to the newly created encoder.
+
+@see    TOptions
+*/
+EXPORT_C CImageEncoder* CImageEncoder::DataNewL(HBufC8*&  aDestinationData, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	if (aDestinationData!=NULL)
+		Panic(ENonNullDescriptorPassed);
+
+	//Get a sorted list of encoders
+	RImplInfoPtrArray encoderList;
+	CleanupResetAndDestroyPushL(encoderList);
+	CImageEncoder::MimeTypeGetEncoderListL(encoderList, aMIMEType, aOptions);
+
+	if(encoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	//Use the highest rated encoder.
+	CImageEncodeConstruct* construct = NewEncodeConstructL(*encoderList[0], aOptions);
+	CleanupStack::PopAndDestroy(&encoderList);
+	CImageEncoder* encoderPtr = NewL(construct, aOptions); // NewL takes ownership of construct - no need to push on stack
+	CleanupStack::PushL(encoderPtr);
+	encoderPtr->iRelay->SetDataL(aDestinationData, aOptions);
+	CleanupStack::Pop(encoderPtr); 
+	return encoderPtr;
+	}
+
+/**
+@internalTechnology
+
+Creates a list of encoders that support the specified MIME type.
+
+@param  aEncoderList
+        Create a list of encoders that support the given MIME type.
+@param	aMIMEType
+        The MIME type to encode to.
+@param	aOptions
+		Decoder options to use.
+*/
+void CImageEncoder::MimeTypeGetEncoderListL(RImplInfoPtrArray& aEncoderList, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	if (aMIMEType.Length() == 0)
+		{ // Get out, empty MIME type string
+		User::Leave(KErrArgument);
+		}
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	customMatchData->SetMatchType(EMatchMIMEType);
+	customMatchData->SetMatchStringL(aMIMEType);
+	customMatchData->SetExtensionOptions(aOptions);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+
+	TEComResolverParams resolverParams; // Parameters on which to match
+	resolverParams.SetDataType(packageDes);
+
+	REComSession::ListImplementationsL(KImageEncoderInterfaceUid, resolverParams, KImageConvertResolverUid, aEncoderList);
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+	}
+
+/**
+@internalTechnology
+
+Create a list of encoders that support the specified image type.
+
+@param  aEncoderList
+        A list of encoders that support the specified image type.
+@param  aImageType
+        The image base type.
+@param  aImageSubType
+        The image sub type.
+@param  aEncoderUid
+        The implementation UID for a specific codec or a decoder/encoder class UID.
+@param	aOptions
+		Encoder options to use.
+
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+*/
+void CImageEncoder::ImageTypeGetEncoderListL(RImplInfoPtrArray& aEncoderList, const TUid aImageType, const TUid aImageSubType, const TUid aEncoderUid, const TOptions aOptions)
+	{
+	if ((aImageType == KNullUid) && (aEncoderUid == KNullUid))
+		{ // Get out, no base type specified
+		Panic(EIllegalImageType); 
+		}
+
+	if ((aImageType == KNullUid) && (aImageSubType != KNullUid))
+		{ // Get out, no base type given for sub-type
+		Panic(EIllegalImageSubType); 
+		}
+
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	customMatchData->SetMatchType(EMatchUids);
+	customMatchData->SetBaseType(aImageType);
+	customMatchData->SetSubType(aImageSubType);
+	customMatchData->SetImplementationType(aEncoderUid);
+	customMatchData->SetExtensionOptions(aOptions);
+
+	HBufC8* package  = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+	
+	TEComResolverParams resolverParams; // Parameters on which to match
+	resolverParams.SetDataType(packageDes);
+   
+	REComSession::ListImplementationsL(KImageEncoderInterfaceUid, resolverParams, KImageConvertResolverUid, aEncoderList);
+
+	CleanupStack::PopAndDestroy(2); // package, customMatchData
+   	}
+
+/**
+@internalTechnology
+
+Create an encode construct using a image type, sub type and encoder
+implementation UID.
+
+@param  aEncoderInfo
+        Implementation information for the encoder to be created.
+@param	aOptions
+		Encoder options to use.
+@return Returns a pointer to the newly created encoder construct.
+
+*/
+CImageEncodeConstruct* CImageEncoder::NewEncodeConstructL(const CImplementationInformation& aEncoderInfo, const TOptions aOptions)
+	{
+	CCustomMatchData* customMatchData = CCustomMatchData::NewLC();
+	COpaqueDataParse* parse = COpaqueDataParse::NewLC(aEncoderInfo.OpaqueData());
+
+	customMatchData->SetMatchType(EMatchUids);
+	customMatchData->SetBaseType(parse->ImageTypeUid());
+	customMatchData->SetSubType(parse->ImageSubTypeUid());
+	customMatchData->SetImplementationType(aEncoderInfo.ImplementationUid());
+	customMatchData->SetExtensionOptions(aOptions);
+
+	CleanupStack::PopAndDestroy(parse);
+
+	HBufC8* package = customMatchData->NewPackLC();
+	TPtr8 packageDes = package->Des();
+
+	TEComResolverParams resolverParams;
+	resolverParams.SetDataType(packageDes);
+
+	CImageEncodeConstruct* construct = NULL;
+	construct = STATIC_CAST(CImageEncodeConstruct*,
+			REComSession::CreateImplementationL(KImageEncoderInterfaceUid,
+			_FOFF(CImageEncodeConstruct, iDtorIDKey),
+			resolverParams,
+			KImageConvertResolverUid));
+	ASSERT(construct!=NULL);
+
+	CleanupStack::PopAndDestroy(2, customMatchData); //package, customMatchData
+
+	return construct;
+	}
+
+/**
+Creates an encoder based on a supplied parameters and writes output to a named file.
+
+The client must supply a basic image type (and a sub-type, if applicable) or a specific
+encoder implementation UID, which will be used to try and select an appropriate plugin
+encoder. If an appropriate encoder is found, it is created.
+
+Note:
+Every image format has two IDs, known as the type and the sub-type (although generally
+the sub-type is KNullUid). To retrieve a list of supported types and sub-types that can be
+encoded, use the static functions GetImageTypesL() and GetImageSubTypesL().
+
+If no plugin encoder can be found that matches the details provided in aImageType, aImageSubType
+and possibly aEncoderUid this function leaves with KErrNotFound or KEComErrNoInterfaceIdentified.
+
+If any file related errors are encountered opening the specified file, this function leaves
+with an appropriate file related leave code.
+
+@param  aFs
+        A reference to a file server session for the encoder to use.
+@param  aDestinationFilename
+        The name of the file into which to put the encoded image.
+@param  aOptions
+        Options to use.
+@param  aImageType
+        The image type to use for the encoding (mandatory).
+@param  aImageSubType
+        The image sub-type to use for the encoding (only if applicable, defaults to KNullUid).
+@param  aEncoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return A pointer to the newly created encoder.
+
+@leave  KErrNotFound
+        No appropriate plugin encoder for this image has been found.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+@panic  ImageConversion 20
+        No base type given for encoder implementation.
+
+@see    TOptions
+*/
+EXPORT_C CImageEncoder* CImageEncoder::FileNewL(RFs& aFs, const TDesC& aDestinationFilename, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aEncoderUid)
+	{
+	//Get a sorted list of encoders
+	RImplInfoPtrArray encoderList;
+	CleanupResetAndDestroyPushL(encoderList);
+	CImageEncoder::ImageTypeGetEncoderListL(encoderList, aImageType, aImageSubType, aEncoderUid, aOptions);
+
+	if(encoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	//Use the highest rated encoder.
+	CImageEncodeConstruct* construct = NewEncodeConstructL(*encoderList[0], aOptions);
+	CleanupStack::PopAndDestroy(&encoderList);
+	CImageEncoder* encoderPtr = NewL(construct, aOptions); // NewL takes ownership of construct - no need to push on cleanstack
+	CleanupStack::PushL(encoderPtr);
+	encoderPtr->iRelay->SetFileL(aFs, aDestinationFilename, aOptions);
+	CleanupStack::Pop(); //encoderPtr
+	return encoderPtr;
+	}
+
+/**
+Creates a plugin encoder based on optional parameters and writes output to a descriptor.
+
+The client must supply a basic image type (and a sub-type, if applicable) or specific encoder/class,
+implementation UID which will be used to try and select an appropriate plugin
+encoder. If an appropriate encoder is found, it is created.
+
+Note: 
+Every image format has two IDs, known as the type and the sub-type (although generally the sub-type 
+is KNullUid). To retrieve a list of supported types and sub-types that can be encoded, use the 
+static functions GetImageTypesL() and GetImageSubTypesL().
+
+If no plugin encoder can be found that matches the details provided in aImageType, aImageSubType
+and possibly aEncoderUid this function leaves with KErrNotFound or KEComErrNoInterfaceIdentified.
+
+@param  aDestinationData
+        The buffer pointer into which to put the encoded image.
+@param  aOptions
+        The encoder options to use.
+@param  aImageType
+        The image type to use for the encoding (mandatory).
+@param  aImageSubType
+        The image sub-type to use for the encoding (only if applicable, defaults to KNullUid).
+@param  aEncoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return A pointer to the newly created encoder.
+
+@leave  KErrNotFound
+        No appropriate plugin encoder for this image has been found.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+@panic  ImageConversion 20
+        No base type given for encoder implementation.
+
+@see    TOptions
+*/
+EXPORT_C CImageEncoder* CImageEncoder::DataNewL(HBufC8*& aDestinationData, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aEncoderUid)
+	{
+	if (aDestinationData!=NULL)
+		Panic(ENonNullDescriptorPassed);
+
+	//Get a sorted list of encoders
+	RImplInfoPtrArray encoderList;
+	CleanupResetAndDestroyPushL(encoderList);
+	CImageEncoder::ImageTypeGetEncoderListL(encoderList, aImageType, aImageSubType, aEncoderUid, aOptions);
+
+	if(encoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	//Use the highest rated encoder.
+	CImageEncodeConstruct* construct = NewEncodeConstructL(*encoderList[0], aOptions);
+	CleanupStack::PopAndDestroy(&encoderList);
+	CImageEncoder* encoderPtr = NewL(construct, aOptions); // NewL takes ownership of construct - no need to push on cleanstack
+	CleanupStack::PushL(encoderPtr);
+	encoderPtr->iRelay->SetDataL(aDestinationData, aOptions);
+	CleanupStack::Pop(); //encoderPtr
+	return encoderPtr;
+	}
+
+/**
+@internalTechnology
+
+Called internally to create a CImageEncoder and associated iRelay body
+*/
+CImageEncoder* CImageEncoder::NewL(CImageEncodeConstruct* aConstruct, TOptions aOptions)
+	{
+	CleanupStack::PushL(aConstruct); // we take ownership of aConstruct
+	CImageEncoder* self = aConstruct->NewEncoderL(); // typically will callback to CImageEncoder::NewL()
+	CleanupStack::PushL(self);
+	TBool alwaysThread = (aOptions & EOptionAlwaysThread)!=EFalse;
+	self->iRelay = MImageEncoderRelay::NewL(aConstruct, alwaysThread); // ownership of aConstruct switches to properties
+	CleanupStack::Pop(2); // self  and aConstruct
+	self->iRelay->TransferConstructOwnership();
+	return self;
+	}
+
+/**
+@internalTechnology
+
+Actual factory function for CImageEncoder - ie. it creates the object
+Called back plugin - to allow plugin to override if required
+*/
+CImageEncoder* CImageEncoder::NewL()
+	{
+	CImageEncoder* self = new (ELeave) CImageEncoder;
+	return self;
+	}
+
+/**
+Constructor for this class.
+*/
+EXPORT_C CImageEncoder::CImageEncoder()
+	{
+	}
+
+/**
+Destructor for this class.
+
+Closes the file. If using a local file session, it closes it.
+Calls ECom to tell it the encoder instance is no longer required.
+
+Frees all other resources owned by the object prior to its destruction.
+*/
+EXPORT_C CImageEncoder::~CImageEncoder()
+	{
+	Cancel();
+
+	delete iRelay;
+	}
+
+/**
+Encodes a bitmap asynchronously.
+
+When encoding is complete, successfully or otherwise, the
+status is returned in aRequestStatus.
+
+@param  aRequestStatus
+        The request status. On completion contains an error code.
+        KErrNone if the bitmap was successfully encoded,
+        otherwise another of the system-wide error codes.
+@param  aSource
+        A bitmap to encode.
+@param  aFrameImageData
+        The frame image data (optional, defaults to NULL).
+		There exists format-specific image data variants that are used by 
+		encoders to obtain image specific data. This behaviour is invoked by specifying 
+		aFrameImageData. Otherwise, encoder specific defaults are invoked.
+@see TBmpImageData
+*/
+EXPORT_C void CImageEncoder::Convert(TRequestStatus* aRequestStatus, const CFbsBitmap& aSource, const CFrameImageData* aFrameImageData)
+	{
+	ASSERT(ValidProperties());
+	iRelay->Convert(aRequestStatus, aSource, aFrameImageData);
+	}
+
+/**
+Asynchronously cancels any conversions currently in progress.
+*/
+EXPORT_C void CImageEncoder::Cancel()
+	{
+	if(ValidProperties())
+		iRelay->Cancel();
+	}
+
+/**
+Returns the implementation UID of the encoder being used to encode the bitmap.
+
+@return	The implementation UID of the encoder.
+*/
+EXPORT_C TUid CImageEncoder::ImplementationUid() const
+	{
+	return iRelay->ImplementationUid();
+	}
+
+/**
+Calls CImageEncoderPlugin::HandleCustomSyncL() that executes user defined
+plugin specific functions. Subsequent behaviour therefore depends on the 
+CImageEncoderPlugin class.
+
+Note:
+For use by plugin writers only.
+
+@param  aParam
+        Interpretation determined by plugin.
+*/
+EXPORT_C void CImageEncoder::CustomSyncL(TInt aParam)
+	{
+	ASSERT(ValidProperties());
+	iRelay->CustomSyncL(aParam);
+	}
+
+/**
+Sets up background convert cycle, bypassing Convert().
+
+Use this function to inititate CImageEncoderPlugin::InitCustomAsyncL(aParam),
+which if successful will start background processing. Convert() uses the same
+mechanism as CustomAsync(), and therefore cannot be used concurrently. Cancel() 
+and other related functions still work as expected.
+
+Note:
+For use by plugin writers only.
+
+@param  aRequestStatus
+        The request status. On completion contains an error code.
+        KErrNone if the bitmap was successfully encoded,
+        otherwise another of the system-wide error codes.
+@param  aParam
+        Interpretation determined by plugin.
+*/
+EXPORT_C void CImageEncoder::CustomAsync(TRequestStatus* aRequestStatus, TInt aParam)
+	{
+	ASSERT(ValidProperties());
+	iRelay->CustomAsync(aRequestStatus, aParam);
+	}
+
+/**
+Returns the associated CImageEncoderPlugin.
+
+This is part of support for extended codecs, for use within classes derived from 
+CImageEncoder. Allows the extended CImageEncoder object to talk to its 
+CImageEncoderPlugin equivalent.
+
+Note:
+For use by plugin writers only.
+*/
+EXPORT_C CImageEncoderPlugin* CImageEncoder::Plugin() const
+	{
+	ASSERT(ValidProperties());
+	return iRelay->Plugin();
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will pannic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageEncoder::ReservedVirtual1()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will pannic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageEncoder::ReservedVirtual2()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will pannic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageEncoder::ReservedVirtual3()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+@internalTechnology
+
+Intended for future proofing - will pannic if called
+
+@panic  ImageConversion 30
+*/
+EXPORT_C void CImageEncoder::ReservedVirtual4()
+	{
+	Panic(EReservedCall);
+	}
+
+/**
+Create a decoder for the image in the named file. The client supplies a
+MIME type which will be used to try and select an appropriate plugin
+decoder. If it finds a decoder it creates it and then goes on to use that
+decoder to scan the beginning of the image file.
+
+If any file related errors are encountered opening the specified file, this 
+function leaves with an appropriate file related leave code.
+
+@param  aFile
+        The handle of the file to decode
+@param  aMIMEType
+        The MIME type of the image in the file.
+@param  aIntent
+		The DRM Intent to open the file with
+@param	aOptions
+        Decoder options to use.
+
+@return	Returns a pointer to the newly created decoder.
+
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        Either the appropriate plugin decoder for this file hasn't been found, or the file itself is missing.
+
+@see    TOptions
+*/
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFile& aFile, const TDesC8& aMIMEType, TIntent aIntent, const TOptions aOptions)
+	{
+	return CImageDecoder::FileNewImplL(aFile, aMIMEType, KDefaultContentObject, aIntent, aOptions);
+	}
+
+/**
+Creates a decoder for the image in the named file. If the client supplies an
+image type (and sub-type, if applicable) or decoder UID, these will be used
+to try and select an appropriate plugin decoder. If not, then the selection
+will be done by matching the image header in the file. If it finds a decoder
+it creates it and then goes on to use that decoder to scan the beginning of
+the image file.
+
+@param  aFile
+        The handle of the file to decode
+@param  aIntent
+        The DRM Intent for image conversion.
+@param  aOptions
+        The decoder options to use. See TOptions.
+@param  aImageType
+        The image type of the image in the file (optional, defaults to KNullUid).
+@param  aImageSubType
+        The image sub-type of the image in the file (optional, defaults to KNullUid).
+@param  aDecoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return	A pointer to the newly created decoder.
+
+@leave  KErrUnderflow
+        Not enough data in file to identify which plugin decoder to use.
+@leave  KErrNotFound
+        Either the appropriate plugin decoder for this file hasn't been found, or the file itself is missing.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+
+@see     TOptions
+*/
+
+EXPORT_C CImageDecoder* CImageDecoder::FileNewL(RFile& aFile, TIntent aIntent, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	return CImageDecoder::FileNewImplL(aFile, KDefaultContentObject, aIntent, aOptions, aImageType, aImageSubType, aDecoderUid);
+	}
+
+CImageDecoder* CImageDecoder::FileNewImplL(RFile& aFile, const TDesC8& aMIMEType, const TDesC& aUniqueId, TIntent aIntent, const TOptions aOptions)
+	{
+	CContent* content = CContent::NewLC(aFile);
+	CData* data = content->OpenContentL(aIntent, aUniqueId); // check file presence, evaluate (not execute) intent
+
+	delete data; // close file
+	CleanupStack::PopAndDestroy(content);
+
+	//Get a sorted list of decoders that will decode the image
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+	CImageDecoder::MimeTypeGetDecoderListL(decoderList, aMIMEType, aOptions);
+
+	CImageDecoder* decoder = NULL;
+	decoder = CImageDecoder::FileFindDecoderNewL(decoderList, aFile, aOptions, aUniqueId);
+
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+	decoder->iRelay->SetIntent(aIntent);
+
+	CleanupStack::Pop(decoder);
+	CleanupStack::PopAndDestroy(&decoderList);
+	return decoder;
+	}
+	
+CImageDecoder* CImageDecoder::FileNewImplL(RFile& aFile, const TDesC& aUniqueId, const TIntent aIntent, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
+	{
+	if ((aImageType == KNullUid) && (aImageSubType != KNullUid))
+		{ // Get out, no base type given for sub-type
+		Panic(EIllegalImageSubType); 
+		}
+
+	RImplInfoPtrArray decoderList;
+	CleanupResetAndDestroyPushL(decoderList);
+
+	CContent* content = CContent::NewLC(aFile);
+	CData* data = content->OpenContentL(aIntent, aUniqueId);
+	CleanupStack::PushL(data);
+
+	if (aImageType == KNullUid && aDecoderUid == KNullUid)
+		{ 
+		TBuf8<KMaxMimeLength> mimeType;
+		if (data->GetMimeTypeL(mimeType))
+			{
+			// try to find a controller based on MIME type
+			CImageDecoder::MimeTypeGetDecoderListL(decoderList, mimeType, aOptions);
+			}
+		if (decoderList.Count()==0)
+			{
+			// read header data
+			TBuf8<KImageHeaderSize> imageHeader;
+			User::LeaveIfError(data->Read(imageHeader, KImageHeaderSize));
+			CImageDecoder::ImageTypeGetDecoderListL(decoderList, imageHeader, aImageType, aImageSubType, aDecoderUid, aOptions);
+			}
+		}
+	else
+		{
+		TBuf8<KImageHeaderSize> imageHeader;
+		User::LeaveIfError(data->Read(imageHeader, KImageHeaderSize));
+		CImageDecoder::ImageTypeGetDecoderListL(decoderList, imageHeader, aImageType, aImageSubType, aDecoderUid, aOptions);
+		}
+	
+	CleanupStack::PopAndDestroy(2, content); // content, data
+
+	//Try to match by file extension only
+	//1) If no plugin was found and 
+	//2) No specific decoder or format was specified
+	TBuf<256> filename;
+	aFile.Name(filename);
+	const TBool formatSpecified = (aImageType!=KNullUid || aImageSubType!=KNullUid || aDecoderUid!=KNullUid);
+	if(decoderList.Count()==0 && !formatSpecified)
+		{
+		CImageDecoder::SuffixTypeGetDecoderListL(decoderList, filename, aOptions);
+		}
+
+	CImageDecoder* decoder = NULL;
+	decoder = CImageDecoder::FileFindDecoderNewL(decoderList, aFile, aOptions, aUniqueId);
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+	decoder->iRelay->SetIntent(aIntent);
+
+	CleanupStack::Pop(decoder);
+	CleanupStack::PopAndDestroy(&decoderList);
+	return decoder;
+	}
+	
+/**
+@internalTechnology
+
+Scans a sorted list of decoders for the first one that can decode the image.
+
+@param  aDecoderList
+        A list of decoders that support the image format.
+@param  aFile
+        A file server session for the decoder to use.
+@param  aOptions
+        The options to use during decoding.
+@param  aUniqueId
+        Identifier of file within a multi-part archive.
+
+@return A pointer to the decoder.
+*/
+CImageDecoder* CImageDecoder::FileFindDecoderNewL(const RImplInfoPtrArray& aDecoderList, RFile& aFile, const TOptions aOptions, const TDesC& aUniqueId)
+	{
+	TInt noOfDecoders = aDecoderList.Count();
+
+	if(noOfDecoders == 0)
+		User::Leave(KErrNotFound);
+
+	CImageDecoder* decoder = NULL;
+	TInt decoderNo = 0;
+	TInt error = KErrNone;
+	do
+		{
+		const CImplementationInformation& decoderInfo = *(aDecoderList[decoderNo++]);
+		TRAP(error,decoder=FileDecoderNewL(decoderInfo, aFile, aOptions, aUniqueId));
+		if (error != KErrCorrupt && error != KErrNotSupported && error != KErrNotFound)
+			break;
+		}
+	while(decoderNo < noOfDecoders);
+
+	if(error!=KErrNone)
+		{
+		ASSERT(decoder==NULL);
+		if (error == KErrCorrupt || error == KErrNotSupported)
+			error = KErrNotFound;
+		User::Leave(error);
+		}
+
+	return decoder;
+	}
+	
+/**
+@internalTechnology
+
+Create a construct that can create a decoder and call
+functions to initialise the decoder with the image data.
+
+@param  aDecoderInfo
+        Implementation information for the decoder to be created.
+@param  aFile
+        A file server session for the decoder to use.
+@param  aOptions
+        Options the decoder must use.
+@param  aUniqueId
+        Identifier of file within a multi-part archive.
+
+@return	A pointer to the decoder.
+*/
+CImageDecoder* CImageDecoder::FileDecoderNewL(const CImplementationInformation& aDecoderInfo, RFile& aFile, const TOptions aOptions, const TDesC& aUniqueId)
+	{
+	CImageDecodeConstruct* construct = NULL;
+	construct = NewDecodeConstructL(aDecoderInfo, aOptions);
+	ASSERT(construct!= NULL);
+
+	CImageDecoder* decoder = NewL(construct, aOptions); // note NewL takes ownership of construct - don't push on stack
+	ASSERT(decoder!=NULL);
+	CleanupStack::PushL(decoder);
+
+	decoder->iRelay->SetUniqueIdL(aUniqueId);
+
+	decoder->iRelay->SetFileL(aFile, aOptions);
+	decoder->iRelay->HandleNewlyOpenedImageL();
+
+	CleanupStack::Pop(decoder);
+	return decoder;
+	}
+
+
+/**
+Creates an encoder based on a specified MIME type and write output to a named file.
+
+The client supplies a MIME type which will be used to try and select an appropriate
+plugin encoder. If an appropriate encoder is found, it is created.
+
+If any file related errors are encountered opening the specified file, this
+function leaves with an appropriate file related leave code.
+
+@param  aFile
+        The handle of an open file to write the encoded image to
+@param  aMIMEType
+        The MIME type to use for the encoding.
+@param  aOptions
+        The encoder options to use.
+
+@return Returns a pointer to the newly created encoder.
+
+@leave  KEComErrNoInterfaceIdentified
+        ECom could not find the specified interface.
+@leave  KErrNotFound
+        No appropriate plugin encoder for this image has been found.
+
+@see    TOptions
+*/
+EXPORT_C CImageEncoder* CImageEncoder::FileNewL(RFile& aFile, const TDesC8& aMIMEType, const TOptions aOptions)
+	{
+	//Get a sorted list of encoders
+	RImplInfoPtrArray encoderList;
+	CleanupResetAndDestroyPushL(encoderList);
+	CImageEncoder::MimeTypeGetEncoderListL(encoderList, aMIMEType, aOptions);
+
+	if(encoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	//Use the highest rated encoder.
+	CImageEncodeConstruct* construct = NewEncodeConstructL(*encoderList[0], aOptions);
+	CleanupStack::PopAndDestroy(&encoderList);
+
+	CImageEncoder* encoderPtr = NewL(construct, aOptions); // NewL takes ownership of construct - no need to push on stack
+	CleanupStack::PushL(encoderPtr);
+	encoderPtr->iRelay->SetFileL(aFile, aOptions);
+	CleanupStack::Pop(encoderPtr); 
+	return encoderPtr;
+	}
+	
+/**
+Creates an encoder based on a supplied parameters and writes output to a named file.
+
+The client must supply a basic image type (and a sub-type, if applicable) or a specific
+encoder/class implementation UID, which will be used to try and select an appropriate plugin
+encoder. If an appropriate encoder is found, it is created.
+
+Note:
+Every image format has two IDs, known as the type and the sub-type (although generally
+the sub-type is KNullUid). To retrieve a list of supported types and sub-types that can be
+encoded, use the static functions GetImageTypesL() and GetImageSubTypesL().
+
+If no plugin encoder can be found that matches the details provided in aImageType, aImageSubType
+and possibly aEncoderUid this function leaves with KErrNotFound or KEComErrNoInterfaceIdentified.
+
+If any file related errors are encountered opening the specified file, this function leaves
+with an appropriate file related leave code.
+
+@param  aFile
+        The handle of an open file to write the encoded image to
+@param  aOptions
+        Options to use.
+@param  aImageType
+        The image type to use for the encoding (mandatory).
+@param  aImageSubType
+        The image sub-type to use for the encoding (only if applicable, defaults to KNullUid).
+@param  aEncoderUid
+		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
+		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
+		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
+		the list of available plugins with the specified class UID will be loaded.
+@see	KUidICLJpegEXIFInterface
+@see	KUidICLJpegImageFrameInterface
+
+@return A pointer to the newly created encoder.
+
+@leave  KErrNotFound
+        No appropriate plugin encoder for this image has been found.
+@leave  KEComErrNoInterfaceIdentified
+		ECom could not find the specified interface.		
+
+@panic  ImageConversion 19
+        No base type given for sub-type.
+@panic  ImageConversion 20
+        No base type given for encoder implementation.
+
+@see    TOptions
+*/
+EXPORT_C CImageEncoder* CImageEncoder::FileNewL(RFile& aFile, const TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aEncoderUid)
+	{
+	//Get a sorted list of encoders
+	RImplInfoPtrArray encoderList;
+	CleanupResetAndDestroyPushL(encoderList);
+	CImageEncoder::ImageTypeGetEncoderListL(encoderList, aImageType, aImageSubType, aEncoderUid, aOptions);
+
+	if(encoderList.Count() == 0)
+		User::Leave(KErrNotFound);
+
+	//Use the highest rated encoder.
+	CImageEncodeConstruct* construct = NewEncodeConstructL(*encoderList[0], aOptions);
+	CleanupStack::PopAndDestroy(&encoderList);
+	CImageEncoder* encoderPtr = NewL(construct, aOptions); // NewL takes ownership of construct - no need to push on cleanstack
+	CleanupStack::PushL(encoderPtr);
+	encoderPtr->iRelay->SetFileL(aFile, aOptions);
+	CleanupStack::Pop(); //encoderPtr
+	return encoderPtr;
+	}
+
+	
+/**
+Select to encode or not the thumbnail
+
+@param  aDoGenerateThumbnail
+		EFalse if no generation of thumbnail
+*/
+EXPORT_C void CImageEncoder::SetThumbnail(TBool aDoGenerateThumbnail)
+	{
+	ASSERT(ValidProperties());
+	iRelay->SetThumbnail(aDoGenerateThumbnail);
+	}
+	
+/**
+Set the encoder worker thread priority
+
+@param  aPriority
+		a new value for worker thread priority
+@return KErrNotSupported 
+		the encoder object doesn't use a worker thread.
+		Other system-wide error codes.
+@see	TThreadPriority
+*/
+EXPORT_C TInt CImageEncoder::SetEncoderThreadPriority(TThreadPriority aPriority)
+	{
+	return iRelay->SetEncoderThreadPriority( aPriority );
+	}
+
+/**
+@publishedAll
+@released
+
+Optional call from client which may be made on the encoder to allow analysis of image prior to calling
+Convert.
+
+Should be called once encode is fully set up e.g. any encode operations defined.
+
+@param	aRequestStatus
+		Request status. On completion this contains an error code. This is KErrNone if the frame
+		was analyzed successfully, KErrNotSupported if the codec does not support analysis, or a
+		system-wide error code.
+
+@see CImageEncoder::Convert
+*/
+EXPORT_C void CImageEncoder::Prepare(TRequestStatus* aRequestStatus)
+	{
+	ASSERT(ValidProperties());
+	ASSERT(aRequestStatus);
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvPrepare* prepare = cache->Prepare();
+
+	if(!prepare)
+		{
+		MImageConvExtension* prepareExtension = NULL;
+		TRAPD(err,
+			{
+			iRelay->GetExtensionL(KICLPrepareUid, prepareExtension);
+			prepare = new (ELeave) TImageConvPrepare();
+			prepare->SetExtension(prepareExtension);
+			cache->SetPrepareExtension(prepare);
+			});
+		if ( err != KErrNone )
+			{
+			User::RequestComplete(aRequestStatus, err);
+			return;
+			}
+		}
+	prepare->Prepare(aRequestStatus);
+	}
+
+CContent* CImageDecoder::GetContentLC(const TDesC& aSourceFilename)
+	{
+	CContent* content = NULL;
+	TRAPD(err,content = CContent::NewL(aSourceFilename, EContentShareReadOnly));
+	if(err != KErrNone && err != KErrNoMemory)
+		{
+		content = CContent::NewL(aSourceFilename, EContentShareReadWrite);
+		}
+	User::LeaveIfNull(content);
+	CleanupStack::PushL(content);
+	return content;
+	}
+
+/**
+@publishedAll
+@released
+
+
+Get the extension interface for operations on the image.
+@return Interface to image conversion operations.
+@leave KErrNotSupported if loaded codec plugin does not support this optional extension.
+@leave Other system wide errors
+
+@note The order of post processing operations when applied for decoding is
+
+- 1. Clip the image 
+- 2. Scale the image 
+- 3. Operate on the image 
+
+@see CImageDecoder::SetClippingRectL()
+@see TImageConvScaler
+@see TImageConvOperation
+*/
+EXPORT_C TImageConvOperation* CImageDecoder::OperationL()
+	{
+	ASSERT(ValidProperties());
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvOperation* operation = cache->Operation();
+
+	if(!operation)
+		{
+		MImageConvExtension* operationExtension = NULL;
+		iRelay->GetExtensionL(KICLOperationUid, operationExtension);
+		operation = new (ELeave) TImageConvOperation();
+		operation->SetExtension(operationExtension);
+		cache->SetOperationExtension(operation);
+		}
+	return operation;
+	}
+
+/**
+@publishedAll
+@released
+
+
+Get the extension interface for scaling the image. @see TImageConvScaler
+@return Interface to image conversion scaler.
+@leave KErrNotSupported if loaded codec plugin does not support this optional extension.
+@leave Other system wide errors.
+
+@see note under CImageDecoder::OperationL.
+*/
+EXPORT_C TImageConvScaler* CImageDecoder::ScalerL()
+	{
+	ASSERT(ValidProperties());
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvScaler* scaler = cache->Scaler();
+
+	if(!scaler)
+		{
+		MImageConvExtension* scalerExtension = NULL;
+		iRelay->GetExtensionL(KICLScalerUid, scalerExtension);
+		scaler = new (ELeave) TImageConvScaler();
+		scaler->SetExtension(scalerExtension);
+		cache->SetScalerExtension(scaler);
+		}
+	return scaler;
+	}
+
+/**
+@publishedAll
+@released
+
+
+Get the extension interface for block streaming on the image. @see TImageConvStreamedDecode
+@return Interface to image conversion block streamer.
+@leave KErrNotSupported if loaded codec plugin does not support this optional extension.
+@leave Other system wide errors.
+*/
+EXPORT_C TImageConvStreamedDecode* CImageDecoder::BlockStreamerL()
+	{
+	ASSERT(ValidProperties());
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvStreamedDecode* streamer = cache->DecodeBlockStreamer();
+
+	if(!streamer)
+		{
+		MImageConvExtension* streamExtension = NULL;
+		iRelay->GetExtensionL(KICLStreamedDecodeUid, streamExtension);
+		streamer = new (ELeave) TImageConvStreamedDecode();
+		streamer->SetExtension(streamExtension);
+		cache->SetBlockStreamerExtension(streamer);
+		}
+	return streamer;
+	}
+
+/**
+@publishedAll
+@released
+
+
+Sets the area of interest of the image to be decoded.  This function can leave with
+any of the system-wide error codes.
+
+@param aClipRect	A pointer to a TRect that specifies the
+					location and size of the region to be decoded.  This
+					rectangle must have positive width and height values as
+					per TRect::IsNormalized() and TRect::Normalize().
+					Passing in a NULL value will clear the clipping rectangle.
+					Note that a clipping rectangle may not be valid for all frames of an image.
+
+@leave KErrNotSupported		This function is not supported.
+@leave KErrArgument			Returned if the clipping rectangle:
+							a) is empty (i.e. IsEmpty() returns ETrue)
+							b) is not normalised (i.e. IsNormalized() returns EFalse)
+							c) has coordinates that are not located within, or on,
+							the coodinates of at least one frame of the original image.
+							d) has a width or a height of 0
+
+@see	TRect::IsEmpty()
+@see	TRect::IsNormalized()
+@see	TRect::Normalize()
+
+@see note under CImageDecoder::OperationL
+*/
+EXPORT_C void CImageDecoder::SetClippingRectL(const TRect* aClipRect)
+	{
+	ASSERT(ValidProperties());
+	iRelay->SetClippingRectL(aClipRect);
+	}
+
+/**
+@publishedAll
+@released
+
+
+Optional call from client which may be made on the decoder to allow analysis of image prior to calling
+Convert.
+
+Should be called once decode is fully set up e.g. clipping rectangle set.
+
+@param	aRequestStatus
+		Request status. On completion this contains an error code. This is KErrNone if the frame
+		was analyzed successfully, KErrNotSupported if the codec does not support analysis, or a
+		system-wide error code.
+
+@see CImageDecoder::Convert
+*/
+EXPORT_C void CImageDecoder::Prepare(TRequestStatus* aRequestStatus)
+	{
+	ASSERT(ValidProperties());
+	ASSERT(aRequestStatus);
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvPrepare* prepare = cache->Prepare();
+
+	if(!prepare)
+		{
+		MImageConvExtension* prepareExtension = NULL;
+		TRAPD(err,
+			{
+			iRelay->GetExtensionL(KICLPrepareUid, prepareExtension);
+			prepare = new (ELeave) TImageConvPrepare();
+			prepare->SetExtension(prepareExtension);
+			cache->SetPrepareExtension(prepare);
+			});
+		if ( err != KErrNone )
+			{
+			User::RequestComplete(aRequestStatus, err);
+			return;
+			}
+		}
+	prepare->Prepare(aRequestStatus);
+	}
+
+/**
+@publishedAll
+@released
+
+
+Get the size of the decoded image for the given frame. The calculation will account for any clipping rectangle set,
+scaling applied through the TImageConvScaler extension and any operation applied through TImageConvOperation.
+If TImageConvScaler::SetScalingL(.. has been called then the size of the bitmap passed to CImageDecoder::Convert must match the size returned from
+this function.
+
+@param aSize 
+	   Returns the size of the decoded image.
+@param aFrameNumber
+	   The frame number.
+	   
+@return KErrArgument if an error in calculation is detected e.g. if clipping rectangle is outside of the overall frame boundary.
+@return Other system wide errors.
+*/
+EXPORT_C TInt CImageDecoder::GetDestinationSize(TSize& aSize, TInt aFrameNumber)
+	{
+	ASSERT(ValidProperties());
+	return iRelay->GetDestinationSize(aSize, aFrameNumber);
+	}
+
+/**
+@publishedAll
+@released
+
+
+Get the extension interface for operations on image. @see TImageConvOperation
+@return Interface to image conversion operations (rotate/mirror over axis).
+@leave KErrNotSupported if loaded codec plugin does not support this optional extension.
+@leave Other system wide errors
+*/
+EXPORT_C TImageConvOperation* CImageEncoder::OperationL()
+	{
+	ASSERT(ValidProperties());
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvOperation* operation = cache->Operation();
+
+	if(!operation)
+		{
+		MImageConvExtension* operationExtension = NULL;
+		iRelay->GetExtensionL(KICLOperationUid, operationExtension);
+		operation = new (ELeave) TImageConvOperation();
+		operation->SetExtension(operationExtension);
+		cache->SetOperationExtension(operation);
+		}
+	return operation;
+	}
+
+/**
+@publishedAll
+@released
+
+
+Get the extension interface for block streaming on image. @see TImageConvStreamedEncode
+@return Interface to image conversion operations.
+@leave KErrNotSupported if loaded codec plugin does not support this optional extension.
+@leave Other system wide errors
+*/
+EXPORT_C TImageConvStreamedEncode* CImageEncoder::BlockStreamerL()
+	{
+	ASSERT(ValidProperties());
+
+	CImageConvExtensionCache* cache = &iRelay->ExtensionCache();
+	TImageConvStreamedEncode* streamer = cache->EncodeBlockStreamer();
+
+	if(!streamer)
+		{
+		MImageConvExtension* streamExtension = NULL;
+		iRelay->GetExtensionL(KICLStreamedEncodeUid, streamExtension);
+		streamer = new (ELeave) TImageConvStreamedEncode();
+		streamer->SetExtension(streamExtension);
+		cache->SetBlockStreamerExtension(streamer);
+		}
+	return streamer;
+	}
+
+
+