--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiservicetab/vimpstutils/src/cvimpstimageprocessor.cpp Wed Sep 01 12:33:36 2010 +0100
@@ -0,0 +1,451 @@
+/*
+* Copyright (c) 2008 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: Image processor and scaler
+ *
+*/
+
+
+#include "cvimpstimageprocessor.h"
+#include "tvimpstconsts.h"
+#include <imageconversion.h>
+#include <bitmaptransforms.h>
+#include <s32file.h>
+#include <e32cmn.h>
+#include "uiservicetabtracer.h"
+// CONSTANTS
+const TInt KChatCustomBitmapWidth = 65;
+const TInt KChatCustomBitmapHeight = 65;
+const TInt KMaxImageSize = 1800; //2k
+const TInt KMimeLength = 16;
+const TInt KScaleSize = 10;
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::CCAImageLoader
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CVimpstImageProcessor::CVimpstImageProcessor( MCAImageProcessObserver* aObserver )
+: CActive( CActive::EPriorityLow ),iObserver(aObserver),iScaleSize(KScaleSize)
+ {
+ CActiveScheduler::Add( this );
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::CVimpstImageProcessor
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CVimpstImageProcessor::~CVimpstImageProcessor()
+ {
+ iFs.Close();
+
+ delete iImageDecoder;
+ delete iScaler;
+ delete iImageEncoder;
+ if(!isBitmapReturned)
+ {
+ delete iBitmap;
+ }
+ delete iMimeType;
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::NewL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CVimpstImageProcessor* CVimpstImageProcessor::NewL( MCAImageProcessObserver* aObserver)
+ {
+ TRACER_AUTO;
+ CVimpstImageProcessor* self =
+ new ( ELeave ) CVimpstImageProcessor(aObserver);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ConstructL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ConstructL()
+ {
+ User::LeaveIfError( iFs.Connect() );
+ }
+
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::RunL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::RunL()
+ {
+ TRACER_AUTO;
+ TInt status = iStatus.Int();
+
+ if(!status)
+ {
+ switch(iProcessingState)
+ {
+ case EConvertImageDatatoBitmap:
+ {
+ ConvertImageToBitmapL();
+ break;
+ }
+ case EScaleBitmap:
+ {
+ ScaleBitmapL();
+ break;
+ }
+ case EConentFromScaledBitmap:
+ {
+ ContentFromScaledBitmapL();
+ break;
+ }
+ case EProcessingComplete:
+ {
+ if( iContent->Length() > KMaxImageSize)
+ {
+ delete iScaler;
+ iScaler = NULL;
+ delete iImageEncoder;
+ iImageEncoder = NULL;
+ delete iContent;
+ iTargetSize.SetSize( KChatCustomBitmapWidth - iScaleSize, KChatCustomBitmapHeight - iScaleSize );
+ iScaleSize += KScaleSize;
+ ScaleBitmapL();
+ }
+ else
+ {
+ TRACE("RunL completed ");
+ CompleteRequestL();
+ }
+ break;
+ }
+ default:
+ {
+
+ }
+ }
+
+ }
+ else
+ {
+ TRACE("RunL completed ");
+ CompleteRequestL();
+ }
+
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ConvertImageToBitmapL()
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ConvertImageToBitmapL()
+ {
+ TRACER_AUTO;
+ TSize origSize( iImageDecoder->FrameInfo().iOverallSizeInPixels );
+ ScaleSize( origSize, iTargetSize );
+ TBool fullyScaleable( iImageDecoder->FrameInfo().iFlags & TFrameInfo::EFullyScaleable );
+ TSize decodeSize( DecodeSize( origSize, iTargetSize, fullyScaleable ) );
+
+ iBitmap = new (ELeave) CFbsBitmap();
+ User::LeaveIfError( iBitmap->Create( decodeSize,
+ iImageDecoder->FrameInfo().iFrameDisplayMode ) );
+ iImageDecoder->Convert( &iStatus, *iBitmap );
+ iProcessingState = EScaleBitmap; // set state to next step
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ScaleBitmapL()
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ScaleBitmapL()
+ {
+ TRACER_AUTO;
+ TSize currentSize( iBitmap ? iBitmap->SizeInPixels() : iTargetSize );
+
+ if( currentSize != iTargetSize )
+ {
+ // bitmap exists and the size is wrong,
+ // we have to scale the bitmap
+ iScaler = CBitmapScaler::NewL();
+ iScaler->Scale( &iStatus, *iBitmap, iTargetSize );
+ iProcessingState = EConentFromScaledBitmap; // set state to next step
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+ }
+ else
+ { // get content from scaled bitmap
+ ContentFromScaledBitmapL();
+ }
+
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ContentFromScaledBitmapL()
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ContentFromScaledBitmapL()
+ {
+ iContent = NULL;
+ iImageEncoder = CImageEncoder::DataNewL( iContent,*iMimeType);
+ iImageEncoder->Convert( &iStatus, *iBitmap );
+ iProcessingState = EProcessingComplete ; // set state to next step
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::DoCancel
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::DoCancel()
+ {
+ ClearState();
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::RunError
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CVimpstImageProcessor::RunError( TInt aError )
+ {
+ if( IsActive() )
+ {
+ iStatus = aError;
+ Cancel();
+ }
+
+ if( aError == KErrNoMemory )
+ {
+ CActiveScheduler::Current()->Error( KErrNoMemory );
+ }
+
+ // Clean up and reset all pending messages
+ ClearState();
+ TRAP_IGNORE( ResetProcessingL( aError ) );
+
+ return KErrNone;
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::StartProcessingFromDataL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CVimpstImageProcessor::ProcessFromDataL( const TDesC8& aImageData , const TDesC8& aMimeType)
+ {
+ TRACER_AUTO;
+ TInt err = KErrNone;
+ if ( aMimeType.Length())
+ {
+ // if the mimetype is passed then allocate the memory
+ iMimeType = aMimeType.AllocL();
+ }
+ else
+ {
+ // if no mimetype find the mimetype
+ iMimeType = HBufC8::NewL( KMimeLength);
+ TPtr8 mimePtr = iMimeType->Des();
+ TRAP(err,CImageDecoder::GetMimeTypeDataL( aImageData , mimePtr ));
+ if(KErrNone != err)
+ {
+ return err;
+ }
+ }
+ iImageDecoder = NULL;
+ // need to check for the mimetype length, as sometimes CImageDecoder::GetMimeTypeDataL
+ // is alos not able to give the mimetype
+ iImageDecoder = CImageDecoder::DataNewL(iFs, aImageData , *iMimeType);
+ iProcessingState = EConvertImageDatatoBitmap;
+ RunL();
+ return err;
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ProcessFromFileL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ProcessFromFileL( const TDesC& aFileName , const TDesC8& aMimeType)
+ {
+ TRACER_AUTO;
+ iMimeType = aMimeType.AllocL();
+ iImageDecoder = NULL;
+ iImageDecoder = CImageDecoder::FileNewL(iFs, aFileName, *iMimeType );
+ iProcessingState = EConvertImageDatatoBitmap;
+ RunL();
+
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::CancelProcessing
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::CancelProcessing()
+ {
+ if( IsActive() )
+ {
+ Cancel();
+ }
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::RegisterObserver
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::RegisterObserver( MCAImageProcessObserver* aObserver )
+ {
+ iObserver = aObserver;
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::GetContentData
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+
+HBufC8* CVimpstImageProcessor::GetContentData()
+ {
+ return iContent;
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::Bitmap
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+
+CFbsBitmap& CVimpstImageProcessor::Bitmap()
+ {
+ isBitmapReturned = ETrue;
+ return *iBitmap;
+ }
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::DecodeSize
+// Scale to nearest (larger or equal) size with ratio 1:1, 1:2, 1:4 or 1:8
+//-----------------------------------------------------------------------------
+TSize CVimpstImageProcessor::DecodeSize( const TSize& aSize, const TSize& aTargetSize,
+ TBool aAnyRatio )
+ {
+ TRACER_AUTO;
+ if( aAnyRatio || aSize == aTargetSize )
+ {
+ // decoder can scale to any ratio or the size is already correct
+ return aTargetSize;
+ }
+
+ // 1:1 is always valid ratio for decode scaling
+ TInt lastValidRatio( 1 );
+ for( TInt ratio( KDecodeScaleRatioMin ); ratio <= KDecodeScaleRatioMax; ratio <<= 1 )
+ {
+ if( aSize.iWidth % ratio + aSize.iHeight % ratio == 0 )
+ {
+ // this ratio is valid
+ if( aSize.iWidth / ratio < aTargetSize.iWidth ||
+ aSize.iHeight / ratio < aTargetSize.iHeight )
+ {
+ // the decoded size was smaller in some dimension,
+ // the last valid ratio should be used
+ break;
+ }
+
+ // this scale ratio results to greater or equal size
+ lastValidRatio = ratio;
+ }
+ }
+
+ // return the size scaled with correct ratio
+ return TSize( aSize.iWidth / lastValidRatio,
+ aSize.iHeight / lastValidRatio );
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ScaleSize
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TBool CVimpstImageProcessor::ScaleSize( const TSize& aSize, TSize& aNewSize )
+ {
+ if( Max( aSize.iHeight, aSize.iWidth ) > KChatCustomBitmapWidth )
+ {
+ aNewSize.SetSize( KChatCustomBitmapWidth, KChatCustomBitmapHeight );
+ return ETrue;
+ }
+
+ // old size is correct
+ aNewSize = aSize;
+ return EFalse;
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::CompleteRequestL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::CompleteRequestL()
+ {
+ iObserver->HandleProcessingCompleteL( iStatus.Int() );
+ }
+
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ResetProcessingL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ResetProcessingL( TInt aReason )
+ {
+ // cancel operation
+ if( IsActive() )
+ {
+ iStatus = aReason;
+ Cancel();
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CVimpstImageProcessor::ClearState
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CVimpstImageProcessor::ClearState()
+ {
+ if( iScaler )
+ {
+ iScaler->Cancel();
+ delete iScaler;
+ iScaler = NULL;
+ }
+ if( iImageDecoder )
+ {
+ iImageDecoder->Cancel();
+ delete iImageDecoder;
+ iImageDecoder = NULL;
+ }
+ if( iImageEncoder )
+ {
+ iImageEncoder->Cancel();
+ delete iImageEncoder;
+ iImageEncoder = NULL;
+ }
+ if( iBitmap )
+ {
+ delete iBitmap;
+ iBitmap = NULL;
+ }
+ if (iMimeType)
+ {
+ delete iMimeType;
+ iMimeType = NULL;
+ }
+
+ }
+
+
+// End of file