--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxmusicplayer/commonui/src/mpximageutil.cpp Wed Sep 01 12:32:02 2010 +0100
@@ -0,0 +1,398 @@
+/*
+* 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 <e32std.h>
+#include <e32base.h>
+#include <bitmaptransforms.h>
+#include <mda/common/video.h>
+#include <eikenv.h>
+#include <icl/imagedata.h>
+#include <imageconversion.h>
+#include <IclExtJpegApi.h>
+
+#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;
+ if ( iBitmap )
+ {
+ delete iBitmap;
+ iBitmap = NULL;
+ }
+ 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