imaging/imagingfws/MediaClientImage/Source/Client/Image/Mclvidpriv.cpp
changeset 0 5752a19fdefe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imaging/imagingfws/MediaClientImage/Source/Client/Image/Mclvidpriv.cpp	Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,1125 @@
+// Copyright (c) 1997-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 <bitdev.h>
+#include <mdaimageconverter.h>
+#include "MdaImageConverterPriv.h"
+#include <ecom/ecom.h>
+
+#include <imageconversion.h>
+#include <bitmaptransforms.h>
+
+#include "CompatAids.h"
+
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	const TInt KWaitTimeMax = 8;
+	const TInt KWaitTimeIncrement = 250000; // 0.25s
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+
+GLDEF_C void Panic (TInt aPanic)
+	{
+	_LIT(KMdaImageConverter, "MDA Image Converter");
+	User::Panic(KMdaImageConverter, aPanic);
+	}
+
+
+//
+// CMdaImageUtilityPriv
+//
+
+CMdaImageUtilityPriv::CMdaImageUtilityPriv(MMdaImageUtilObserver& aObserver, CMdaImageUtility* aParent):
+	iObserver(aObserver), iParent(aParent)
+	{}
+
+CMdaImageUtilityPriv::~CMdaImageUtilityPriv()
+	{
+	delete iImageData;
+	delete iFrameData;
+	iFs.Close();
+	CloseEcomSession();
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	iWaitTimer.Close(); 
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+	}
+
+void CMdaImageUtilityPriv::CloseEcomSession()
+	{
+	if (iEcomSession)
+		iEcomSession->Close();
+	iEcomSession = NULL;
+	}
+
+void CMdaImageUtilityPriv::OpenEcomSessionL()
+	{
+	if (iEcomSession==NULL)
+		iEcomSession = &(REComSession::OpenL());
+	}
+
+/**
+ *
+ * Closes the open file-based or descriptor-based image.
+ *
+ * Any conversion operation in progress is cancelled.
+ *
+ */
+void CMdaImageUtilityPriv::Close()
+	{
+	Close(ETrue);
+	}
+
+// officially reset at end - in practice we always make this call before opening too
+void CMdaImageUtilityPriv::Close(TBool aFullClose)
+	{
+	ASSERT(iParent);
+	iParent->Cancel();
+	DoClose();
+	if (aFullClose)
+		CloseEcomSession();
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	iWaitTimeCount = 0; 
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+	}
+
+void CMdaImageUtilityPriv::DoClose()
+	{
+	}
+
+void CMdaImageUtilityPriv::Initialize()
+	{
+	ASSERT(iParent);
+	CActiveScheduler::Add(iParent);
+	}
+
+void CMdaImageUtilityPriv::OpenFsSessionL()
+	{
+	ASSERT(iFs.Handle()==0); // intended for use from ConstructL only
+
+	User::LeaveIfError(iFs.Connect());
+	}
+
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+void CMdaImageUtilityPriv::OpenWaitTimerL()
+	{
+	ASSERT(iWaitTimer.Handle()==0); // intended for use from ConstructL etc only
+	User::LeaveIfError(iWaitTimer.CreateLocal());
+	}
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+
+/**
+Retrieves information about the specified frame.
+
+This function should only be called after an existing image has been
+successfully opened or a new image successfully created.
+
+@param     aFrame
+           The frame number. This value is relative to zero. The
+           value must be less than the total number of frames in
+           the image, otherwise the function raises a USER 0
+           panic
+@param     aInfo
+           Frame information.
+*/
+void CMdaImageUtilityPriv::FrameInfo(TInt /*aFrame*/,TFrameInfo& /*aInfo*/) const
+	{
+	__PANIC_COMPAT(Panic(EMDAImConvPanicNotImplemented)); // only implemented for data read
+	}
+
+/**
+Returns the number of frames in the image.
+
+@return   The number of frames in the image
+*/
+TInt CMdaImageUtilityPriv::FrameCount() const
+	{
+	__PANIC_COMPAT(Panic(EMDAImConvPanicNotImplemented)); // only implemented for data read
+	return 0; 
+	}
+
+//
+// Performs a User::RequestComplete() operation on this itself.
+//
+void CMdaImageUtilityPriv::SelfComplete(TInt aError)
+	{
+	ASSERT(iParent);
+	iParent->SelfComplete(aError);
+	}
+
+// Effectively converts the old format converts to the new ones. The
+// results are placed in iImageType and iImageSubType, plus perhaps iImageData
+//
+//	TMdaClipFormat* aFormat = NULL
+//		The data format. This is optional.
+//	TMdaPackage* aCodec = NULL
+//		The codec to use. This is optional.
+//	TMdaPackage* aExtra = NULL
+//		Additional information which the Media Server may need
+//		to recognise the data format. This is optional.
+//
+void CMdaImageUtilityPriv::SetUidsFromOrigFormatsL(TMdaClipFormat* aFormat,
+											   TMdaPackage* aCodec,
+											   TMdaPackage* /*aExtra*/)
+	{
+	// set default values first
+	delete iImageData; iImageData=NULL;
+	iImageType = KNullUid;
+	iImageSubType = KNullUid;
+
+	// Note in general below we ignore the codec settings, unless the latter is used
+	// to indicate format. 
+
+	if (aFormat)
+		{
+		TUid formatUid = aFormat->Uid();
+		if (formatUid==KUidMdaBmpClipFormat)
+			{
+			iImageType = KImageTypeBMPUid;
+			if (aCodec)
+				{
+				iImageData = new (ELeave) TBmpImageData;
+				TBmpImageData *data = STATIC_CAST(TBmpImageData*,iImageData);
+				if (aCodec->Uid() == KUidMda1BppBmpCodec)
+					data->iBitsPerPixel = 1;
+				else if (aCodec->Uid() == KUidMda4BppBmpCodec)
+					data->iBitsPerPixel = 4;
+				else if (aCodec->Uid() == KUidMda8BppBmpCodec)
+					data->iBitsPerPixel = 8;
+				else if (aCodec->Uid() == KUidMda24BppBmpCodec)
+					data->iBitsPerPixel = 24;
+				else
+					{
+					// unknown value - so leave undefined
+					delete iImageData; iImageData = NULL;
+					}
+				}
+			}
+		else if (formatUid==KUidMdaGif87aClipFormat || formatUid==KUidMdaGif89aClipFormat) 
+			iImageType = KImageTypeGIFUid; 
+		else if (formatUid==KUidMdaJfifClipFormat)
+			{
+			TMdaJfifClipFormat *jfifFormat = STATIC_CAST(TMdaJfifClipFormat*, aFormat);
+			TMdaJpgSettings::TColorSampling sampling = jfifFormat->iSettings.iSampleScheme;
+			iImageType = KImageTypeJPGUid; 
+			iImageData = new (ELeave) TJpegImageData;
+			TJpegImageData* data = STATIC_CAST(TJpegImageData*, iImageData);
+			ASSERT(TInt(TMdaJpgSettings::EMonochrome)==TInt(TJpegImageData::EMonochrome)); // check old sample type = new one
+			ASSERT(TInt(TMdaJpgSettings::EColor420)==TInt(TJpegImageData::EColor420));
+			ASSERT(TInt(TMdaJpgSettings::EColor422)==TInt(TJpegImageData::EColor422));
+			ASSERT(TInt(TMdaJpgSettings::EColor444)==TInt(TJpegImageData::EColor444));
+			ASSERT(sampling>=TMdaJpgSettings::EMonochrome && sampling <= TMdaJpgSettings::EColor444); // valid range
+			data->iSampleScheme = TJpegImageData::TColorSampling(sampling); // can just copy value
+			data->iQualityFactor = jfifFormat->iSettings.iQualityFactor;
+			}
+		else if (formatUid==KUidMdaMbmClipFormat)
+			{
+			TMdaMbmClipFormat *mbmFormat = STATIC_CAST(TMdaMbmClipFormat*, aFormat);
+			TDisplayMode displayMode = mbmFormat->iDisplayMode;
+			iImageType = KImageTypeMBMUid;
+			iFrameData = new (ELeave) TMbmEncodeData;
+			TMbmEncodeData* data = STATIC_CAST(TMbmEncodeData*, iFrameData);
+			data->iDisplayMode = displayMode;
+			}
+		else if (formatUid==KUidMdaOtaClipFormat) // SMS OTA format
+			iImageType = KImageTypeOTAUid; 
+		else if (formatUid==KUidMdaWbmpClipFormat)
+			iImageType = KImageTypeWBMPUid;
+		else if (formatUid==KUidMdaPngClipFormat)
+			iImageType = KImageTypePNGUid;
+		else if (formatUid==KUidMdaTiffLittleEndianClipFormat ||
+				 formatUid==KUidMdaTiffBigEndianClipFormat)
+			{
+			iImageType=KImageTypeTIFFUid;
+			if (formatUid==KUidMdaTiffLittleEndianClipFormat)
+				iImageSubType=KImageTypeTIFFSubTypeLittleEndianUid;
+			else
+				{
+				ASSERT(formatUid==KUidMdaTiffBigEndianClipFormat);
+				iImageSubType=KImageTypeTIFFSubTypeBigEndianUid;
+				}
+			}
+		else if (formatUid==KUidMdaTiffBigEndianClipFormat)
+			{
+			iImageType = KImageTypeTIFFUid;
+			iImageSubType = KImageTypeTIFFSubTypeBigEndianUid;
+			}
+		else if (formatUid==KUidMdaWmfClipFormat ||
+			     formatUid==KUidMdaWmfApmClipFormat ||
+			     formatUid==KUidMdaWmfClpClipFormat)
+			{
+			iImageType = KImageTypeWMFUid;
+			if (formatUid==KUidMdaWmfApmClipFormat)
+				iImageSubType = KImageTypeWMFSubTypeApmUid;
+			else if (formatUid==KUidMdaWmfClpClipFormat)
+				iImageSubType = KImageTypeWMFSubTypeClpUid;
+			else
+				{
+				ASSERT(formatUid==KUidMdaWmfClipFormat);
+				iImageSubType = KImageTypeWMFSubTypeStdUid;
+				}
+			}
+		else
+			User::Leave(KErrNotSupported);
+		}
+	}
+
+//
+// CMdaImageDataReadUtilityPriv
+//
+
+CMdaImageDataReadUtilityPriv::CMdaImageDataReadUtilityPriv(MMdaImageUtilObserver& aObserver,
+														   CMdaImageDataReadUtility* aParent):
+	CMdaImageUtilityPriv(aObserver, aParent)
+	{
+	}
+
+CMdaImageDataReadUtilityPriv::~CMdaImageDataReadUtilityPriv()
+	{
+	Close(ETrue);
+	ASSERT(iDecoder==NULL); // should have been deleted by Close
+	}
+
+void CMdaImageDataReadUtilityPriv::ConvertL(CFbsBitmap& aBitmap,TInt aFrameNumber)
+	{
+	ASSERT(Parent());
+	if (iState != EStateOpen)
+		User::Leave(KErrNotReady);
+
+	ASSERT(iDecoder);
+
+	TBool doContinue = EFalse;
+	if (iPrevConvertUnderflowed && iKeptFrameNumber == aFrameNumber)
+		{
+		// if previous convert Underflowed, and same bitmap, we ContinueConvert instead of Convert
+		if (iDestinationHandle == aBitmap.Handle() && 
+			iDestinationDisplayMode == aBitmap.DisplayMode() && 
+			iDestinationMaskHandle == 0 &&
+			iDestinationSize == aBitmap.SizeInPixels())
+			doContinue = ETrue;
+		}
+
+	if (doContinue)
+		iDecoder->ContinueConvert(&Parent()->iStatus);
+	else
+		{
+		iDestinationHandle = aBitmap.Handle();
+		iDestinationMaskHandle = 0;
+		if (aBitmap.Handle())
+			{
+			iDestinationDisplayMode = aBitmap.DisplayMode();
+			iDestinationSize = aBitmap.SizeInPixels();
+			}
+		iDecoder->Convert(&Parent()->iStatus, aBitmap, aFrameNumber); 
+		}
+	Parent()->SetActive();
+	iState = EStateConverting;
+	}
+
+void CMdaImageDataReadUtilityPriv::ConvertL(CFbsBitmap& aBitmap,CFbsBitmap& aMaskBitmap,TInt aFrameNumber)
+	{
+	ASSERT(Parent());
+	if (iState != EStateOpen)
+		User::Leave(KErrNotReady);
+
+	ASSERT(iDecoder);
+
+	TBool doContinue = EFalse;
+	if (iPrevConvertUnderflowed && iKeptFrameNumber == aFrameNumber)
+		{
+		// if previous convert Underflowed, and same bitmap, we ContinueConvert instead of Convert
+		if (iDestinationHandle == aBitmap.Handle() && 
+			iDestinationDisplayMode == aBitmap.DisplayMode() && 
+			iDestinationMaskHandle == aMaskBitmap.Handle() &&
+			iDestinationMaskDisplayMode == aMaskBitmap.DisplayMode() && 
+			iDestinationSize == aBitmap.SizeInPixels())
+			doContinue = ETrue;
+		}
+
+	if (doContinue)
+		iDecoder->ContinueConvert(&Parent()->iStatus);
+	else
+		{
+		iDestinationHandle = aBitmap.Handle();
+		iDestinationMaskHandle = aMaskBitmap.Handle();
+		if (aBitmap.Handle())
+			{
+			iDestinationDisplayMode = aBitmap.DisplayMode();
+			iDestinationSize = aBitmap.SizeInPixels();
+			}
+		if (aMaskBitmap.Handle())
+			iDestinationMaskDisplayMode = aMaskBitmap.DisplayMode();
+		iDecoder->Convert(&Parent()->iStatus, aBitmap, aMaskBitmap, aFrameNumber); 
+		}
+	Parent()->SetActive();
+	iState = EStateConverting;
+	}
+
+void CMdaImageDataReadUtilityPriv::CancelConvertL()
+	{
+	Parent()->Cancel();
+	}
+
+void CMdaImageDataReadUtilityPriv::RunL()
+	{
+	ASSERT(Parent());
+	switch (iState)
+		{
+		case EStateClosed:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateOpening:
+			{
+			TInt error = Parent()->iStatus.Int();
+			if (error==KErrNone)
+				TRAP(error, OpenEcomSessionL());
+			if (error==KErrNone)
+				TRAP(error, DoOpenL());
+			ASSERT(error!=KErrNone || iDecoder); // if successful should have an iDecoder
+			if (error==KErrNone)
+				{
+				iState=EStateOpen;
+				iObserver.MiuoOpenComplete(error);
+				}
+			else
+				{
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+				if (error==KEComErrListCurrentlyUnavailable && iWaitTimeCount < KWaitTimeMax)
+					{
+					iWaitTimeCount ++;
+					TInt waitTime = iWaitTimeCount * KWaitTimeIncrement;
+					iState = EStateOpeningWait;
+					iWaitTimer.After(Parent()->iStatus, waitTime);
+					Parent()->SetActive();
+					}
+				else
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+					{
+					if (error!=KErrUnderflow) // keep ecom session on streaming
+						CloseEcomSession();
+					iState=EStateClosed;
+					iObserver.MiuoOpenComplete(error);
+					}
+				}
+			}
+			break;
+		case EStateOpeningWait:
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+			{
+			TInt error = Parent()->iStatus.Int();	
+			if (error!=KErrNone)
+				{
+				CloseEcomSession();
+				iState = EStateClosed;
+				iObserver.MiuoOpenComplete(error);
+				}
+			else
+				{
+				iState = EStateOpening;
+				SelfComplete(error);
+				}
+			}
+#else
+			ASSERT(EFalse); // should not get here if __ECOM_POWERDOWN_WORKAROUND not defined
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+			break;
+		case EStateOpen:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateConverting:
+			{
+			TInt error = Parent()->iStatus.Int();
+
+			//Add comments
+			if(error==KErrNone)
+				TRAP(error,GetCommentL());
+
+			iState = EStateOpen; // clear first to allow immediate re-conversion
+			iPrevConvertUnderflowed = error==KErrUnderflow;
+			iObserver.MiuoConvertComplete(error);
+			}
+			break;
+		default:
+			ASSERT(EFalse); // unknown state
+		}
+	}
+
+void CMdaImageDataReadUtilityPriv::DoCancel()
+	{
+	switch (iState)
+		{
+		case EStateClosed:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateOpening:
+			// ignore - makes no difference to do something here
+			break;
+		case EStateOpeningWait:
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+			iWaitTimer.Cancel();
+#else
+			ASSERT(EFalse);
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+			break;
+		case EStateOpen:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateConverting:
+			{
+			iDecoder->Cancel(); 
+			iState = EStateOpen; 
+			}
+			break;
+		default:
+			ASSERT(EFalse); // unknown state
+		}
+	}
+
+void CMdaImageDataReadUtilityPriv::DoClose()
+	{
+	ASSERT(Parent());
+	ASSERT(!Parent()->IsActive()); // Cancel should be called by this point
+	if (iDecoder)
+		iDecoder->Cancel();
+	delete iDecoder; iDecoder = NULL;
+	iComment.ResetAndDestroy();
+	iPrevConvertUnderflowed = EFalse;
+	iState = EStateClosed;
+	}
+
+const TDesC& CMdaImageDataReadUtilityPriv::FrameCommentL(TInt aFrameNumber)
+	{
+	if (aFrameNumber >= iComment.Count())
+		User::Leave(KErrArgument);
+
+	if (iComment[aFrameNumber])
+		return *iComment[aFrameNumber];
+
+	return KNullDesC;
+	}
+
+void CMdaImageDataReadUtilityPriv::GetCommentL()
+	{
+	if(iDecoder->IsImageHeaderProcessingComplete()&&iComment.Count()==0)
+		{
+		TInt noOfComments = 0;
+		TInt commentNo = 0;
+
+		const TInt noOfFrames = iDecoder->FrameCount();
+		for(TInt currentFrame=0; currentFrame<noOfFrames; currentFrame++)
+			{
+			HBufC* nullComment = KNullDesC().AllocL();
+			CleanupStack::PushL(nullComment);
+			User::LeaveIfError(iComment.Append(nullComment));
+			CleanupStack::Pop(nullComment);
+
+			//Add the general comments if it is the first frame
+			if(currentFrame==0)
+				{
+				noOfComments = iDecoder->NumberOfImageComments();
+				for(commentNo = 0; commentNo < noOfComments; commentNo++)
+					{
+					HBufC* currentComment = iComment[currentFrame];
+					HBufC* newComment = iDecoder->ImageCommentL(commentNo);
+					CleanupStack::PushL(newComment);
+
+					TInt newLength = currentComment->Length() + newComment->Length();
+
+					iComment[currentFrame] = currentComment->ReAllocL(newLength);
+					iComment[currentFrame]->Des().Append(*newComment);
+
+					CleanupStack::PopAndDestroy(newComment);
+					}
+				}
+
+			//Add the frame comments
+			noOfComments = iDecoder->NumberOfFrameComments(currentFrame);
+			for(commentNo = 0; commentNo < noOfComments; commentNo++)
+				{
+				HBufC* currentComment = iComment[currentFrame];
+				HBufC* newComment = iDecoder->FrameCommentL(currentFrame,commentNo);
+				CleanupStack::PushL(newComment);
+
+				TInt newLength = currentComment->Length() + newComment->Length();
+
+				iComment[currentFrame] = currentComment->ReAllocL(newLength);
+				iComment[currentFrame]->Des().Append(*newComment);
+
+				CleanupStack::PopAndDestroy(newComment);
+				}
+			}
+		}
+	}
+
+/**
+ *
+ * Retrieves information about the specified frame.
+ *
+ * This function should only be called after an existing image has been
+ * successfully opened or a new image successfully created.
+ *
+ * @param     "TInt aFrame"
+ *            The frame number. This value is relative to zero. The
+ *            value must be less than the total number of frames in
+ *            the image, otherwise the function raises a USER 0
+ *            panic
+ * @param     "TFrameInfo& aInfo"
+ *            Frame information.
+ */
+void CMdaImageDataReadUtilityPriv::FrameInfo(TInt aFrame,TFrameInfo& aInfo) const
+	{
+	__ASSERT_ALWAYS(iDecoder,Panic(EMDAImConvPanicNotYetOpen));
+	TFrameInfo iclInfo = iDecoder->FrameInfo(aFrame);
+	aInfo.iFrameCoordsInPixels = iclInfo.iFrameCoordsInPixels;
+	aInfo.iFrameSizeInTwips = iclInfo.iFrameSizeInTwips;
+	aInfo.iBitsPerPixel = iclInfo.iBitsPerPixel;
+	aInfo.iDelay = iclInfo.iDelay;
+	aInfo.iFlags = iclInfo.iFlags;
+	aInfo.iOverallSizeInPixels = iclInfo.iOverallSizeInPixels;
+	}
+
+/**
+ *
+ * Returns the number of frames in the image.
+ *
+ * @return   "TInt"
+ *            The number of frames in the image
+ */
+TInt CMdaImageDataReadUtilityPriv::FrameCount() const
+	{
+	__ASSERT_ALWAYS(iDecoder,Panic(EMDAImConvPanicNotYetOpen));
+	return iDecoder->FrameCount();
+	}
+
+//
+// CMdaImageDataWriteUtilityPriv
+//
+
+CMdaImageDataWriteUtilityPriv::CMdaImageDataWriteUtilityPriv(MMdaImageUtilObserver& aObserver,
+															 CMdaImageDataWriteUtility* aParent):
+	CMdaImageUtilityPriv(aObserver, aParent)
+	{}
+
+CMdaImageDataWriteUtilityPriv::~CMdaImageDataWriteUtilityPriv()
+	{
+	Close(ETrue);
+	ASSERT(iEncoder==NULL); // should have been deleted by Close
+	ASSERT(iFrameImageData==NULL); // ditto
+	}
+
+void CMdaImageDataWriteUtilityPriv::ConvertL(CFbsBitmap& aBitmap,TInt aFrameNumber)
+	{
+	ASSERT(Parent())
+	if (iState == EStateCancelled) 
+		{
+		delete iEncoder;
+		iEncoder = NULL;
+
+		TRAPD(err,DoCreateL(EFalse));
+
+		if (err==KErrNone)
+			iState = EStateOpen;
+		}
+
+	if (iState != EStateOpen)
+		User::Leave(KErrNotReady);
+
+	if (aFrameNumber != 0)
+		User::Leave(KErrArgument);
+
+	ASSERT(iEncoder);
+
+	iEncoder->Convert(&Parent()->iStatus, aBitmap, iFrameImageData);
+
+	Parent()->SetActive();
+	iState = EStateConverting;
+	}
+
+void CMdaImageDataWriteUtilityPriv::ConvertL(CFbsBitmap& /*aBitmap*/,const TRect& /*aSourceRect*/,TInt /*aFrameNumber*/)
+	{
+	User::Leave(KErrNotSupported);
+	}
+
+void CMdaImageDataWriteUtilityPriv::ConvertL(CFbsBitmap& /*aBitmap*/,CFbsBitmap& /*aMaskBitmap*/,TInt /*aFrameNumber*/)
+	{
+	User::Leave(KErrNotSupported);
+	}
+
+void CMdaImageDataWriteUtilityPriv::CancelConvertL()
+	{
+	ASSERT(Parent());
+	Parent()->Cancel();
+	}
+
+void CMdaImageDataWriteUtilityPriv::RunL()
+	{
+	ASSERT(Parent());
+	switch (iState)
+		{
+		case EStateClosed:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateCreating:
+			{
+			TInt error = Parent()->iStatus.Int();
+			if (error==KErrNone)
+				TRAP(error, DoCreateL());
+			if (error==KErrNone)
+				iState=EStateOpen;
+			else
+				iState=EStateClosed;
+			iObserver.MiuoCreateComplete(error);
+			}
+			break;
+		case EStateOpen:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateConverting:
+			{
+			TInt error = Parent()->iStatus.Int();
+			if (error!=KErrNone)
+				{
+				iState = EStateOpen; // clear first to allow immediate re-conversion
+				iObserver.MiuoConvertComplete(error);
+				}
+			else
+				{
+				iState = EStateCopying;
+				SelfComplete(KErrNone);
+				}
+			}
+			break;
+		case EStateCopying:
+			{
+			TInt error = KErrNone;
+			TRAP(error,DoFinalCopyL()); // assumes can't fail
+			iState = EStateOpen; // even if fail, we go to "open"
+			iObserver.MiuoConvertComplete(error);
+			}
+			break;
+		case EStateCancelled:
+			ASSERT(EFalse); // should not get here!
+			break;
+		default:
+			ASSERT(EFalse);
+		}
+	}
+
+void CMdaImageDataWriteUtilityPriv::DoCancel()
+	{
+	switch (iState)
+		{
+		case EStateClosed:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateCreating:
+			// ignore - makes no difference to do something here
+			break;
+		case EStateOpen:
+			ASSERT(EFalse); // should not happen
+			break;
+		case EStateConverting:
+			{
+			iEncoder->Cancel(); 
+			iState = EStateCancelled;
+			}
+			break;
+		case EStateCopying:
+			// ignore - makes no difference to do something here
+			break;
+		default:
+			ASSERT(EFalse);
+		}
+	}
+
+CImageEncoder* CMdaImageDataWriteUtilityPriv::Encoder() const
+	{
+	return iEncoder;
+	}
+
+void CMdaImageDataWriteUtilityPriv::DoClose()
+	{
+	ASSERT(Parent());
+	ASSERT(!Parent()->IsActive()); // Cancel should be called by this point
+	if (iEncoder)
+		iEncoder->Cancel();
+	delete iEncoder; iEncoder = NULL;
+	delete iFrameImageData; iFrameImageData=NULL;
+	iState=EStateClosed;
+	}
+
+void CMdaImageDataWriteUtilityPriv::DoFinalCopyL()
+	{
+	}
+
+void CMdaImageDataWriteUtilityPriv::CompleteEncoderCreationL()
+	{
+	ASSERT(iEncoder); // should have been created by now
+	delete iFrameImageData; iFrameImageData=NULL;
+
+	if(iFrameData || iImageData)
+		{
+		iFrameImageData = CFrameImageData::NewL();
+		}
+
+	if (iFrameData)
+		{
+		User::LeaveIfError(iFrameImageData->AppendFrameData(iFrameData));
+		iFrameData = NULL;
+		}
+
+	if (iImageData)
+		{
+		User::LeaveIfError(iFrameImageData->AppendImageData(iImageData));
+		iImageData = NULL;
+		}
+
+	}
+
+//
+// CMdaImageFileToBitmapUtilityPriv
+//
+
+CMdaImageFileToBitmapUtilityPriv* CMdaImageFileToBitmapUtilityPriv::NewL(MMdaImageUtilObserver& aObserver,
+																		 CMdaImageFileToBitmapUtility* aParent)
+	{
+	CMdaImageFileToBitmapUtilityPriv* self = new(ELeave) CMdaImageFileToBitmapUtilityPriv(aObserver, aParent);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	self->OpenWaitTimerL();
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+CMdaImageFileToBitmapUtilityPriv::CMdaImageFileToBitmapUtilityPriv(MMdaImageUtilObserver& aObserver,
+																   CMdaImageFileToBitmapUtility* aParent):
+	CMdaImageDataReadUtilityPriv(aObserver, aParent)
+	{
+	}
+
+void CMdaImageFileToBitmapUtilityPriv::ConstructL()
+	{
+	Initialize(); 
+	OpenFsSessionL();
+	}
+
+CMdaImageFileToBitmapUtilityPriv::~CMdaImageFileToBitmapUtilityPriv()
+	{
+	delete iFileName;
+	}
+
+void CMdaImageFileToBitmapUtilityPriv::OpenL(const TDesC& aFileName,TMdaClipFormat* aFormat,TMdaPackage* aCodec,TMdaPackage* aExtra)
+	{
+	Close(EFalse);
+	ASSERT(iState == EStateClosed);
+	delete iFileName; iFileName = NULL;
+
+	iState = EStateOpening;
+
+	TRAPD(error, iFileName = aFileName.AllocL());
+	if (error==KErrNone) 
+		TRAP(error,SetUidsFromOrigFormatsL(aFormat, aCodec, aExtra));
+
+	// note handle error on AO to approximate original functionality that did not leave
+	SelfComplete(error);
+	}
+
+void CMdaImageFileToBitmapUtilityPriv::DoOpenL()
+	{
+	ASSERT(iDecoder==NULL); // should have been deleted before this
+	ASSERT(iFileName); // should already exist
+	iDecoder=CImageDecoder::FileNewL(iFs, *iFileName, CImageDecoder::EOptionNone, iImageType, iImageSubType);
+	}
+
+
+//
+// CMdaImageDescToBitmapUtilityPriv
+//
+
+CMdaImageDescToBitmapUtilityPriv* CMdaImageDescToBitmapUtilityPriv::NewL(MMdaImageUtilObserver& aObserver,
+																		 CMdaImageDescToBitmapUtility* aParent)
+	{
+	CMdaImageDescToBitmapUtilityPriv* self = new(ELeave) CMdaImageDescToBitmapUtilityPriv(aObserver, aParent);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	self->OpenWaitTimerL();
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+	CleanupStack::Pop(); // self
+	return self; 
+	}
+
+CMdaImageDescToBitmapUtilityPriv::CMdaImageDescToBitmapUtilityPriv(MMdaImageUtilObserver& aObserver,
+																   CMdaImageDescToBitmapUtility* aParent):
+	CMdaImageDataReadUtilityPriv(aObserver, aParent)
+	{
+	}
+
+void CMdaImageDescToBitmapUtilityPriv::OpenL(const TDesC8& aDescriptor,TMdaClipFormat* aFormat,TMdaPackage* aCodec,TMdaPackage* aExtra)
+	{
+	Close(EFalse);
+	ASSERT(iState == EStateClosed);
+
+	iState = EStateOpening;
+
+	iDescriptor = &aDescriptor;
+
+	TRAPD(error, SetUidsFromOrigFormatsL(aFormat, aCodec, aExtra));
+
+	SelfComplete(error);
+	}
+
+void CMdaImageDescToBitmapUtilityPriv::DoOpenL()
+	{
+	ASSERT(iDecoder==NULL);
+	iDecoder=CImageDecoder::DataNewL(iFs, *iDescriptor, CImageDecoder::EOptionNone, iImageType, iImageSubType);
+	}
+
+void CMdaImageDescToBitmapUtilityPriv::ConstructL()
+	{
+	Initialize(); 
+	OpenFsSessionL();
+	}
+
+//
+// CMdaImageBitmapToFileUtilityPriv
+//
+
+CMdaImageBitmapToFileUtilityPriv* CMdaImageBitmapToFileUtilityPriv::NewL(MMdaImageUtilObserver& aObserver,CMdaImageBitmapToFileUtility* aParent)
+	{
+	CMdaImageBitmapToFileUtilityPriv* self = new(ELeave) CMdaImageBitmapToFileUtilityPriv(aObserver, aParent);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	self->OpenWaitTimerL();
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+CMdaImageBitmapToFileUtilityPriv::CMdaImageBitmapToFileUtilityPriv(MMdaImageUtilObserver& aObserver,
+																   CMdaImageBitmapToFileUtility* aParent):
+	CMdaImageDataWriteUtilityPriv(aObserver, aParent)
+	{
+	}
+
+void CMdaImageBitmapToFileUtilityPriv::ConstructL()
+	{
+	Initialize(); 
+	OpenFsSessionL();
+	}
+
+CMdaImageBitmapToFileUtilityPriv::~CMdaImageBitmapToFileUtilityPriv()
+	{
+	delete iFileName;
+	}
+
+void CMdaImageBitmapToFileUtilityPriv::CreateL(const TDesC& aFileName,TMdaClipFormat* aFormat,TMdaPackage* aCodec,TMdaPackage* aExtra)
+	{
+	Close(EFalse);
+	ASSERT(iState == EStateClosed);
+	delete iFileName; iFileName = NULL;
+
+	iState = EStateCreating;
+
+	TRAPD(error, iFileName = aFileName.AllocL());
+
+	if (error==KErrNone)
+		TRAP(error,SetUidsFromOrigFormatsL(aFormat, aCodec, aExtra));
+
+	SelfComplete (error);
+	}
+
+void CMdaImageBitmapToFileUtilityPriv::DoCreateL(TBool aFullCreate)
+	{
+	ASSERT(iEncoder==NULL); // assumed to have been deleted first
+	ASSERT(iFileName); // should be set by this point
+	iEncoder = CImageEncoder::FileNewL(iFs, *iFileName, CImageEncoder::EOptionNone, iImageType, iImageSubType);
+	if (aFullCreate)
+		CompleteEncoderCreationL();
+	}
+
+//
+// CMdaImageBitmapToDescUtilityPriv
+//
+
+CMdaImageBitmapToDescUtilityPriv* CMdaImageBitmapToDescUtilityPriv::NewL(MMdaImageUtilObserver& aObserver,
+																		 CMdaImageBitmapToDescUtility* aParent)
+	{
+	CMdaImageBitmapToDescUtilityPriv* self = new(ELeave) CMdaImageBitmapToDescUtilityPriv(aObserver, aParent);
+	self->Initialize();
+#if defined(__ECOM_POWERDOWN_WORKAROUND)
+	CleanupStack::PushL(self);
+	self->OpenWaitTimerL();
+	CleanupStack::Pop();
+#endif  // defined(__ECOM_POWERDOWN_WORKAROUND)
+	return self;
+	}
+
+CMdaImageBitmapToDescUtilityPriv::CMdaImageBitmapToDescUtilityPriv(MMdaImageUtilObserver& aObserver,
+																   CMdaImageBitmapToDescUtility* aParent):
+	CMdaImageDataWriteUtilityPriv(aObserver, aParent)
+	{
+	}
+
+CMdaImageBitmapToDescUtilityPriv::~CMdaImageBitmapToDescUtilityPriv()
+	{
+	Close(ETrue);
+	delete iSecondBuffer;
+	}
+
+void CMdaImageBitmapToDescUtilityPriv::CreateL(TDes8& aDescriptor,TMdaClipFormat* aFormat,TMdaPackage* aCodec,TMdaPackage* aExtra)
+	{
+	Close(EFalse);
+	ASSERT(iState == EStateClosed);
+
+	iState = EStateCreating;
+
+	iDescriptor = &aDescriptor;
+
+	TRAPD(error, SetUidsFromOrigFormatsL(aFormat, aCodec, aExtra));
+
+	SelfComplete (error);
+	}
+
+void CMdaImageBitmapToDescUtilityPriv::DoCreateL(TBool aFullCreate)
+	{
+	ASSERT(iEncoder==NULL);
+	delete iSecondBuffer; iSecondBuffer = NULL; // ensure no previous buffer left around
+	iEncoder = CImageEncoder::DataNewL(iSecondBuffer, CImageEncoder::EOptionNone, iImageType, iImageSubType);
+	if (aFullCreate)
+		CompleteEncoderCreationL();
+	}
+
+void CMdaImageBitmapToDescUtilityPriv::DoFinalCopyL()
+	{
+	ASSERT(iSecondBuffer!=NULL); // should have been set during conversion
+	TInt error = KErrNone;
+	if (iDescriptor->MaxLength() < iSecondBuffer->Length())
+		error = KErrArgument; // will leave with this
+	else
+		*iDescriptor = *iSecondBuffer; // safe to copy buffer
+	delete iSecondBuffer; iSecondBuffer = NULL; // save space - throw away the buffer we no longer need
+	User::LeaveIfError(error);
+	}
+
+// CMdaImageBitmapToBitmapUtilityPriv
+
+CMdaImageBitmapToBitmapUtilityPriv::CMdaImageBitmapToBitmapUtilityPriv(
+									MMdaImageUtilObserver& aObserver, 
+									CMdaImageBitmapToBitmapUtility* aParent)
+	: CMdaImageUtilityPriv(aObserver, aParent)
+	{
+	}
+
+CMdaImageBitmapToBitmapUtilityPriv* CMdaImageBitmapToBitmapUtilityPriv::NewL(MMdaImageUtilObserver& aObserver, CMdaImageBitmapToBitmapUtility* aParent)
+	{
+	CMdaImageBitmapToBitmapUtilityPriv* self = new(ELeave) CMdaImageBitmapToBitmapUtilityPriv(aObserver, aParent);
+	self->Initialize();
+	return self;
+	}
+
+CMdaImageBitmapToBitmapUtilityPriv::~CMdaImageBitmapToBitmapUtilityPriv()
+	{
+	Close();
+	delete iBitmapCopier;
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::OpenL(CFbsBitmap& aBitmap)
+	{
+	if (iState != EClosed)
+		Close();
+
+	if (!iBitmapCopier)
+		iBitmapCopier = CBitmapConverter::NewL();
+
+	iSrcBitmap=&aBitmap;
+
+	iState = EOpening;
+	SelfComplete(KErrNone);	//& perform callback
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::ConvertL(CFbsBitmap& aBitmap, TInt aFrameNumber)
+	{
+	if (iState != EReady)
+		User::Leave(KErrNotReady);
+
+	if (aFrameNumber != 0)
+		User::Leave(KErrArgument);
+
+	iBitmapCopier->Convert(&Parent()->iStatus, aBitmap, *iSrcBitmap);
+	iState = ECopying;
+	Parent()->SetActive();
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::ConvertL(CFbsBitmap& /* aBitmap */, CFbsBitmap& /* aMaskBitmap */, TInt /* aFrameNumber = 0 */)
+	{
+	User::Leave(KErrNotSupported);
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::CancelConvertL()
+	{
+	Parent()->Cancel();
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::RunL()
+	{
+	//Called only on completion of OpenL() or ConvertL()
+	TInt errorStatus = Parent()->iStatus.Int();	//should always be KErrNone
+	
+	switch (iState)
+		{
+	case EOpening:
+		iState = EReady;
+		iObserver.MiuoOpenComplete(errorStatus);
+		return;
+	case ECopying:
+		iState = EReady;
+		iObserver.MiuoConvertComplete(errorStatus);
+		return;
+	default:
+		User::Invariant();
+		}
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::DoCancel()
+	{
+	switch (iState)
+		{
+	case EReady:
+	case EClosed:
+		return;
+	case EOpening:
+		//Message will have already been completed with KErrNone
+		// INC037143. This unnecessary Close() call causes infinite 
+		// recursion if the utility is cancelled in the EOpening state.
+		//Close();
+		return;
+	case ECopying:
+		//Copier will complete our message with KErrCancel
+		iBitmapCopier->Cancel();
+		return;
+	default:
+		User::Invariant();
+		}
+	}
+
+void CMdaImageBitmapToBitmapUtilityPriv::DoClose()
+	{
+	if(iState != EClosed)
+		{
+		iState = EClosed;
+		CMdaImageUtilityPriv::DoClose();
+		}
+	}