imagehandlingutilities/thumbnailmanager/plugins/audio/src/thumbnailimagedecoderv3.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 12 Mar 2010 15:43:57 +0200
branchRCL_3
changeset 9 2eb74cf6572e
parent 5 82749d516180
child 11 dea39715fc05
permissions -rw-r--r--
Revision: 201007 Kit: 201008

/*
* Copyright (c) 2006-2007 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 thumbnail decoder
 *
*/


//INCLUDE FILES
#include <e32base.h>
#include <imageconversion.h>
#include <ExifRead.h>

#include <IclExtJpegApi.h>
#include "thumbnailimagedecoderv3.h"
#include "thumbnaillog.h"
#include "thumbnailpanic.h"


// CImageDecoder supports up to 1/8 size reduction if EFullyScaleable is
// not set.
const TInt KMaximumReductionFactor = 8;


// ============================ MEMBER FUNCTIONS ===============================

// ---------------------------------------------------------------------------
// CThumbnailImageDecoder::CThumbnailImageDecoder()
// C++ default constructor can NOT contain any code, that might leave.
// ---------------------------------------------------------------------------
//
CThumbnailImageDecoderv3::CThumbnailImageDecoderv3( RFs& aFs ): CActive(
    EPriorityStandard ), iFs( aFs )
    {
    CActiveScheduler::Add( this );
    }


// ---------------------------------------------------------------------------
// CThumbnailImageDecoderv3::~CThumbnailImageDecoderv3()
// Destructor.
// ---------------------------------------------------------------------------
//
CThumbnailImageDecoderv3::~CThumbnailImageDecoderv3()
    {
    Release();
    }


// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::CreateL()
// Creates thumbnail of image
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::CreateL( const TDesC8* aBuffer, MThumbnailProviderObserver&
    aObserver, const CThumbnailManager::TThumbnailFlags /*aFlags*/, const
    TDataType& aMimeType, const TSize& aSize )
    {

    TN_DEBUG1( "CCThumbnailImageDecoderv3::CreateL() called" );

    iSize = aSize;
    iMimeType = aMimeType;
    iObserver = &aObserver;
    iBuffer = aBuffer;

    CreateDecoderL();

    const TFrameInfo info( iDecoder->FrameInfo());
    if (( info.iOverallSizeInPixels.iWidth < 1 ) || (
        info.iOverallSizeInPixels.iHeight < 1 ))
        {
        User::Leave( KErrCorrupt );
        }
    iFrameInfoFlags = info.iFlags;
    iOriginalSize = info.iOverallSizeInPixels; 
    }

// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::DecodeL()
// Decode the thumbnail image
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::DecodeL( const TDisplayMode aDisplayMode )
    {
    // Create the bitmap
    if ( !iBitmap )
        {
        iBitmap = new( ELeave )CFbsBitmap();
        }

    //Size in both x and y dimension must be non-zero, positive value
    TSize loadSize( iOriginalSize) ;

    // If EFullyScaleable flag is not set, we need to figure out a size
    // reduction factor. 1/1, 1/2, 1/4, and 1/8 are possible values for all
    // plug-ins. SVG graphics can be rendered at any size even though
    // EFullyScaleable is not set.
    if ( !( iFrameInfoFlags& TFrameInfo::EFullyScaleable ) )
        {
        loadSize = iOriginalSize;
        TInt reductionFactor = 1;
        while ( reductionFactor < KMaximumReductionFactor && ( iSize.iWidth <
            loadSize.iWidth / 2 ) && ( iSize.iHeight < loadSize.iHeight / 2 ))
            {
            // magic: use loadSize that is half of previous size
            loadSize.iWidth /= 2;
            loadSize.iHeight /= 2;
            reductionFactor *= 2;
            }
        // If original size is not an exact multiple of reduction factor,
        // we need to round loadSize up
        if ( reductionFactor && iOriginalSize.iWidth % reductionFactor )
            {
            loadSize.iWidth++;
            }
        if ( reductionFactor && iOriginalSize.iHeight % reductionFactor )
            {
            loadSize.iHeight++;
            }
        TN_DEBUG4( 
            "EFullyScaleable not set for image - loadSize=(%d,%d) reduction=1/%d ", loadSize.iWidth, loadSize.iHeight, reductionFactor );
        }

    User::LeaveIfError( iBitmap->Create( loadSize, aDisplayMode ));

    iDecoder->Convert( &iStatus, * iBitmap );
    while ( iStatus == KErrUnderflow )
        {
        iDecoder->ContinueConvert( &iStatus );
        }
    SetActive();
    }


// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::Release()
// Releases resources
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::Release()
    {
    Cancel();
    delete iDecoder;
    iDecoder = NULL;
    }


// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::DoCancel()
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::DoCancel()
    {
    if ( iDecoder )
        {
        iDecoder->Cancel();
        delete iDecoder;
        iDecoder = NULL;
        }
    }


// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::RunL()
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::RunL()
    {
    // This call takes ownership of iBitmap
    iObserver->ThumbnailProviderReady( iStatus.Int(), iBitmap, iOriginalSize, EFalse, EFalse );

    iBitmap = NULL; // owned by server now
    delete iBuffer;
    iBuffer = NULL;
    Release();
    }


// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::CreateDecoderL
// Creates image decoder
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::CreateDecoderL()
    {
    delete iDecoder;
    iDecoder = NULL;
	
    CImageDecoder::TOptions options = ( CImageDecoder::TOptions )( 
            CImageDecoder::EOptionNoDither | CImageDecoder::EPreferFastDecode | CImageDecoder::EOptionAlwaysThread );
 
    TRAPD( decErr, iDecoder = CExtJpegDecoder::DataNewL(
            CExtJpegDecoder::EHwImplementation, iFs, *iBuffer, options ));
    
    if ( decErr != KErrNone )
        {
        TN_DEBUG2( "CThumbnailImageDecoderv3::CreateDecoderL() - HW CExtJpegDecoder failed %d", decErr);
        
        LeaveIfCorruptL( decErr );
        
        TRAP( decErr, iDecoder = CExtJpegDecoder::DataNewL(
                CExtJpegDecoder::ESwImplementation, iFs, *iBuffer, options ));
        
        if ( decErr != KErrNone )
            {                             
            TN_DEBUG2( "CThumbnailImageDecoderv3::CreateDecoderL() - SW CExtJpegDecoder failed %d", decErr);
            
            LeaveIfCorruptL( decErr );
            // don't force any mime type
            TRAPD( decErr, iDecoder = CImageDecoder::DataNewL( iFs, *iBuffer, options ) );
            if ( decErr != KErrNone )
                {
                delete iBuffer;
                iBuffer = NULL;
                
                TN_DEBUG2( "CThumbnailImageDecoderv3::CreateDecoderL() - CImageDecoder error %d", decErr );
                
                User::Leave( decErr );
                }     
            
            TN_DEBUG1( "CThumbnailImageDecoderv3::CreateDecoderL() - CImageDecoder created" );
            }
        else
            {
            TN_DEBUG1( "CThumbnailImageDecoderv3::CreateDecoderL() - SW CExtJpegDecoder created" );
            }               
        }
    else
        {
        TN_DEBUG1( "CThumbnailImageDecoderv3::CreateDecoderL() - HW CExtJpegDecoder created" );
        }    
    }


// -----------------------------------------------------------------------------
// CThumbnailImageDecoderv3::CreateExifDecoderL()
// Returns size of original image
// -----------------------------------------------------------------------------
//
const TSize& CThumbnailImageDecoderv3::OriginalSize()const
    {
    return iOriginalSize;
    }

// -----------------------------------------------------------------------------
// CThumbnailImageDecoder3::LeaveIfCorruptL()
// Leave is image is corrupted
// -----------------------------------------------------------------------------
//
void CThumbnailImageDecoderv3::LeaveIfCorruptL(const TInt aError )
    {
    //no sense to try other codecs if image is corrupted
    if( aError == KErrCorrupt || aError == KErrUnderflow)
        {
        User::Leave( aError );
        }
    }

//End of file