wvuing/wvuieng/EngSrc/CCAImageLoader.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvuieng/EngSrc/CCAImageLoader.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,707 @@
+/*
+* Copyright (c) 2005 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 loader and scaler
+*
+*/
+
+
+#include "CCAImageLoader.h"
+#include "MCAChatInterface.h"
+#include "CCAContentMessage.h"
+
+#include "ChatDebugPrint.h"
+#include "chatdebugassert.h"
+#include "impsbuilddefinitions.h"
+
+#include "mcaimpsfactory.h"
+#include "mcaimpsimclient.h"
+#include "wvengutils.h"
+#include "imnginternalcrkeys.h"
+#include "imprivatecrkeys.h"
+#include "imvariant.hrh"
+
+#include <ImageConversion.h>
+#include <BitmapTransforms.h>
+#include <s32file.h>
+
+// CONSTANTS
+const TInt KChatCustomBitmapWidth = 320;
+const TInt KChatCustomBitmapHeight = 240;
+
+// From ICL documentation:
+// "all decoder plugins also support thumbnail decodes with ratios of 1:2, 1:4 and 1:8."
+const TInt KDecodeScaleRatioMin = 2;
+const TInt KDecodeScaleRatioMax = 8;
+
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::CCAImageLoader
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CCAImageLoader::CCAImageLoader(
+    MCAChatInterface& aChatInterface, MCAImpsFactory& aImpsFactory )
+        : CActive( CActive::EPriorityLow ),
+        iChatInterface( aChatInterface ),
+        iImpsFactory( aImpsFactory )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::CCAImageLoader" );
+    CActiveScheduler::Add( this );
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::CCAImageLoader" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::CCAImageLoader
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CCAImageLoader::~CCAImageLoader()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::~CCAImageLoader" );
+    iFs.Close();
+
+    delete iDecoder;
+    delete iScaler;
+    delete iEncoder;
+    delete iBitmap;
+    delete iContent;
+
+    iMessages.Close();
+
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::~CCAImageLoader" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::NewL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CCAImageLoader* CCAImageLoader::NewL( MCAChatInterface& aChatInterface,
+                                      MCAImpsFactory& aImpsFactory )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::NewL" );
+    CCAImageLoader* self =
+        new ( ELeave ) CCAImageLoader( aChatInterface, aImpsFactory );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::NewL" );
+    return self;
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::ConstructL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::ConstructL()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::ConstructL" );
+    User::LeaveIfError( iFs.Connect() );
+
+    iSendNotScalable = WVEngUtils::CRKeyL( KCRUidIMVariation, KIMVariationKey )
+                       & EIMFeatSendNotScalable;
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::ConstructL" );
+    }
+
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::RunL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::RunL()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::RunL" );
+    TInt status = iStatus.Int();
+    CHAT_DP( D_CHAT_LIT( "Status %d" ), status );
+    switch ( status )
+        {
+        case KErrUnderflow:
+            {
+            if ( iDecoder )
+                {
+                CHAT_DP( D_CHAT_LIT( "Continue converting." ) );
+                iStatus = KRequestPending;
+                iDecoder->ContinueConvert( &iStatus );
+                }
+            else
+                {
+                CompleteRequestL();
+                }
+            break;
+            }
+        case KErrNone:
+            {
+            if ( iDecoder )
+                {
+                delete iDecoder;
+                iDecoder = NULL;
+                switch ( iCurrentMessage->ContentProcessState() )
+                    {
+                    case MCAMessage::EContentNotProcessed:
+                        {
+                        CHAT_DP( D_CHAT_LIT( "-> Start scaling." ) );
+                        // Decode ready -> Start scaling.
+                        iCurrentMessage->SetProcessState(
+                            MCAMessage::EBitmapDecoded );
+                        StartProcessingL( *iCurrentMessage );
+                        break;
+                        }
+                    case MCAMessage::EContentReady:
+                        {
+                        CHAT_DP(
+                            D_CHAT_LIT( "-> Start scaling to thumbnail." ) );
+                        // Decode ready -> Start making thumbnail.
+                        iCurrentMessage->SetProcessState(
+                            MCAMessage::EContentDecoded );
+                        StartProcessingL( *iCurrentMessage );
+                        break;
+                        }
+                    default:
+                        {
+                        iStatus = KErrNotSupported;
+                        CompleteRequestL();
+                        break;
+                        }
+                    }
+
+                }
+            else if ( iScaler )
+                {
+                // scaling ready -> start encoding
+                delete iScaler;
+                iScaler = NULL;
+                switch ( iCurrentMessage->ContentProcessState() )
+                    {
+                    case MCAMessage::EBitmapDecoded:
+                        {
+                        CHAT_DP( D_CHAT_LIT( "-> Start encoding." ) );
+                        iCurrentMessage->SetProcessState(
+                            MCAMessage::EBitmapScaled );
+                        StartProcessingL( *iCurrentMessage );
+                        break;
+                        }
+                    case MCAMessage::EContentDecoded:
+                        {
+                        CHAT_DP( D_CHAT_LIT( "Thumbnail ready." ) );
+                        CCAContentMessage* message =
+                            static_cast< CCAContentMessage* >( iCurrentMessage );
+                        message->SetThumbnail( iBitmap );
+                        iBitmap = NULL;
+                        iCurrentMessage->SetProcessState(
+                            MCAMessage::EThumbnailReady );
+                        CompleteRequestL();
+                        break;
+                        }
+                    default:
+                        {
+                        iStatus = KErrNotSupported;
+                        CompleteRequestL();
+                        break;
+                        }
+                    }
+                }
+            else if ( iEncoder )
+                {
+                CHAT_DP( D_CHAT_LIT( "Content ready. -> Stop processing." ) );
+                delete iEncoder;
+                iEncoder = NULL;
+                iCurrentMessage->SetProcessState( MCAMessage::EContentReady );
+                iCurrentMessage->SetContentData( iContent );
+                iContent = NULL;
+                delete iBitmap;
+                iBitmap = NULL;
+                CompleteRequestL();
+                }
+            else
+                {
+                iStatus = KErrNotSupported;
+                CompleteRequestL();
+                }
+            break;
+            }
+        case KErrNoMemory:
+            {
+            // RunError will handle this case
+            User::Leave( KErrNoMemory );
+            }
+        default:
+            {
+            CompleteRequestL();
+            break;
+            }
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::RunL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::DoCancel
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::DoCancel()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::DoCancel" );
+
+    ClearState();
+    iCurrentMessage->HandleProcessingComplete( *this, iStatus.Int() );
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::DoCancel" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::RunError
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CCAImageLoader::RunError( TInt aError )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::RunError" );
+    if ( IsActive() )
+        {
+        iStatus = aError;
+        Cancel();
+        }
+
+    if ( aError == KErrNoMemory )
+        {
+        CActiveScheduler::Current()->Error( KErrNoMemory );
+        }
+
+    // Clean up and reset all pending messages
+    ClearState();
+    TRAP_IGNORE( ResetProcessingL( aError ) );
+
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::RunError" );
+    return KErrNone;
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::RequestProcessing
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::RequestProcessingL( MCAMessage& aMessage )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::RequestProcessingL" );
+    // Append to scheduler
+    iMessages.AppendL( &aMessage );
+    LaunchProcessingL();
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::RequestProcessingL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::StartProcessing
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::StartProcessingL( MCAMessage& aMessage )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::StartProcessingL" );
+    // File -> bitmap
+    // bitmap -> scaled bitmap
+    // scaled bitmap -> encoded content
+
+    iCurrentMessage = &aMessage;
+    switch ( aMessage.ContentProcessState() )
+        {
+        case MCAMessage::EContentNotProcessed:  // File -> bitmap
+            {
+            __CHAT_ASSERT_DEBUG( !iDecoder );
+            iDecoder = CImageDecoder::FileNewL( iFs, aMessage.Text() );
+
+            TSize origSize( iDecoder->FrameInfo().iOverallSizeInPixels );
+            ScaleSize( origSize, iTargetSize );
+            TBool fullyScaleable( iDecoder->FrameInfo().iFlags & TFrameInfo::EFullyScaleable );
+
+            TInt frameCount = iDecoder->FrameCount();
+            if ( frameCount > 1 && iSendNotScalable )
+                {
+                // Animated gif, try to send file as it is
+                // Animation would be lost in decoding/scaling process
+
+                delete iDecoder;    // Delete -> unlocks image file
+                iDecoder = NULL;
+
+                // Open file
+                RFile file;
+                User::LeaveIfError( file.Open( iFs, aMessage.Text(), EFileRead ) );
+                CleanupClosePushL( file );
+
+                // Get file size
+                TInt fileSize = 0;
+                User::LeaveIfError( file.Size( fileSize ) );
+
+                // Check file size, if bigger than max transaction content -> leave
+                if ( fileSize >
+                     iImpsFactory.CreateImClientL()->MaxTransactionContentLengthL() )
+                    {
+                    User::Leave( KErrOverflow );
+                    }
+
+                // Get file content
+                HBufC8* content = HBufC8::NewLC( fileSize );
+                TPtr8 ptr( content->Des() );
+                User::LeaveIfError( file.Read( ptr, fileSize ) );
+
+                // Set content to message, ownership is transferred
+                CleanupStack::Pop( content );
+                CleanupStack::PopAndDestroy();  // file.Close()
+                iCurrentMessage->SetProcessState( MCAMessage::EContentReady );
+                iCurrentMessage->SetContentData( content );
+
+                // Complete
+                CompleteRequestL();
+                break;
+                }
+
+            TSize decodeSize( DecodeSize( origSize, iTargetSize, fullyScaleable ) );
+
+            __CHAT_ASSERT_DEBUG( !iBitmap );
+            iBitmap = new ( ELeave ) CFbsBitmap();
+            User::LeaveIfError( iBitmap->Create( decodeSize,
+                                                 iDecoder->FrameInfo().iFrameDisplayMode ) );
+            iDecoder->Convert( &iStatus, *iBitmap );
+            if ( !IsActive() )
+                {
+                SetActive();
+                }
+            break;
+            }
+        case MCAMessage::EBitmapDecoded:        // scale bitmap to size 320x240
+            {
+            TSize currentSize( iBitmap ? iBitmap->SizeInPixels() : iTargetSize );
+
+            if ( currentSize != iTargetSize )
+                {
+                // bitmap exists and the size is wrong,
+                // we have to scale the bitmap
+                __CHAT_ASSERT_DEBUG( !iScaler );
+                iScaler = CBitmapScaler::NewL();
+                iScaler->Scale( &iStatus, *iBitmap, iTargetSize );
+                if ( !IsActive() )
+                    {
+                    SetActive();
+                    }
+                }
+            else
+                {
+                // the size is already correct => skip this step
+                aMessage.SetProcessState( MCAMessage::EBitmapScaled );
+                StartProcessingL( aMessage );
+                }
+            break;
+            }
+        case MCAMessage::EBitmapScaled:         // encode bitmap for sending
+            {
+            __CHAT_ASSERT_DEBUG( !iEncoder );
+            iEncoder = CImageEncoder::DataNewL( iContent, aMessage.MimeType() );
+            iEncoder->Convert( &iStatus, *iBitmap );
+            if ( !IsActive() )
+                {
+                SetActive();
+                }
+            break;
+            }
+        case MCAMessage::EContentReady:         // decode bitmap for creating thumbnail
+            {
+            __CHAT_ASSERT_DEBUG( !iDecoder );
+            iDecoder = CImageDecoder::DataNewL( iFs, aMessage.ContentData() );
+
+            CCAContentMessage* message =
+                static_cast< CCAContentMessage* >( iCurrentMessage );
+            iThumbSize = message->ThumbnailSize();
+
+            TSize origSize( iDecoder->FrameInfo().iOverallSizeInPixels );
+            TBool fullyScaleable( iDecoder->FrameInfo().iFlags & TFrameInfo::EFullyScaleable );
+
+            TSize decodeSize( DecodeSize( origSize, iThumbSize, fullyScaleable ) );
+
+            __CHAT_ASSERT_DEBUG( !iBitmap );
+            iBitmap = new ( ELeave ) CFbsBitmap();
+            User::LeaveIfError( iBitmap->Create( decodeSize,
+                                                 iDecoder->FrameInfo().iFrameDisplayMode ) );
+            iDecoder->Convert( &iStatus, *iBitmap );
+            if ( !IsActive() )
+                {
+                SetActive();
+                }
+            break;
+            }
+        case MCAMessage::EContentDecoded:       // scale bitmap to thumbnail size.
+            {
+            TSize currentSize( iBitmap ? iBitmap->SizeInPixels() : iThumbSize );
+
+            if ( currentSize != iThumbSize )
+                {
+                // bitmap exists and the size is wrong,
+                // we have to scale the bitmap
+                __CHAT_ASSERT_DEBUG( !iScaler );
+                iScaler = CBitmapScaler::NewL();
+                iScaler->Scale( &iStatus, *iBitmap, iThumbSize );
+                if ( !IsActive() )
+                    {
+                    SetActive();
+                    }
+                }
+            else
+                {
+                // bitmap size is already correct,
+                // set the thumbnail and complete request
+                CCAContentMessage* message =
+                    static_cast< CCAContentMessage* >( iCurrentMessage );
+                message->SetThumbnail( iBitmap );
+                iBitmap = NULL;
+                aMessage.SetProcessState( MCAMessage::EThumbnailReady );
+                CompleteRequestL();
+                }
+            break;
+            }
+#ifdef RD_SEND_NOT_SUPPORTED_CONTENT
+        case MCAMessage::EContentNotSupported:
+        case MCAMessage::EContentNotSupportedDrm:
+        case MCAMessage::EContentCorrupted:
+            {
+            RFileReadStream fileStream;
+            User::LeaveIfError( fileStream.Open(	iFs,
+                                                 aMessage.Text(),
+                                                 EFileRead ) );
+            CleanupClosePushL( fileStream );
+            TInt length = fileStream.Source()->SizeL();
+            HBufC8* temp = HBufC8::NewLC( length );
+            TPtr8 ptr( temp->Des() );
+            fileStream.ReadL( ptr, length );
+            CleanupStack::Pop( temp );
+            iCurrentMessage->SetContentData( temp );
+            CleanupStack::PopAndDestroy();  // fileStream
+            CompleteRequestL();
+            break;
+            }
+#endif //RD_SEND_NOT_SUPPORTED_CONTENT
+        default:
+            {
+            // State is not known for processing. Complete it.
+            CompleteRequestL();
+            break;
+            }
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::StartProcessingL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::CancelProcessing
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::CancelProcessing( MCAMessage& aMessage )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::CancelProcessing" );
+    if ( iCurrentMessage == &aMessage )
+        {
+        if ( IsActive() )
+            {
+            Cancel();
+            }
+        iCurrentMessage = NULL;
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::CancelProcessing" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::CancelProcessing
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::RemoveProcessingL( MCAMessage& aMessage )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::RemoveProcessingL" );
+    // Cancel if message is processed at the moment.
+    CancelProcessing( aMessage );
+    // Remove message from scheduler
+    TInt messageIndex( iMessages.Find( &aMessage ) );
+    if ( messageIndex >= 0 )
+        {
+        iMessages.Remove( messageIndex );
+        LaunchProcessingL();
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::RemoveProcessingL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::LaunchProcessing
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::LaunchProcessingL()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::LaunchProcessingL" );
+    TInt count( iMessages.Count() );
+    if ( count > 0 && !IsActive() )
+        {
+        TRAPD( error, StartProcessingL( *iMessages[ 0 ] ) );
+        if ( error == KErrNoMemory )
+            {
+            // if no memory: stop the whole process
+            TRAP_IGNORE( ResetProcessingL( error ) );
+            }
+        else if ( error < 0 )
+            {
+            iMessages[ 0 ]->SetProcessState( MCAMessage::EContentCorrupted );
+            TInt ignore;
+            TRAP( ignore, CompleteRequestL() );
+            User::Leave( error );
+            }
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::LaunchProcessingL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::DecodeSize
+// Scale to nearest (larger or equal) size with ratio 1:1, 1:2, 1:4 or 1:8
+//-----------------------------------------------------------------------------
+TSize CCAImageLoader::DecodeSize( const TSize& aSize, const TSize& aTargetSize,
+                                  TBool aAnyRatio )
+    {
+    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 );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::ScaleSize
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TBool CCAImageLoader::ScaleSize( const TSize& aSize, TSize& aNewSize )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::ScaleSize" );
+    if ( Max( aSize.iHeight, aSize.iWidth ) > KChatCustomBitmapWidth )
+        {
+        // scaling needed
+        if ( aSize.iHeight > aSize.iWidth )
+            {
+            aNewSize.SetSize( KChatCustomBitmapHeight, KChatCustomBitmapWidth );
+            }
+        else
+            {
+            aNewSize.SetSize( KChatCustomBitmapWidth, KChatCustomBitmapHeight );
+            }
+        return ETrue;
+        }
+
+    // old size is correct
+    aNewSize = aSize;
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::ScaleSize" );
+    return EFalse;
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::CompleteRequestL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::CompleteRequestL()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::CompleteRequestL" );
+    iCurrentMessage->HandleProcessingComplete( *this, iStatus.Int() );
+    TInt index = iMessages.Find( iCurrentMessage );
+    if ( index >= 0 )
+        {
+        iMessages.Remove( index );
+        }
+    iCurrentMessage = NULL;
+    LaunchProcessingL();
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::CompleteRequestL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::ResetProcessingL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::ResetProcessingL( TInt aReason )
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::ResetProcessingL" );
+    // cancel operation
+    if ( IsActive() )
+        {
+        iStatus = aReason;
+        Cancel();
+        }
+
+    // show note
+    if ( aReason == KErrNoMemory )
+        {
+        CActiveScheduler::Current()->Error( KErrNoMemory );
+        }
+
+    // reset all pending messages
+    TInt count = iMessages.Count();
+    for ( TInt i = count - 1; i >= 0; --i )
+        {
+        iMessages[ i ]->SetProcessState( MCAMessage::EContentCorrupted );
+        iMessages[ i ]->HandleProcessingComplete( *this, aReason );
+        iMessages.Remove( i );
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::ResetProcessingL" );
+    }
+
+//-----------------------------------------------------------------------------
+// CCAImageLoader::ClearState
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CCAImageLoader::ClearState()
+    {
+    CHAT_DP_FUNC_ENTER( "CCAImageLoader::ClearState" );
+    if ( iScaler )
+        {
+        CHAT_DP_TXT( "CCAImageLoader::ClearState - Cancel scaler" );
+        iScaler->Cancel();
+        delete iScaler;
+        iScaler = NULL;
+        }
+    if ( iDecoder )
+        {
+        CHAT_DP_TXT( "CCAImageLoader::ClearState - Cancel decoder" );
+        iDecoder->Cancel();
+        delete iDecoder;
+        iDecoder = NULL;
+        }
+    if ( iEncoder )
+        {
+        CHAT_DP_TXT( "CCAImageLoader::ClearState - Cancel encoder" );
+        iEncoder->Cancel();
+        delete iEncoder;
+        iEncoder = NULL;
+        }
+    if ( iBitmap )
+        {
+        delete iBitmap;
+        iBitmap = NULL;
+        }
+    CHAT_DP_FUNC_DONE( "CCAImageLoader::ClearState" );
+    }
+
+// End of file