imagehandlingutilities/thumbnailmanager/thumbnailserver/src/thumbnailscaletask.cpp
changeset 0 2014ca87e772
child 5 82749d516180
child 14 2edacbf5d3f9
equal deleted inserted replaced
-1:000000000000 0:2014ca87e772
       
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Task for scaling thumbnails.
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <fbs.h>
       
    21 #include <e32math.h>
       
    22 #include <bitdev.h>
       
    23 #include <bitstd.h>
       
    24 
       
    25 #include "thumbnailscaletask.h"
       
    26 #include "thumbnailprovider.h"
       
    27 #include "thumbnailserver.h"
       
    28 #include "thumbnailmanagerconstants.h"
       
    29 #include "thumbnaillog.h"
       
    30 #include "thumbnailpanic.h"
       
    31 
       
    32 
       
    33 // ======== MEMBER FUNCTIONS ========
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // CThumbnailScaleTask::NewL()
       
    37 // Two-phased constructor.
       
    38 // ---------------------------------------------------------------------------
       
    39 //
       
    40 CThumbnailScaleTask* CThumbnailScaleTask::NewL( CThumbnailTaskProcessor&
       
    41     aProcessor, CThumbnailServer& aServer, const TDesC& aFilename, CFbsBitmap*
       
    42     aBitmap, const TSize& aOriginalSize, const TSize& aTargetSize, TBool aCrop,
       
    43     TDisplayMode aDisplayMode, TInt aPriority, const TDesC& aTargetUri,
       
    44     const TThumbnailSize aThumbnailSize, const TThumbnailId aThumbnailId,
       
    45     TBool aBitmapToPool, const TBool aEXIF)
       
    46     {
       
    47     // We take ownership of aBitmap
       
    48     CleanupStack::PushL( aBitmap );
       
    49     CThumbnailScaleTask* self = new( ELeave )CThumbnailScaleTask( aProcessor,
       
    50         aServer, aFilename, aBitmap, aOriginalSize, aTargetSize, aCrop,
       
    51         aDisplayMode, aPriority, aTargetUri, aThumbnailSize, aThumbnailId,
       
    52         aBitmapToPool, aEXIF);
       
    53     CleanupStack::Pop( aBitmap );
       
    54     CleanupStack::PushL( self );
       
    55     self->ConstructL();
       
    56     CleanupStack::Pop( self );
       
    57     return self;
       
    58     }
       
    59 
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // CThumbnailScaleTask::CThumbnailScaleTask()
       
    63 // C++ default constructor can NOT contain any code, that might leave.
       
    64 // ---------------------------------------------------------------------------
       
    65 //
       
    66 CThumbnailScaleTask::CThumbnailScaleTask( CThumbnailTaskProcessor& aProcessor,
       
    67     CThumbnailServer& aServer, const TDesC& aFilename, CFbsBitmap* aBitmap,
       
    68     const TSize& aOriginalSize, const TSize& aTargetSize, TBool aCrop,
       
    69     TDisplayMode aDisplayMode, TInt aPriority, const TDesC& aTargetUri,
       
    70     const TThumbnailSize aThumbnailSize, const TThumbnailId aThumbnailId,
       
    71     TBool aBitmapToPool, const TBool aEXIF):
       
    72     CThumbnailTask( aProcessor, aPriority ), iServer( aServer ), iOwnBitmap( aBitmap ),
       
    73     iOriginalSize( aOriginalSize ), iTargetSize( aTargetSize ), iCrop( aCrop ),
       
    74     iDisplayMode( aDisplayMode ), iFilename( aFilename ), iTargetUri( aTargetUri ),
       
    75     iThumbnailSize(aThumbnailSize), iThumbnailId(aThumbnailId),
       
    76     iBitmapToPool(aBitmapToPool), iEXIF(aEXIF)
       
    77     {
       
    78     TN_DEBUG2( "CThumbnailScaleTask(0x%08x)::CThumbnailScaleTask()", this );
       
    79     }
       
    80 
       
    81 
       
    82 // ---------------------------------------------------------------------------
       
    83 // CThumbnailScaleTask::ConstructL()
       
    84 // Symbian 2nd phase constructor can leave.
       
    85 // ---------------------------------------------------------------------------
       
    86 //
       
    87 void CThumbnailScaleTask::ConstructL()
       
    88     {
       
    89     iServer.AddBitmapToPoolL( NULL, iOwnBitmap );
       
    90 
       
    91     // Successfully added bitmap to pool, we are no longer responsible for
       
    92     // deleting it directly.
       
    93     iBitmap = iOwnBitmap;
       
    94     iOwnBitmap = NULL;
       
    95     iBitmapInPool = ETrue;
       
    96     
       
    97     iScaledBitmap = NULL;
       
    98     iScaledBitmapHandle = 0;
       
    99     }
       
   100 
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // CThumbnailScaleTask::~CThumbnailScaleTask()
       
   104 // Destructor.
       
   105 // ---------------------------------------------------------------------------
       
   106 //
       
   107 CThumbnailScaleTask::~CThumbnailScaleTask()
       
   108     {
       
   109     iServer.CancelScale();
       
   110     
       
   111     if ( iBitmapInPool && iBitmap )
       
   112         {
       
   113         TN_DEBUG1("CThumbnailScaleTask()::~CThumbnailScaleTask() delete original bitmap from pool");
       
   114         
       
   115         // Original bitmap is owned by server, decrease reference count
       
   116         iServer.DeleteBitmapFromPool( iBitmap->Handle());
       
   117         }
       
   118 
       
   119     if ( iScaledBitmapHandle )
       
   120         {
       
   121         TN_DEBUG1("CThumbnailScaleTask()::~CThumbnailScaleTask() delete scaled bitmap from pool");
       
   122         
       
   123         // Scaled bitmap is owned by server, decrease reference count
       
   124         iServer.DeleteBitmapFromPool( iScaledBitmapHandle );
       
   125         }
       
   126 
       
   127     // Scaled bitmap is owned by us, delete now
       
   128     delete iScaledBitmap;
       
   129     }
       
   130 
       
   131 
       
   132 // ---------------------------------------------------------------------------
       
   133 // CThumbnailScaleTask::StartL()
       
   134 // ---------------------------------------------------------------------------
       
   135 //
       
   136 void CThumbnailScaleTask::StartL()
       
   137     {
       
   138     TN_DEBUG2( "CThumbnailScaleTask(0x%08x)::StartL()", this );
       
   139 
       
   140     CThumbnailTask::StartL();
       
   141 
       
   142     if ( !iCrop )
       
   143         {
       
   144         // target size at max, keep aspect ratio
       
   145         CalculateTargetSize();
       
   146         }
       
   147     else
       
   148         {
       
   149         // exact target size, crop excess
       
   150         CalculateCropRectangle();
       
   151         }
       
   152     
       
   153 #ifdef _DEBUG
       
   154     aStart.UniversalTime();
       
   155 #endif
       
   156     
       
   157     delete iScaledBitmap;
       
   158     iScaledBitmap = NULL;
       
   159     iScaledBitmap = new( ELeave )CFbsBitmap();
       
   160     
       
   161     TSize bitmapSize = iBitmap->SizeInPixels();
       
   162     
       
   163     if(bitmapSize.iHeight == iTargetSize.iHeight && bitmapSize.iWidth == iTargetSize.iWidth)
       
   164         {
       
   165         // copy bitmap 1:1
       
   166         User::LeaveIfError( iScaledBitmap->Create( bitmapSize, iBitmap->DisplayMode() ));
       
   167         CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(iScaledBitmap);
       
   168         CleanupStack::PushL(device);
       
   169         CFbsBitGc* gc = NULL;
       
   170         User::LeaveIfError(device->CreateContext(gc));
       
   171         CleanupStack::PushL(gc);
       
   172         gc->BitBlt(TPoint(0, 0), iBitmap);
       
   173         CleanupStack::PopAndDestroy(2, device); // gc
       
   174         
       
   175         TN_DEBUG2( "CThumbnailScaleTask(0x%08x)::StartL() - no need for scaling", this);
       
   176         TRAPD( err, StoreAndCompleteL());
       
   177         Complete( err );
       
   178         ResetMessageData();
       
   179         }
       
   180     else
       
   181         {
       
   182         TN_DEBUG2( "CThumbnailScaleTask(0x%08x)::StartL() - scaling", this);
       
   183         User::LeaveIfError( iScaledBitmap->Create( iTargetSize, iBitmap->DisplayMode() ));
       
   184         iServer.ScaleBitmapL( iStatus, * iBitmap, * iScaledBitmap, iCropRectangle );
       
   185         SetActive();
       
   186         }
       
   187    
       
   188     }
       
   189 
       
   190 
       
   191 // ---------------------------------------------------------------------------
       
   192 // CThumbnailScaleTask::RunL()
       
   193 // ---------------------------------------------------------------------------
       
   194 //
       
   195 void CThumbnailScaleTask::RunL()
       
   196     {
       
   197     TInt err = iStatus.Int();
       
   198 
       
   199     TN_DEBUG3( "CThumbnailScaleTask(0x%08x)::RunL() err=%d)", this, err );
       
   200 
       
   201     #ifdef _DEBUG
       
   202     aStop.UniversalTime();
       
   203     TN_DEBUG2( "CThumbnailScaleTask::RunL() scale took %d ms", (TInt)aStop.MicroSecondsFrom(aStart).Int64()/1000);
       
   204     #endif
       
   205 
       
   206     if ( !err )
       
   207         {
       
   208         TRAP( err, StoreAndCompleteL());
       
   209         }
       
   210     
       
   211     Complete( err );
       
   212     ResetMessageData();
       
   213     }
       
   214 
       
   215 
       
   216 // ---------------------------------------------------------------------------
       
   217 // CThumbnailScaleTask::DoCancel()
       
   218 // ---------------------------------------------------------------------------
       
   219 //
       
   220 void CThumbnailScaleTask::DoCancel()
       
   221     {
       
   222     TN_DEBUG2( "CThumbnailScaleTask(0x%08x)::DoCancel()", this );
       
   223     iServer.CancelScale();
       
   224     }
       
   225 
       
   226 
       
   227 // ---------------------------------------------------------------------------
       
   228 // Calculates target size to be used for the thumbnail
       
   229 // ---------------------------------------------------------------------------
       
   230 //
       
   231 void CThumbnailScaleTask::CalculateTargetSize()
       
   232     {
       
   233     __ASSERT_DEBUG( iOriginalSize.iHeight && iTargetSize.iHeight,
       
   234         ThumbnailPanic( EThumbnailBadSize ));
       
   235     
       
   236     if ( (iThumbnailSize == EFullScreenThumbnailSize ||
       
   237           iThumbnailSize == EImageFullScreenThumbnailSize ||
       
   238           iThumbnailSize == EVideoFullScreenThumbnailSize ||
       
   239           iThumbnailSize == EAudioFullScreenThumbnailSize) &&
       
   240           iOriginalSize.iHeight < iTargetSize.iHeight && 
       
   241           iOriginalSize.iWidth < iTargetSize.iWidth )
       
   242         {
       
   243         // do not upscale fullscreen thumbs
       
   244         iTargetSize = iOriginalSize;
       
   245         }
       
   246     else if ( iOriginalSize.iHeight && iTargetSize.iHeight )
       
   247         {
       
   248         const TReal32 srcAspect = static_cast < TReal32 > (
       
   249             iOriginalSize.iWidth ) / iOriginalSize.iHeight;
       
   250 
       
   251         // scale to maximum size within target size 
       
   252         if ( (iTargetSize.iHeight * srcAspect) <= iTargetSize.iWidth )
       
   253             {
       
   254             TReal trg = 0;
       
   255             TReal src( iTargetSize.iHeight * srcAspect );
       
   256             Math::Round( trg, src, 0 );
       
   257             iTargetSize.SetSize( trg, iTargetSize.iHeight );
       
   258             }
       
   259         else
       
   260             {
       
   261             TReal trg;
       
   262             TReal src( iTargetSize.iWidth / srcAspect );
       
   263             Math::Round( trg, src, 0 );
       
   264             iTargetSize.SetSize( iTargetSize.iWidth, trg );
       
   265             }
       
   266         }
       
   267     else
       
   268         {
       
   269         iTargetSize.SetSize( 0, 0 );
       
   270         }
       
   271     iCropRectangle.SetRect( TPoint(), iBitmap->SizeInPixels());
       
   272     }
       
   273 
       
   274 
       
   275 // ---------------------------------------------------------------------------
       
   276 // Calculates target size to be used for the thumbnail
       
   277 // ---------------------------------------------------------------------------
       
   278 //
       
   279 void CThumbnailScaleTask::CalculateCropRectangle()
       
   280     {
       
   281     const TSize srcSize = iBitmap->SizeInPixels();
       
   282 
       
   283     __ASSERT_DEBUG( srcSize.iHeight && iTargetSize.iHeight, ThumbnailPanic(
       
   284         EThumbnailBadSize ));
       
   285 
       
   286     if ( srcSize.iHeight && iTargetSize.iHeight )
       
   287         {
       
   288         const TReal32 srcAspect = static_cast < TReal32 > ( srcSize.iWidth ) /
       
   289             srcSize.iHeight;
       
   290         const TReal32 reqAspect = static_cast < TReal32 > ( iTargetSize.iWidth )
       
   291             / iTargetSize.iHeight;
       
   292 
       
   293         if ( (iTargetSize.iHeight * srcAspect) > iTargetSize.iWidth )
       
   294             {
       
   295             // Thumbnail is wider than requested and we crop
       
   296             // some of the right and left parts.
       
   297             TReal trg;
       
   298             TReal src( srcSize.iHeight* reqAspect );
       
   299             Math::Round( trg, src, 0 );
       
   300             const TSize cropSize( trg, srcSize.iHeight );
       
   301             iCropRectangle.iTl.SetXY(( srcSize.iWidth - cropSize.iWidth ) / 2, 0 );
       
   302             iCropRectangle.SetSize( cropSize );
       
   303             }
       
   304         else
       
   305             {
       
   306             // Thumbnail is taller than requested and we crop
       
   307             // some of the top and bottom parts.
       
   308             TReal trg;
       
   309             TReal src( srcSize.iWidth / reqAspect );
       
   310             Math::Round( trg, src, 0 );
       
   311             const TSize cropSize( srcSize.iWidth, trg );
       
   312             iCropRectangle.iTl.SetXY(0, ( srcSize.iHeight - cropSize.iHeight ) / 2 );
       
   313             iCropRectangle.SetSize( cropSize );
       
   314             }
       
   315 
       
   316         }
       
   317     else
       
   318         {
       
   319         iTargetSize.SetSize( 0, 0 );
       
   320         }
       
   321     }
       
   322 
       
   323 // ---------------------------------------------------------------------------
       
   324 // CThumbnailScaleTask::StoreAndCompleteL()
       
   325 // ---------------------------------------------------------------------------
       
   326 //
       
   327 void CThumbnailScaleTask::StoreAndCompleteL()
       
   328     {
       
   329     TN_DEBUG5( "CThumbnailScaleTask(0x%08x)::StoreAndCompleteL() iFilename=%S, iBitmap=0x%08x, iScaledBitmap=0x%08x)", 
       
   330                this, &iFilename, iBitmap, iScaledBitmap );
       
   331 		 
       
   332     // do not store TN if quality is too low eg. orignal size of image is smaller than requested size
       
   333     // (do not store upscaled images)
       
   334     if ( iTargetSize.iWidth >= iOriginalSize.iWidth && 
       
   335          iTargetSize.iHeight >= iOriginalSize.iHeight && iEXIF)
       
   336         {
       
   337         TN_DEBUG1("CThumbnailScaleTask()::StoreAndCompleteL() too low quality");
       
   338         //don't store preview image
       
   339         iDoStore = EFalse;
       
   340         }
       
   341     
       
   342     TN_DEBUG3("CThumbnailScaleTask(0x%08x)::StoreAndCompleteL() iDoStore = %d", this, iDoStore);
       
   343     
       
   344     if ( iDoStore )
       
   345         {
       
   346         if (iTargetUri != KNullDesC)
       
   347             {
       
   348             if (iFilename != KNullDesC && iFilename.CompareF(iTargetUri) == 0)
       
   349                 {
       
   350                 // filename and target URI match, so thumb created from associated path
       
   351                 iServer.StoreThumbnailL( iTargetUri, iScaledBitmap, iOriginalSize, iCrop, iThumbnailSize, iThumbnailId, ETrue );
       
   352                 }
       
   353             else
       
   354                 {
       
   355                 // thumb not created from associated path
       
   356                 iServer.StoreThumbnailL( iTargetUri, iScaledBitmap, iOriginalSize, iCrop, iThumbnailSize, iThumbnailId, EFalse, EFalse );
       
   357                 }  
       
   358             }
       
   359         else if (iFilename != KNullDesC)
       
   360             {
       
   361             iServer.StoreThumbnailL( iFilename, iScaledBitmap, iOriginalSize, iCrop, iThumbnailSize, iThumbnailId, ETrue );
       
   362             }
       
   363         }    
       
   364     
       
   365     if ( iMessage.Handle() )
       
   366         {
       
   367         TN_DEBUG1("CThumbnailScaleTask()::StoreAndCompleteL() scaled bitmap handle to params");
       
   368         
       
   369     	TThumbnailRequestParams& params = iParamsBuf();
       
   370 		iMessage.ReadL( 0, iParamsBuf );
       
   371 		params.iBitmapHandle = iScaledBitmap->Handle();
       
   372 	   
       
   373         // if need to add scaled bitmap to pool
       
   374         if (iBitmapToPool)
       
   375             {
       
   376             TN_DEBUG1("CThumbnailScaleTask()::StoreAndCompleteL() scaled bitmap to pool");
       
   377             
       
   378             iServer.AddBitmapToPoolL( iRequestId.iSession, iScaledBitmap );
       
   379             iScaledBitmapHandle = params.iBitmapHandle;
       
   380             }    
       
   381 		
       
   382 	    if( params.iQualityPreference == CThumbnailManager::EOptimizeForQualityWithPreview
       
   383 	        && iEXIF && !iDoStore)
       
   384 	        {
       
   385 		    // this is upscaled preview image
       
   386 	        params.iControlFlags = EThumbnailPreviewThumbnail;
       
   387 	        TN_DEBUG1("CThumbnailScaleTask()::StoreAndCompleteL() EThumbnailPreviewThumbnail");
       
   388 	        }
       
   389 
       
   390         // Server owns the bitmap now. If the code below leaves, we will
       
   391         // release the bitmap reference in destructor using iScaledBitmapHandle.
       
   392         if (iBitmapToPool)
       
   393            {
       
   394            iScaledBitmap = NULL;
       
   395            }
       
   396 	    
       
   397         TN_DEBUG1("CThumbnailScaleTask()::StoreAndCompleteL() write params to message");
       
   398         
       
   399 	    // pass bitmap handle to client
       
   400 	    iMessage.WriteL( 0, iParamsBuf );
       
   401 	    
       
   402 	    // Successfully completed the message. The client will send
       
   403 	    // EReleaseBitmap message later to delete the bitmap from pool.
       
   404 	    // CThumbnailScaleTask is no longer responsible for that.
       
   405 	    iScaledBitmapHandle = 0;
       
   406         }
       
   407     
       
   408     TN_DEBUG1("CThumbnailScaleTask()::StoreAndCompleteL() - end");
       
   409     }
       
   410 
       
   411 
       
   412 // ---------------------------------------------------------------------------
       
   413 // CThumbnailScaleTask::StoreAndCompleteL()
       
   414 // Changes priority of the task.
       
   415 // ---------------------------------------------------------------------------
       
   416 //
       
   417 void CThumbnailScaleTask::ChangeTaskPriority( TInt /*aNewPriority*/ )
       
   418     {
       
   419     // The priority of scale tasks is fixed. Do nothing.
       
   420     }
       
   421 
       
   422 // ---------------------------------------------------------------------------
       
   423 // CThumbnailScaleTask::SetDoStore()
       
   424 // Changes the store flag
       
   425 // ---------------------------------------------------------------------------
       
   426 //
       
   427 void CThumbnailScaleTask::SetDoStore( TBool aDoStore )
       
   428     {
       
   429     iDoStore = aDoStore;
       
   430     }