diff -r 000000000000 -r 96612d01cf9f videofeeds/utils/src/vcxnsimageconverter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videofeeds/utils/src/vcxnsimageconverter.cpp Mon Jan 18 20:21:12 2010 +0200 @@ -0,0 +1,560 @@ +/* +* Copyright (c) 2009-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: Converter that creates icons from picture files.* +*/ + + + + +// INCLUDE FILES +#include // TAknWindowLineLayout +#include // CGulIcon +#include // BaflUtils +#include // Image converter +#include + +#include "vcxnsimageconverter.h" +#include "vcxnsimageconverterobserver.h" +#include "IptvDebug.h" + +_LIT(KMifExtension, ".mif"); + + +// ============================ LOCAL FUNCTIONS ================================ + +void ScaleBitmapL( CFbsBitmap*& aImage, TSize aSize ) + { + if ( aImage ) + { + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap(); + CleanupStack::PushL( bitmap ); + bitmap->Create( aSize, aImage->DisplayMode() ); + AknIconUtils::ScaleBitmapL( aSize, bitmap, aImage ); + delete aImage; + aImage = bitmap; + CleanupStack::Pop( bitmap ); + } + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::CVcxNsImageConverter() +// ----------------------------------------------------------------------------- +// +CVcxNsImageConverter::CVcxNsImageConverter( + MVcxNsImageConverterObserver& aObserver, + RFs& aFsSession ) + : CActive( EPriorityStandard ), + iFsSession( aFsSession ), + iSynchronous( EFalse ), + iConvertingMif( EFalse ), + iMifBitmapId( 0 ), + iMifMaskId( 0 ), + iObserver( aObserver ) + { + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::ConstructL() +// ----------------------------------------------------------------------------- +// +void CVcxNsImageConverter::ConstructL() + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::NewL() +// ----------------------------------------------------------------------------- +// +EXPORT_C CVcxNsImageConverter* CVcxNsImageConverter::NewL( + MVcxNsImageConverterObserver& aObserver, + RFs& aFsSession ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::NewL()"); + + CVcxNsImageConverter* self = new (ELeave) CVcxNsImageConverter( + aObserver, aFsSession ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::~CVcxNsImageConverter() +// ----------------------------------------------------------------------------- +// +CVcxNsImageConverter::~CVcxNsImageConverter() + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::~CVcxNsImageConverter()"); + + Cancel(); + + // If decoder is cancelled, these might stay reserved. + delete iDecoder; + delete iBitmap; + delete iMask; + delete iMifFileName; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::GetImageType() +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CVcxNsImageConverter::GetImageType( + const TDesC& aFileName, + TImageType& aImageType ) + { + IPTVLOGSTRING2_LOW_LEVEL("CVcxNsImageConverter::GetImageType() %S", &aFileName); + + TBuf ext; + + if ( GetExtension( aFileName, ext )) + { + ext.LowerCase(); + + if ( ext.Compare( KMifExtension )) // Returns zero if match. + { + aImageType = EOther; + } + else + { + aImageType = EMif; + } + + return KErrNone; + } + + return KErrGeneral; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::ConvertL() +// Converts image file synchronoysly. +// ----------------------------------------------------------------------------- +// +EXPORT_C CGulIcon* CVcxNsImageConverter::ConvertL( + const TDesC& aFileName, + TSize aImageSize, + TBool aCreateMask ) + { + IPTVLOGSTRING2_LOW_LEVEL("CVcxNsImageConverter::ConvertL(picture) %S", &aFileName); + + CGulIcon* icon = NULL; + + // Start sycnhronous image convert + iSynchronous = ETrue; + + if ( StartConvertL( aFileName, aImageSize, aCreateMask ) == KErrNone) + { + CActiveScheduler::Start(); + + if ( iStatus == KErrNone ) + { + if ( !iImageScalable ) // use AknIconUtils:ScaleBitmap to scale image. + { + ScaleBitmapL( iBitmap, iMifImageSize ); + ScaleBitmapL( iMask, iMifImageSize ); + } + + icon = CGulIcon::NewL( iBitmap, iMask ); + icon->SetBitmapsOwnedExternally( EFalse ); + + iBitmap = NULL; // Not owned by us anymore. + iMask = NULL; + } + } + + return icon; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::ConvertL() +// Converts mif file synchronoysly. +// ----------------------------------------------------------------------------- +// +EXPORT_C CGulIcon* CVcxNsImageConverter::ConvertL( + const TDesC& aFileName, + TSize aImageSize, + TInt aBitmapId, + TInt aMaskId ) + { + IPTVLOGSTRING2_LOW_LEVEL("CVcxNsImageConverter::ConvertL(mif) %S", &aFileName); + + CFbsBitmap* bitmap = NULL; + CFbsBitmap* mask = NULL; + + if ( aFileName.Length() == 0 ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::ConvertL(mif) file did not exist."); + return NULL; + } + + // Skip the file-existence check with file names starting with \ -character. + // BaflUtils cannot handle these (e.g. select drive) so it would fail. + if ( aFileName[0] != '\\' ) + { + if ( ! BaflUtils::FileExists( iFsSession, aFileName ) ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::ConvertL(mif) file did not exist."); + return NULL; + } + } + + AknIconUtils::CreateIconLC(bitmap, mask, aFileName, aBitmapId, aMaskId); + + CGulIcon* icon = CGulIcon::NewL(bitmap, mask); + CleanupStack::PushL(icon); + + // ownership of bitmap and mask transferred to icon + icon->SetBitmapsOwnedExternally(EFalse); + + AknIconUtils::SetSize(bitmap, aImageSize); + AknIconUtils::SetSize(mask, aImageSize); + + CleanupStack::Pop(icon); + CleanupStack::Pop(mask); + CleanupStack::Pop(bitmap); + + return icon; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::StartConvertL() +// Starts converting image file asynchronously. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CVcxNsImageConverter::StartConvertL( + const TDesC& aFileName, + TSize aReqSize, + TBool aCreateMask ) + { + IPTVLOGSTRING2_LOW_LEVEL("CVcxNsImageConverter::StartConvertL(picture) %S", &aFileName); + + if ( IsActive() ) + { + return KErrInUse; + } + + if ( iDecoder ) + { + iDecoder->Cancel(); + delete iDecoder; + iDecoder = NULL; + } + + if ( ! BaflUtils::FileExists( iFsSession, aFileName ) ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::StartConvertL(picture) file did not exist."); + return KErrNotFound; + } + + TRAPD( createError, { iDecoder = CImageDecoder::FileNewL( iFsSession, aFileName ); } ); + + if ( createError != KErrNone ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::StartConvertL(picture) file not supported?"); + return createError; + } + + // original image size + TFrameInfo info = iDecoder->FrameInfo(); + TSize trueSize = info.iOverallSizeInPixels; + TSize wantedSize( trueSize ); + iImageScalable = info.iFlags & TFrameInfo::EFullyScaleable; + + // Count mismatch of true size to requested size in horisontal and vertical direction. + TReal verticalMismatch = ((TReal) trueSize.iHeight) / ((TReal) aReqSize.iHeight); + TReal horisontalMismatch = ((TReal) trueSize.iWidth) / ((TReal) aReqSize.iWidth); + + if (verticalMismatch == 0 || horisontalMismatch == 0) + { + return KErrDivideByZero; + } + + // Picture size is more off the requested size horisontally than vertically. + if (horisontalMismatch > verticalMismatch) + { + wantedSize.SetSize((TInt) aReqSize.iWidth, // Width + (TInt) (((TReal)trueSize.iHeight) / horisontalMismatch)); // Height + } + // Picture size is more off the requested size vertically than horisontally. + else + { + wantedSize.SetSize((TInt) (((TReal)trueSize.iWidth) / verticalMismatch), // Width + (TInt) aReqSize.iHeight); // Height + } + + // Make sure size we did not go over the requested limits because + // of rounding errors or other additions made to rectangle. + if (wantedSize.iWidth > aReqSize.iWidth) + { + wantedSize.iWidth = aReqSize.iWidth; + } + if (wantedSize.iHeight > aReqSize.iHeight) + { + wantedSize.iHeight = aReqSize.iHeight; + } + + if ( iImageScalable ) + { + trueSize = wantedSize; + } + else + { + iMifImageSize = wantedSize; + } + + // create bitmap for the proper size + iBitmap = new ( ELeave ) CFbsBitmap(); + iBitmap->Create( trueSize, info.iFrameDisplayMode ); + + // create mask if available and requested. + if ( aCreateMask && (info.iFlags & TFrameInfo::ETransparencyPossible) ) + { + iMask = new (ELeave) CFbsBitmap; + + if ( info.iFlags & TFrameInfo::EAlphaChannel ) + { + iMask->Create( trueSize, EGray256 ); + } + else + { + iMask->Create( trueSize, EGray2 ); + } + } + else + { + iMask = NULL; + } + + // start converting. + if (iMask) + { + iDecoder->Convert( &iStatus, *iBitmap, *iMask ); + } + else + { + iDecoder->Convert( &iStatus, *iBitmap ); + } + + // start waiting for completion + iConvertingMif = EFalse; + SetActive(); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::StartConvertL() +// Starts converting mif file asynchronously. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CVcxNsImageConverter::StartConvertL( + const TDesC& aFileName, + TSize aImageSize, + TInt aBitmapId, + TInt aMaskId ) + { + IPTVLOGSTRING2_LOW_LEVEL("CVcxNsImageConverter::StartConvertL(mif) %S", &aFileName); + + if ( IsActive() ) + { + return KErrInUse; + } + + delete iMifFileName; + iMifFileName = NULL; + + iMifFileName = HBufC16::NewL( aFileName.Length() ); + *iMifFileName = aFileName; + iMifImageSize = aImageSize; + iMifBitmapId = aBitmapId; + iMifMaskId = aMaskId; + + iConvertingMif = ETrue; + + // Sets this object as active and completes immediately, but asynchronously. + SetActive(); + iStatus = KRequestPending; + TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, KErrNone); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::RunL() +// From CActive, called when converting is done +// ----------------------------------------------------------------------------- +// +void CVcxNsImageConverter::RunL() + { + if ( iConvertingMif ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::RunL() after mif conversion."); + + CGulIcon* icon = ConvertL( *iMifFileName, iMifImageSize, iMifBitmapId, iMifMaskId ); + + iObserver.ImageConversionCompletedL( (icon ? KErrNone : KErrGeneral), icon ); + } + else // Converting image + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::RunL() after image conversion."); + + // Free decoder. Otherwise the last image file (on disk) stays reserved + // until client releases this object (CVcxNsImageConverter). + if ( iDecoder ) + { + iDecoder->Cancel(); + delete iDecoder; + iDecoder = NULL; + } + + // On error cases, free the already reserved bitmaps. + if ( iStatus != KErrNone ) + { + if ( iBitmap ) + { + delete iBitmap; + iBitmap = NULL; + } + if ( iMask ) + { + delete iMask; + iMask = NULL; + } + } + + if( iSynchronous ) + { + // Stop the scheduler. Rest is handlen in ConvertL method + iSynchronous = EFalse; + CActiveScheduler::Stop(); + } + else + { + if ( iStatus == KErrNone ) + { + if ( !iImageScalable ) // use AknIconUtils:ScaleBitmapL to scale image. + { + ScaleBitmapL( iBitmap, iMifImageSize ); + ScaleBitmapL( iMask, iMifImageSize ); + } + + // set converted image to icon array + CreateAndSetIconL(); + } + else + { + // In case of error, we just set default icon for application + ReportErrorL(); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::DoCancel() +// ----------------------------------------------------------------------------- +// +void CVcxNsImageConverter::DoCancel() + { + if ( iDecoder ) + { + iDecoder->Cancel(); + delete iDecoder; + iDecoder = NULL; + } + + delete iBitmap; + iBitmap = NULL; + + delete iMask; + iMask = NULL; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::RunError() +// ----------------------------------------------------------------------------- +// +TInt CVcxNsImageConverter::RunError(TInt aError) + { + DoCancel(); + + TRAP_IGNORE( iObserver.ImageConversionCompletedL( aError, NULL ) ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::CreateAndSetIconL() +// ----------------------------------------------------------------------------- +// +void CVcxNsImageConverter::CreateAndSetIconL() + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::CreateAndSetIconL()"); + + CGulIcon* icon = CGulIcon::NewL( iBitmap, iMask ); + CleanupStack::PushL( icon ); + icon->SetBitmapsOwnedExternally( EFalse ); + + iBitmap = NULL; // Not owned by us anymore. + iMask = NULL; + + iObserver.ImageConversionCompletedL( KErrNone, icon ); + + CleanupStack::Pop( icon ); + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::ReportErrorL() +// ----------------------------------------------------------------------------- +// +void CVcxNsImageConverter::ReportErrorL() + { + IPTVLOGSTRING_LOW_LEVEL("CVcxNsImageConverter::ReportErrorL()"); + + iObserver.ImageConversionCompletedL( iStatus.Int(), NULL ); + } + +// ----------------------------------------------------------------------------- +// CVcxNsImageConverter::GetExtension() +// ----------------------------------------------------------------------------- +// +TBool CVcxNsImageConverter::GetExtension(const TDesC& aPath, TDes& aExtension) + { + if (aPath.Length() > 0) + { + TInt dot = aPath.LocateReverse('.'); + + if (dot != KErrNotFound) + { + TPtrC16 suffixPtr = aPath.Mid(dot); + if ( suffixPtr.Length() >= KSuffixPtrMinLength && + suffixPtr.Length() <= KSuffixPtrMaxLength) + { + aExtension.Copy(suffixPtr); + + return ETrue; + } + else + { + aExtension.Zero(); + } + } + } + + return EFalse; + }