mpxmusicplayer/commonui/src/mpximageutil.cpp
changeset 0 ff3acec5bc43
child 2 b70d77332e66
--- /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 <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;
+            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