camerauis/cameraapp/generic/src/cameracontroller/camimagedecoder.cpp
changeset 0 1ddebce53859
child 10 8c55c525d5d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camerauis/cameraapp/generic/src/cameracontroller/camimagedecoder.cpp	Thu Jan 07 16:18:56 2010 +0200
@@ -0,0 +1,344 @@
+/*
+* Copyright (c) 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:  Implementation of Camera image decoder
+*
+*/
+
+
+
+
+#include <imageconversion.h>
+#include <ExifRead.h>
+#include <ecam.h> // MCameraBuffer
+
+#include <eikenv.h>
+
+#include "camlogging.h"
+#include "camfilesaveutility.h"
+#include "cambuffershare.h"
+
+#include "camimagedecoder.h"
+
+// ===========================================================================
+// Local constants
+
+namespace NCamCameraController
+  {
+  // Decoding flags
+  static const TUint32 KConversionOptions = 
+    ( CImageDecoder::EOptionNone
+    | CImageDecoder::EOptionAlwaysThread
+    | CImageDecoder::EPreferFastDecode
+    );
+  
+  // EXIF reader flags
+  //   Only need the thumbnail, so no need to parse the
+  //   main (jpeg) image.
+  static const TUint KExifReaderFlags = CExifRead::ENoJpeg;
+  
+  // Other constants
+  static const TInt KMaxRetries = 10;
+  static const TInt KPriority = CActive::EPriorityHigh;
+  }
+
+using namespace NCamCameraController;
+
+// ===========================================================================
+// public constructor and destructor
+
+CCamImageDecoder* 
+CCamImageDecoder::NewL( MCamImageDecoderObserver& aObserver )
+  {
+  CCamImageDecoder* self = 
+      new (ELeave) CCamImageDecoder( aObserver );
+
+  CleanupStack::PushL( self );
+  self->ConstructL();
+  CleanupStack::Pop( self );
+
+  return self;  
+  }
+
+
+CCamImageDecoder::~CCamImageDecoder()
+  {
+  PRINT( _L("Camera => ~CCamImageDecoder") );
+  Cancel();
+
+  delete iDecoder;
+
+  SetImageData( NULL );
+ if(iDecodedBitmap)
+  	{
+  	delete iDecodedBitmap;
+  	iDecodedBitmap = NULL;
+  	}
+  iFs.Close();
+  PRINT( _L("Camera <= ~CCamImageDecoder") );
+  }
+
+// ===========================================================================
+// public methods
+void
+CCamImageDecoder::StartConversionL( CCamBufferShare* aBuffer )
+  {
+  PRINT( _L("Camera => CCamImageDecoder::StartConversionL") );
+
+  // Data for CImageDecoder must be available throughout the conversion.
+  // Need to stop any outstanding operation before deleting the descriptor.
+  Cancel();
+
+  PRINT( _L("Camera <> CCamImageDecoder: Copying image data..") );
+  
+  SetImageData( aBuffer );
+
+  // GetImageDataL leaves if no data available.
+  TDesC8* imageData = GetImageDataL();
+
+  PRINT( _L("Camera <> CCamImageDecoder: Creating decoder..") );
+
+  delete iDecoder;
+  iDecoder = NULL;
+  iDecoder = CImageDecoder::DataNewL( iFs, *imageData, (CImageDecoder::TOptions)KConversionOptions );
+
+  if( iDecoder->FrameCount() > 0 )
+    {
+    const TFrameInfo& info( iDecoder->FrameInfo() );
+    
+#ifdef _DEBUG   
+    TSize size = info.iOverallSizeInPixels;
+    PRINT2( _L("Camera <> CCamImageDecoder: Bmp size(%d,%d)"), size.iWidth, size.iHeight );
+    PRINT1( _L("Camera <> CCamImageDecoder: Bmp dispmode(%d)"), info.iFrameDisplayMode );
+#endif
+
+    PRINT( _L("Camera <> CCamImageDecoder: Create bitmap for snapshot..") );
+    if( !iDecodedBitmap ) iDecodedBitmap = new (ELeave) CFbsBitmap;
+    else                  iDecodedBitmap->Reset();
+    
+    TInt createError = iDecodedBitmap->Create( info.iOverallSizeInPixels, 
+                                               info.iFrameDisplayMode );
+    if( KErrNone != createError )
+      {
+      delete iDecodedBitmap;
+      iDecodedBitmap = NULL;
+      User::Leave( createError );
+      }
+
+    PRINT( _L("Camera <> CCamImageDecoder: start conversion..") );
+    iRetryCounter = 0;
+    iDecoder->Convert( &iStatus, *iDecodedBitmap, 0 );
+    SetActive();
+    }
+  else
+    {
+    PRINT( _L("Camera <> CCamImageDecoder: No frame provided, leave..") );
+    User::Leave( KErrNotFound );    
+    }
+
+  PRINT( _L("Camera <= CCamImageDecoder::StartConversionL") );
+  }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+TDesC8*
+CCamImageDecoder::GetImageDataL()
+  {
+  PRINT( _L("Camera => CCamImageDecoder::GetImageDataL") );
+  
+  if( !iSharedImageData ||
+      !iSharedImageData->SharedBuffer() )
+    {
+    User::Leave( KErrNotFound );
+    }
+
+  TDesC8* data = iSharedImageData->SharedBuffer()->DataL( 0 );
+
+  if( !data )
+    User::Leave( KErrNotFound );
+
+  delete iThumbnailData;
+  iThumbnailData = ReadExifThumbNail( *data ); // Returns NULL on errors
+
+#ifdef CAMERAAPP_CREATE_TESTIMAGE
+  TRAPD( saveStatus1, SaveImageDataToFileL( *data, _L("testimagefull.jpg") ) );
+  PRINT1( _L("Camera <> CCamImageDecoder: Save full image to file status:%d"), saveStatus1 );
+  if( iThumbnailData )
+    {
+    TRAPD( saveStatus2, SaveImageDataToFileL( *iThumbnailData, _L("testimagethumb.jpg") ) );
+    PRINT1( _L("Camera <> CCamImageDecoder: Save thumbnail to file status:%d"), saveStatus2 );
+    }
+#endif
+
+
+  if( iThumbnailData )
+    {
+    data = iThumbnailData;
+    }  
+
+  PRINT1( _L("Camera <= CCamImageDecoder::GetImageDataL, data size:%d"), data->Size() );
+  return data;
+  }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+HBufC8*
+CCamImageDecoder::ReadExifThumbNail( const TDesC8& aExifData )
+  {
+  PRINT( _L("Camera => CCamImageDecoder::ReadExifThumbNailL") );
+  HBufC8* thumb = NULL;
+  TRAP_IGNORE( 
+    {
+    CExifRead* reader = CExifRead::NewL( aExifData, KExifReaderFlags );
+    CleanupStack::PushL( reader );
+    thumb = reader->GetThumbnailL();
+    CleanupStack::PopAndDestroy( reader );
+    });
+
+  PRINT( _L("Camera <= CCamImageDecoder::ReadExifThumbNailL") );
+  return thumb;
+  }
+
+// ===========================================================================
+// from CActive
+
+// ---------------------------------------------------------------------------
+// virtual 
+// ---------------------------------------------------------------------------
+//
+void 
+CCamImageDecoder::DoCancel()
+  {
+  PRINT( _L("Camera => CCamImageDecoder::DoCancel") );
+
+  if( iDecoder )
+    {
+    iDecoder->Cancel();
+    delete iDecoder;
+    iDecoder = NULL;    
+    }
+
+  SetImageData( NULL );
+
+  PRINT( _L("Camera <= CCamImageDecoder::DoCancel") );
+  }
+
+
+// ---------------------------------------------------------------------------
+// virtual 
+// ---------------------------------------------------------------------------
+//
+void 
+CCamImageDecoder::RunL()
+  {
+  PRINT1( _L("Camera => CCamImageDecoder::RunL, iStatus:%d"), iStatus.Int() );
+
+  switch( iStatus.Int() )
+    {
+    case KErrNone :
+      {
+      // CImageDecoder has finished using the data,
+      // so we are able to free it.
+      SetImageData( NULL );
+      iObserver.ImageDecoded( iStatus.Int(), iDecodedBitmap );
+      break;
+      }
+    case KErrUnderflow :
+      {
+      // Decoder did not have enough data to convert.
+      // CImageDecoder documentation recommends calling
+      // repeatedly ContinueConvert.
+      if( iRetryCounter++ < KMaxRetries )
+        {
+        iStatus = KErrNone;
+        iDecoder->ContinueConvert( &iStatus );
+        SetActive();
+        }
+      else
+        {
+        // Handled in RunError
+        User::Leave( KErrUnderflow );
+        }
+      break;
+      }
+    case KErrCancel :
+    default :
+      {
+      User::Leave( iStatus.Int() );
+      break;
+      }
+    }
+
+  PRINT( _L("Camera <= CCamImageDecoder::RunL") );
+  }
+
+
+// ---------------------------------------------------------------------------
+// virtual 
+// ---------------------------------------------------------------------------
+//
+TInt 
+CCamImageDecoder::RunError( TInt aError )
+  {
+  PRINT1( _L("Camera => CCamImageDecoder::RunError(%d)"), aError );
+
+  SetImageData( NULL );
+  // Leave has occurred in RunL.
+  // Notify observer with error.
+  iObserver.ImageDecoded( aError, NULL );
+
+  PRINT( _L("Camera <= CCamImageDecoder::RunError") );
+  return KErrNone;
+  }
+
+
+// ===========================================================================
+void
+CCamImageDecoder::SetImageData( CCamBufferShare* aBuffer )
+  {
+  if( iSharedImageData )
+    {
+    iSharedImageData->Release();
+    iSharedImageData = NULL;
+    }
+
+  iSharedImageData = aBuffer;
+
+  if( iSharedImageData )
+    iSharedImageData->Reserve();
+  }
+
+// ===========================================================================
+// private constructors
+
+
+void
+CCamImageDecoder::ConstructL()
+  {
+  User::LeaveIfError( iFs.Connect() );
+
+  CActiveScheduler::Add( this );
+  }
+
+
+
+CCamImageDecoder::CCamImageDecoder( MCamImageDecoderObserver& aObserver )
+  : CActive( KPriority  ),
+    iObserver( aObserver )
+  {
+  }
+
+// end of file