diff -r 000000000000 -r ff3acec5bc43 mpxmusicplayer/commonui/src/mpximageutil.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpxmusicplayer/commonui/src/mpximageutil.cpp Thu Dec 17 08:45:05 2009 +0200 @@ -0,0 +1,393 @@ +/* +* Copyright (c) 2006 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: Implementation of CMPXImageUtil. +* +*/ + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpximageutil.h" + +//This value is used to stretch so the image fills the container. +const TReal MaxStretchRatio = 1.1f; + +LOCAL_C TInt Stretch (TInt aValue, TInt aLimit) + { + TInt ret( aValue * MaxStretchRatio ); + ret = (ret>aLimit) ? aLimit : ret; + return ret; + } + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMPXImageUtil* CMPXImageUtil::NewL( + MMPXAlbumArtUtilObserver& aObserver) + { + CMPXImageUtil* self = new ( ELeave ) CMPXImageUtil(aObserver); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); // self + return self; + } + +// ----------------------------------------------------------------------------- +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMPXImageUtil::CMPXImageUtil(MMPXAlbumArtUtilObserver& aObserver) +: CActive(EPriorityStandard), iObserver(aObserver) + { + iBitmap = NULL; + iState = EIdle; + } + +// ----------------------------------------------------------------------------- +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::ConstructL() + { + iScaler = CBitmapScaler::NewL(); + User::LeaveIfError(iFs.Connect()); + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CMPXImageUtil::~CMPXImageUtil() + { + Cancel(); + delete iImageDecoder; // CImageDecoder must be deleted before the + delete iScaler; + iFs.Close(); + delete iImageData; + } + +// ----------------------------------------------------------------------------- +// Starts to decode an image from a file. +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::StartToDecodeL(const TDesC& aFileName, + const TSize& aSize, + TDisplayMode aDisplayMode /*=EColor64K*/) + { + if(iState) + { + User::Leave(KErrNotReady); + } + + delete iImageDecoder; + iImageDecoder = NULL; + delete iBitmap; + iBitmap = NULL; + delete iImageData; + iImageData = NULL; + + // create the decoder + + TRAPD( err, iImageDecoder = CExtJpegDecoder::FileNewL( + CExtJpegDecoder::EHwImplementation, + iFs, + aFileName, + CImageDecoder::EOptionNone ) ); + if (KErrNone != err) + { + TRAP(err,iImageDecoder = CExtJpegDecoder::FileNewL( + CExtJpegDecoder::ESwImplementation, + iFs, + aFileName, + CImageDecoder::EOptionNone ) ); + if (KErrNone != err) + { + iImageDecoder = CImageDecoder::FileNewL( + iFs, + aFileName, + CImageDecoder::EOptionNone); + } + } + + // Get image size + TSize bitmapSize = CalculateDecodeSize(aSize); + // create the destination bitmap + iBitmap = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBitmap->Create(bitmapSize, aDisplayMode)); + + // start conversion to bitmap + iState = EDecoding; + iImageDecoder->Convert(&iStatus, *iBitmap); + + iObserver.ExtractAlbumArtStarted(); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CMPXImageUtil::DoCancel +// Implementation of CActive +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::DoCancel() + { + switch ( iState ) + { + case EDecoding: + { + iImageDecoder->Cancel(); + // need to delete bitmap as we have are still the owner until the + // operation completes + if ( iBitmap ) + { + delete iBitmap; + iBitmap = NULL; + } + break; + } + case EScaling: + { + iScaler->Cancel(); + if ( iBitmap ) + { + delete iBitmap; + iBitmap = NULL; + } + break; + } + default: // No Asynchronous events are taking place, do nothing. + { + break; + } + } + + delete iImageData; + iImageData = NULL; + delete iImageDecoder; + iImageDecoder = NULL; + } + +// ----------------------------------------------------------------------------- +// Implementation of CActive +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::RunL() + { + TInt deleteDecoder( ETrue ); + switch( iState ) + { + case EDecoding: + { + if( iStatus == KErrNone ) + { + if ( !iScaleRquired ) + { + iState = EIdle; + iObserver.ExtractAlbumArtCompleted(iBitmap,KErrNone); + iBitmap = NULL; + } + else + { + deleteDecoder = EFalse; + ScaleL(); + } + break; + } + else + { + // some error + if ( iBitmap ) + { + delete iBitmap; + iBitmap = NULL; + } + iState = EIdle; + iObserver.ExtractAlbumArtCompleted(iBitmap, iStatus.Int()); + break; + } + } + case EScaling: + { + iState = EIdle; + iObserver.ExtractAlbumArtCompleted(iBitmap,iStatus.Int()); + iBitmap = NULL; + } + break; + + default: // some error + { + iState = EIdle; + iObserver.ExtractAlbumArtCompleted(iBitmap,iStatus.Int()); + break; + } + } + + // It's safe to destroy iImageData here + delete iImageData; + iImageData = NULL; + + if ( deleteDecoder ) + { + delete iImageDecoder; + iImageDecoder = NULL; + } + } + +// ----------------------------------------------------------------------------- +// Scales iBitmap by iSize +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::ScaleL() + { + iScaler->Scale(&iStatus, *iBitmap, iSize, EFalse); + iState = EScaling; + SetActive(); + } + +// ----------------------------------------------------------------------------- +// Starts to decode an image from a buffer. +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::StartToDecodeL( const TSize& aSize, + HBufC8* aAlbumArt, TDisplayMode aDisplayMode/*=EColor64K*/ ) + { + if(iState) + { + User::Leave( KErrNotReady ); + } + + delete iImageDecoder; + iImageDecoder = NULL; + delete iBitmap; + iBitmap = NULL; + delete iImageData; + iImageData = NULL; + // storing the pointer to aAlbumArt, ownership was transferred to us. + iImageData = aAlbumArt; + // create the decoder + + + TRAPD( err, iImageDecoder = CExtJpegDecoder::DataNewL( + CExtJpegDecoder::EHwImplementation, + iFs, + *iImageData, + CImageDecoder::EOptionNone ) ); + if ( KErrNone != err ) + { + TRAP(err,iImageDecoder = CExtJpegDecoder::DataNewL( + CExtJpegDecoder::ESwImplementation, + iFs, + *iImageData, + CImageDecoder::EOptionNone ) ); + if ( KErrNone != err ) + { + iImageDecoder = CImageDecoder::DataNewL( + iFs, + *iImageData, + CImageDecoder::EOptionNone ); + } + } + + + + + TSize bitmapSize = CalculateDecodeSize( aSize ); + + // create the destination bitmap + iBitmap = new ( ELeave ) CFbsBitmap(); + User::LeaveIfError( iBitmap->Create( bitmapSize, aDisplayMode ) ); + // start conversion to bitmap + iState = EDecoding; + iImageDecoder->Convert( &iStatus, *iBitmap ); + + iObserver.ExtractAlbumArtStarted(); + SetActive(); + } +// ----------------------------------------------------------------------------- +// Calculates the decode size and prepares members for scaling. +// ----------------------------------------------------------------------------- +// +TSize CMPXImageUtil::CalculateDecodeSize(const TSize& aSize) + { + const TFrameInfo& frameInfo = iImageDecoder->FrameInfo(); + TSize bitmapSize = frameInfo.iOverallSizeInPixels; + TReal sourceAspectRatio( TReal( bitmapSize.iWidth) / bitmapSize.iHeight ); + TReal destinationAspectRatio( TReal( aSize.iWidth ) / aSize.iHeight ); + TReal xScale = TReal( bitmapSize.iWidth ) / aSize.iWidth; + TReal yScale = TReal( bitmapSize.iHeight ) / aSize.iHeight; + TReal scale(0.0f); + + if ( sourceAspectRatio > destinationAspectRatio ) + { + scale = xScale; + iSize.iWidth = aSize.iWidth; + iSize.iHeight = Stretch( TReal( bitmapSize.iHeight ) / scale , + aSize.iHeight ); + } + else + { + scale = yScale; + iSize.iWidth = Stretch( TReal( bitmapSize.iWidth ) / scale , + aSize.iWidth); + iSize.iHeight = aSize.iHeight; + } + + if ((frameInfo.iFlags & TFrameInfo::EFullyScaleable)) + { + iScaleRquired = EFalse; + bitmapSize = iSize; + } + else + //Decoder only supports 2, 4 and 8 scallyng, the image will need + //to be reescaled after decoding. + //Decoding to a scale that is just a bit bigger thant the target, + //this will save memory and resources and we will get a sharp image + //after scaling. + { + TInt intscale = ( scale >= 8 ) ? 8 : + ( scale >= 4 ) ? 4 : + ( scale >= 2 ) ? 2 : 1; + TUint xCorrection = ( bitmapSize.iWidth % intscale ) ? 1 : 0; + TUint yCorrection = ( bitmapSize.iHeight % intscale ) ? 1 : 0; + bitmapSize.iWidth /= intscale; + bitmapSize.iHeight /= intscale; + bitmapSize += TSize( xCorrection, yCorrection ); + iScaleRquired = ETrue; + } + return bitmapSize; + } + +// ----------------------------------------------------------------------------- +// CMPXImageUtil::CancelRequest +// Cancel Asynch requests +// ----------------------------------------------------------------------------- +// +void CMPXImageUtil::CancelRequest() + { + Cancel(); + } + +// End of File