--- /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 <AknUtils.h> // TAknWindowLineLayout
+#include <gulicon.h> // CGulIcon
+#include <bautils.h> // BaflUtils
+#include <imageconversion.h> // Image converter
+#include <AknIconUtils.h>
+
+#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<KFileExtensionLength> 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;
+ }