camerauis/cameraapp/generic/src/cameracontroller/camimagedecoder.cpp
branchRCL_3
changeset 24 bac7acad7cb3
equal deleted inserted replaced
23:61bc0f252b2b 24:bac7acad7cb3
       
     1 /*
       
     2 * Copyright (c) 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:  Implementation of Camera image decoder
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <imageconversion.h>
       
    20 #include <ExifRead.h>
       
    21 #include <ecam.h> // MCameraBuffer
       
    22 
       
    23 #include <eikenv.h>
       
    24 #include <SvgCodecImageConstants.hrh>
       
    25 #include <SVGEngineInterfaceImpl.h>
       
    26 
       
    27 #include "camlogging.h"
       
    28 #include "camfilesaveutility.h"
       
    29 #include "cambuffershare.h"
       
    30 
       
    31 #include "camimagedecoder.h"
       
    32 
       
    33 // ===========================================================================
       
    34 // Local constants
       
    35 
       
    36 namespace NCamCameraController
       
    37   {
       
    38   // Decoding flags
       
    39   static const TUint32 KConversionOptions = 
       
    40     ( CImageDecoder::EOptionNone
       
    41     | CImageDecoder::EOptionAlwaysThread
       
    42     | CImageDecoder::EPreferFastDecode
       
    43     );
       
    44   
       
    45   // EXIF reader flags
       
    46   //   Only need the thumbnail, so no need to parse the
       
    47   //   main (jpeg) image.
       
    48   static const TUint KExifReaderFlags = CExifRead::ENoJpeg;
       
    49   
       
    50   // Other constants
       
    51   static const TInt KMaxRetries = 10;
       
    52   static const TInt KPriority = CActive::EPriorityHigh;
       
    53   }
       
    54 
       
    55 using namespace NCamCameraController;
       
    56 
       
    57 // ===========================================================================
       
    58 // public constructor and destructor
       
    59 
       
    60 CCamImageDecoder* 
       
    61 CCamImageDecoder::NewL( MCamImageDecoderObserver& aObserver )
       
    62   {
       
    63   CCamImageDecoder* self = 
       
    64       new (ELeave) CCamImageDecoder( aObserver );
       
    65 
       
    66   CleanupStack::PushL( self );
       
    67   self->ConstructL();
       
    68   CleanupStack::Pop( self );
       
    69 
       
    70   return self;  
       
    71   }
       
    72 
       
    73 
       
    74 CCamImageDecoder::~CCamImageDecoder()
       
    75   {
       
    76   PRINT( _L("Camera => ~CCamImageDecoder") );
       
    77   Cancel();
       
    78 
       
    79   delete iDecoder;
       
    80 
       
    81   SetImageData( NULL );
       
    82   if(iDecodedBitmap)
       
    83   	{
       
    84   	delete iDecodedBitmap;
       
    85   	iDecodedBitmap = NULL;
       
    86   	}
       
    87   if ( iDecodedMask )
       
    88      {
       
    89      delete iDecodedMask;
       
    90      iDecodedMask = NULL;
       
    91      }
       
    92 
       
    93   delete iSvgEngine;
       
    94   iFs.Close();
       
    95   PRINT( _L("Camera <= ~CCamImageDecoder") );
       
    96   }
       
    97 
       
    98 // ===========================================================================
       
    99 // public methods
       
   100 void
       
   101 CCamImageDecoder::StartConversionL( CCamBufferShare* aBuffer )
       
   102   {
       
   103   PRINT( _L("Camera => CCamImageDecoder::StartConversionL") );
       
   104 
       
   105   // Data for CImageDecoder must be available throughout the conversion.
       
   106   // Need to stop any outstanding operation before deleting the descriptor.
       
   107   Cancel();
       
   108 
       
   109   PRINT( _L("Camera <> CCamImageDecoder: Copying image data..") );
       
   110   
       
   111   SetImageData( aBuffer );
       
   112 
       
   113   // GetImageDataL leaves if no data available.
       
   114   TDesC8* imageData = GetImageDataL();
       
   115 
       
   116   PRINT( _L("Camera <> CCamImageDecoder: Creating decoder..") );
       
   117 
       
   118   delete iDecoder;
       
   119   iDecoder = NULL;
       
   120   iDecoder = CImageDecoder::DataNewL( iFs, *imageData, (CImageDecoder::TOptions)KConversionOptions );
       
   121 
       
   122   if( iDecoder->FrameCount() > 0 )
       
   123     {
       
   124     const TFrameInfo& info( iDecoder->FrameInfo() );
       
   125     
       
   126 #ifdef _DEBUG   
       
   127     TSize size = info.iOverallSizeInPixels;
       
   128     PRINT2( _L("Camera <> CCamImageDecoder: Bmp size(%d,%d)"), size.iWidth, size.iHeight );
       
   129     PRINT1( _L("Camera <> CCamImageDecoder: Bmp dispmode(%d)"), info.iFrameDisplayMode );
       
   130 #endif
       
   131 
       
   132     PRINT( _L("Camera <> CCamImageDecoder: Create bitmap for snapshot..") );
       
   133     if( !iDecodedBitmap ) iDecodedBitmap = new (ELeave) CFbsBitmap;
       
   134     else                  iDecodedBitmap->Reset();
       
   135     
       
   136     TInt createError = iDecodedBitmap->Create( info.iOverallSizeInPixels, 
       
   137                                                info.iFrameDisplayMode );
       
   138     if( KErrNone != createError )
       
   139       {
       
   140       delete iDecodedBitmap;
       
   141       iDecodedBitmap = NULL;
       
   142       User::Leave( createError );
       
   143       }
       
   144 
       
   145     PRINT( _L("Camera <> CCamImageDecoder: start conversion..") );
       
   146     iRetryCounter = 0;
       
   147     iDecoder->Convert( &iStatus, *iDecodedBitmap, 0 );
       
   148     SetActive();
       
   149     }
       
   150   else
       
   151     {
       
   152     PRINT( _L("Camera <> CCamImageDecoder: No frame provided, leave..") );
       
   153     User::Leave( KErrNotFound );    
       
   154     }
       
   155 
       
   156   PRINT( _L("Camera <= CCamImageDecoder::StartConversionL") );
       
   157   }
       
   158 
       
   159 // ---------------------------------------------------------------------------
       
   160 // CCamImageDecoder::StartIconConversionL
       
   161 // ---------------------------------------------------------------------------
       
   162 //
       
   163 void CCamImageDecoder::StartIconConversionL( TDesC* aFilePath, TSize& aSize )
       
   164     {
       
   165     PRINT3( _L("Camera => CCamImageDecoder::StartIconConversionL, file:[%S], size:(%d,%d)"),
       
   166               &(*aFilePath), aSize.iWidth, aSize.iHeight );
       
   167 
       
   168     // Delete any previous bitmaps, if any
       
   169     delete iDecodedBitmap,
       
   170     iDecodedBitmap = NULL;
       
   171     delete iDecodedMask;
       
   172     iDecodedMask = NULL;
       
   173     
       
   174     // Create bitmap for use while decoding 
       
   175     CFbsBitmap* frameBuffer = new (ELeave) CFbsBitmap;
       
   176     CleanupStack::PushL( frameBuffer );
       
   177 
       
   178     TFontSpec spec;
       
   179     if ( !iSvgEngine )
       
   180         {
       
   181         iSvgEngine = CSvgEngineInterfaceImpl::NewL( frameBuffer, NULL, spec );
       
   182         }
       
   183     
       
   184     TInt domHandle = KErrNotFound;
       
   185     MSvgError* serr = iSvgEngine->PrepareDom( *aFilePath, domHandle );
       
   186     PRINT3( _L("Camera <> prepare svg dom reader, warning:%d, err code:%d, description:[%S]"), 
       
   187                 serr->IsWarning(), serr->ErrorCode(), &(serr->Description()) );
       
   188     if ( serr->HasError() && !serr->IsWarning() )
       
   189         {
       
   190         PRINT1( _L("Camera <> leaving with error:%d"), serr->SystemErrorCode() );
       
   191         User::Leave( serr->SystemErrorCode() );
       
   192         }
       
   193 
       
   194     // create image bitmap
       
   195     PRINT( _L("Camera <> CCamImageDecoder: Create bitmap for snapshot..") );
       
   196     if( !iDecodedBitmap ) iDecodedBitmap = new (ELeave) CFbsBitmap;
       
   197     else                  iDecodedBitmap->Reset();
       
   198 
       
   199     if( !iDecodedMask ) iDecodedMask = new (ELeave) CFbsBitmap;
       
   200     else                iDecodedMask->Reset();
       
   201 
       
   202     TRAPD ( createError, 
       
   203         {
       
   204         iDecodedBitmap->Create( aSize, EColor64K );
       
   205         iDecodedMask->Create( aSize, EGray256 );
       
   206         } );
       
   207     if( createError )
       
   208       {
       
   209       PRINT1( _L("Camera <> Error while creating bitmaps:%d"), createError );
       
   210       delete iDecodedBitmap;
       
   211       iDecodedBitmap = NULL;
       
   212       delete iDecodedMask;
       
   213       iDecodedMask = NULL;
       
   214       User::Leave( createError );
       
   215       }
       
   216 
       
   217     // create soft mask
       
   218     iSvgEngine->SetViewportHeight((CSvgDocumentImpl *)domHandle, aSize.iHeight);
       
   219     iSvgEngine->SetViewportWidth((CSvgDocumentImpl *)domHandle, aSize.iWidth);
       
   220 
       
   221     // render svg image
       
   222     serr = iSvgEngine->RenderDom( domHandle, iDecodedBitmap, iDecodedMask );
       
   223     PRINT3( _L("Camera <> render svg, warning:%d, err code:%d, description:[%S]"), 
       
   224                 serr->IsWarning(), serr->ErrorCode(), &(serr->Description()) );
       
   225     if ( serr->HasError() && !serr->IsWarning() )
       
   226         {
       
   227         PRINT1( _L("Camera <> leaving with error:%d"), serr->SystemErrorCode() );
       
   228         User::Leave( serr->SystemErrorCode() );
       
   229         }
       
   230 
       
   231     CleanupStack::PopAndDestroy( frameBuffer );
       
   232     if ( !IsActive() )
       
   233         {
       
   234         SetActive();
       
   235         }
       
   236 
       
   237     PRINT( _L("Camera <= CCamImageDecoder::StartIconConversionL") );
       
   238     }
       
   239 
       
   240 
       
   241 // ---------------------------------------------------------------------------
       
   242 // ---------------------------------------------------------------------------
       
   243 //
       
   244 TDesC8*
       
   245 CCamImageDecoder::GetImageDataL()
       
   246   {
       
   247   PRINT( _L("Camera => CCamImageDecoder::GetImageDataL") );
       
   248   
       
   249   if( !iSharedImageData ||
       
   250       !iSharedImageData->SharedBuffer() )
       
   251     {
       
   252     User::Leave( KErrNotFound );
       
   253     }
       
   254 
       
   255   TDesC8* data = iSharedImageData->SharedBuffer()->DataL( 0 );
       
   256 
       
   257   if( !data )
       
   258     User::Leave( KErrNotFound );
       
   259 
       
   260   delete iThumbnailData;
       
   261   iThumbnailData = ReadExifThumbNail( *data ); // Returns NULL on errors
       
   262 
       
   263 #ifdef CAMERAAPP_CREATE_TESTIMAGE
       
   264   TRAPD( saveStatus1, SaveImageDataToFileL( *data, _L("testimagefull.jpg") ) );
       
   265   PRINT1( _L("Camera <> CCamImageDecoder: Save full image to file status:%d"), saveStatus1 );
       
   266   if( iThumbnailData )
       
   267     {
       
   268     TRAPD( saveStatus2, SaveImageDataToFileL( *iThumbnailData, _L("testimagethumb.jpg") ) );
       
   269     PRINT1( _L("Camera <> CCamImageDecoder: Save thumbnail to file status:%d"), saveStatus2 );
       
   270     }
       
   271 #endif
       
   272 
       
   273 
       
   274   if( iThumbnailData )
       
   275     {
       
   276     data = iThumbnailData;
       
   277     }  
       
   278 
       
   279   PRINT1( _L("Camera <= CCamImageDecoder::GetImageDataL, data size:%d"), data->Size() );
       
   280   return data;
       
   281   }
       
   282 
       
   283 // ---------------------------------------------------------------------------
       
   284 // ---------------------------------------------------------------------------
       
   285 //
       
   286 HBufC8*
       
   287 CCamImageDecoder::ReadExifThumbNail( const TDesC8& aExifData )
       
   288   {
       
   289   PRINT( _L("Camera => CCamImageDecoder::ReadExifThumbNailL") );
       
   290   HBufC8* thumb = NULL;
       
   291   TRAP_IGNORE( 
       
   292     {
       
   293     CExifRead* reader = CExifRead::NewL( aExifData, KExifReaderFlags );
       
   294     CleanupStack::PushL( reader );
       
   295     thumb = reader->GetThumbnailL();
       
   296     CleanupStack::PopAndDestroy( reader );
       
   297     });
       
   298 
       
   299   PRINT( _L("Camera <= CCamImageDecoder::ReadExifThumbNailL") );
       
   300   return thumb;
       
   301   }
       
   302 
       
   303 // ===========================================================================
       
   304 // from CActive
       
   305 
       
   306 // ---------------------------------------------------------------------------
       
   307 // virtual 
       
   308 // ---------------------------------------------------------------------------
       
   309 //
       
   310 void 
       
   311 CCamImageDecoder::DoCancel()
       
   312   {
       
   313   PRINT( _L("Camera => CCamImageDecoder::DoCancel") );
       
   314 
       
   315   if( iDecoder )
       
   316     {
       
   317     iDecoder->Cancel();
       
   318     delete iDecoder;
       
   319     iDecoder = NULL;    
       
   320     }
       
   321 
       
   322   SetImageData( NULL );
       
   323 
       
   324   PRINT( _L("Camera <= CCamImageDecoder::DoCancel") );
       
   325   }
       
   326 
       
   327 
       
   328 // ---------------------------------------------------------------------------
       
   329 // virtual 
       
   330 // ---------------------------------------------------------------------------
       
   331 //
       
   332 void 
       
   333 CCamImageDecoder::RunL()
       
   334   {
       
   335   PRINT1( _L("Camera => CCamImageDecoder::RunL, iStatus:%d"), iStatus.Int() );
       
   336 
       
   337   switch( iStatus.Int() )
       
   338     {
       
   339     case KErrNone :
       
   340       {
       
   341       // CImageDecoder has finished using the data,
       
   342       // so we are able to free it.
       
   343       if ( iSvgEngine )
       
   344           {
       
   345           iSvgEngine->Destroy();
       
   346           delete iSvgEngine;
       
   347           iSvgEngine = NULL;
       
   348           }
       
   349       SetImageData( NULL );
       
   350       iObserver.ImageDecodedL( iStatus.Int(), iDecodedBitmap, iDecodedMask );
       
   351       break;
       
   352       }
       
   353     case KErrUnderflow :
       
   354       {
       
   355       // Decoder did not have enough data to convert.
       
   356       // CImageDecoder documentation recommends calling
       
   357       // repeatedly ContinueConvert.
       
   358       if( iRetryCounter++ < KMaxRetries )
       
   359         {
       
   360         iStatus = KErrNone;
       
   361         iDecoder->ContinueConvert( &iStatus );
       
   362         SetActive();
       
   363         }
       
   364       else
       
   365         {
       
   366         // Handled in RunError
       
   367         User::Leave( KErrUnderflow );
       
   368         }
       
   369       break;
       
   370       }
       
   371     case KErrCancel :
       
   372     default :
       
   373       {
       
   374       User::Leave( iStatus.Int() );
       
   375       break;
       
   376       }
       
   377     }
       
   378 
       
   379   PRINT( _L("Camera <= CCamImageDecoder::RunL") );
       
   380   }
       
   381 
       
   382 
       
   383 // ---------------------------------------------------------------------------
       
   384 // virtual 
       
   385 // ---------------------------------------------------------------------------
       
   386 //
       
   387 TInt 
       
   388 CCamImageDecoder::RunError( TInt aError )
       
   389   {
       
   390   PRINT1( _L("Camera => CCamImageDecoder::RunError(%d)"), aError );
       
   391 
       
   392   SetImageData( NULL );
       
   393   // Leave has occurred in RunL.
       
   394   // Notify observer with error.
       
   395   TRAP_IGNORE(iObserver.ImageDecodedL( aError, NULL, NULL ));
       
   396 
       
   397   PRINT( _L("Camera <= CCamImageDecoder::RunError") );
       
   398   return KErrNone;
       
   399   }
       
   400 
       
   401 
       
   402 // ===========================================================================
       
   403 void
       
   404 CCamImageDecoder::SetImageData( CCamBufferShare* aBuffer )
       
   405   {
       
   406   if( iSharedImageData )
       
   407     {
       
   408     iSharedImageData->Release();
       
   409     iSharedImageData = NULL;
       
   410     }
       
   411 
       
   412   iSharedImageData = aBuffer;
       
   413 
       
   414   if( iSharedImageData )
       
   415     iSharedImageData->Reserve();
       
   416   }
       
   417 
       
   418 // ===========================================================================
       
   419 // private constructors
       
   420 
       
   421 
       
   422 void
       
   423 CCamImageDecoder::ConstructL()
       
   424   {
       
   425   User::LeaveIfError( iFs.Connect() );
       
   426 
       
   427   CActiveScheduler::Add( this );
       
   428   }
       
   429 
       
   430 
       
   431 
       
   432 CCamImageDecoder::CCamImageDecoder( MCamImageDecoderObserver& aObserver )
       
   433   : CActive( KPriority  ),
       
   434     iObserver( aObserver )
       
   435   {
       
   436   }
       
   437 
       
   438 // end of file